diff options
author | Archit Taneja <architt@codeaurora.org> | 2016-10-25 02:47:59 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2016-11-02 10:48:09 -0400 |
commit | 8d23ea403044efe97553dd64228b172c8ffca047 (patch) | |
tree | a2a9244f5ed21c2a3732d7be14d04d069caaa767 /drivers/gpu | |
parent | b0a6af8b34c9ad20894aa46f85f4bf59d444f286 (diff) |
drm/msm/dsi: Queue HPD helper work in attach/detach callbacks
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 <architt@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_host.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index f05ed0e1f3d6..6f240021705b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c | |||
@@ -139,6 +139,7 @@ struct msm_dsi_host { | |||
139 | 139 | ||
140 | u32 err_work_state; | 140 | u32 err_work_state; |
141 | struct work_struct err_work; | 141 | struct work_struct err_work; |
142 | struct work_struct hpd_work; | ||
142 | struct workqueue_struct *workqueue; | 143 | struct workqueue_struct *workqueue; |
143 | 144 | ||
144 | /* DSI 6G TX buffer*/ | 145 | /* DSI 6G TX buffer*/ |
@@ -1294,6 +1295,14 @@ static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host) | |||
1294 | wmb(); /* make sure dsi controller enabled again */ | 1295 | wmb(); /* make sure dsi controller enabled again */ |
1295 | } | 1296 | } |
1296 | 1297 | ||
1298 | static void dsi_hpd_worker(struct work_struct *work) | ||
1299 | { | ||
1300 | struct msm_dsi_host *msm_host = | ||
1301 | container_of(work, struct msm_dsi_host, hpd_work); | ||
1302 | |||
1303 | drm_helper_hpd_irq_event(msm_host->dev); | ||
1304 | } | ||
1305 | |||
1297 | static void dsi_err_worker(struct work_struct *work) | 1306 | static void dsi_err_worker(struct work_struct *work) |
1298 | { | 1307 | { |
1299 | struct msm_dsi_host *msm_host = | 1308 | struct msm_dsi_host *msm_host = |
@@ -1480,7 +1489,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host, | |||
1480 | 1489 | ||
1481 | DBG("id=%d", msm_host->id); | 1490 | DBG("id=%d", msm_host->id); |
1482 | if (msm_host->dev) | 1491 | if (msm_host->dev) |
1483 | drm_helper_hpd_irq_event(msm_host->dev); | 1492 | queue_work(msm_host->workqueue, &msm_host->hpd_work); |
1484 | 1493 | ||
1485 | return 0; | 1494 | return 0; |
1486 | } | 1495 | } |
@@ -1494,7 +1503,7 @@ static int dsi_host_detach(struct mipi_dsi_host *host, | |||
1494 | 1503 | ||
1495 | DBG("id=%d", msm_host->id); | 1504 | DBG("id=%d", msm_host->id); |
1496 | if (msm_host->dev) | 1505 | if (msm_host->dev) |
1497 | drm_helper_hpd_irq_event(msm_host->dev); | 1506 | queue_work(msm_host->workqueue, &msm_host->hpd_work); |
1498 | 1507 | ||
1499 | return 0; | 1508 | return 0; |
1500 | } | 1509 | } |
@@ -1748,6 +1757,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) | |||
1748 | /* setup workqueue */ | 1757 | /* setup workqueue */ |
1749 | msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0); | 1758 | msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0); |
1750 | INIT_WORK(&msm_host->err_work, dsi_err_worker); | 1759 | INIT_WORK(&msm_host->err_work, dsi_err_worker); |
1760 | INIT_WORK(&msm_host->hpd_work, dsi_hpd_worker); | ||
1751 | 1761 | ||
1752 | msm_dsi->host = &msm_host->base; | 1762 | msm_dsi->host = &msm_host->base; |
1753 | msm_dsi->id = msm_host->id; | 1763 | msm_dsi->id = msm_host->id; |