Skip to content

Commit

Permalink
drm/msm/dsi: Queue HPD helper work in attach/detach callbacks
Browse files Browse the repository at this point in the history
The msm/dsi host drivers calls drm_helper_hpd_irq_event in the
mipi_dsi_host attach/detatch callbacks.

mipi_dsi_attach()/mipi_dsi_detach() from a panel/bridge
driver could be called from a context where the drm_device's
mode_config.mutex is already held, resulting in a deadlock.
Queue it as work instead.

Signed-off-by: Archit Taneja <[email protected]>
Signed-off-by: Rob Clark <[email protected]>
  • Loading branch information
boddob authored and robclark committed Nov 2, 2016
1 parent b0a6af8 commit 8d23ea4
Showing 1 changed file with 12 additions and 2 deletions.
14 changes: 12 additions & 2 deletions drivers/gpu/drm/msm/dsi/dsi_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct msm_dsi_host {

u32 err_work_state;
struct work_struct err_work;
struct work_struct hpd_work;
struct workqueue_struct *workqueue;

/* DSI 6G TX buffer*/
Expand Down Expand Up @@ -1294,6 +1295,14 @@ static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host)
wmb(); /* make sure dsi controller enabled again */
}

static void dsi_hpd_worker(struct work_struct *work)
{
struct msm_dsi_host *msm_host =
container_of(work, struct msm_dsi_host, hpd_work);

drm_helper_hpd_irq_event(msm_host->dev);
}

static void dsi_err_worker(struct work_struct *work)
{
struct msm_dsi_host *msm_host =
Expand Down Expand Up @@ -1480,7 +1489,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host,

DBG("id=%d", msm_host->id);
if (msm_host->dev)
drm_helper_hpd_irq_event(msm_host->dev);
queue_work(msm_host->workqueue, &msm_host->hpd_work);

return 0;
}
Expand All @@ -1494,7 +1503,7 @@ static int dsi_host_detach(struct mipi_dsi_host *host,

DBG("id=%d", msm_host->id);
if (msm_host->dev)
drm_helper_hpd_irq_event(msm_host->dev);
queue_work(msm_host->workqueue, &msm_host->hpd_work);

return 0;
}
Expand Down Expand Up @@ -1748,6 +1757,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
/* setup workqueue */
msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);
INIT_WORK(&msm_host->err_work, dsi_err_worker);
INIT_WORK(&msm_host->hpd_work, dsi_hpd_worker);

msm_dsi->host = &msm_host->base;
msm_dsi->id = msm_host->id;
Expand Down

0 comments on commit 8d23ea4

Please sign in to comment.