Skip to content

Commit

Permalink
drm/i915: Fixing mutex deadlock window at eDP DRRS
Browse files Browse the repository at this point in the history
In invalidate and flush functions of eDP DRRS, if deferred downclock
work starts execution at a time window between acquiring the drrs
mutex and cancellation of the deferred work
(intel_edp_drrs_downclock_work), then deferred work will find
drrs mutex locked and wait for the same.

Meanwhile the function that acquired mutex drrs invalidate/flush will
wait for the completion of the deferred work before releasing the mutex.
Thats a deadlock.

To avoid such deadlock scenario, this change cancels the deferred work
before acquiring the mutex at invalidate and flush functions.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Ramalingam C authored and Daniel Vetter committed Mar 17, 2015
1 parent a54746e commit 3954e73
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4966,12 +4966,13 @@ void intel_edp_drrs_invalidate(struct drm_device *dev,
if (!dev_priv->drrs.dp)
return;

cancel_delayed_work_sync(&dev_priv->drrs.work);

mutex_lock(&dev_priv->drrs.mutex);
crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
pipe = to_intel_crtc(crtc)->pipe;

if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
cancel_delayed_work_sync(&dev_priv->drrs.work);
intel_dp_set_drrs_state(dev_priv->dev,
dev_priv->drrs.dp->attached_connector->panel.
fixed_mode->vrefresh);
Expand Down Expand Up @@ -5004,13 +5005,13 @@ void intel_edp_drrs_flush(struct drm_device *dev,
if (!dev_priv->drrs.dp)
return;

cancel_delayed_work_sync(&dev_priv->drrs.work);

mutex_lock(&dev_priv->drrs.mutex);
crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
pipe = to_intel_crtc(crtc)->pipe;
dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;

cancel_delayed_work_sync(&dev_priv->drrs.work);

if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR &&
!dev_priv->drrs.busy_frontbuffer_bits)
schedule_delayed_work(&dev_priv->drrs.work,
Expand Down

0 comments on commit 3954e73

Please sign in to comment.