]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commit - drivers/gpu/drm/drm_irq.c
drm: Fix deadlock between event_lock and vbl_lock/vblank_time_lock
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 6 Aug 2014 11:49:51 +0000 (14:49 +0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 6 Aug 2014 20:39:26 +0000 (22:39 +0200)
commit56cc279b29c7b204fe7d0943509ae209b8b128db
tree021e1b9d6044ccd573f8307236d0ade036f89a01
parent8a51d5bef07f1c8c59de20089fb27ea39d395f1b
drm: Fix deadlock between event_lock and vbl_lock/vblank_time_lock

Currently both drm_irq.c and several drivers call drm_vblank_put()
while holding event_lock. Now that drm_vblank_put() can disable the
vblank interrupt directly it may need to grab vbl_lock and
vblank_time_lock. That causes deadlocks since we take the locks
in the opposite order in two places in drm_irq.c. So let's make
sure the locking order is always event_lock->vbl_lock->vblank_time_lock.

In drm_vblank_off() pull up event_lock from underneath vbl_lock. Hold
the event_lock across the whole operation to make sure we only send
out the events that were on the queue when we disabled the interrupt,
and not ones that got added just after (assuming drm_vblank_on() already
managed to get called somewhere between).

To sort the other deadlock pull the event_lock out from
drm_handle_vblank_events() into drm_handle_vblank() to be taken outside
vblank_time_lock. Add the appropriate assert_spin_locked() to
drm_handle_vblank_events().

Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/drm_irq.c