aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_crtc.c109
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c24
-rw-r--r--include/drm/drm_crtc.h2
3 files changed, 86 insertions, 49 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 13a3d3426961..f2ccda85309f 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -294,11 +294,24 @@ static void drm_mode_object_put(struct drm_device *dev,
294 mutex_unlock(&dev->mode_config.idr_mutex); 294 mutex_unlock(&dev->mode_config.idr_mutex);
295} 295}
296 296
297/**
298 * drm_mode_object_find - look up a drm object with static lifetime
299 * @dev: drm device
300 * @id: id of the mode object
301 * @type: type of the mode object
302 *
303 * Note that framebuffers cannot be looked up with this functions - since those
304 * are reference counted, they need special treatment.
305 */
297struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, 306struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
298 uint32_t id, uint32_t type) 307 uint32_t id, uint32_t type)
299{ 308{
300 struct drm_mode_object *obj = NULL; 309 struct drm_mode_object *obj = NULL;
301 310
311 /* Framebuffers are reference counted and need their own lookup
312 * function.*/
313 WARN_ON(type == DRM_MODE_OBJECT_FB);
314
302 mutex_lock(&dev->mode_config.idr_mutex); 315 mutex_lock(&dev->mode_config.idr_mutex);
303 obj = idr_find(&dev->mode_config.crtc_idr, id); 316 obj = idr_find(&dev->mode_config.crtc_idr, id);
304 if (!obj || (obj->type != type) || (obj->id != id)) 317 if (!obj || (obj->type != type) || (obj->id != id))
@@ -359,6 +372,40 @@ static void drm_framebuffer_free(struct kref *kref)
359} 372}
360 373
361/** 374/**
375 * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
376 * @dev: drm device
377 * @id: id of the fb object
378 *
379 * If successful, this grabs an additional reference to the framebuffer -
380 * callers need to make sure to eventually unreference the returned framebuffer
381 * again.
382 */
383struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
384 uint32_t id)
385{
386 struct drm_mode_object *obj = NULL;
387 struct drm_framebuffer *fb;
388
389 mutex_lock(&dev->mode_config.fb_lock);
390
391 mutex_lock(&dev->mode_config.idr_mutex);
392 obj = idr_find(&dev->mode_config.crtc_idr, id);
393 if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id))
394 fb = NULL;
395 else
396 fb = obj_to_fb(obj);
397 mutex_unlock(&dev->mode_config.idr_mutex);
398
399 if (fb)
400 kref_get(&fb->refcount);
401
402 mutex_unlock(&dev->mode_config.fb_lock);
403
404 return fb;
405}
406EXPORT_SYMBOL(drm_framebuffer_lookup);
407
408/**
362 * drm_framebuffer_unreference - unref a framebuffer 409 * drm_framebuffer_unreference - unref a framebuffer
363 * @fb: framebuffer to unref 410 * @fb: framebuffer to unref
364 * 411 *
@@ -1788,17 +1835,15 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
1788 } 1835 }
1789 crtc = obj_to_crtc(obj); 1836 crtc = obj_to_crtc(obj);
1790 1837
1791 mutex_lock(&dev->mode_config.fb_lock); 1838 fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
1792 obj = drm_mode_object_find(dev, plane_req->fb_id, 1839 if (!fb) {
1793 DRM_MODE_OBJECT_FB);
1794 mutex_unlock(&dev->mode_config.fb_lock);
1795 if (!obj) {
1796 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", 1840 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
1797 plane_req->fb_id); 1841 plane_req->fb_id);
1798 ret = -ENOENT; 1842 ret = -ENOENT;
1799 goto out; 1843 goto out;
1800 } 1844 }
1801 fb = obj_to_fb(obj); 1845 /* fb is protect by the mode_config lock, so drop the ref immediately */
1846 drm_framebuffer_unreference(fb);
1802 1847
1803 /* Check whether this plane supports the fb pixel format. */ 1848 /* Check whether this plane supports the fb pixel format. */
1804 for (i = 0; i < plane->format_count; i++) 1849 for (i = 0; i < plane->format_count; i++)
@@ -1933,17 +1978,16 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
1933 } 1978 }
1934 fb = crtc->fb; 1979 fb = crtc->fb;
1935 } else { 1980 } else {
1936 mutex_lock(&dev->mode_config.fb_lock); 1981 fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
1937 obj = drm_mode_object_find(dev, crtc_req->fb_id, 1982 if (!fb) {
1938 DRM_MODE_OBJECT_FB);
1939 mutex_unlock(&dev->mode_config.fb_lock);
1940 if (!obj) {
1941 DRM_DEBUG_KMS("Unknown FB ID%d\n", 1983 DRM_DEBUG_KMS("Unknown FB ID%d\n",
1942 crtc_req->fb_id); 1984 crtc_req->fb_id);
1943 ret = -EINVAL; 1985 ret = -EINVAL;
1944 goto out; 1986 goto out;
1945 } 1987 }
1946 fb = obj_to_fb(obj); 1988 /* fb is protect by the mode_config lock, so drop the
1989 * ref immediately */
1990 drm_framebuffer_unreference(fb);
1947 } 1991 }
1948 1992
1949 mode = drm_mode_create(dev); 1993 mode = drm_mode_create(dev);
@@ -2392,7 +2436,6 @@ int drm_mode_addfb2(struct drm_device *dev,
2392int drm_mode_rmfb(struct drm_device *dev, 2436int drm_mode_rmfb(struct drm_device *dev,
2393 void *data, struct drm_file *file_priv) 2437 void *data, struct drm_file *file_priv)
2394{ 2438{
2395 struct drm_mode_object *obj;
2396 struct drm_framebuffer *fb = NULL; 2439 struct drm_framebuffer *fb = NULL;
2397 struct drm_framebuffer *fbl = NULL; 2440 struct drm_framebuffer *fbl = NULL;
2398 uint32_t *id = data; 2441 uint32_t *id = data;
@@ -2403,16 +2446,13 @@ int drm_mode_rmfb(struct drm_device *dev,
2403 return -EINVAL; 2446 return -EINVAL;
2404 2447
2405 drm_modeset_lock_all(dev); 2448 drm_modeset_lock_all(dev);
2406 mutex_lock(&dev->mode_config.fb_lock); 2449 fb = drm_framebuffer_lookup(dev, *id);
2407 obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); 2450 if (!fb) {
2408 /* TODO check that we really get a framebuffer back. */
2409 if (!obj) {
2410 mutex_unlock(&dev->mode_config.fb_lock);
2411 ret = -EINVAL; 2451 ret = -EINVAL;
2412 goto out; 2452 goto out;
2413 } 2453 }
2414 fb = obj_to_fb(obj); 2454 /* fb is protect by the mode_config lock, so drop the ref immediately */
2415 mutex_unlock(&dev->mode_config.fb_lock); 2455 drm_framebuffer_unreference(fb);
2416 2456
2417 mutex_lock(&file_priv->fbs_lock); 2457 mutex_lock(&file_priv->fbs_lock);
2418 list_for_each_entry(fbl, &file_priv->fbs, filp_head) 2458 list_for_each_entry(fbl, &file_priv->fbs, filp_head)
@@ -2451,7 +2491,6 @@ int drm_mode_getfb(struct drm_device *dev,
2451 void *data, struct drm_file *file_priv) 2491 void *data, struct drm_file *file_priv)
2452{ 2492{
2453 struct drm_mode_fb_cmd *r = data; 2493 struct drm_mode_fb_cmd *r = data;
2454 struct drm_mode_object *obj;
2455 struct drm_framebuffer *fb; 2494 struct drm_framebuffer *fb;
2456 int ret = 0; 2495 int ret = 0;
2457 2496
@@ -2459,14 +2498,13 @@ int drm_mode_getfb(struct drm_device *dev,
2459 return -EINVAL; 2498 return -EINVAL;
2460 2499
2461 drm_modeset_lock_all(dev); 2500 drm_modeset_lock_all(dev);
2462 mutex_lock(&dev->mode_config.fb_lock); 2501 fb = drm_framebuffer_lookup(dev, r->fb_id);
2463 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); 2502 if (!fb) {
2464 mutex_unlock(&dev->mode_config.fb_lock);
2465 if (!obj) {
2466 ret = -EINVAL; 2503 ret = -EINVAL;
2467 goto out; 2504 goto out;
2468 } 2505 }
2469 fb = obj_to_fb(obj); 2506 /* fb is protect by the mode_config lock, so drop the ref immediately */
2507 drm_framebuffer_unreference(fb);
2470 2508
2471 r->height = fb->height; 2509 r->height = fb->height;
2472 r->width = fb->width; 2510 r->width = fb->width;
@@ -2489,7 +2527,6 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
2489 struct drm_clip_rect __user *clips_ptr; 2527 struct drm_clip_rect __user *clips_ptr;
2490 struct drm_clip_rect *clips = NULL; 2528 struct drm_clip_rect *clips = NULL;
2491 struct drm_mode_fb_dirty_cmd *r = data; 2529 struct drm_mode_fb_dirty_cmd *r = data;
2492 struct drm_mode_object *obj;
2493 struct drm_framebuffer *fb; 2530 struct drm_framebuffer *fb;
2494 unsigned flags; 2531 unsigned flags;
2495 int num_clips; 2532 int num_clips;
@@ -2499,14 +2536,13 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
2499 return -EINVAL; 2536 return -EINVAL;
2500 2537
2501 drm_modeset_lock_all(dev); 2538 drm_modeset_lock_all(dev);
2502 mutex_lock(&dev->mode_config.fb_lock); 2539 fb = drm_framebuffer_lookup(dev, r->fb_id);
2503 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); 2540 if (!fb) {
2504 mutex_unlock(&dev->mode_config.fb_lock);
2505 if (!obj) {
2506 ret = -EINVAL; 2541 ret = -EINVAL;
2507 goto out_err1; 2542 goto out_err1;
2508 } 2543 }
2509 fb = obj_to_fb(obj); 2544 /* fb is protect by the mode_config lock, so drop the ref immediately */
2545 drm_framebuffer_unreference(fb);
2510 2546
2511 num_clips = r->num_clips; 2547 num_clips = r->num_clips;
2512 clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; 2548 clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
@@ -3586,12 +3622,11 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
3586 if (crtc->funcs->page_flip == NULL) 3622 if (crtc->funcs->page_flip == NULL)
3587 goto out; 3623 goto out;
3588 3624
3589 mutex_lock(&dev->mode_config.fb_lock); 3625 fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
3590 obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); 3626 if (!fb)
3591 mutex_unlock(&dev->mode_config.fb_lock);
3592 if (!obj)
3593 goto out; 3627 goto out;
3594 fb = obj_to_fb(obj); 3628 /* fb is protect by the mode_config lock, so drop the ref immediately */
3629 drm_framebuffer_unreference(fb);
3595 3630
3596 hdisplay = crtc->mode.hdisplay; 3631 hdisplay = crtc->mode.hdisplay;
3597 vdisplay = crtc->mode.vdisplay; 3632 vdisplay = crtc->mode.vdisplay;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 0d6a161b204b..1b8f428accae 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -131,7 +131,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
131 struct vmw_master *vmaster = vmw_master(file_priv->master); 131 struct vmw_master *vmaster = vmw_master(file_priv->master);
132 struct drm_vmw_rect __user *clips_ptr; 132 struct drm_vmw_rect __user *clips_ptr;
133 struct drm_vmw_rect *clips = NULL; 133 struct drm_vmw_rect *clips = NULL;
134 struct drm_mode_object *obj; 134 struct drm_framebuffer *fb;
135 struct vmw_framebuffer *vfb; 135 struct vmw_framebuffer *vfb;
136 struct vmw_resource *res; 136 struct vmw_resource *res;
137 uint32_t num_clips; 137 uint32_t num_clips;
@@ -165,15 +165,15 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
165 165
166 drm_modeset_lock_all(dev); 166 drm_modeset_lock_all(dev);
167 167
168 mutex_lock(&dev->mode_config.fb_lock); 168 fb = drm_framebuffer_lookup(dev, arg->fb_id);
169 obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); 169 if (!fb) {
170 mutex_unlock(&dev->mode_config.fb_lock);
171 if (!obj) {
172 DRM_ERROR("Invalid framebuffer id.\n"); 170 DRM_ERROR("Invalid framebuffer id.\n");
173 ret = -EINVAL; 171 ret = -EINVAL;
174 goto out_no_fb; 172 goto out_no_fb;
175 } 173 }
176 vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj)); 174 /* fb is protect by the mode_config lock, so drop the ref immediately */
175 drm_framebuffer_unreference(fb);
176 vfb = vmw_framebuffer_to_vfb(fb);
177 177
178 ret = ttm_read_lock(&vmaster->lock, true); 178 ret = ttm_read_lock(&vmaster->lock, true);
179 if (unlikely(ret != 0)) 179 if (unlikely(ret != 0))
@@ -217,7 +217,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
217 struct vmw_master *vmaster = vmw_master(file_priv->master); 217 struct vmw_master *vmaster = vmw_master(file_priv->master);
218 struct drm_vmw_rect __user *clips_ptr; 218 struct drm_vmw_rect __user *clips_ptr;
219 struct drm_vmw_rect *clips = NULL; 219 struct drm_vmw_rect *clips = NULL;
220 struct drm_mode_object *obj; 220 struct drm_framebuffer *fb;
221 struct vmw_framebuffer *vfb; 221 struct vmw_framebuffer *vfb;
222 uint32_t num_clips; 222 uint32_t num_clips;
223 int ret; 223 int ret;
@@ -250,16 +250,16 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
250 250
251 drm_modeset_lock_all(dev); 251 drm_modeset_lock_all(dev);
252 252
253 mutex_lock(&dev->mode_config.fb_lock); 253 fb = drm_framebuffer_lookup(dev, arg->fb_id);
254 obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); 254 if (!fb) {
255 mutex_unlock(&dev->mode_config.fb_lock);
256 if (!obj) {
257 DRM_ERROR("Invalid framebuffer id.\n"); 255 DRM_ERROR("Invalid framebuffer id.\n");
258 ret = -EINVAL; 256 ret = -EINVAL;
259 goto out_no_fb; 257 goto out_no_fb;
260 } 258 }
259 /* fb is protect by the mode_config lock, so drop the ref immediately */
260 drm_framebuffer_unreference(fb);
261 261
262 vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj)); 262 vfb = vmw_framebuffer_to_vfb(fb);
263 if (!vfb->dmabuf) { 263 if (!vfb->dmabuf) {
264 DRM_ERROR("Framebuffer not dmabuf backed.\n"); 264 DRM_ERROR("Framebuffer not dmabuf backed.\n");
265 ret = -EINVAL; 265 ret = -EINVAL;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index c35a807d7e5c..7dc1b31059d4 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -958,6 +958,8 @@ extern void drm_framebuffer_set_object(struct drm_device *dev,
958extern int drm_framebuffer_init(struct drm_device *dev, 958extern int drm_framebuffer_init(struct drm_device *dev,
959 struct drm_framebuffer *fb, 959 struct drm_framebuffer *fb,
960 const struct drm_framebuffer_funcs *funcs); 960 const struct drm_framebuffer_funcs *funcs);
961extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
962 uint32_t id);
961extern void drm_framebuffer_unreference(struct drm_framebuffer *fb); 963extern void drm_framebuffer_unreference(struct drm_framebuffer *fb);
962extern void drm_framebuffer_reference(struct drm_framebuffer *fb); 964extern void drm_framebuffer_reference(struct drm_framebuffer *fb);
963extern void drm_framebuffer_remove(struct drm_framebuffer *fb); 965extern void drm_framebuffer_remove(struct drm_framebuffer *fb);