drm: bridge: analogix/dp: Fix the dead lock when disable bridge
authorJacob Chen <jacob2.chen@rock-chips.com>
Wed, 4 Jan 2017 06:01:02 +0000 (14:01 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Sat, 1 Apr 2017 08:53:53 +0000 (16:53 +0800)
dead lock :
IN --> drm_fb_helper_restore_fbdev_mode_unlocked
        1. Acquire mode_config lock
IN --> atomic commit
IN --> rockchip_atomic_commit_complete
IN --> drm_atomic_helper_commit_modeset_disables
IN --> bridge disable
IN --> analogix_dp_irq_thread
IN --> drm_helper_hpd_irq_event
3. Acquire mode_config lock (have been acquired)

[  363.054554] INFO: task irq/54-analogix:174 blocked for more than 120 seconds.
[  363.054612]       Not tainted 4.4.55 #31
[  363.054631] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  363.054651] irq/54-analogix D ffffff8008084f98     0   174      2 0x00000000
[  363.054691] Call trace:
[  363.054726] [<ffffff8008084f98>] __switch_to+0xb4/0xc0
[  363.054759] [<ffffff8008b21308>] __schedule+0x3f0/0x670
[  363.054785] [<ffffff8008b2160c>] schedule+0x84/0xa4
[  363.054813] [<ffffff8008b21954>] schedule_preempt_disabled+0x20/0x38
[  363.054842] [<ffffff8008b23084>] __mutex_lock_slowpath+0xfc/0x178
[  363.054869] [<ffffff8008b2312c>] mutex_lock+0x2c/0x44
[  363.054897] [<ffffff800844419c>] drm_helper_hpd_irq_event+0x34/0x154
[  363.054929] [<ffffff800848e578>] analogix_dp_irq_thread+0x30/0x58
[  363.054957] [<ffffff80080eb198>] irq_thread_fn+0x28/0x68
[  363.054991] [<ffffff80080eb3ac>] irq_thread+0x10c/0x1ec
[  363.055016] [<ffffff80080b7e58>] kthread+0xe8/0xf0
[  363.055042] [<ffffff8008082690>] ret_from_fork+0x10/0x40
[  363.055097] INFO: task surfaceflinger:240 blocked for more than 120 seconds.
[  363.055119]       Not tainted 4.4.55 #31
[  363.055136] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  363.055155] surfaceflinger  D ffffff8008084f98     0   240      1 0x00000009
[  363.055191] Call trace:
[  363.055214] [<ffffff8008084f98>] __switch_to+0xb4/0xc0
[  363.055241] [<ffffff8008b21308>] __schedule+0x3f0/0x670
[  363.055268] [<ffffff8008b2160c>] schedule+0x84/0xa4
[  363.055292] [<ffffff80080ea61c>] synchronize_irq+0x64/0x98
[  363.055316] [<ffffff80080eb9d8>] disable_irq+0x20/0x2c
[  363.055344] [<ffffff800848e224>] analogix_dp_bridge_disable+0x70/0xa8
[  363.055370] [<ffffff800846fabc>] drm_bridge_disable+0x2c/0x38
[  363.055403] [<ffffff800844b930>] drm_atomic_helper_commit_modeset_disables+0x120/0x39c
[  363.055432] [<ffffff800847e018>] rockchip_atomic_commit_complete+0x30/0x14c
[  363.055459] [<ffffff800847e1b0>] rockchip_drm_atomic_commit+0x7c/0x9c
[  363.055484] [<ffffff800846e898>] drm_atomic_commit+0x64/0x70
[  363.055511] [<ffffff800844ae28>] drm_atomic_helper_connector_dpms+0xf4/0x154
[  363.055541] [<ffffff800846398c>] drm_mode_obj_set_property_ioctl+0x148/0x204
[  363.055575] [<ffffff8008463a88>] drm_mode_connector_property_set_ioctl+0x40/0x60
[  363.055602] [<ffffff80084541a8>] drm_ioctl+0x27c/0x400
[  363.055630] [<ffffff80081ba1d4>] do_vfs_ioctl+0x4d0/0x5c0
[  363.055655] [<ffffff80081ba324>] SyS_ioctl+0x60/0x88
[  363.055680] [<ffffff80080826f0>] el0_svc_naked+0x24/0x28

Change-Id: I6d5eeb83b9640a54b33b1cad03c2207196a56e16
Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c

index 31f384b..df3d47b 100644 (file)
@@ -871,6 +871,11 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
        struct analogix_dp_device *dp = arg;
        enum dp_irq_type irq_type;
 
+       if (dp->dpms_mode != DRM_MODE_DPMS_ON)
+               return IRQ_HANDLED;
+
+       pm_runtime_get_sync(dp->dev);
+
        irq_type = analogix_dp_get_irq_type(dp);
        if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN ||
            irq_type & DP_IRQ_TYPE_HP_CABLE_OUT) {
@@ -884,6 +889,8 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
                analogix_dp_unmute_hpd_interrupt(dp);
        }
 
+       pm_runtime_put(dp->dev);
+
        return IRQ_HANDLED;
 }
 
@@ -1099,7 +1106,7 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
                }
        }
 
-       disable_irq(dp->irq);
+       disable_irq_nosync(dp->irq);
        phy_power_off(dp->phy);
 
        if (dp->plat_data->power_off)