diff options
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 116 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 4 | ||||
-rw-r--r-- | drivers/staging/omapdrm/omap_debugfs.c | 2 | ||||
-rw-r--r-- | include/drm/drmP.h | 8 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 14 |
7 files changed, 113 insertions, 37 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4af6a3d5c9a1..13a3d3426961 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -262,15 +262,21 @@ again: | |||
262 | 262 | ||
263 | mutex_lock(&dev->mode_config.idr_mutex); | 263 | mutex_lock(&dev->mode_config.idr_mutex); |
264 | ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); | 264 | ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); |
265 | |||
266 | if (!ret) { | ||
267 | /* | ||
268 | * Set up the object linking under the protection of the idr | ||
269 | * lock so that other users can't see inconsistent state. | ||
270 | */ | ||
271 | obj->id = new_id; | ||
272 | obj->type = obj_type; | ||
273 | } | ||
265 | mutex_unlock(&dev->mode_config.idr_mutex); | 274 | mutex_unlock(&dev->mode_config.idr_mutex); |
275 | |||
266 | if (ret == -EAGAIN) | 276 | if (ret == -EAGAIN) |
267 | goto again; | 277 | goto again; |
268 | else if (ret) | ||
269 | return ret; | ||
270 | 278 | ||
271 | obj->id = new_id; | 279 | return ret; |
272 | obj->type = obj_type; | ||
273 | return 0; | ||
274 | } | 280 | } |
275 | 281 | ||
276 | /** | 282 | /** |
@@ -312,6 +318,12 @@ EXPORT_SYMBOL(drm_mode_object_find); | |||
312 | * Allocates an ID for the framebuffer's parent mode object, sets its mode | 318 | * Allocates an ID for the framebuffer's parent mode object, sets its mode |
313 | * functions & device file and adds it to the master fd list. | 319 | * functions & device file and adds it to the master fd list. |
314 | * | 320 | * |
321 | * IMPORTANT: | ||
322 | * This functions publishes the fb and makes it available for concurrent access | ||
323 | * by other users. Which means by this point the fb _must_ be fully set up - | ||
324 | * since all the fb attributes are invariant over its lifetime, no further | ||
325 | * locking but only correct reference counting is required. | ||
326 | * | ||
315 | * RETURNS: | 327 | * RETURNS: |
316 | * Zero on success, error code on failure. | 328 | * Zero on success, error code on failure. |
317 | */ | 329 | */ |
@@ -320,16 +332,20 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, | |||
320 | { | 332 | { |
321 | int ret; | 333 | int ret; |
322 | 334 | ||
335 | mutex_lock(&dev->mode_config.fb_lock); | ||
323 | kref_init(&fb->refcount); | 336 | kref_init(&fb->refcount); |
337 | INIT_LIST_HEAD(&fb->filp_head); | ||
338 | fb->dev = dev; | ||
339 | fb->funcs = funcs; | ||
324 | 340 | ||
325 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); | 341 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); |
326 | if (ret) | 342 | if (ret) |
327 | return ret; | 343 | goto out; |
328 | 344 | ||
329 | fb->dev = dev; | ||
330 | fb->funcs = funcs; | ||
331 | dev->mode_config.num_fb++; | 345 | dev->mode_config.num_fb++; |
332 | list_add(&fb->head, &dev->mode_config.fb_list); | 346 | list_add(&fb->head, &dev->mode_config.fb_list); |
347 | out: | ||
348 | mutex_unlock(&dev->mode_config.fb_lock); | ||
333 | 349 | ||
334 | return 0; | 350 | return 0; |
335 | } | 351 | } |
@@ -385,8 +401,10 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) | |||
385 | * this.) | 401 | * this.) |
386 | */ | 402 | */ |
387 | drm_mode_object_put(dev, &fb->base); | 403 | drm_mode_object_put(dev, &fb->base); |
404 | mutex_lock(&dev->mode_config.fb_lock); | ||
388 | list_del(&fb->head); | 405 | list_del(&fb->head); |
389 | dev->mode_config.num_fb--; | 406 | dev->mode_config.num_fb--; |
407 | mutex_unlock(&dev->mode_config.fb_lock); | ||
390 | } | 408 | } |
391 | EXPORT_SYMBOL(drm_framebuffer_cleanup); | 409 | EXPORT_SYMBOL(drm_framebuffer_cleanup); |
392 | 410 | ||
@@ -406,6 +424,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) | |||
406 | int ret; | 424 | int ret; |
407 | 425 | ||
408 | WARN_ON(!drm_modeset_is_locked(dev)); | 426 | WARN_ON(!drm_modeset_is_locked(dev)); |
427 | WARN_ON(!list_empty(&fb->filp_head)); | ||
409 | 428 | ||
410 | /* remove from any CRTC */ | 429 | /* remove from any CRTC */ |
411 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 430 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
@@ -432,8 +451,6 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) | |||
432 | } | 451 | } |
433 | } | 452 | } |
434 | 453 | ||
435 | list_del(&fb->filp_head); | ||
436 | |||
437 | drm_framebuffer_unreference(fb); | 454 | drm_framebuffer_unreference(fb); |
438 | } | 455 | } |
439 | EXPORT_SYMBOL(drm_framebuffer_remove); | 456 | EXPORT_SYMBOL(drm_framebuffer_remove); |
@@ -989,6 +1006,7 @@ void drm_mode_config_init(struct drm_device *dev) | |||
989 | { | 1006 | { |
990 | mutex_init(&dev->mode_config.mutex); | 1007 | mutex_init(&dev->mode_config.mutex); |
991 | mutex_init(&dev->mode_config.idr_mutex); | 1008 | mutex_init(&dev->mode_config.idr_mutex); |
1009 | mutex_init(&dev->mode_config.fb_lock); | ||
992 | INIT_LIST_HEAD(&dev->mode_config.fb_list); | 1010 | INIT_LIST_HEAD(&dev->mode_config.fb_list); |
993 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); | 1011 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
994 | INIT_LIST_HEAD(&dev->mode_config.connector_list); | 1012 | INIT_LIST_HEAD(&dev->mode_config.connector_list); |
@@ -1091,6 +1109,9 @@ void drm_mode_config_cleanup(struct drm_device *dev) | |||
1091 | drm_property_destroy(dev, property); | 1109 | drm_property_destroy(dev, property); |
1092 | } | 1110 | } |
1093 | 1111 | ||
1112 | /* Single-threaded teardown context, so it's not requied to grab the | ||
1113 | * fb_lock to protect against concurrent fb_list access. Contrary, it | ||
1114 | * would actually deadlock with the drm_framebuffer_cleanup function. */ | ||
1094 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { | 1115 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { |
1095 | drm_framebuffer_remove(fb); | 1116 | drm_framebuffer_remove(fb); |
1096 | } | 1117 | } |
@@ -1220,8 +1241,8 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1220 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1241 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1221 | return -EINVAL; | 1242 | return -EINVAL; |
1222 | 1243 | ||
1223 | drm_modeset_lock_all(dev); | ||
1224 | 1244 | ||
1245 | mutex_lock(&file_priv->fbs_lock); | ||
1225 | /* | 1246 | /* |
1226 | * For the non-control nodes we need to limit the list of resources | 1247 | * For the non-control nodes we need to limit the list of resources |
1227 | * by IDs in the group list for this node | 1248 | * by IDs in the group list for this node |
@@ -1229,6 +1250,23 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1229 | list_for_each(lh, &file_priv->fbs) | 1250 | list_for_each(lh, &file_priv->fbs) |
1230 | fb_count++; | 1251 | fb_count++; |
1231 | 1252 | ||
1253 | /* handle this in 4 parts */ | ||
1254 | /* FBs */ | ||
1255 | if (card_res->count_fbs >= fb_count) { | ||
1256 | copied = 0; | ||
1257 | fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; | ||
1258 | list_for_each_entry(fb, &file_priv->fbs, filp_head) { | ||
1259 | if (put_user(fb->base.id, fb_id + copied)) { | ||
1260 | mutex_unlock(&file_priv->fbs_lock); | ||
1261 | return -EFAULT; | ||
1262 | } | ||
1263 | copied++; | ||
1264 | } | ||
1265 | } | ||
1266 | card_res->count_fbs = fb_count; | ||
1267 | mutex_unlock(&file_priv->fbs_lock); | ||
1268 | |||
1269 | drm_modeset_lock_all(dev); | ||
1232 | mode_group = &file_priv->master->minor->mode_group; | 1270 | mode_group = &file_priv->master->minor->mode_group; |
1233 | if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { | 1271 | if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { |
1234 | 1272 | ||
@@ -1252,21 +1290,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1252 | card_res->max_width = dev->mode_config.max_width; | 1290 | card_res->max_width = dev->mode_config.max_width; |
1253 | card_res->min_width = dev->mode_config.min_width; | 1291 | card_res->min_width = dev->mode_config.min_width; |
1254 | 1292 | ||
1255 | /* handle this in 4 parts */ | ||
1256 | /* FBs */ | ||
1257 | if (card_res->count_fbs >= fb_count) { | ||
1258 | copied = 0; | ||
1259 | fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; | ||
1260 | list_for_each_entry(fb, &file_priv->fbs, filp_head) { | ||
1261 | if (put_user(fb->base.id, fb_id + copied)) { | ||
1262 | ret = -EFAULT; | ||
1263 | goto out; | ||
1264 | } | ||
1265 | copied++; | ||
1266 | } | ||
1267 | } | ||
1268 | card_res->count_fbs = fb_count; | ||
1269 | |||
1270 | /* CRTCs */ | 1293 | /* CRTCs */ |
1271 | if (card_res->count_crtcs >= crtc_count) { | 1294 | if (card_res->count_crtcs >= crtc_count) { |
1272 | copied = 0; | 1295 | copied = 0; |
@@ -1765,8 +1788,10 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
1765 | } | 1788 | } |
1766 | crtc = obj_to_crtc(obj); | 1789 | crtc = obj_to_crtc(obj); |
1767 | 1790 | ||
1791 | mutex_lock(&dev->mode_config.fb_lock); | ||
1768 | obj = drm_mode_object_find(dev, plane_req->fb_id, | 1792 | obj = drm_mode_object_find(dev, plane_req->fb_id, |
1769 | DRM_MODE_OBJECT_FB); | 1793 | DRM_MODE_OBJECT_FB); |
1794 | mutex_unlock(&dev->mode_config.fb_lock); | ||
1770 | if (!obj) { | 1795 | if (!obj) { |
1771 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", | 1796 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", |
1772 | plane_req->fb_id); | 1797 | plane_req->fb_id); |
@@ -1908,8 +1933,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
1908 | } | 1933 | } |
1909 | fb = crtc->fb; | 1934 | fb = crtc->fb; |
1910 | } else { | 1935 | } else { |
1936 | mutex_lock(&dev->mode_config.fb_lock); | ||
1911 | obj = drm_mode_object_find(dev, crtc_req->fb_id, | 1937 | obj = drm_mode_object_find(dev, crtc_req->fb_id, |
1912 | DRM_MODE_OBJECT_FB); | 1938 | DRM_MODE_OBJECT_FB); |
1939 | mutex_unlock(&dev->mode_config.fb_lock); | ||
1913 | if (!obj) { | 1940 | if (!obj) { |
1914 | DRM_DEBUG_KMS("Unknown FB ID%d\n", | 1941 | DRM_DEBUG_KMS("Unknown FB ID%d\n", |
1915 | crtc_req->fb_id); | 1942 | crtc_req->fb_id); |
@@ -2151,16 +2178,17 @@ int drm_mode_addfb(struct drm_device *dev, | |||
2151 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); | 2178 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); |
2152 | if (IS_ERR(fb)) { | 2179 | if (IS_ERR(fb)) { |
2153 | DRM_DEBUG_KMS("could not create framebuffer\n"); | 2180 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
2154 | ret = PTR_ERR(fb); | 2181 | drm_modeset_unlock_all(dev); |
2155 | goto out; | 2182 | return PTR_ERR(fb); |
2156 | } | 2183 | } |
2157 | 2184 | ||
2185 | mutex_lock(&file_priv->fbs_lock); | ||
2158 | or->fb_id = fb->base.id; | 2186 | or->fb_id = fb->base.id; |
2159 | list_add(&fb->filp_head, &file_priv->fbs); | 2187 | list_add(&fb->filp_head, &file_priv->fbs); |
2160 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | 2188 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
2161 | 2189 | mutex_unlock(&file_priv->fbs_lock); | |
2162 | out: | ||
2163 | drm_modeset_unlock_all(dev); | 2190 | drm_modeset_unlock_all(dev); |
2191 | |||
2164 | return ret; | 2192 | return ret; |
2165 | } | 2193 | } |
2166 | 2194 | ||
@@ -2333,16 +2361,18 @@ int drm_mode_addfb2(struct drm_device *dev, | |||
2333 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); | 2361 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
2334 | if (IS_ERR(fb)) { | 2362 | if (IS_ERR(fb)) { |
2335 | DRM_DEBUG_KMS("could not create framebuffer\n"); | 2363 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
2336 | ret = PTR_ERR(fb); | 2364 | drm_modeset_unlock_all(dev); |
2337 | goto out; | 2365 | return PTR_ERR(fb); |
2338 | } | 2366 | } |
2339 | 2367 | ||
2368 | mutex_lock(&file_priv->fbs_lock); | ||
2340 | r->fb_id = fb->base.id; | 2369 | r->fb_id = fb->base.id; |
2341 | list_add(&fb->filp_head, &file_priv->fbs); | 2370 | list_add(&fb->filp_head, &file_priv->fbs); |
2342 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | 2371 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
2372 | mutex_unlock(&file_priv->fbs_lock); | ||
2343 | 2373 | ||
2344 | out: | ||
2345 | drm_modeset_unlock_all(dev); | 2374 | drm_modeset_unlock_all(dev); |
2375 | |||
2346 | return ret; | 2376 | return ret; |
2347 | } | 2377 | } |
2348 | 2378 | ||
@@ -2373,27 +2403,34 @@ int drm_mode_rmfb(struct drm_device *dev, | |||
2373 | return -EINVAL; | 2403 | return -EINVAL; |
2374 | 2404 | ||
2375 | drm_modeset_lock_all(dev); | 2405 | drm_modeset_lock_all(dev); |
2406 | mutex_lock(&dev->mode_config.fb_lock); | ||
2376 | obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); | 2407 | obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); |
2377 | /* TODO check that we really get a framebuffer back. */ | 2408 | /* TODO check that we really get a framebuffer back. */ |
2378 | if (!obj) { | 2409 | if (!obj) { |
2410 | mutex_unlock(&dev->mode_config.fb_lock); | ||
2379 | ret = -EINVAL; | 2411 | ret = -EINVAL; |
2380 | goto out; | 2412 | goto out; |
2381 | } | 2413 | } |
2382 | fb = obj_to_fb(obj); | 2414 | fb = obj_to_fb(obj); |
2415 | mutex_unlock(&dev->mode_config.fb_lock); | ||
2383 | 2416 | ||
2417 | mutex_lock(&file_priv->fbs_lock); | ||
2384 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) | 2418 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) |
2385 | if (fb == fbl) | 2419 | if (fb == fbl) |
2386 | found = 1; | 2420 | found = 1; |
2387 | |||
2388 | if (!found) { | 2421 | if (!found) { |
2389 | ret = -EINVAL; | 2422 | ret = -EINVAL; |
2423 | mutex_unlock(&file_priv->fbs_lock); | ||
2390 | goto out; | 2424 | goto out; |
2391 | } | 2425 | } |
2392 | 2426 | ||
2393 | drm_framebuffer_remove(fb); | 2427 | list_del_init(&fb->filp_head); |
2428 | mutex_unlock(&file_priv->fbs_lock); | ||
2394 | 2429 | ||
2430 | drm_framebuffer_remove(fb); | ||
2395 | out: | 2431 | out: |
2396 | drm_modeset_unlock_all(dev); | 2432 | drm_modeset_unlock_all(dev); |
2433 | |||
2397 | return ret; | 2434 | return ret; |
2398 | } | 2435 | } |
2399 | 2436 | ||
@@ -2422,7 +2459,9 @@ int drm_mode_getfb(struct drm_device *dev, | |||
2422 | return -EINVAL; | 2459 | return -EINVAL; |
2423 | 2460 | ||
2424 | drm_modeset_lock_all(dev); | 2461 | drm_modeset_lock_all(dev); |
2462 | mutex_lock(&dev->mode_config.fb_lock); | ||
2425 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); | 2463 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
2464 | mutex_unlock(&dev->mode_config.fb_lock); | ||
2426 | if (!obj) { | 2465 | if (!obj) { |
2427 | ret = -EINVAL; | 2466 | ret = -EINVAL; |
2428 | goto out; | 2467 | goto out; |
@@ -2460,7 +2499,9 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | |||
2460 | return -EINVAL; | 2499 | return -EINVAL; |
2461 | 2500 | ||
2462 | drm_modeset_lock_all(dev); | 2501 | drm_modeset_lock_all(dev); |
2502 | mutex_lock(&dev->mode_config.fb_lock); | ||
2463 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); | 2503 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
2504 | mutex_unlock(&dev->mode_config.fb_lock); | ||
2464 | if (!obj) { | 2505 | if (!obj) { |
2465 | ret = -EINVAL; | 2506 | ret = -EINVAL; |
2466 | goto out_err1; | 2507 | goto out_err1; |
@@ -2535,9 +2576,12 @@ void drm_fb_release(struct drm_file *priv) | |||
2535 | struct drm_framebuffer *fb, *tfb; | 2576 | struct drm_framebuffer *fb, *tfb; |
2536 | 2577 | ||
2537 | drm_modeset_lock_all(dev); | 2578 | drm_modeset_lock_all(dev); |
2579 | mutex_lock(&priv->fbs_lock); | ||
2538 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { | 2580 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
2581 | list_del_init(&fb->filp_head); | ||
2539 | drm_framebuffer_remove(fb); | 2582 | drm_framebuffer_remove(fb); |
2540 | } | 2583 | } |
2584 | mutex_unlock(&priv->fbs_lock); | ||
2541 | drm_modeset_unlock_all(dev); | 2585 | drm_modeset_unlock_all(dev); |
2542 | } | 2586 | } |
2543 | 2587 | ||
@@ -3542,7 +3586,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3542 | if (crtc->funcs->page_flip == NULL) | 3586 | if (crtc->funcs->page_flip == NULL) |
3543 | goto out; | 3587 | goto out; |
3544 | 3588 | ||
3589 | mutex_lock(&dev->mode_config.fb_lock); | ||
3545 | obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); | 3590 | obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); |
3591 | mutex_unlock(&dev->mode_config.fb_lock); | ||
3546 | if (!obj) | 3592 | if (!obj) |
3547 | goto out; | 3593 | goto out; |
3548 | fb = obj_to_fb(obj); | 3594 | fb = obj_to_fb(obj); |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 133b4132983e..13fdcd10a605 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -276,6 +276,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
276 | 276 | ||
277 | INIT_LIST_HEAD(&priv->lhead); | 277 | INIT_LIST_HEAD(&priv->lhead); |
278 | INIT_LIST_HEAD(&priv->fbs); | 278 | INIT_LIST_HEAD(&priv->fbs); |
279 | mutex_init(&priv->fbs_lock); | ||
279 | INIT_LIST_HEAD(&priv->event_list); | 280 | INIT_LIST_HEAD(&priv->event_list); |
280 | init_waitqueue_head(&priv->event_wait); | 281 | init_waitqueue_head(&priv->event_wait); |
281 | priv->event_space = 4096; /* set aside 4k for event buffer */ | 282 | priv->event_space = 4096; /* set aside 4k for event buffer */ |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6a11ca85eaf..a40c674a57be 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -1374,7 +1374,9 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) | |||
1374 | fb->base.bits_per_pixel); | 1374 | fb->base.bits_per_pixel); |
1375 | describe_obj(m, fb->obj); | 1375 | describe_obj(m, fb->obj); |
1376 | seq_printf(m, "\n"); | 1376 | seq_printf(m, "\n"); |
1377 | mutex_unlock(&dev->mode_config.mutex); | ||
1377 | 1378 | ||
1379 | mutex_lock(&dev->mode_config.fb_lock); | ||
1378 | list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { | 1380 | list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { |
1379 | if (&fb->base == ifbdev->helper.fb) | 1381 | if (&fb->base == ifbdev->helper.fb) |
1380 | continue; | 1382 | continue; |
@@ -1387,8 +1389,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) | |||
1387 | describe_obj(m, fb->obj); | 1389 | describe_obj(m, fb->obj); |
1388 | seq_printf(m, "\n"); | 1390 | seq_printf(m, "\n"); |
1389 | } | 1391 | } |
1390 | 1392 | mutex_unlock(&dev->mode_config.fb_lock); | |
1391 | mutex_unlock(&dev->mode_config.mutex); | ||
1392 | 1393 | ||
1393 | return 0; | 1394 | return 0; |
1394 | } | 1395 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index a135498a1298..0d6a161b204b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | |||
@@ -165,7 +165,9 @@ 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 | obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); | 169 | obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); |
170 | mutex_unlock(&dev->mode_config.fb_lock); | ||
169 | if (!obj) { | 171 | if (!obj) { |
170 | DRM_ERROR("Invalid framebuffer id.\n"); | 172 | DRM_ERROR("Invalid framebuffer id.\n"); |
171 | ret = -EINVAL; | 173 | ret = -EINVAL; |
@@ -248,7 +250,9 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, | |||
248 | 250 | ||
249 | drm_modeset_lock_all(dev); | 251 | drm_modeset_lock_all(dev); |
250 | 252 | ||
253 | mutex_lock(&dev->mode_config.fb_lock); | ||
251 | obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); | 254 | obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); |
255 | mutex_unlock(&dev->mode_config.fb_lock); | ||
252 | if (!obj) { | 256 | if (!obj) { |
253 | DRM_ERROR("Invalid framebuffer id.\n"); | 257 | DRM_ERROR("Invalid framebuffer id.\n"); |
254 | ret = -EINVAL; | 258 | ret = -EINVAL; |
diff --git a/drivers/staging/omapdrm/omap_debugfs.c b/drivers/staging/omapdrm/omap_debugfs.c index 2f122e00b51d..e95540b3e2f6 100644 --- a/drivers/staging/omapdrm/omap_debugfs.c +++ b/drivers/staging/omapdrm/omap_debugfs.c | |||
@@ -72,6 +72,7 @@ static int fb_show(struct seq_file *m, void *arg) | |||
72 | seq_printf(m, "fbcon "); | 72 | seq_printf(m, "fbcon "); |
73 | omap_framebuffer_describe(priv->fbdev->fb, m); | 73 | omap_framebuffer_describe(priv->fbdev->fb, m); |
74 | 74 | ||
75 | mutex_lock(&dev->mode_config.fb_lock); | ||
75 | list_for_each_entry(fb, &dev->mode_config.fb_list, head) { | 76 | list_for_each_entry(fb, &dev->mode_config.fb_list, head) { |
76 | if (fb == priv->fbdev->fb) | 77 | if (fb == priv->fbdev->fb) |
77 | continue; | 78 | continue; |
@@ -79,6 +80,7 @@ static int fb_show(struct seq_file *m, void *arg) | |||
79 | seq_printf(m, "user "); | 80 | seq_printf(m, "user "); |
80 | omap_framebuffer_describe(fb, m); | 81 | omap_framebuffer_describe(fb, m); |
81 | } | 82 | } |
83 | mutex_unlock(&dev->mode_config.fb_lock); | ||
82 | 84 | ||
83 | mutex_unlock(&dev->struct_mutex); | 85 | mutex_unlock(&dev->struct_mutex); |
84 | mutex_unlock(&dev->mode_config.mutex); | 86 | mutex_unlock(&dev->mode_config.mutex); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3c609abe8c80..e74731c1a912 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -446,7 +446,15 @@ struct drm_file { | |||
446 | int is_master; /* this file private is a master for a minor */ | 446 | int is_master; /* this file private is a master for a minor */ |
447 | struct drm_master *master; /* master this node is currently associated with | 447 | struct drm_master *master; /* master this node is currently associated with |
448 | N.B. not always minor->master */ | 448 | N.B. not always minor->master */ |
449 | |||
450 | /** | ||
451 | * fbs - List of framebuffers associated with this file. | ||
452 | * | ||
453 | * Protected by fbs_lock. Note that the fbs list holds a reference on | ||
454 | * the fb object to prevent it from untimely disappearing. | ||
455 | */ | ||
449 | struct list_head fbs; | 456 | struct list_head fbs; |
457 | struct mutex fbs_lock; | ||
450 | 458 | ||
451 | wait_queue_head_t event_wait; | 459 | wait_queue_head_t event_wait; |
452 | struct list_head event_list; | 460 | struct list_head event_list; |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c89b1161f0be..c35a807d7e5c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -254,6 +254,10 @@ struct drm_framebuffer { | |||
254 | * userspace perspective. | 254 | * userspace perspective. |
255 | */ | 255 | */ |
256 | struct kref refcount; | 256 | struct kref refcount; |
257 | /* | ||
258 | * Place on the dev->mode_config.fb_list, access protected by | ||
259 | * dev->mode_config.fb_lock. | ||
260 | */ | ||
257 | struct list_head head; | 261 | struct list_head head; |
258 | struct drm_mode_object base; | 262 | struct drm_mode_object base; |
259 | const struct drm_framebuffer_funcs *funcs; | 263 | const struct drm_framebuffer_funcs *funcs; |
@@ -780,8 +784,18 @@ struct drm_mode_config { | |||
780 | struct mutex idr_mutex; /* for IDR management */ | 784 | struct mutex idr_mutex; /* for IDR management */ |
781 | struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ | 785 | struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ |
782 | /* this is limited to one for now */ | 786 | /* this is limited to one for now */ |
787 | |||
788 | |||
789 | /** | ||
790 | * fb_lock - mutex to protect fb state | ||
791 | * | ||
792 | * Besides the global fb list his also protects the fbs list in the | ||
793 | * file_priv | ||
794 | */ | ||
795 | struct mutex fb_lock; | ||
783 | int num_fb; | 796 | int num_fb; |
784 | struct list_head fb_list; | 797 | struct list_head fb_list; |
798 | |||
785 | int num_connector; | 799 | int num_connector; |
786 | struct list_head connector_list; | 800 | struct list_head connector_list; |
787 | int num_encoder; | 801 | int num_encoder; |