From 7e9b80092bc6ea8c9d5258a18771b55bd21df752 Mon Sep 17 00:00:00 2001 From: Christopher Braga Date: Thu, 2 May 2019 18:04:44 -0400 Subject: [PATCH] disp: msm: Ensure clean slate when starting and stopping HDCP The DP HDCP layer fails to wait on and clear its internal thread upon an HDCP stop or failure. This can result in use after free failures if a read or write over aux channel operation is already queued. Update the DP HDCP layer to stop and wait on kthread completion upon HDCP failures, and clear the kthread command queue before resuming kthread execution. Additionally, ensure the SDE HDCP worker thread correctly starts and stops execution upon HDCP enablement and disablement respectively. Change-Id: I4218d7935f89416b5e5d74afd8f5d22e031b9a38 Signed-off-by: Christopher Braga --- msm/dp/dp_display.c | 2 +- msm/dp/dp_hdcp2p2.c | 10 ++++++++-- msm/sde_hdcp_2x.c | 9 +++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index c4f2f22207..17d83295e6 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -382,12 +382,12 @@ static void dp_display_hdcp_cb_work(struct work_struct *work) return; } dp_display_hdcp_register_streams(dp); - status->hdcp_state = HDCP_STATE_AUTHENTICATING; if (ops && ops->reauthenticate) { rc = ops->reauthenticate(data); if (rc) pr_err("failed rc=%d\n", rc); } + status->hdcp_state = HDCP_STATE_AUTHENTICATING; } else { pr_debug("not reauthenticating, cable disconnected\n"); } diff --git a/msm/dp/dp_hdcp2p2.c b/msm/dp/dp_hdcp2p2.c index 61404be550..44d366809d 100644 --- a/msm/dp/dp_hdcp2p2.c +++ b/msm/dp/dp_hdcp2p2.c @@ -196,16 +196,20 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) switch (data->cmd) { case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED); + kfifo_put(&ctrl->cmd_q, data->cmd); + wake_up(&ctrl->wait_q); break; case HDCP_TRANSPORT_CMD_STATUS_FAILED: atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); + kfifo_put(&ctrl->cmd_q, data->cmd); + kthread_park(ctrl->thread); break; default: + kfifo_put(&ctrl->cmd_q, data->cmd); + wake_up(&ctrl->wait_q); break; } - kfifo_put(&ctrl->cmd_q, data->cmd); - wake_up(&ctrl->wait_q); exit: return 0; } @@ -310,6 +314,8 @@ static int dp_hdcp2p2_authenticate(void *input) ctrl->sink_status = SINK_CONNECTED; atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING); + kthread_park(ctrl->thread); + kfifo_reset(&ctrl->cmd_q); kthread_unpark(ctrl->thread); cdata.context = input; diff --git a/msm/sde_hdcp_2x.c b/msm/sde_hdcp_2x.c index c4f7c210d0..853e1fef08 100644 --- a/msm/sde_hdcp_2x.c +++ b/msm/sde_hdcp_2x.c @@ -829,9 +829,16 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data) if (!atomic_cmpxchg(&hdcp->enable_pending, 0, 1)) { hdcp->device_type = data->device_type; kfifo_put(&hdcp->cmd_q, data->cmd); + kthread_unpark(hdcp->thread); wake_up(&hdcp->wait_q); } break; + case HDCP_2X_CMD_DISABLE: + if (!atomic_xchg(&hdcp->hdcp_off, 1)) + kfifo_put(&hdcp->cmd_q, HDCP_2X_CMD_STOP); + kfifo_put(&hdcp->cmd_q, data->cmd); + kthread_park(hdcp->thread); + break; case HDCP_2X_CMD_STOP: atomic_set(&hdcp->hdcp_off, 1); @@ -926,8 +933,6 @@ static int sde_hdcp_2x_main(void *data) atomic_set(&hdcp->enable_pending, 0); break; case HDCP_2X_CMD_DISABLE: - if (!atomic_xchg(&hdcp->hdcp_off, 1)) - sde_hdcp_2x_clean(hdcp); sde_hdcp_2x_disable(hdcp); break; case HDCP_2X_CMD_START: