aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-12-02 15:53:40 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-20 16:16:59 -0500
commit786b99ed13223d8ac58a937dd348aead45eb8191 (patch)
treed2fed735d5be17d37d02a2a30260c766c079cf43
parent4b096ac10da0b63f09bd123b86fed8deb80646ce (diff)
drm: create drm_framebuffer_lookup
And replace all fb lookups with it. Also add a WARN to drm_mode_object_find since that is now no longer the blessed interface to look up an fb. And add kerneldoc to both functions. This only updates all callsites, but immediately drops the acquired refence again. Hence all callers still rely on the fact that a mode fb can't disappear while they're holding the struct mutex. Subsequent patches will instate proper use of refcounts, and then rework the rmfb and unref code to no longer serialize fb destruction with the mode_config lock. We don't want that since otherwise a compositor might end up stalling for a few frames in rmfb. v2: Don't use kref_get_unless_zero - Greg KH doesn't like that kind of interface. Reviewed-by: Rob Clark <rob@ti.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-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);