Skip to content

Commit 570d3e5

Browse files
Kuogee Hsiehlumag
authored andcommitted
drm/msm/dp: stop event kernel thread when DP unbind
Current DP driver implementation, event thread is kept running after DP display is unbind. This patch fix this problem by disabling DP irq and stop event thread to exit gracefully at dp_display_unbind(). Changes in v2: -- start event thread at dp_display_bind() Changes in v3: -- disable all HDP interrupts at unbind -- replace dp_hpd_event_setup() with dp_hpd_event_thread_start() -- replace dp_hpd_event_stop() with dp_hpd_event_thread_stop() -- move init_waitqueue_head(&dp->event_q) to probe() -- move spin_lock_init(&dp->event_lock) to probe() Changes in v4: -- relocate both dp_display_bind() and dp_display_unbind() to bottom of file Changes in v5: -- cancel relocation of both dp_display_bind() and dp_display_unbind() Changes in v6: -- move empty event q to dp_event_thread_start() Changes in v7: -- call ktheread_stop() directly instead of dp_hpd_event_thread_stop() function Changes in v8: -- return error immediately if audio registration failed. Changes in v9: -- return error immediately if event thread create failed. Changes in v10: -- delete extra DRM_ERROR("failed to create DP event thread\n"); Fixes: 8ede2ec ("drm/msm/dp: Add DP compliance tests on Snapdragon Chipsets") Signed-off-by: Kuogee Hsieh <[email protected]> Reported-by: Dmitry Baryshkov <[email protected]> Reviewed-by: Stephen Boyd <[email protected]> Patchwork: https://patchwork.freedesktop.org/patch/482399/ Link: https://lore.kernel.org/r/[email protected] [DB: fixed Fixes tag] Signed-off-by: Dmitry Baryshkov <[email protected]>
1 parent 13b73e1 commit 570d3e5

File tree

1 file changed

+31
-8
lines changed

1 file changed

+31
-8
lines changed

drivers/gpu/drm/msm/dp/dp_display.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ struct dp_display_private {
113113
u32 hpd_state;
114114
u32 event_pndx;
115115
u32 event_gndx;
116+
struct task_struct *ev_tsk;
116117
struct dp_event event_list[DP_EVENT_Q_MAX];
117118
spinlock_t event_lock;
118119

@@ -252,6 +253,8 @@ void dp_display_signal_audio_complete(struct msm_dp *dp_display)
252253
complete_all(&dp->audio_comp);
253254
}
254255

256+
static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv);
257+
255258
static int dp_display_bind(struct device *dev, struct device *master,
256259
void *data)
257260
{
@@ -286,9 +289,18 @@ static int dp_display_bind(struct device *dev, struct device *master,
286289
}
287290

288291
rc = dp_register_audio_driver(dev, dp->audio);
289-
if (rc)
292+
if (rc) {
290293
DRM_ERROR("Audio registration Dp failed\n");
294+
goto end;
295+
}
291296

297+
rc = dp_hpd_event_thread_start(dp);
298+
if (rc) {
299+
DRM_ERROR("Event thread create failed\n");
300+
goto end;
301+
}
302+
303+
return 0;
292304
end:
293305
return rc;
294306
}
@@ -299,6 +311,11 @@ static void dp_display_unbind(struct device *dev, struct device *master,
299311
struct dp_display_private *dp = dev_get_dp_display_private(dev);
300312
struct msm_drm_private *priv = dev_get_drvdata(master);
301313

314+
/* disable all HPD interrupts */
315+
dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false);
316+
317+
kthread_stop(dp->ev_tsk);
318+
302319
dp_power_client_deinit(dp->power);
303320
dp_aux_unregister(dp->aux);
304321
priv->dp[dp->id] = NULL;
@@ -1113,7 +1130,7 @@ static int hpd_event_thread(void *data)
11131130

11141131
dp_priv = (struct dp_display_private *)data;
11151132

1116-
while (1) {
1133+
while (!kthread_should_stop()) {
11171134
if (timeout_mode) {
11181135
wait_event_timeout(dp_priv->event_q,
11191136
(dp_priv->event_pndx == dp_priv->event_gndx),
@@ -1191,12 +1208,17 @@ static int hpd_event_thread(void *data)
11911208
return 0;
11921209
}
11931210

1194-
static void dp_hpd_event_setup(struct dp_display_private *dp_priv)
1211+
static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv)
11951212
{
1196-
init_waitqueue_head(&dp_priv->event_q);
1197-
spin_lock_init(&dp_priv->event_lock);
1213+
/* set event q to empty */
1214+
dp_priv->event_gndx = 0;
1215+
dp_priv->event_pndx = 0;
11981216

1199-
kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
1217+
dp_priv->ev_tsk = kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
1218+
if (IS_ERR(dp_priv->ev_tsk))
1219+
return PTR_ERR(dp_priv->ev_tsk);
1220+
1221+
return 0;
12001222
}
12011223

12021224
static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
@@ -1327,7 +1349,10 @@ static int dp_display_probe(struct platform_device *pdev)
13271349
return -EPROBE_DEFER;
13281350
}
13291351

1352+
/* setup event q */
13301353
mutex_init(&dp->event_mutex);
1354+
init_waitqueue_head(&dp->event_q);
1355+
spin_lock_init(&dp->event_lock);
13311356

13321357
/* Store DP audio handle inside DP display */
13331358
dp->dp_display.dp_audio = dp->audio;
@@ -1510,8 +1535,6 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display)
15101535

15111536
dp = container_of(dp_display, struct dp_display_private, dp_display);
15121537

1513-
dp_hpd_event_setup(dp);
1514-
15151538
dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
15161539
}
15171540

0 commit comments

Comments
 (0)