diff options
author | Ramalingam C <ramalingam.c@intel.com> | 2015-03-03 12:11:46 +0530 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-03-17 22:29:55 +0100 |
commit | 3954e733ab0c9449443897f2669e17fff4471a0e (patch) | |
tree | 6f8906ace38a1d3843e3cbbd1d9216a9f2a18113 | |
parent | a54746e39ad5cc27cf3099bec1e813cdf8ad7f7e (diff) | |
download | lwn-3954e733ab0c9449443897f2669e17fff4471a0e.tar.gz lwn-3954e733ab0c9449443897f2669e17fff4471a0e.zip |
drm/i915: Fixing mutex deadlock window at eDP DRRS
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>
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d1141d37e205..0a57763e73fa 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -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); @@ -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, |