diff options
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_cursor.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 13 |
3 files changed, 24 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 58fa69e5ff4c..4af6a3d5c9a1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2039,34 +2039,32 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); if (!obj) { DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); - ret = -EINVAL; - goto out; + return -EINVAL; } crtc = obj_to_crtc(obj); + mutex_lock(&crtc->mutex); if (req->flags & DRM_MODE_CURSOR_BO) { if (!crtc->funcs->cursor_set) { ret = -ENXIO; goto out; } /* Turns off the cursor if handle is 0 */ - mutex_lock(&crtc->mutex); ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, req->width, req->height); - mutex_unlock(&crtc->mutex); } if (req->flags & DRM_MODE_CURSOR_MOVE) { if (crtc->funcs->cursor_move) { - drm_modeset_lock_all(dev); ret = crtc->funcs->cursor_move(crtc, req->x, req->y); - drm_modeset_unlock_all(dev); } else { ret = -EFAULT; goto out; } } out: + mutex_unlock(&crtc->mutex); + return ret; } diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index ad6df625e8b8..c1680e6d76ad 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -245,8 +245,14 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, int i = 0; struct drm_crtc *crtc_p; - /* avivo cursor image can't end on 128 pixel boundary or + /* + * avivo cursor image can't end on 128 pixel boundary or * go past the end of the frame if both crtcs are enabled + * + * NOTE: It is safe to access crtc->enabled of other crtcs + * without holding either the mode_config lock or the other + * crtc's lock as long as write access to this flag _always_ + * grabs all locks. */ list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) { if (crtc_p->enabled) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 8d82e631c305..3e3c7ab33ca2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -264,10 +264,23 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) du->cursor_x = x + crtc->x; du->cursor_y = y + crtc->y; + /* + * FIXME: Unclear whether there's any global state touched by the + * cursor_set function, especially vmw_cursor_update_position looks + * suspicious. For now take the easy route and reacquire all locks. We + * can do this since the caller in the drm core doesn't check anything + * which is protected by any looks. + */ + mutex_unlock(&crtc->mutex); + drm_modeset_lock_all(dev_priv->dev); + vmw_cursor_update_position(dev_priv, shown, du->cursor_x + du->hotspot_x, du->cursor_y + du->hotspot_y); + drm_modeset_unlock_all(dev_priv->dev); + mutex_lock(&crtc->mutex); + return 0; } |