aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_overlay.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-01-20 16:44:58 -0500
committerDave Airlie <airlied@redhat.com>2013-01-20 16:44:58 -0500
commit735dc0d1e29329ff34ec97f66e130cce481c9607 (patch)
treecf946856ff1defac833e601a3e4a4d8e841ee73e /drivers/gpu/drm/i915/intel_overlay.c
parentbac4b7c3b5c0660c08dc4949fe40e08e20364ee3 (diff)
parent20c60c35de3285222b3476c3445c66bedf0c449c (diff)
Merge branch 'drm-kms-locking' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
The aim of this locking rework is that ioctls which a compositor should be might call for every frame (set_cursor, page_flip, addfb, rmfb and getfb/create_handle) should not be able to block on kms background activities like output detection. And since each EDID read takes about 25ms (in the best case), that always means we'll drop at least one frame. The solution is to add per-crtc locking for these ioctls, and restrict background activities to only use the global lock. Change-the-world type of events (modeset, dpms, ...) need to grab all locks. Two tricky parts arose in the conversion: - A lot of current code assumes that a kms fb object can't disappear while holding the global lock, since the current code serializes fb destruction with it. Hence proper lifetime management using the already created refcounting for fbs need to be instantiated for all ioctls and interfaces/users. - The rmfb ioctl removes the to-be-deleted fb from all active users. But unconditionally taking the global kms lock to do so introduces an unacceptable potential stall point. And obviously changing the userspace abi isn't on the table, either. Hence this conversion opportunistically checks whether the rmfb ioctl holds the very last reference, which guarantees that the fb isn't in active use on any crtc or plane (thanks to the conversion to the new lifetime rules using proper refcounting). Only if this is not the case will the code go through the slowpath and grab all modeset locks. Sane compositors will never hit this path and so avoid the stall, but userspace relying on these semantics will also not break. All these cases are exercised by the newly added subtests for the i-g-t kms_flip, tested on a machine where a full detect cycle takes around 100 ms. It works, and no frames are dropped any more with these patches applied. kms_flip also contains a special case to exercise the above-describe rmfb slowpath. * 'drm-kms-locking' of git://people.freedesktop.org/~danvet/drm-intel: (335 commits) drm/fb_helper: check whether fbcon is bound drm/doc: updates for new framebuffer lifetime rules drm: don't hold crtc mutexes for connector ->detect callbacks drm: only grab the crtc lock for pageflips drm: optimize drm_framebuffer_remove drm/vmwgfx: add proper framebuffer refcounting drm/i915: dump refcount into framebuffer debugfs file drm: refcounting for crtc framebuffers drm: refcounting for sprite framebuffers drm: fb refcounting for dirtyfb_ioctl drm: don't take modeset locks in getfb ioctl drm: push modeset_lock_all into ->fb_create driver callbacks drm: nest modeset locks within fpriv->fbs_lock drm: reference framebuffers which are on the idr drm: revamp framebuffer cleanup interfaces drm: create drm_framebuffer_lookup drm: revamp locking around fb creation/destruction drm: only take the crtc lock for ->cursor_move drm: only take the crtc lock for ->cursor_set drm: add per-crtc locks ...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_overlay.c')
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index fabe0acf808d..1e901c3c18af 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -1045,13 +1045,13 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1045 } 1045 }
1046 1046
1047 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) { 1047 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1048 mutex_lock(&dev->mode_config.mutex); 1048 drm_modeset_lock_all(dev);
1049 mutex_lock(&dev->struct_mutex); 1049 mutex_lock(&dev->struct_mutex);
1050 1050
1051 ret = intel_overlay_switch_off(overlay); 1051 ret = intel_overlay_switch_off(overlay);
1052 1052
1053 mutex_unlock(&dev->struct_mutex); 1053 mutex_unlock(&dev->struct_mutex);
1054 mutex_unlock(&dev->mode_config.mutex); 1054 drm_modeset_unlock_all(dev);
1055 1055
1056 return ret; 1056 return ret;
1057 } 1057 }
@@ -1075,7 +1075,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1075 goto out_free; 1075 goto out_free;
1076 } 1076 }
1077 1077
1078 mutex_lock(&dev->mode_config.mutex); 1078 drm_modeset_lock_all(dev);
1079 mutex_lock(&dev->struct_mutex); 1079 mutex_lock(&dev->struct_mutex);
1080 1080
1081 if (new_bo->tiling_mode) { 1081 if (new_bo->tiling_mode) {
@@ -1157,7 +1157,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1157 goto out_unlock; 1157 goto out_unlock;
1158 1158
1159 mutex_unlock(&dev->struct_mutex); 1159 mutex_unlock(&dev->struct_mutex);
1160 mutex_unlock(&dev->mode_config.mutex); 1160 drm_modeset_unlock_all(dev);
1161 1161
1162 kfree(params); 1162 kfree(params);
1163 1163
@@ -1165,7 +1165,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1165 1165
1166out_unlock: 1166out_unlock:
1167 mutex_unlock(&dev->struct_mutex); 1167 mutex_unlock(&dev->struct_mutex);
1168 mutex_unlock(&dev->mode_config.mutex); 1168 drm_modeset_unlock_all(dev);
1169 drm_gem_object_unreference_unlocked(&new_bo->base); 1169 drm_gem_object_unreference_unlocked(&new_bo->base);
1170out_free: 1170out_free:
1171 kfree(params); 1171 kfree(params);
@@ -1241,7 +1241,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
1241 return -ENODEV; 1241 return -ENODEV;
1242 } 1242 }
1243 1243
1244 mutex_lock(&dev->mode_config.mutex); 1244 drm_modeset_lock_all(dev);
1245 mutex_lock(&dev->struct_mutex); 1245 mutex_lock(&dev->struct_mutex);
1246 1246
1247 ret = -EINVAL; 1247 ret = -EINVAL;
@@ -1307,7 +1307,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
1307 ret = 0; 1307 ret = 0;
1308out_unlock: 1308out_unlock:
1309 mutex_unlock(&dev->struct_mutex); 1309 mutex_unlock(&dev->struct_mutex);
1310 mutex_unlock(&dev->mode_config.mutex); 1310 drm_modeset_unlock_all(dev);
1311 1311
1312 return ret; 1312 return ret;
1313} 1313}