diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 826 |
1 files changed, 495 insertions, 331 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f2d667b8bee2..792c3e3795ca 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -37,6 +37,54 @@ | |||
37 | #include <drm/drm_edid.h> | 37 | #include <drm/drm_edid.h> |
38 | #include <drm/drm_fourcc.h> | 38 | #include <drm/drm_fourcc.h> |
39 | 39 | ||
40 | /** | ||
41 | * drm_modeset_lock_all - take all modeset locks | ||
42 | * @dev: drm device | ||
43 | * | ||
44 | * This function takes all modeset locks, suitable where a more fine-grained | ||
45 | * scheme isn't (yet) implemented. | ||
46 | */ | ||
47 | void drm_modeset_lock_all(struct drm_device *dev) | ||
48 | { | ||
49 | struct drm_crtc *crtc; | ||
50 | |||
51 | mutex_lock(&dev->mode_config.mutex); | ||
52 | |||
53 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
54 | mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex); | ||
55 | } | ||
56 | EXPORT_SYMBOL(drm_modeset_lock_all); | ||
57 | |||
58 | /** | ||
59 | * drm_modeset_unlock_all - drop all modeset locks | ||
60 | * @dev: device | ||
61 | */ | ||
62 | void drm_modeset_unlock_all(struct drm_device *dev) | ||
63 | { | ||
64 | struct drm_crtc *crtc; | ||
65 | |||
66 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
67 | mutex_unlock(&crtc->mutex); | ||
68 | |||
69 | mutex_unlock(&dev->mode_config.mutex); | ||
70 | } | ||
71 | EXPORT_SYMBOL(drm_modeset_unlock_all); | ||
72 | |||
73 | /** | ||
74 | * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked | ||
75 | * @dev: device | ||
76 | */ | ||
77 | void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) | ||
78 | { | ||
79 | struct drm_crtc *crtc; | ||
80 | |||
81 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
82 | WARN_ON(!mutex_is_locked(&crtc->mutex)); | ||
83 | |||
84 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
85 | } | ||
86 | EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); | ||
87 | |||
40 | /* Avoid boilerplate. I'm tired of typing. */ | 88 | /* Avoid boilerplate. I'm tired of typing. */ |
41 | #define DRM_ENUM_NAME_FN(fnname, list) \ | 89 | #define DRM_ENUM_NAME_FN(fnname, list) \ |
42 | char *fnname(int val) \ | 90 | char *fnname(int val) \ |
@@ -203,12 +251,10 @@ char *drm_get_connector_status_name(enum drm_connector_status status) | |||
203 | } | 251 | } |
204 | 252 | ||
205 | /** | 253 | /** |
206 | * drm_mode_object_get - allocate a new identifier | 254 | * drm_mode_object_get - allocate a new modeset identifier |
207 | * @dev: DRM device | 255 | * @dev: DRM device |
208 | * @ptr: object pointer, used to generate unique ID | 256 | * @obj: object pointer, used to generate unique ID |
209 | * @type: object type | 257 | * @obj_type: object type |
210 | * | ||
211 | * LOCKING: | ||
212 | * | 258 | * |
213 | * Create a unique identifier based on @ptr in @dev's identifier space. Used | 259 | * Create a unique identifier based on @ptr in @dev's identifier space. Used |
214 | * for tracking modes, CRTCs and connectors. | 260 | * for tracking modes, CRTCs and connectors. |
@@ -220,35 +266,27 @@ char *drm_get_connector_status_name(enum drm_connector_status status) | |||
220 | static int drm_mode_object_get(struct drm_device *dev, | 266 | static int drm_mode_object_get(struct drm_device *dev, |
221 | struct drm_mode_object *obj, uint32_t obj_type) | 267 | struct drm_mode_object *obj, uint32_t obj_type) |
222 | { | 268 | { |
223 | int new_id = 0; | ||
224 | int ret; | 269 | int ret; |
225 | 270 | ||
226 | again: | ||
227 | if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { | ||
228 | DRM_ERROR("Ran out memory getting a mode number\n"); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | |||
232 | mutex_lock(&dev->mode_config.idr_mutex); | 271 | mutex_lock(&dev->mode_config.idr_mutex); |
233 | ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); | 272 | ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL); |
273 | if (ret >= 0) { | ||
274 | /* | ||
275 | * Set up the object linking under the protection of the idr | ||
276 | * lock so that other users can't see inconsistent state. | ||
277 | */ | ||
278 | obj->id = ret; | ||
279 | obj->type = obj_type; | ||
280 | } | ||
234 | mutex_unlock(&dev->mode_config.idr_mutex); | 281 | mutex_unlock(&dev->mode_config.idr_mutex); |
235 | if (ret == -EAGAIN) | ||
236 | goto again; | ||
237 | else if (ret) | ||
238 | return ret; | ||
239 | 282 | ||
240 | obj->id = new_id; | 283 | return ret < 0 ? ret : 0; |
241 | obj->type = obj_type; | ||
242 | return 0; | ||
243 | } | 284 | } |
244 | 285 | ||
245 | /** | 286 | /** |
246 | * drm_mode_object_put - free an identifer | 287 | * drm_mode_object_put - free a modeset identifer |
247 | * @dev: DRM device | 288 | * @dev: DRM device |
248 | * @id: ID to free | 289 | * @object: object to free |
249 | * | ||
250 | * LOCKING: | ||
251 | * Caller must hold DRM mode_config lock. | ||
252 | * | 290 | * |
253 | * Free @id from @dev's unique identifier pool. | 291 | * Free @id from @dev's unique identifier pool. |
254 | */ | 292 | */ |
@@ -260,11 +298,24 @@ static void drm_mode_object_put(struct drm_device *dev, | |||
260 | mutex_unlock(&dev->mode_config.idr_mutex); | 298 | mutex_unlock(&dev->mode_config.idr_mutex); |
261 | } | 299 | } |
262 | 300 | ||
301 | /** | ||
302 | * drm_mode_object_find - look up a drm object with static lifetime | ||
303 | * @dev: drm device | ||
304 | * @id: id of the mode object | ||
305 | * @type: type of the mode object | ||
306 | * | ||
307 | * Note that framebuffers cannot be looked up with this functions - since those | ||
308 | * are reference counted, they need special treatment. | ||
309 | */ | ||
263 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, | 310 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, |
264 | uint32_t id, uint32_t type) | 311 | uint32_t id, uint32_t type) |
265 | { | 312 | { |
266 | struct drm_mode_object *obj = NULL; | 313 | struct drm_mode_object *obj = NULL; |
267 | 314 | ||
315 | /* Framebuffers are reference counted and need their own lookup | ||
316 | * function.*/ | ||
317 | WARN_ON(type == DRM_MODE_OBJECT_FB); | ||
318 | |||
268 | mutex_lock(&dev->mode_config.idr_mutex); | 319 | mutex_lock(&dev->mode_config.idr_mutex); |
269 | obj = idr_find(&dev->mode_config.crtc_idr, id); | 320 | obj = idr_find(&dev->mode_config.crtc_idr, id); |
270 | if (!obj || (obj->type != type) || (obj->id != id)) | 321 | if (!obj || (obj->type != type) || (obj->id != id)) |
@@ -278,13 +329,18 @@ EXPORT_SYMBOL(drm_mode_object_find); | |||
278 | /** | 329 | /** |
279 | * drm_framebuffer_init - initialize a framebuffer | 330 | * drm_framebuffer_init - initialize a framebuffer |
280 | * @dev: DRM device | 331 | * @dev: DRM device |
281 | * | 332 | * @fb: framebuffer to be initialized |
282 | * LOCKING: | 333 | * @funcs: ... with these functions |
283 | * Caller must hold mode config lock. | ||
284 | * | 334 | * |
285 | * Allocates an ID for the framebuffer's parent mode object, sets its mode | 335 | * Allocates an ID for the framebuffer's parent mode object, sets its mode |
286 | * functions & device file and adds it to the master fd list. | 336 | * functions & device file and adds it to the master fd list. |
287 | * | 337 | * |
338 | * IMPORTANT: | ||
339 | * This functions publishes the fb and makes it available for concurrent access | ||
340 | * by other users. Which means by this point the fb _must_ be fully set up - | ||
341 | * since all the fb attributes are invariant over its lifetime, no further | ||
342 | * locking but only correct reference counting is required. | ||
343 | * | ||
288 | * RETURNS: | 344 | * RETURNS: |
289 | * Zero on success, error code on failure. | 345 | * Zero on success, error code on failure. |
290 | */ | 346 | */ |
@@ -293,16 +349,23 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, | |||
293 | { | 349 | { |
294 | int ret; | 350 | int ret; |
295 | 351 | ||
352 | mutex_lock(&dev->mode_config.fb_lock); | ||
296 | kref_init(&fb->refcount); | 353 | kref_init(&fb->refcount); |
354 | INIT_LIST_HEAD(&fb->filp_head); | ||
355 | fb->dev = dev; | ||
356 | fb->funcs = funcs; | ||
297 | 357 | ||
298 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); | 358 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); |
299 | if (ret) | 359 | if (ret) |
300 | return ret; | 360 | goto out; |
361 | |||
362 | /* Grab the idr reference. */ | ||
363 | drm_framebuffer_reference(fb); | ||
301 | 364 | ||
302 | fb->dev = dev; | ||
303 | fb->funcs = funcs; | ||
304 | dev->mode_config.num_fb++; | 365 | dev->mode_config.num_fb++; |
305 | list_add(&fb->head, &dev->mode_config.fb_list); | 366 | list_add(&fb->head, &dev->mode_config.fb_list); |
367 | out: | ||
368 | mutex_unlock(&dev->mode_config.fb_lock); | ||
306 | 369 | ||
307 | return 0; | 370 | return 0; |
308 | } | 371 | } |
@@ -315,23 +378,63 @@ static void drm_framebuffer_free(struct kref *kref) | |||
315 | fb->funcs->destroy(fb); | 378 | fb->funcs->destroy(fb); |
316 | } | 379 | } |
317 | 380 | ||
381 | static struct drm_framebuffer *__drm_framebuffer_lookup(struct drm_device *dev, | ||
382 | uint32_t id) | ||
383 | { | ||
384 | struct drm_mode_object *obj = NULL; | ||
385 | struct drm_framebuffer *fb; | ||
386 | |||
387 | mutex_lock(&dev->mode_config.idr_mutex); | ||
388 | obj = idr_find(&dev->mode_config.crtc_idr, id); | ||
389 | if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id)) | ||
390 | fb = NULL; | ||
391 | else | ||
392 | fb = obj_to_fb(obj); | ||
393 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
394 | |||
395 | return fb; | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference | ||
400 | * @dev: drm device | ||
401 | * @id: id of the fb object | ||
402 | * | ||
403 | * If successful, this grabs an additional reference to the framebuffer - | ||
404 | * callers need to make sure to eventually unreference the returned framebuffer | ||
405 | * again. | ||
406 | */ | ||
407 | struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, | ||
408 | uint32_t id) | ||
409 | { | ||
410 | struct drm_framebuffer *fb; | ||
411 | |||
412 | mutex_lock(&dev->mode_config.fb_lock); | ||
413 | fb = __drm_framebuffer_lookup(dev, id); | ||
414 | if (fb) | ||
415 | kref_get(&fb->refcount); | ||
416 | mutex_unlock(&dev->mode_config.fb_lock); | ||
417 | |||
418 | return fb; | ||
419 | } | ||
420 | EXPORT_SYMBOL(drm_framebuffer_lookup); | ||
421 | |||
318 | /** | 422 | /** |
319 | * drm_framebuffer_unreference - unref a framebuffer | 423 | * drm_framebuffer_unreference - unref a framebuffer |
424 | * @fb: framebuffer to unref | ||
320 | * | 425 | * |
321 | * LOCKING: | 426 | * This functions decrements the fb's refcount and frees it if it drops to zero. |
322 | * Caller must hold mode config lock. | ||
323 | */ | 427 | */ |
324 | void drm_framebuffer_unreference(struct drm_framebuffer *fb) | 428 | void drm_framebuffer_unreference(struct drm_framebuffer *fb) |
325 | { | 429 | { |
326 | struct drm_device *dev = fb->dev; | ||
327 | DRM_DEBUG("FB ID: %d\n", fb->base.id); | 430 | DRM_DEBUG("FB ID: %d\n", fb->base.id); |
328 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
329 | kref_put(&fb->refcount, drm_framebuffer_free); | 431 | kref_put(&fb->refcount, drm_framebuffer_free); |
330 | } | 432 | } |
331 | EXPORT_SYMBOL(drm_framebuffer_unreference); | 433 | EXPORT_SYMBOL(drm_framebuffer_unreference); |
332 | 434 | ||
333 | /** | 435 | /** |
334 | * drm_framebuffer_reference - incr the fb refcnt | 436 | * drm_framebuffer_reference - incr the fb refcnt |
437 | * @fb: framebuffer | ||
335 | */ | 438 | */ |
336 | void drm_framebuffer_reference(struct drm_framebuffer *fb) | 439 | void drm_framebuffer_reference(struct drm_framebuffer *fb) |
337 | { | 440 | { |
@@ -340,29 +443,74 @@ void drm_framebuffer_reference(struct drm_framebuffer *fb) | |||
340 | } | 443 | } |
341 | EXPORT_SYMBOL(drm_framebuffer_reference); | 444 | EXPORT_SYMBOL(drm_framebuffer_reference); |
342 | 445 | ||
446 | static void drm_framebuffer_free_bug(struct kref *kref) | ||
447 | { | ||
448 | BUG(); | ||
449 | } | ||
450 | |||
451 | static void __drm_framebuffer_unreference(struct drm_framebuffer *fb) | ||
452 | { | ||
453 | DRM_DEBUG("FB ID: %d\n", fb->base.id); | ||
454 | kref_put(&fb->refcount, drm_framebuffer_free_bug); | ||
455 | } | ||
456 | |||
457 | /* dev->mode_config.fb_lock must be held! */ | ||
458 | static void __drm_framebuffer_unregister(struct drm_device *dev, | ||
459 | struct drm_framebuffer *fb) | ||
460 | { | ||
461 | mutex_lock(&dev->mode_config.idr_mutex); | ||
462 | idr_remove(&dev->mode_config.crtc_idr, fb->base.id); | ||
463 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
464 | |||
465 | fb->base.id = 0; | ||
466 | |||
467 | __drm_framebuffer_unreference(fb); | ||
468 | } | ||
469 | |||
470 | /** | ||
471 | * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr | ||
472 | * @fb: fb to unregister | ||
473 | * | ||
474 | * Drivers need to call this when cleaning up driver-private framebuffers, e.g. | ||
475 | * those used for fbdev. Note that the caller must hold a reference of it's own, | ||
476 | * i.e. the object may not be destroyed through this call (since it'll lead to a | ||
477 | * locking inversion). | ||
478 | */ | ||
479 | void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) | ||
480 | { | ||
481 | struct drm_device *dev = fb->dev; | ||
482 | |||
483 | mutex_lock(&dev->mode_config.fb_lock); | ||
484 | /* Mark fb as reaped and drop idr ref. */ | ||
485 | __drm_framebuffer_unregister(dev, fb); | ||
486 | mutex_unlock(&dev->mode_config.fb_lock); | ||
487 | } | ||
488 | EXPORT_SYMBOL(drm_framebuffer_unregister_private); | ||
489 | |||
343 | /** | 490 | /** |
344 | * drm_framebuffer_cleanup - remove a framebuffer object | 491 | * drm_framebuffer_cleanup - remove a framebuffer object |
345 | * @fb: framebuffer to remove | 492 | * @fb: framebuffer to remove |
346 | * | 493 | * |
347 | * LOCKING: | 494 | * Cleanup references to a user-created framebuffer. This function is intended |
348 | * Caller must hold mode config lock. | 495 | * to be used from the drivers ->destroy callback. |
349 | * | 496 | * |
350 | * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes | 497 | * Note that this function does not remove the fb from active usuage - if it is |
351 | * it, setting it to NULL. | 498 | * still used anywhere, hilarity can ensue since userspace could call getfb on |
499 | * the id and get back -EINVAL. Obviously no concern at driver unload time. | ||
500 | * | ||
501 | * Also, the framebuffer will not be removed from the lookup idr - for | ||
502 | * user-created framebuffers this will happen in in the rmfb ioctl. For | ||
503 | * driver-private objects (e.g. for fbdev) drivers need to explicitly call | ||
504 | * drm_framebuffer_unregister_private. | ||
352 | */ | 505 | */ |
353 | void drm_framebuffer_cleanup(struct drm_framebuffer *fb) | 506 | void drm_framebuffer_cleanup(struct drm_framebuffer *fb) |
354 | { | 507 | { |
355 | struct drm_device *dev = fb->dev; | 508 | struct drm_device *dev = fb->dev; |
356 | /* | 509 | |
357 | * This could be moved to drm_framebuffer_remove(), but for | 510 | mutex_lock(&dev->mode_config.fb_lock); |
358 | * debugging is nice to keep around the list of fb's that are | ||
359 | * no longer associated w/ a drm_file but are not unreferenced | ||
360 | * yet. (i915 and omapdrm have debugfs files which will show | ||
361 | * this.) | ||
362 | */ | ||
363 | drm_mode_object_put(dev, &fb->base); | ||
364 | list_del(&fb->head); | 511 | list_del(&fb->head); |
365 | dev->mode_config.num_fb--; | 512 | dev->mode_config.num_fb--; |
513 | mutex_unlock(&dev->mode_config.fb_lock); | ||
366 | } | 514 | } |
367 | EXPORT_SYMBOL(drm_framebuffer_cleanup); | 515 | EXPORT_SYMBOL(drm_framebuffer_cleanup); |
368 | 516 | ||
@@ -370,11 +518,13 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup); | |||
370 | * drm_framebuffer_remove - remove and unreference a framebuffer object | 518 | * drm_framebuffer_remove - remove and unreference a framebuffer object |
371 | * @fb: framebuffer to remove | 519 | * @fb: framebuffer to remove |
372 | * | 520 | * |
373 | * LOCKING: | ||
374 | * Caller must hold mode config lock. | ||
375 | * | ||
376 | * Scans all the CRTCs and planes in @dev's mode_config. If they're | 521 | * Scans all the CRTCs and planes in @dev's mode_config. If they're |
377 | * using @fb, removes it, setting it to NULL. | 522 | * using @fb, removes it, setting it to NULL. Then drops the reference to the |
523 | * passed-in framebuffer. Might take the modeset locks. | ||
524 | * | ||
525 | * Note that this function optimizes the cleanup away if the caller holds the | ||
526 | * last reference to the framebuffer. It is also guaranteed to not take the | ||
527 | * modeset locks in this case. | ||
378 | */ | 528 | */ |
379 | void drm_framebuffer_remove(struct drm_framebuffer *fb) | 529 | void drm_framebuffer_remove(struct drm_framebuffer *fb) |
380 | { | 530 | { |
@@ -384,33 +534,53 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) | |||
384 | struct drm_mode_set set; | 534 | struct drm_mode_set set; |
385 | int ret; | 535 | int ret; |
386 | 536 | ||
387 | /* remove from any CRTC */ | 537 | WARN_ON(!list_empty(&fb->filp_head)); |
388 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 538 | |
389 | if (crtc->fb == fb) { | 539 | /* |
390 | /* should turn off the crtc */ | 540 | * drm ABI mandates that we remove any deleted framebuffers from active |
391 | memset(&set, 0, sizeof(struct drm_mode_set)); | 541 | * useage. But since most sane clients only remove framebuffers they no |
392 | set.crtc = crtc; | 542 | * longer need, try to optimize this away. |
393 | set.fb = NULL; | 543 | * |
394 | ret = crtc->funcs->set_config(&set); | 544 | * Since we're holding a reference ourselves, observing a refcount of 1 |
395 | if (ret) | 545 | * means that we're the last holder and can skip it. Also, the refcount |
396 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); | 546 | * can never increase from 1 again, so we don't need any barriers or |
547 | * locks. | ||
548 | * | ||
549 | * Note that userspace could try to race with use and instate a new | ||
550 | * usage _after_ we've cleared all current ones. End result will be an | ||
551 | * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot | ||
552 | * in this manner. | ||
553 | */ | ||
554 | if (atomic_read(&fb->refcount.refcount) > 1) { | ||
555 | drm_modeset_lock_all(dev); | ||
556 | /* remove from any CRTC */ | ||
557 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
558 | if (crtc->fb == fb) { | ||
559 | /* should turn off the crtc */ | ||
560 | memset(&set, 0, sizeof(struct drm_mode_set)); | ||
561 | set.crtc = crtc; | ||
562 | set.fb = NULL; | ||
563 | ret = drm_mode_set_config_internal(&set); | ||
564 | if (ret) | ||
565 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); | ||
566 | } | ||
397 | } | 567 | } |
398 | } | ||
399 | 568 | ||
400 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) { | 569 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) { |
401 | if (plane->fb == fb) { | 570 | if (plane->fb == fb) { |
402 | /* should turn off the crtc */ | 571 | /* should turn off the crtc */ |
403 | ret = plane->funcs->disable_plane(plane); | 572 | ret = plane->funcs->disable_plane(plane); |
404 | if (ret) | 573 | if (ret) |
405 | DRM_ERROR("failed to disable plane with busy fb\n"); | 574 | DRM_ERROR("failed to disable plane with busy fb\n"); |
406 | /* disconnect the plane from the fb and crtc: */ | 575 | /* disconnect the plane from the fb and crtc: */ |
407 | plane->fb = NULL; | 576 | __drm_framebuffer_unreference(plane->fb); |
408 | plane->crtc = NULL; | 577 | plane->fb = NULL; |
578 | plane->crtc = NULL; | ||
579 | } | ||
409 | } | 580 | } |
581 | drm_modeset_unlock_all(dev); | ||
410 | } | 582 | } |
411 | 583 | ||
412 | list_del(&fb->filp_head); | ||
413 | |||
414 | drm_framebuffer_unreference(fb); | 584 | drm_framebuffer_unreference(fb); |
415 | } | 585 | } |
416 | EXPORT_SYMBOL(drm_framebuffer_remove); | 586 | EXPORT_SYMBOL(drm_framebuffer_remove); |
@@ -421,9 +591,6 @@ EXPORT_SYMBOL(drm_framebuffer_remove); | |||
421 | * @crtc: CRTC object to init | 591 | * @crtc: CRTC object to init |
422 | * @funcs: callbacks for the new CRTC | 592 | * @funcs: callbacks for the new CRTC |
423 | * | 593 | * |
424 | * LOCKING: | ||
425 | * Takes mode_config lock. | ||
426 | * | ||
427 | * Inits a new object created as base part of an driver crtc object. | 594 | * Inits a new object created as base part of an driver crtc object. |
428 | * | 595 | * |
429 | * RETURNS: | 596 | * RETURNS: |
@@ -438,7 +605,9 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | |||
438 | crtc->funcs = funcs; | 605 | crtc->funcs = funcs; |
439 | crtc->invert_dimensions = false; | 606 | crtc->invert_dimensions = false; |
440 | 607 | ||
441 | mutex_lock(&dev->mode_config.mutex); | 608 | drm_modeset_lock_all(dev); |
609 | mutex_init(&crtc->mutex); | ||
610 | mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex); | ||
442 | 611 | ||
443 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); | 612 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
444 | if (ret) | 613 | if (ret) |
@@ -450,7 +619,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | |||
450 | dev->mode_config.num_crtc++; | 619 | dev->mode_config.num_crtc++; |
451 | 620 | ||
452 | out: | 621 | out: |
453 | mutex_unlock(&dev->mode_config.mutex); | 622 | drm_modeset_unlock_all(dev); |
454 | 623 | ||
455 | return ret; | 624 | return ret; |
456 | } | 625 | } |
@@ -460,9 +629,6 @@ EXPORT_SYMBOL(drm_crtc_init); | |||
460 | * drm_crtc_cleanup - Cleans up the core crtc usage. | 629 | * drm_crtc_cleanup - Cleans up the core crtc usage. |
461 | * @crtc: CRTC to cleanup | 630 | * @crtc: CRTC to cleanup |
462 | * | 631 | * |
463 | * LOCKING: | ||
464 | * Caller must hold mode config lock. | ||
465 | * | ||
466 | * Cleanup @crtc. Removes from drm modesetting space | 632 | * Cleanup @crtc. Removes from drm modesetting space |
467 | * does NOT free object, caller does that. | 633 | * does NOT free object, caller does that. |
468 | */ | 634 | */ |
@@ -484,9 +650,6 @@ EXPORT_SYMBOL(drm_crtc_cleanup); | |||
484 | * @connector: connector the new mode | 650 | * @connector: connector the new mode |
485 | * @mode: mode data | 651 | * @mode: mode data |
486 | * | 652 | * |
487 | * LOCKING: | ||
488 | * Caller must hold mode config lock. | ||
489 | * | ||
490 | * Add @mode to @connector's mode list for later use. | 653 | * Add @mode to @connector's mode list for later use. |
491 | */ | 654 | */ |
492 | void drm_mode_probed_add(struct drm_connector *connector, | 655 | void drm_mode_probed_add(struct drm_connector *connector, |
@@ -501,9 +664,6 @@ EXPORT_SYMBOL(drm_mode_probed_add); | |||
501 | * @connector: connector list to modify | 664 | * @connector: connector list to modify |
502 | * @mode: mode to remove | 665 | * @mode: mode to remove |
503 | * | 666 | * |
504 | * LOCKING: | ||
505 | * Caller must hold mode config lock. | ||
506 | * | ||
507 | * Remove @mode from @connector's mode list, then free it. | 667 | * Remove @mode from @connector's mode list, then free it. |
508 | */ | 668 | */ |
509 | void drm_mode_remove(struct drm_connector *connector, | 669 | void drm_mode_remove(struct drm_connector *connector, |
@@ -519,10 +679,7 @@ EXPORT_SYMBOL(drm_mode_remove); | |||
519 | * @dev: DRM device | 679 | * @dev: DRM device |
520 | * @connector: the connector to init | 680 | * @connector: the connector to init |
521 | * @funcs: callbacks for this connector | 681 | * @funcs: callbacks for this connector |
522 | * @name: user visible name of the connector | 682 | * @connector_type: user visible type of the connector |
523 | * | ||
524 | * LOCKING: | ||
525 | * Takes mode config lock. | ||
526 | * | 683 | * |
527 | * Initialises a preallocated connector. Connectors should be | 684 | * Initialises a preallocated connector. Connectors should be |
528 | * subclassed as part of driver connector objects. | 685 | * subclassed as part of driver connector objects. |
@@ -537,7 +694,7 @@ int drm_connector_init(struct drm_device *dev, | |||
537 | { | 694 | { |
538 | int ret; | 695 | int ret; |
539 | 696 | ||
540 | mutex_lock(&dev->mode_config.mutex); | 697 | drm_modeset_lock_all(dev); |
541 | 698 | ||
542 | ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); | 699 | ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); |
543 | if (ret) | 700 | if (ret) |
@@ -567,7 +724,7 @@ int drm_connector_init(struct drm_device *dev, | |||
567 | dev->mode_config.dpms_property, 0); | 724 | dev->mode_config.dpms_property, 0); |
568 | 725 | ||
569 | out: | 726 | out: |
570 | mutex_unlock(&dev->mode_config.mutex); | 727 | drm_modeset_unlock_all(dev); |
571 | 728 | ||
572 | return ret; | 729 | return ret; |
573 | } | 730 | } |
@@ -577,9 +734,6 @@ EXPORT_SYMBOL(drm_connector_init); | |||
577 | * drm_connector_cleanup - cleans up an initialised connector | 734 | * drm_connector_cleanup - cleans up an initialised connector |
578 | * @connector: connector to cleanup | 735 | * @connector: connector to cleanup |
579 | * | 736 | * |
580 | * LOCKING: | ||
581 | * Takes mode config lock. | ||
582 | * | ||
583 | * Cleans up the connector but doesn't free the object. | 737 | * Cleans up the connector but doesn't free the object. |
584 | */ | 738 | */ |
585 | void drm_connector_cleanup(struct drm_connector *connector) | 739 | void drm_connector_cleanup(struct drm_connector *connector) |
@@ -596,11 +750,9 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
596 | list_for_each_entry_safe(mode, t, &connector->user_modes, head) | 750 | list_for_each_entry_safe(mode, t, &connector->user_modes, head) |
597 | drm_mode_remove(connector, mode); | 751 | drm_mode_remove(connector, mode); |
598 | 752 | ||
599 | mutex_lock(&dev->mode_config.mutex); | ||
600 | drm_mode_object_put(dev, &connector->base); | 753 | drm_mode_object_put(dev, &connector->base); |
601 | list_del(&connector->head); | 754 | list_del(&connector->head); |
602 | dev->mode_config.num_connector--; | 755 | dev->mode_config.num_connector--; |
603 | mutex_unlock(&dev->mode_config.mutex); | ||
604 | } | 756 | } |
605 | EXPORT_SYMBOL(drm_connector_cleanup); | 757 | EXPORT_SYMBOL(drm_connector_cleanup); |
606 | 758 | ||
@@ -622,7 +774,7 @@ int drm_encoder_init(struct drm_device *dev, | |||
622 | { | 774 | { |
623 | int ret; | 775 | int ret; |
624 | 776 | ||
625 | mutex_lock(&dev->mode_config.mutex); | 777 | drm_modeset_lock_all(dev); |
626 | 778 | ||
627 | ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); | 779 | ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); |
628 | if (ret) | 780 | if (ret) |
@@ -636,7 +788,7 @@ int drm_encoder_init(struct drm_device *dev, | |||
636 | dev->mode_config.num_encoder++; | 788 | dev->mode_config.num_encoder++; |
637 | 789 | ||
638 | out: | 790 | out: |
639 | mutex_unlock(&dev->mode_config.mutex); | 791 | drm_modeset_unlock_all(dev); |
640 | 792 | ||
641 | return ret; | 793 | return ret; |
642 | } | 794 | } |
@@ -645,11 +797,11 @@ EXPORT_SYMBOL(drm_encoder_init); | |||
645 | void drm_encoder_cleanup(struct drm_encoder *encoder) | 797 | void drm_encoder_cleanup(struct drm_encoder *encoder) |
646 | { | 798 | { |
647 | struct drm_device *dev = encoder->dev; | 799 | struct drm_device *dev = encoder->dev; |
648 | mutex_lock(&dev->mode_config.mutex); | 800 | drm_modeset_lock_all(dev); |
649 | drm_mode_object_put(dev, &encoder->base); | 801 | drm_mode_object_put(dev, &encoder->base); |
650 | list_del(&encoder->head); | 802 | list_del(&encoder->head); |
651 | dev->mode_config.num_encoder--; | 803 | dev->mode_config.num_encoder--; |
652 | mutex_unlock(&dev->mode_config.mutex); | 804 | drm_modeset_unlock_all(dev); |
653 | } | 805 | } |
654 | EXPORT_SYMBOL(drm_encoder_cleanup); | 806 | EXPORT_SYMBOL(drm_encoder_cleanup); |
655 | 807 | ||
@@ -661,7 +813,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
661 | { | 813 | { |
662 | int ret; | 814 | int ret; |
663 | 815 | ||
664 | mutex_lock(&dev->mode_config.mutex); | 816 | drm_modeset_lock_all(dev); |
665 | 817 | ||
666 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); | 818 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
667 | if (ret) | 819 | if (ret) |
@@ -695,7 +847,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
695 | } | 847 | } |
696 | 848 | ||
697 | out: | 849 | out: |
698 | mutex_unlock(&dev->mode_config.mutex); | 850 | drm_modeset_unlock_all(dev); |
699 | 851 | ||
700 | return ret; | 852 | return ret; |
701 | } | 853 | } |
@@ -705,7 +857,7 @@ void drm_plane_cleanup(struct drm_plane *plane) | |||
705 | { | 857 | { |
706 | struct drm_device *dev = plane->dev; | 858 | struct drm_device *dev = plane->dev; |
707 | 859 | ||
708 | mutex_lock(&dev->mode_config.mutex); | 860 | drm_modeset_lock_all(dev); |
709 | kfree(plane->format_types); | 861 | kfree(plane->format_types); |
710 | drm_mode_object_put(dev, &plane->base); | 862 | drm_mode_object_put(dev, &plane->base); |
711 | /* if not added to a list, it must be a private plane */ | 863 | /* if not added to a list, it must be a private plane */ |
@@ -713,7 +865,7 @@ void drm_plane_cleanup(struct drm_plane *plane) | |||
713 | list_del(&plane->head); | 865 | list_del(&plane->head); |
714 | dev->mode_config.num_plane--; | 866 | dev->mode_config.num_plane--; |
715 | } | 867 | } |
716 | mutex_unlock(&dev->mode_config.mutex); | 868 | drm_modeset_unlock_all(dev); |
717 | } | 869 | } |
718 | EXPORT_SYMBOL(drm_plane_cleanup); | 870 | EXPORT_SYMBOL(drm_plane_cleanup); |
719 | 871 | ||
@@ -721,9 +873,6 @@ EXPORT_SYMBOL(drm_plane_cleanup); | |||
721 | * drm_mode_create - create a new display mode | 873 | * drm_mode_create - create a new display mode |
722 | * @dev: DRM device | 874 | * @dev: DRM device |
723 | * | 875 | * |
724 | * LOCKING: | ||
725 | * Caller must hold DRM mode_config lock. | ||
726 | * | ||
727 | * Create a new drm_display_mode, give it an ID, and return it. | 876 | * Create a new drm_display_mode, give it an ID, and return it. |
728 | * | 877 | * |
729 | * RETURNS: | 878 | * RETURNS: |
@@ -751,9 +900,6 @@ EXPORT_SYMBOL(drm_mode_create); | |||
751 | * @dev: DRM device | 900 | * @dev: DRM device |
752 | * @mode: mode to remove | 901 | * @mode: mode to remove |
753 | * | 902 | * |
754 | * LOCKING: | ||
755 | * Caller must hold mode config lock. | ||
756 | * | ||
757 | * Free @mode's unique identifier, then free it. | 903 | * Free @mode's unique identifier, then free it. |
758 | */ | 904 | */ |
759 | void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) | 905 | void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) |
@@ -978,16 +1124,19 @@ EXPORT_SYMBOL(drm_mode_create_dirty_info_property); | |||
978 | * drm_mode_config_init - initialize DRM mode_configuration structure | 1124 | * drm_mode_config_init - initialize DRM mode_configuration structure |
979 | * @dev: DRM device | 1125 | * @dev: DRM device |
980 | * | 1126 | * |
981 | * LOCKING: | ||
982 | * None, should happen single threaded at init time. | ||
983 | * | ||
984 | * Initialize @dev's mode_config structure, used for tracking the graphics | 1127 | * Initialize @dev's mode_config structure, used for tracking the graphics |
985 | * configuration of @dev. | 1128 | * configuration of @dev. |
1129 | * | ||
1130 | * Since this initializes the modeset locks, no locking is possible. Which is no | ||
1131 | * problem, since this should happen single threaded at init time. It is the | ||
1132 | * driver's problem to ensure this guarantee. | ||
1133 | * | ||
986 | */ | 1134 | */ |
987 | void drm_mode_config_init(struct drm_device *dev) | 1135 | void drm_mode_config_init(struct drm_device *dev) |
988 | { | 1136 | { |
989 | mutex_init(&dev->mode_config.mutex); | 1137 | mutex_init(&dev->mode_config.mutex); |
990 | mutex_init(&dev->mode_config.idr_mutex); | 1138 | mutex_init(&dev->mode_config.idr_mutex); |
1139 | mutex_init(&dev->mode_config.fb_lock); | ||
991 | INIT_LIST_HEAD(&dev->mode_config.fb_list); | 1140 | INIT_LIST_HEAD(&dev->mode_config.fb_list); |
992 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); | 1141 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
993 | INIT_LIST_HEAD(&dev->mode_config.connector_list); | 1142 | INIT_LIST_HEAD(&dev->mode_config.connector_list); |
@@ -997,9 +1146,9 @@ void drm_mode_config_init(struct drm_device *dev) | |||
997 | INIT_LIST_HEAD(&dev->mode_config.plane_list); | 1146 | INIT_LIST_HEAD(&dev->mode_config.plane_list); |
998 | idr_init(&dev->mode_config.crtc_idr); | 1147 | idr_init(&dev->mode_config.crtc_idr); |
999 | 1148 | ||
1000 | mutex_lock(&dev->mode_config.mutex); | 1149 | drm_modeset_lock_all(dev); |
1001 | drm_mode_create_standard_connector_properties(dev); | 1150 | drm_mode_create_standard_connector_properties(dev); |
1002 | mutex_unlock(&dev->mode_config.mutex); | 1151 | drm_modeset_unlock_all(dev); |
1003 | 1152 | ||
1004 | /* Just to be sure */ | 1153 | /* Just to be sure */ |
1005 | dev->mode_config.num_fb = 0; | 1154 | dev->mode_config.num_fb = 0; |
@@ -1057,12 +1206,13 @@ EXPORT_SYMBOL(drm_mode_group_init_legacy_group); | |||
1057 | * drm_mode_config_cleanup - free up DRM mode_config info | 1206 | * drm_mode_config_cleanup - free up DRM mode_config info |
1058 | * @dev: DRM device | 1207 | * @dev: DRM device |
1059 | * | 1208 | * |
1060 | * LOCKING: | ||
1061 | * Caller must hold mode config lock. | ||
1062 | * | ||
1063 | * Free up all the connectors and CRTCs associated with this DRM device, then | 1209 | * Free up all the connectors and CRTCs associated with this DRM device, then |
1064 | * free up the framebuffers and associated buffer objects. | 1210 | * free up the framebuffers and associated buffer objects. |
1065 | * | 1211 | * |
1212 | * Note that since this /should/ happen single-threaded at driver/device | ||
1213 | * teardown time, no locking is required. It's the driver's job to ensure that | ||
1214 | * this guarantee actually holds true. | ||
1215 | * | ||
1066 | * FIXME: cleanup any dangling user buffer objects too | 1216 | * FIXME: cleanup any dangling user buffer objects too |
1067 | */ | 1217 | */ |
1068 | void drm_mode_config_cleanup(struct drm_device *dev) | 1218 | void drm_mode_config_cleanup(struct drm_device *dev) |
@@ -1089,6 +1239,15 @@ void drm_mode_config_cleanup(struct drm_device *dev) | |||
1089 | drm_property_destroy(dev, property); | 1239 | drm_property_destroy(dev, property); |
1090 | } | 1240 | } |
1091 | 1241 | ||
1242 | /* | ||
1243 | * Single-threaded teardown context, so it's not required to grab the | ||
1244 | * fb_lock to protect against concurrent fb_list access. Contrary, it | ||
1245 | * would actually deadlock with the drm_framebuffer_cleanup function. | ||
1246 | * | ||
1247 | * Also, if there are any framebuffers left, that's a driver leak now, | ||
1248 | * so politely WARN about this. | ||
1249 | */ | ||
1250 | WARN_ON(!list_empty(&dev->mode_config.fb_list)); | ||
1092 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { | 1251 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { |
1093 | drm_framebuffer_remove(fb); | 1252 | drm_framebuffer_remove(fb); |
1094 | } | 1253 | } |
@@ -1102,7 +1261,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) | |||
1102 | crtc->funcs->destroy(crtc); | 1261 | crtc->funcs->destroy(crtc); |
1103 | } | 1262 | } |
1104 | 1263 | ||
1105 | idr_remove_all(&dev->mode_config.crtc_idr); | ||
1106 | idr_destroy(&dev->mode_config.crtc_idr); | 1264 | idr_destroy(&dev->mode_config.crtc_idr); |
1107 | } | 1265 | } |
1108 | EXPORT_SYMBOL(drm_mode_config_cleanup); | 1266 | EXPORT_SYMBOL(drm_mode_config_cleanup); |
@@ -1112,9 +1270,6 @@ EXPORT_SYMBOL(drm_mode_config_cleanup); | |||
1112 | * @out: drm_mode_modeinfo struct to return to the user | 1270 | * @out: drm_mode_modeinfo struct to return to the user |
1113 | * @in: drm_display_mode to use | 1271 | * @in: drm_display_mode to use |
1114 | * | 1272 | * |
1115 | * LOCKING: | ||
1116 | * None. | ||
1117 | * | ||
1118 | * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to | 1273 | * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to |
1119 | * the user. | 1274 | * the user. |
1120 | */ | 1275 | */ |
@@ -1151,9 +1306,6 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, | |||
1151 | * @out: drm_display_mode to return to the user | 1306 | * @out: drm_display_mode to return to the user |
1152 | * @in: drm_mode_modeinfo to use | 1307 | * @in: drm_mode_modeinfo to use |
1153 | * | 1308 | * |
1154 | * LOCKING: | ||
1155 | * None. | ||
1156 | * | ||
1157 | * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to | 1309 | * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to |
1158 | * the caller. | 1310 | * the caller. |
1159 | * | 1311 | * |
@@ -1188,13 +1340,9 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out, | |||
1188 | 1340 | ||
1189 | /** | 1341 | /** |
1190 | * drm_mode_getresources - get graphics configuration | 1342 | * drm_mode_getresources - get graphics configuration |
1191 | * @inode: inode from the ioctl | 1343 | * @dev: drm device for the ioctl |
1192 | * @filp: file * from the ioctl | 1344 | * @data: data pointer for the ioctl |
1193 | * @cmd: cmd from ioctl | 1345 | * @file_priv: drm file for the ioctl call |
1194 | * @arg: arg from ioctl | ||
1195 | * | ||
1196 | * LOCKING: | ||
1197 | * Takes mode config lock. | ||
1198 | * | 1346 | * |
1199 | * Construct a set of configuration description structures and return | 1347 | * Construct a set of configuration description structures and return |
1200 | * them to the user, including CRTC, connector and framebuffer configuration. | 1348 | * them to the user, including CRTC, connector and framebuffer configuration. |
@@ -1228,8 +1376,8 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1228 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1376 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1229 | return -EINVAL; | 1377 | return -EINVAL; |
1230 | 1378 | ||
1231 | mutex_lock(&dev->mode_config.mutex); | ||
1232 | 1379 | ||
1380 | mutex_lock(&file_priv->fbs_lock); | ||
1233 | /* | 1381 | /* |
1234 | * For the non-control nodes we need to limit the list of resources | 1382 | * For the non-control nodes we need to limit the list of resources |
1235 | * by IDs in the group list for this node | 1383 | * by IDs in the group list for this node |
@@ -1237,6 +1385,23 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1237 | list_for_each(lh, &file_priv->fbs) | 1385 | list_for_each(lh, &file_priv->fbs) |
1238 | fb_count++; | 1386 | fb_count++; |
1239 | 1387 | ||
1388 | /* handle this in 4 parts */ | ||
1389 | /* FBs */ | ||
1390 | if (card_res->count_fbs >= fb_count) { | ||
1391 | copied = 0; | ||
1392 | fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; | ||
1393 | list_for_each_entry(fb, &file_priv->fbs, filp_head) { | ||
1394 | if (put_user(fb->base.id, fb_id + copied)) { | ||
1395 | mutex_unlock(&file_priv->fbs_lock); | ||
1396 | return -EFAULT; | ||
1397 | } | ||
1398 | copied++; | ||
1399 | } | ||
1400 | } | ||
1401 | card_res->count_fbs = fb_count; | ||
1402 | mutex_unlock(&file_priv->fbs_lock); | ||
1403 | |||
1404 | drm_modeset_lock_all(dev); | ||
1240 | mode_group = &file_priv->master->minor->mode_group; | 1405 | mode_group = &file_priv->master->minor->mode_group; |
1241 | if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { | 1406 | if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { |
1242 | 1407 | ||
@@ -1260,21 +1425,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1260 | card_res->max_width = dev->mode_config.max_width; | 1425 | card_res->max_width = dev->mode_config.max_width; |
1261 | card_res->min_width = dev->mode_config.min_width; | 1426 | card_res->min_width = dev->mode_config.min_width; |
1262 | 1427 | ||
1263 | /* handle this in 4 parts */ | ||
1264 | /* FBs */ | ||
1265 | if (card_res->count_fbs >= fb_count) { | ||
1266 | copied = 0; | ||
1267 | fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; | ||
1268 | list_for_each_entry(fb, &file_priv->fbs, filp_head) { | ||
1269 | if (put_user(fb->base.id, fb_id + copied)) { | ||
1270 | ret = -EFAULT; | ||
1271 | goto out; | ||
1272 | } | ||
1273 | copied++; | ||
1274 | } | ||
1275 | } | ||
1276 | card_res->count_fbs = fb_count; | ||
1277 | |||
1278 | /* CRTCs */ | 1428 | /* CRTCs */ |
1279 | if (card_res->count_crtcs >= crtc_count) { | 1429 | if (card_res->count_crtcs >= crtc_count) { |
1280 | copied = 0; | 1430 | copied = 0; |
@@ -1370,19 +1520,15 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1370 | card_res->count_connectors, card_res->count_encoders); | 1520 | card_res->count_connectors, card_res->count_encoders); |
1371 | 1521 | ||
1372 | out: | 1522 | out: |
1373 | mutex_unlock(&dev->mode_config.mutex); | 1523 | drm_modeset_unlock_all(dev); |
1374 | return ret; | 1524 | return ret; |
1375 | } | 1525 | } |
1376 | 1526 | ||
1377 | /** | 1527 | /** |
1378 | * drm_mode_getcrtc - get CRTC configuration | 1528 | * drm_mode_getcrtc - get CRTC configuration |
1379 | * @inode: inode from the ioctl | 1529 | * @dev: drm device for the ioctl |
1380 | * @filp: file * from the ioctl | 1530 | * @data: data pointer for the ioctl |
1381 | * @cmd: cmd from ioctl | 1531 | * @file_priv: drm file for the ioctl call |
1382 | * @arg: arg from ioctl | ||
1383 | * | ||
1384 | * LOCKING: | ||
1385 | * Takes mode config lock. | ||
1386 | * | 1532 | * |
1387 | * Construct a CRTC configuration structure to return to the user. | 1533 | * Construct a CRTC configuration structure to return to the user. |
1388 | * | 1534 | * |
@@ -1402,7 +1548,7 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
1402 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1548 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1403 | return -EINVAL; | 1549 | return -EINVAL; |
1404 | 1550 | ||
1405 | mutex_lock(&dev->mode_config.mutex); | 1551 | drm_modeset_lock_all(dev); |
1406 | 1552 | ||
1407 | obj = drm_mode_object_find(dev, crtc_resp->crtc_id, | 1553 | obj = drm_mode_object_find(dev, crtc_resp->crtc_id, |
1408 | DRM_MODE_OBJECT_CRTC); | 1554 | DRM_MODE_OBJECT_CRTC); |
@@ -1430,19 +1576,15 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
1430 | } | 1576 | } |
1431 | 1577 | ||
1432 | out: | 1578 | out: |
1433 | mutex_unlock(&dev->mode_config.mutex); | 1579 | drm_modeset_unlock_all(dev); |
1434 | return ret; | 1580 | return ret; |
1435 | } | 1581 | } |
1436 | 1582 | ||
1437 | /** | 1583 | /** |
1438 | * drm_mode_getconnector - get connector configuration | 1584 | * drm_mode_getconnector - get connector configuration |
1439 | * @inode: inode from the ioctl | 1585 | * @dev: drm device for the ioctl |
1440 | * @filp: file * from the ioctl | 1586 | * @data: data pointer for the ioctl |
1441 | * @cmd: cmd from ioctl | 1587 | * @file_priv: drm file for the ioctl call |
1442 | * @arg: arg from ioctl | ||
1443 | * | ||
1444 | * LOCKING: | ||
1445 | * Takes mode config lock. | ||
1446 | * | 1588 | * |
1447 | * Construct a connector configuration structure to return to the user. | 1589 | * Construct a connector configuration structure to return to the user. |
1448 | * | 1590 | * |
@@ -1575,6 +1717,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1575 | 1717 | ||
1576 | out: | 1718 | out: |
1577 | mutex_unlock(&dev->mode_config.mutex); | 1719 | mutex_unlock(&dev->mode_config.mutex); |
1720 | |||
1578 | return ret; | 1721 | return ret; |
1579 | } | 1722 | } |
1580 | 1723 | ||
@@ -1589,7 +1732,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, | |||
1589 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1732 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1590 | return -EINVAL; | 1733 | return -EINVAL; |
1591 | 1734 | ||
1592 | mutex_lock(&dev->mode_config.mutex); | 1735 | drm_modeset_lock_all(dev); |
1593 | obj = drm_mode_object_find(dev, enc_resp->encoder_id, | 1736 | obj = drm_mode_object_find(dev, enc_resp->encoder_id, |
1594 | DRM_MODE_OBJECT_ENCODER); | 1737 | DRM_MODE_OBJECT_ENCODER); |
1595 | if (!obj) { | 1738 | if (!obj) { |
@@ -1608,7 +1751,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, | |||
1608 | enc_resp->possible_clones = encoder->possible_clones; | 1751 | enc_resp->possible_clones = encoder->possible_clones; |
1609 | 1752 | ||
1610 | out: | 1753 | out: |
1611 | mutex_unlock(&dev->mode_config.mutex); | 1754 | drm_modeset_unlock_all(dev); |
1612 | return ret; | 1755 | return ret; |
1613 | } | 1756 | } |
1614 | 1757 | ||
@@ -1618,9 +1761,6 @@ out: | |||
1618 | * @data: ioctl data | 1761 | * @data: ioctl data |
1619 | * @file_priv: DRM file info | 1762 | * @file_priv: DRM file info |
1620 | * | 1763 | * |
1621 | * LOCKING: | ||
1622 | * Takes mode config lock. | ||
1623 | * | ||
1624 | * Return an plane count and set of IDs. | 1764 | * Return an plane count and set of IDs. |
1625 | */ | 1765 | */ |
1626 | int drm_mode_getplane_res(struct drm_device *dev, void *data, | 1766 | int drm_mode_getplane_res(struct drm_device *dev, void *data, |
@@ -1635,7 +1775,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, | |||
1635 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1775 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1636 | return -EINVAL; | 1776 | return -EINVAL; |
1637 | 1777 | ||
1638 | mutex_lock(&dev->mode_config.mutex); | 1778 | drm_modeset_lock_all(dev); |
1639 | config = &dev->mode_config; | 1779 | config = &dev->mode_config; |
1640 | 1780 | ||
1641 | /* | 1781 | /* |
@@ -1657,7 +1797,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, | |||
1657 | plane_resp->count_planes = config->num_plane; | 1797 | plane_resp->count_planes = config->num_plane; |
1658 | 1798 | ||
1659 | out: | 1799 | out: |
1660 | mutex_unlock(&dev->mode_config.mutex); | 1800 | drm_modeset_unlock_all(dev); |
1661 | return ret; | 1801 | return ret; |
1662 | } | 1802 | } |
1663 | 1803 | ||
@@ -1667,9 +1807,6 @@ out: | |||
1667 | * @data: ioctl data | 1807 | * @data: ioctl data |
1668 | * @file_priv: DRM file info | 1808 | * @file_priv: DRM file info |
1669 | * | 1809 | * |
1670 | * LOCKING: | ||
1671 | * Takes mode config lock. | ||
1672 | * | ||
1673 | * Return plane info, including formats supported, gamma size, any | 1810 | * Return plane info, including formats supported, gamma size, any |
1674 | * current fb, etc. | 1811 | * current fb, etc. |
1675 | */ | 1812 | */ |
@@ -1685,7 +1822,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data, | |||
1685 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1822 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1686 | return -EINVAL; | 1823 | return -EINVAL; |
1687 | 1824 | ||
1688 | mutex_lock(&dev->mode_config.mutex); | 1825 | drm_modeset_lock_all(dev); |
1689 | obj = drm_mode_object_find(dev, plane_resp->plane_id, | 1826 | obj = drm_mode_object_find(dev, plane_resp->plane_id, |
1690 | DRM_MODE_OBJECT_PLANE); | 1827 | DRM_MODE_OBJECT_PLANE); |
1691 | if (!obj) { | 1828 | if (!obj) { |
@@ -1725,7 +1862,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data, | |||
1725 | plane_resp->count_format_types = plane->format_count; | 1862 | plane_resp->count_format_types = plane->format_count; |
1726 | 1863 | ||
1727 | out: | 1864 | out: |
1728 | mutex_unlock(&dev->mode_config.mutex); | 1865 | drm_modeset_unlock_all(dev); |
1729 | return ret; | 1866 | return ret; |
1730 | } | 1867 | } |
1731 | 1868 | ||
@@ -1733,10 +1870,7 @@ out: | |||
1733 | * drm_mode_setplane - set up or tear down an plane | 1870 | * drm_mode_setplane - set up or tear down an plane |
1734 | * @dev: DRM device | 1871 | * @dev: DRM device |
1735 | * @data: ioctl data* | 1872 | * @data: ioctl data* |
1736 | * @file_prive: DRM file info | 1873 | * @file_priv: DRM file info |
1737 | * | ||
1738 | * LOCKING: | ||
1739 | * Takes mode config lock. | ||
1740 | * | 1874 | * |
1741 | * Set plane info, including placement, fb, scaling, and other factors. | 1875 | * Set plane info, including placement, fb, scaling, and other factors. |
1742 | * Or pass a NULL fb to disable. | 1876 | * Or pass a NULL fb to disable. |
@@ -1748,7 +1882,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
1748 | struct drm_mode_object *obj; | 1882 | struct drm_mode_object *obj; |
1749 | struct drm_plane *plane; | 1883 | struct drm_plane *plane; |
1750 | struct drm_crtc *crtc; | 1884 | struct drm_crtc *crtc; |
1751 | struct drm_framebuffer *fb; | 1885 | struct drm_framebuffer *fb = NULL, *old_fb = NULL; |
1752 | int ret = 0; | 1886 | int ret = 0; |
1753 | unsigned int fb_width, fb_height; | 1887 | unsigned int fb_width, fb_height; |
1754 | int i; | 1888 | int i; |
@@ -1756,8 +1890,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
1756 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1890 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1757 | return -EINVAL; | 1891 | return -EINVAL; |
1758 | 1892 | ||
1759 | mutex_lock(&dev->mode_config.mutex); | ||
1760 | |||
1761 | /* | 1893 | /* |
1762 | * First, find the plane, crtc, and fb objects. If not available, | 1894 | * First, find the plane, crtc, and fb objects. If not available, |
1763 | * we don't bother to call the driver. | 1895 | * we don't bother to call the driver. |
@@ -1767,16 +1899,18 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
1767 | if (!obj) { | 1899 | if (!obj) { |
1768 | DRM_DEBUG_KMS("Unknown plane ID %d\n", | 1900 | DRM_DEBUG_KMS("Unknown plane ID %d\n", |
1769 | plane_req->plane_id); | 1901 | plane_req->plane_id); |
1770 | ret = -ENOENT; | 1902 | return -ENOENT; |
1771 | goto out; | ||
1772 | } | 1903 | } |
1773 | plane = obj_to_plane(obj); | 1904 | plane = obj_to_plane(obj); |
1774 | 1905 | ||
1775 | /* No fb means shut it down */ | 1906 | /* No fb means shut it down */ |
1776 | if (!plane_req->fb_id) { | 1907 | if (!plane_req->fb_id) { |
1908 | drm_modeset_lock_all(dev); | ||
1909 | old_fb = plane->fb; | ||
1777 | plane->funcs->disable_plane(plane); | 1910 | plane->funcs->disable_plane(plane); |
1778 | plane->crtc = NULL; | 1911 | plane->crtc = NULL; |
1779 | plane->fb = NULL; | 1912 | plane->fb = NULL; |
1913 | drm_modeset_unlock_all(dev); | ||
1780 | goto out; | 1914 | goto out; |
1781 | } | 1915 | } |
1782 | 1916 | ||
@@ -1790,15 +1924,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
1790 | } | 1924 | } |
1791 | crtc = obj_to_crtc(obj); | 1925 | crtc = obj_to_crtc(obj); |
1792 | 1926 | ||
1793 | obj = drm_mode_object_find(dev, plane_req->fb_id, | 1927 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); |
1794 | DRM_MODE_OBJECT_FB); | 1928 | if (!fb) { |
1795 | if (!obj) { | ||
1796 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", | 1929 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", |
1797 | plane_req->fb_id); | 1930 | plane_req->fb_id); |
1798 | ret = -ENOENT; | 1931 | ret = -ENOENT; |
1799 | goto out; | 1932 | goto out; |
1800 | } | 1933 | } |
1801 | fb = obj_to_fb(obj); | ||
1802 | 1934 | ||
1803 | /* Check whether this plane supports the fb pixel format. */ | 1935 | /* Check whether this plane supports the fb pixel format. */ |
1804 | for (i = 0; i < plane->format_count; i++) | 1936 | for (i = 0; i < plane->format_count; i++) |
@@ -1844,31 +1976,62 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
1844 | goto out; | 1976 | goto out; |
1845 | } | 1977 | } |
1846 | 1978 | ||
1979 | drm_modeset_lock_all(dev); | ||
1847 | ret = plane->funcs->update_plane(plane, crtc, fb, | 1980 | ret = plane->funcs->update_plane(plane, crtc, fb, |
1848 | plane_req->crtc_x, plane_req->crtc_y, | 1981 | plane_req->crtc_x, plane_req->crtc_y, |
1849 | plane_req->crtc_w, plane_req->crtc_h, | 1982 | plane_req->crtc_w, plane_req->crtc_h, |
1850 | plane_req->src_x, plane_req->src_y, | 1983 | plane_req->src_x, plane_req->src_y, |
1851 | plane_req->src_w, plane_req->src_h); | 1984 | plane_req->src_w, plane_req->src_h); |
1852 | if (!ret) { | 1985 | if (!ret) { |
1986 | old_fb = plane->fb; | ||
1853 | plane->crtc = crtc; | 1987 | plane->crtc = crtc; |
1854 | plane->fb = fb; | 1988 | plane->fb = fb; |
1989 | fb = NULL; | ||
1855 | } | 1990 | } |
1991 | drm_modeset_unlock_all(dev); | ||
1856 | 1992 | ||
1857 | out: | 1993 | out: |
1858 | mutex_unlock(&dev->mode_config.mutex); | 1994 | if (fb) |
1995 | drm_framebuffer_unreference(fb); | ||
1996 | if (old_fb) | ||
1997 | drm_framebuffer_unreference(old_fb); | ||
1859 | 1998 | ||
1860 | return ret; | 1999 | return ret; |
1861 | } | 2000 | } |
1862 | 2001 | ||
1863 | /** | 2002 | /** |
1864 | * drm_mode_setcrtc - set CRTC configuration | 2003 | * drm_mode_set_config_internal - helper to call ->set_config |
1865 | * @inode: inode from the ioctl | 2004 | * @set: modeset config to set |
1866 | * @filp: file * from the ioctl | ||
1867 | * @cmd: cmd from ioctl | ||
1868 | * @arg: arg from ioctl | ||
1869 | * | 2005 | * |
1870 | * LOCKING: | 2006 | * This is a little helper to wrap internal calls to the ->set_config driver |
1871 | * Takes mode config lock. | 2007 | * interface. The only thing it adds is correct refcounting dance. |
2008 | */ | ||
2009 | int drm_mode_set_config_internal(struct drm_mode_set *set) | ||
2010 | { | ||
2011 | struct drm_crtc *crtc = set->crtc; | ||
2012 | struct drm_framebuffer *fb, *old_fb; | ||
2013 | int ret; | ||
2014 | |||
2015 | old_fb = crtc->fb; | ||
2016 | fb = set->fb; | ||
2017 | |||
2018 | ret = crtc->funcs->set_config(set); | ||
2019 | if (ret == 0) { | ||
2020 | if (old_fb) | ||
2021 | drm_framebuffer_unreference(old_fb); | ||
2022 | if (fb) | ||
2023 | drm_framebuffer_reference(fb); | ||
2024 | } | ||
2025 | |||
2026 | return ret; | ||
2027 | } | ||
2028 | EXPORT_SYMBOL(drm_mode_set_config_internal); | ||
2029 | |||
2030 | /** | ||
2031 | * drm_mode_setcrtc - set CRTC configuration | ||
2032 | * @dev: drm device for the ioctl | ||
2033 | * @data: data pointer for the ioctl | ||
2034 | * @file_priv: drm file for the ioctl call | ||
1872 | * | 2035 | * |
1873 | * Build a new CRTC configuration based on user request. | 2036 | * Build a new CRTC configuration based on user request. |
1874 | * | 2037 | * |
@@ -1899,7 +2062,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
1899 | if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) | 2062 | if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) |
1900 | return -ERANGE; | 2063 | return -ERANGE; |
1901 | 2064 | ||
1902 | mutex_lock(&dev->mode_config.mutex); | 2065 | drm_modeset_lock_all(dev); |
1903 | obj = drm_mode_object_find(dev, crtc_req->crtc_id, | 2066 | obj = drm_mode_object_find(dev, crtc_req->crtc_id, |
1904 | DRM_MODE_OBJECT_CRTC); | 2067 | DRM_MODE_OBJECT_CRTC); |
1905 | if (!obj) { | 2068 | if (!obj) { |
@@ -1921,16 +2084,16 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
1921 | goto out; | 2084 | goto out; |
1922 | } | 2085 | } |
1923 | fb = crtc->fb; | 2086 | fb = crtc->fb; |
2087 | /* Make refcounting symmetric with the lookup path. */ | ||
2088 | drm_framebuffer_reference(fb); | ||
1924 | } else { | 2089 | } else { |
1925 | obj = drm_mode_object_find(dev, crtc_req->fb_id, | 2090 | fb = drm_framebuffer_lookup(dev, crtc_req->fb_id); |
1926 | DRM_MODE_OBJECT_FB); | 2091 | if (!fb) { |
1927 | if (!obj) { | ||
1928 | DRM_DEBUG_KMS("Unknown FB ID%d\n", | 2092 | DRM_DEBUG_KMS("Unknown FB ID%d\n", |
1929 | crtc_req->fb_id); | 2093 | crtc_req->fb_id); |
1930 | ret = -EINVAL; | 2094 | ret = -EINVAL; |
1931 | goto out; | 2095 | goto out; |
1932 | } | 2096 | } |
1933 | fb = obj_to_fb(obj); | ||
1934 | } | 2097 | } |
1935 | 2098 | ||
1936 | mode = drm_mode_create(dev); | 2099 | mode = drm_mode_create(dev); |
@@ -2027,12 +2190,15 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2027 | set.connectors = connector_set; | 2190 | set.connectors = connector_set; |
2028 | set.num_connectors = crtc_req->count_connectors; | 2191 | set.num_connectors = crtc_req->count_connectors; |
2029 | set.fb = fb; | 2192 | set.fb = fb; |
2030 | ret = crtc->funcs->set_config(&set); | 2193 | ret = drm_mode_set_config_internal(&set); |
2031 | 2194 | ||
2032 | out: | 2195 | out: |
2196 | if (fb) | ||
2197 | drm_framebuffer_unreference(fb); | ||
2198 | |||
2033 | kfree(connector_set); | 2199 | kfree(connector_set); |
2034 | drm_mode_destroy(dev, mode); | 2200 | drm_mode_destroy(dev, mode); |
2035 | mutex_unlock(&dev->mode_config.mutex); | 2201 | drm_modeset_unlock_all(dev); |
2036 | return ret; | 2202 | return ret; |
2037 | } | 2203 | } |
2038 | 2204 | ||
@@ -2050,15 +2216,14 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, | |||
2050 | if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) | 2216 | if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) |
2051 | return -EINVAL; | 2217 | return -EINVAL; |
2052 | 2218 | ||
2053 | mutex_lock(&dev->mode_config.mutex); | ||
2054 | obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); | 2219 | obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); |
2055 | if (!obj) { | 2220 | if (!obj) { |
2056 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); | 2221 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); |
2057 | ret = -EINVAL; | 2222 | return -EINVAL; |
2058 | goto out; | ||
2059 | } | 2223 | } |
2060 | crtc = obj_to_crtc(obj); | 2224 | crtc = obj_to_crtc(obj); |
2061 | 2225 | ||
2226 | mutex_lock(&crtc->mutex); | ||
2062 | if (req->flags & DRM_MODE_CURSOR_BO) { | 2227 | if (req->flags & DRM_MODE_CURSOR_BO) { |
2063 | if (!crtc->funcs->cursor_set) { | 2228 | if (!crtc->funcs->cursor_set) { |
2064 | ret = -ENXIO; | 2229 | ret = -ENXIO; |
@@ -2078,7 +2243,8 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, | |||
2078 | } | 2243 | } |
2079 | } | 2244 | } |
2080 | out: | 2245 | out: |
2081 | mutex_unlock(&dev->mode_config.mutex); | 2246 | mutex_unlock(&crtc->mutex); |
2247 | |||
2082 | return ret; | 2248 | return ret; |
2083 | } | 2249 | } |
2084 | 2250 | ||
@@ -2089,7 +2255,7 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) | |||
2089 | 2255 | ||
2090 | switch (bpp) { | 2256 | switch (bpp) { |
2091 | case 8: | 2257 | case 8: |
2092 | fmt = DRM_FORMAT_RGB332; | 2258 | fmt = DRM_FORMAT_C8; |
2093 | break; | 2259 | break; |
2094 | case 16: | 2260 | case 16: |
2095 | if (depth == 15) | 2261 | if (depth == 15) |
@@ -2120,13 +2286,9 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format); | |||
2120 | 2286 | ||
2121 | /** | 2287 | /** |
2122 | * drm_mode_addfb - add an FB to the graphics configuration | 2288 | * drm_mode_addfb - add an FB to the graphics configuration |
2123 | * @inode: inode from the ioctl | 2289 | * @dev: drm device for the ioctl |
2124 | * @filp: file * from the ioctl | 2290 | * @data: data pointer for the ioctl |
2125 | * @cmd: cmd from ioctl | 2291 | * @file_priv: drm file for the ioctl call |
2126 | * @arg: arg from ioctl | ||
2127 | * | ||
2128 | * LOCKING: | ||
2129 | * Takes mode config lock. | ||
2130 | * | 2292 | * |
2131 | * Add a new FB to the specified CRTC, given a user request. | 2293 | * Add a new FB to the specified CRTC, given a user request. |
2132 | * | 2294 | * |
@@ -2161,24 +2323,19 @@ int drm_mode_addfb(struct drm_device *dev, | |||
2161 | if ((config->min_height > r.height) || (r.height > config->max_height)) | 2323 | if ((config->min_height > r.height) || (r.height > config->max_height)) |
2162 | return -EINVAL; | 2324 | return -EINVAL; |
2163 | 2325 | ||
2164 | mutex_lock(&dev->mode_config.mutex); | ||
2165 | |||
2166 | /* TODO check buffer is sufficiently large */ | ||
2167 | /* TODO setup destructor callback */ | ||
2168 | |||
2169 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); | 2326 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); |
2170 | if (IS_ERR(fb)) { | 2327 | if (IS_ERR(fb)) { |
2171 | DRM_DEBUG_KMS("could not create framebuffer\n"); | 2328 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
2172 | ret = PTR_ERR(fb); | 2329 | drm_modeset_unlock_all(dev); |
2173 | goto out; | 2330 | return PTR_ERR(fb); |
2174 | } | 2331 | } |
2175 | 2332 | ||
2333 | mutex_lock(&file_priv->fbs_lock); | ||
2176 | or->fb_id = fb->base.id; | 2334 | or->fb_id = fb->base.id; |
2177 | list_add(&fb->filp_head, &file_priv->fbs); | 2335 | list_add(&fb->filp_head, &file_priv->fbs); |
2178 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | 2336 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
2337 | mutex_unlock(&file_priv->fbs_lock); | ||
2179 | 2338 | ||
2180 | out: | ||
2181 | mutex_unlock(&dev->mode_config.mutex); | ||
2182 | return ret; | 2339 | return ret; |
2183 | } | 2340 | } |
2184 | 2341 | ||
@@ -2304,13 +2461,9 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | |||
2304 | 2461 | ||
2305 | /** | 2462 | /** |
2306 | * drm_mode_addfb2 - add an FB to the graphics configuration | 2463 | * drm_mode_addfb2 - add an FB to the graphics configuration |
2307 | * @inode: inode from the ioctl | 2464 | * @dev: drm device for the ioctl |
2308 | * @filp: file * from the ioctl | 2465 | * @data: data pointer for the ioctl |
2309 | * @cmd: cmd from ioctl | 2466 | * @file_priv: drm file for the ioctl call |
2310 | * @arg: arg from ioctl | ||
2311 | * | ||
2312 | * LOCKING: | ||
2313 | * Takes mode config lock. | ||
2314 | * | 2467 | * |
2315 | * Add a new FB to the specified CRTC, given a user request with format. | 2468 | * Add a new FB to the specified CRTC, given a user request with format. |
2316 | * | 2469 | * |
@@ -2350,33 +2503,28 @@ int drm_mode_addfb2(struct drm_device *dev, | |||
2350 | if (ret) | 2503 | if (ret) |
2351 | return ret; | 2504 | return ret; |
2352 | 2505 | ||
2353 | mutex_lock(&dev->mode_config.mutex); | ||
2354 | |||
2355 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); | 2506 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
2356 | if (IS_ERR(fb)) { | 2507 | if (IS_ERR(fb)) { |
2357 | DRM_DEBUG_KMS("could not create framebuffer\n"); | 2508 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
2358 | ret = PTR_ERR(fb); | 2509 | drm_modeset_unlock_all(dev); |
2359 | goto out; | 2510 | return PTR_ERR(fb); |
2360 | } | 2511 | } |
2361 | 2512 | ||
2513 | mutex_lock(&file_priv->fbs_lock); | ||
2362 | r->fb_id = fb->base.id; | 2514 | r->fb_id = fb->base.id; |
2363 | list_add(&fb->filp_head, &file_priv->fbs); | 2515 | list_add(&fb->filp_head, &file_priv->fbs); |
2364 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | 2516 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
2517 | mutex_unlock(&file_priv->fbs_lock); | ||
2518 | |||
2365 | 2519 | ||
2366 | out: | ||
2367 | mutex_unlock(&dev->mode_config.mutex); | ||
2368 | return ret; | 2520 | return ret; |
2369 | } | 2521 | } |
2370 | 2522 | ||
2371 | /** | 2523 | /** |
2372 | * drm_mode_rmfb - remove an FB from the configuration | 2524 | * drm_mode_rmfb - remove an FB from the configuration |
2373 | * @inode: inode from the ioctl | 2525 | * @dev: drm device for the ioctl |
2374 | * @filp: file * from the ioctl | 2526 | * @data: data pointer for the ioctl |
2375 | * @cmd: cmd from ioctl | 2527 | * @file_priv: drm file for the ioctl call |
2376 | * @arg: arg from ioctl | ||
2377 | * | ||
2378 | * LOCKING: | ||
2379 | * Takes mode config lock. | ||
2380 | * | 2528 | * |
2381 | * Remove the FB specified by the user. | 2529 | * Remove the FB specified by the user. |
2382 | * | 2530 | * |
@@ -2388,50 +2536,49 @@ out: | |||
2388 | int drm_mode_rmfb(struct drm_device *dev, | 2536 | int drm_mode_rmfb(struct drm_device *dev, |
2389 | void *data, struct drm_file *file_priv) | 2537 | void *data, struct drm_file *file_priv) |
2390 | { | 2538 | { |
2391 | struct drm_mode_object *obj; | ||
2392 | struct drm_framebuffer *fb = NULL; | 2539 | struct drm_framebuffer *fb = NULL; |
2393 | struct drm_framebuffer *fbl = NULL; | 2540 | struct drm_framebuffer *fbl = NULL; |
2394 | uint32_t *id = data; | 2541 | uint32_t *id = data; |
2395 | int ret = 0; | ||
2396 | int found = 0; | 2542 | int found = 0; |
2397 | 2543 | ||
2398 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2544 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2399 | return -EINVAL; | 2545 | return -EINVAL; |
2400 | 2546 | ||
2401 | mutex_lock(&dev->mode_config.mutex); | 2547 | mutex_lock(&file_priv->fbs_lock); |
2402 | obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); | 2548 | mutex_lock(&dev->mode_config.fb_lock); |
2403 | /* TODO check that we really get a framebuffer back. */ | 2549 | fb = __drm_framebuffer_lookup(dev, *id); |
2404 | if (!obj) { | 2550 | if (!fb) |
2405 | ret = -EINVAL; | 2551 | goto fail_lookup; |
2406 | goto out; | ||
2407 | } | ||
2408 | fb = obj_to_fb(obj); | ||
2409 | 2552 | ||
2410 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) | 2553 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) |
2411 | if (fb == fbl) | 2554 | if (fb == fbl) |
2412 | found = 1; | 2555 | found = 1; |
2556 | if (!found) | ||
2557 | goto fail_lookup; | ||
2413 | 2558 | ||
2414 | if (!found) { | 2559 | /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ |
2415 | ret = -EINVAL; | 2560 | __drm_framebuffer_unregister(dev, fb); |
2416 | goto out; | 2561 | |
2417 | } | 2562 | list_del_init(&fb->filp_head); |
2563 | mutex_unlock(&dev->mode_config.fb_lock); | ||
2564 | mutex_unlock(&file_priv->fbs_lock); | ||
2418 | 2565 | ||
2419 | drm_framebuffer_remove(fb); | 2566 | drm_framebuffer_remove(fb); |
2420 | 2567 | ||
2421 | out: | 2568 | return 0; |
2422 | mutex_unlock(&dev->mode_config.mutex); | 2569 | |
2423 | return ret; | 2570 | fail_lookup: |
2571 | mutex_unlock(&dev->mode_config.fb_lock); | ||
2572 | mutex_unlock(&file_priv->fbs_lock); | ||
2573 | |||
2574 | return -EINVAL; | ||
2424 | } | 2575 | } |
2425 | 2576 | ||
2426 | /** | 2577 | /** |
2427 | * drm_mode_getfb - get FB info | 2578 | * drm_mode_getfb - get FB info |
2428 | * @inode: inode from the ioctl | 2579 | * @dev: drm device for the ioctl |
2429 | * @filp: file * from the ioctl | 2580 | * @data: data pointer for the ioctl |
2430 | * @cmd: cmd from ioctl | 2581 | * @file_priv: drm file for the ioctl call |
2431 | * @arg: arg from ioctl | ||
2432 | * | ||
2433 | * LOCKING: | ||
2434 | * Takes mode config lock. | ||
2435 | * | 2582 | * |
2436 | * Lookup the FB given its ID and return info about it. | 2583 | * Lookup the FB given its ID and return info about it. |
2437 | * | 2584 | * |
@@ -2444,30 +2591,28 @@ int drm_mode_getfb(struct drm_device *dev, | |||
2444 | void *data, struct drm_file *file_priv) | 2591 | void *data, struct drm_file *file_priv) |
2445 | { | 2592 | { |
2446 | struct drm_mode_fb_cmd *r = data; | 2593 | struct drm_mode_fb_cmd *r = data; |
2447 | struct drm_mode_object *obj; | ||
2448 | struct drm_framebuffer *fb; | 2594 | struct drm_framebuffer *fb; |
2449 | int ret = 0; | 2595 | int ret; |
2450 | 2596 | ||
2451 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2597 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2452 | return -EINVAL; | 2598 | return -EINVAL; |
2453 | 2599 | ||
2454 | mutex_lock(&dev->mode_config.mutex); | 2600 | fb = drm_framebuffer_lookup(dev, r->fb_id); |
2455 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); | 2601 | if (!fb) |
2456 | if (!obj) { | 2602 | return -EINVAL; |
2457 | ret = -EINVAL; | ||
2458 | goto out; | ||
2459 | } | ||
2460 | fb = obj_to_fb(obj); | ||
2461 | 2603 | ||
2462 | r->height = fb->height; | 2604 | r->height = fb->height; |
2463 | r->width = fb->width; | 2605 | r->width = fb->width; |
2464 | r->depth = fb->depth; | 2606 | r->depth = fb->depth; |
2465 | r->bpp = fb->bits_per_pixel; | 2607 | r->bpp = fb->bits_per_pixel; |
2466 | r->pitch = fb->pitches[0]; | 2608 | r->pitch = fb->pitches[0]; |
2467 | fb->funcs->create_handle(fb, file_priv, &r->handle); | 2609 | if (fb->funcs->create_handle) |
2610 | ret = fb->funcs->create_handle(fb, file_priv, &r->handle); | ||
2611 | else | ||
2612 | ret = -ENODEV; | ||
2613 | |||
2614 | drm_framebuffer_unreference(fb); | ||
2468 | 2615 | ||
2469 | out: | ||
2470 | mutex_unlock(&dev->mode_config.mutex); | ||
2471 | return ret; | 2616 | return ret; |
2472 | } | 2617 | } |
2473 | 2618 | ||
@@ -2477,7 +2622,6 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | |||
2477 | struct drm_clip_rect __user *clips_ptr; | 2622 | struct drm_clip_rect __user *clips_ptr; |
2478 | struct drm_clip_rect *clips = NULL; | 2623 | struct drm_clip_rect *clips = NULL; |
2479 | struct drm_mode_fb_dirty_cmd *r = data; | 2624 | struct drm_mode_fb_dirty_cmd *r = data; |
2480 | struct drm_mode_object *obj; | ||
2481 | struct drm_framebuffer *fb; | 2625 | struct drm_framebuffer *fb; |
2482 | unsigned flags; | 2626 | unsigned flags; |
2483 | int num_clips; | 2627 | int num_clips; |
@@ -2486,13 +2630,9 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | |||
2486 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2630 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2487 | return -EINVAL; | 2631 | return -EINVAL; |
2488 | 2632 | ||
2489 | mutex_lock(&dev->mode_config.mutex); | 2633 | fb = drm_framebuffer_lookup(dev, r->fb_id); |
2490 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); | 2634 | if (!fb) |
2491 | if (!obj) { | 2635 | return -EINVAL; |
2492 | ret = -EINVAL; | ||
2493 | goto out_err1; | ||
2494 | } | ||
2495 | fb = obj_to_fb(obj); | ||
2496 | 2636 | ||
2497 | num_clips = r->num_clips; | 2637 | num_clips = r->num_clips; |
2498 | clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; | 2638 | clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; |
@@ -2530,27 +2670,26 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | |||
2530 | } | 2670 | } |
2531 | 2671 | ||
2532 | if (fb->funcs->dirty) { | 2672 | if (fb->funcs->dirty) { |
2673 | drm_modeset_lock_all(dev); | ||
2533 | ret = fb->funcs->dirty(fb, file_priv, flags, r->color, | 2674 | ret = fb->funcs->dirty(fb, file_priv, flags, r->color, |
2534 | clips, num_clips); | 2675 | clips, num_clips); |
2676 | drm_modeset_unlock_all(dev); | ||
2535 | } else { | 2677 | } else { |
2536 | ret = -ENOSYS; | 2678 | ret = -ENOSYS; |
2537 | goto out_err2; | ||
2538 | } | 2679 | } |
2539 | 2680 | ||
2540 | out_err2: | 2681 | out_err2: |
2541 | kfree(clips); | 2682 | kfree(clips); |
2542 | out_err1: | 2683 | out_err1: |
2543 | mutex_unlock(&dev->mode_config.mutex); | 2684 | drm_framebuffer_unreference(fb); |
2685 | |||
2544 | return ret; | 2686 | return ret; |
2545 | } | 2687 | } |
2546 | 2688 | ||
2547 | 2689 | ||
2548 | /** | 2690 | /** |
2549 | * drm_fb_release - remove and free the FBs on this file | 2691 | * drm_fb_release - remove and free the FBs on this file |
2550 | * @filp: file * from the ioctl | 2692 | * @priv: drm file for the ioctl |
2551 | * | ||
2552 | * LOCKING: | ||
2553 | * Takes mode config lock. | ||
2554 | * | 2693 | * |
2555 | * Destroy all the FBs associated with @filp. | 2694 | * Destroy all the FBs associated with @filp. |
2556 | * | 2695 | * |
@@ -2564,11 +2703,20 @@ void drm_fb_release(struct drm_file *priv) | |||
2564 | struct drm_device *dev = priv->minor->dev; | 2703 | struct drm_device *dev = priv->minor->dev; |
2565 | struct drm_framebuffer *fb, *tfb; | 2704 | struct drm_framebuffer *fb, *tfb; |
2566 | 2705 | ||
2567 | mutex_lock(&dev->mode_config.mutex); | 2706 | mutex_lock(&priv->fbs_lock); |
2568 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { | 2707 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
2708 | |||
2709 | mutex_lock(&dev->mode_config.fb_lock); | ||
2710 | /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ | ||
2711 | __drm_framebuffer_unregister(dev, fb); | ||
2712 | mutex_unlock(&dev->mode_config.fb_lock); | ||
2713 | |||
2714 | list_del_init(&fb->filp_head); | ||
2715 | |||
2716 | /* This will also drop the fpriv->fbs reference. */ | ||
2569 | drm_framebuffer_remove(fb); | 2717 | drm_framebuffer_remove(fb); |
2570 | } | 2718 | } |
2571 | mutex_unlock(&dev->mode_config.mutex); | 2719 | mutex_unlock(&priv->fbs_lock); |
2572 | } | 2720 | } |
2573 | 2721 | ||
2574 | /** | 2722 | /** |
@@ -2660,10 +2808,9 @@ EXPORT_SYMBOL(drm_mode_detachmode_crtc); | |||
2660 | 2808 | ||
2661 | /** | 2809 | /** |
2662 | * drm_fb_attachmode - Attach a user mode to an connector | 2810 | * drm_fb_attachmode - Attach a user mode to an connector |
2663 | * @inode: inode from the ioctl | 2811 | * @dev: drm device for the ioctl |
2664 | * @filp: file * from the ioctl | 2812 | * @data: data pointer for the ioctl |
2665 | * @cmd: cmd from ioctl | 2813 | * @file_priv: drm file for the ioctl call |
2666 | * @arg: arg from ioctl | ||
2667 | * | 2814 | * |
2668 | * This attaches a user specified mode to an connector. | 2815 | * This attaches a user specified mode to an connector. |
2669 | * Called by the user via ioctl. | 2816 | * Called by the user via ioctl. |
@@ -2684,7 +2831,7 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, | |||
2684 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2831 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2685 | return -EINVAL; | 2832 | return -EINVAL; |
2686 | 2833 | ||
2687 | mutex_lock(&dev->mode_config.mutex); | 2834 | drm_modeset_lock_all(dev); |
2688 | 2835 | ||
2689 | obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); | 2836 | obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); |
2690 | if (!obj) { | 2837 | if (!obj) { |
@@ -2708,17 +2855,16 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, | |||
2708 | 2855 | ||
2709 | drm_mode_attachmode(dev, connector, mode); | 2856 | drm_mode_attachmode(dev, connector, mode); |
2710 | out: | 2857 | out: |
2711 | mutex_unlock(&dev->mode_config.mutex); | 2858 | drm_modeset_unlock_all(dev); |
2712 | return ret; | 2859 | return ret; |
2713 | } | 2860 | } |
2714 | 2861 | ||
2715 | 2862 | ||
2716 | /** | 2863 | /** |
2717 | * drm_fb_detachmode - Detach a user specified mode from an connector | 2864 | * drm_fb_detachmode - Detach a user specified mode from an connector |
2718 | * @inode: inode from the ioctl | 2865 | * @dev: drm device for the ioctl |
2719 | * @filp: file * from the ioctl | 2866 | * @data: data pointer for the ioctl |
2720 | * @cmd: cmd from ioctl | 2867 | * @file_priv: drm file for the ioctl call |
2721 | * @arg: arg from ioctl | ||
2722 | * | 2868 | * |
2723 | * Called by the user via ioctl. | 2869 | * Called by the user via ioctl. |
2724 | * | 2870 | * |
@@ -2738,7 +2884,7 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, | |||
2738 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2884 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2739 | return -EINVAL; | 2885 | return -EINVAL; |
2740 | 2886 | ||
2741 | mutex_lock(&dev->mode_config.mutex); | 2887 | drm_modeset_lock_all(dev); |
2742 | 2888 | ||
2743 | obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); | 2889 | obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); |
2744 | if (!obj) { | 2890 | if (!obj) { |
@@ -2755,7 +2901,7 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, | |||
2755 | 2901 | ||
2756 | ret = drm_mode_detachmode(dev, connector, &mode); | 2902 | ret = drm_mode_detachmode(dev, connector, &mode); |
2757 | out: | 2903 | out: |
2758 | mutex_unlock(&dev->mode_config.mutex); | 2904 | drm_modeset_unlock_all(dev); |
2759 | return ret; | 2905 | return ret; |
2760 | } | 2906 | } |
2761 | 2907 | ||
@@ -3001,7 +3147,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3001 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3147 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3002 | return -EINVAL; | 3148 | return -EINVAL; |
3003 | 3149 | ||
3004 | mutex_lock(&dev->mode_config.mutex); | 3150 | drm_modeset_lock_all(dev); |
3005 | obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); | 3151 | obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); |
3006 | if (!obj) { | 3152 | if (!obj) { |
3007 | ret = -EINVAL; | 3153 | ret = -EINVAL; |
@@ -3079,7 +3225,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3079 | out_resp->count_enum_blobs = blob_count; | 3225 | out_resp->count_enum_blobs = blob_count; |
3080 | } | 3226 | } |
3081 | done: | 3227 | done: |
3082 | mutex_unlock(&dev->mode_config.mutex); | 3228 | drm_modeset_unlock_all(dev); |
3083 | return ret; | 3229 | return ret; |
3084 | } | 3230 | } |
3085 | 3231 | ||
@@ -3130,7 +3276,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, | |||
3130 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3276 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3131 | return -EINVAL; | 3277 | return -EINVAL; |
3132 | 3278 | ||
3133 | mutex_lock(&dev->mode_config.mutex); | 3279 | drm_modeset_lock_all(dev); |
3134 | obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); | 3280 | obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); |
3135 | if (!obj) { | 3281 | if (!obj) { |
3136 | ret = -EINVAL; | 3282 | ret = -EINVAL; |
@@ -3148,7 +3294,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, | |||
3148 | out_resp->length = blob->length; | 3294 | out_resp->length = blob->length; |
3149 | 3295 | ||
3150 | done: | 3296 | done: |
3151 | mutex_unlock(&dev->mode_config.mutex); | 3297 | drm_modeset_unlock_all(dev); |
3152 | return ret; | 3298 | return ret; |
3153 | } | 3299 | } |
3154 | 3300 | ||
@@ -3290,7 +3436,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | |||
3290 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3436 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3291 | return -EINVAL; | 3437 | return -EINVAL; |
3292 | 3438 | ||
3293 | mutex_lock(&dev->mode_config.mutex); | 3439 | drm_modeset_lock_all(dev); |
3294 | 3440 | ||
3295 | obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); | 3441 | obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); |
3296 | if (!obj) { | 3442 | if (!obj) { |
@@ -3327,7 +3473,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | |||
3327 | } | 3473 | } |
3328 | arg->count_props = props_count; | 3474 | arg->count_props = props_count; |
3329 | out: | 3475 | out: |
3330 | mutex_unlock(&dev->mode_config.mutex); | 3476 | drm_modeset_unlock_all(dev); |
3331 | return ret; | 3477 | return ret; |
3332 | } | 3478 | } |
3333 | 3479 | ||
@@ -3344,7 +3490,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
3344 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3490 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3345 | return -EINVAL; | 3491 | return -EINVAL; |
3346 | 3492 | ||
3347 | mutex_lock(&dev->mode_config.mutex); | 3493 | drm_modeset_lock_all(dev); |
3348 | 3494 | ||
3349 | arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); | 3495 | arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); |
3350 | if (!arg_obj) | 3496 | if (!arg_obj) |
@@ -3382,7 +3528,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
3382 | } | 3528 | } |
3383 | 3529 | ||
3384 | out: | 3530 | out: |
3385 | mutex_unlock(&dev->mode_config.mutex); | 3531 | drm_modeset_unlock_all(dev); |
3386 | return ret; | 3532 | return ret; |
3387 | } | 3533 | } |
3388 | 3534 | ||
@@ -3444,7 +3590,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
3444 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3590 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3445 | return -EINVAL; | 3591 | return -EINVAL; |
3446 | 3592 | ||
3447 | mutex_lock(&dev->mode_config.mutex); | 3593 | drm_modeset_lock_all(dev); |
3448 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); | 3594 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
3449 | if (!obj) { | 3595 | if (!obj) { |
3450 | ret = -EINVAL; | 3596 | ret = -EINVAL; |
@@ -3485,7 +3631,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
3485 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); | 3631 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); |
3486 | 3632 | ||
3487 | out: | 3633 | out: |
3488 | mutex_unlock(&dev->mode_config.mutex); | 3634 | drm_modeset_unlock_all(dev); |
3489 | return ret; | 3635 | return ret; |
3490 | 3636 | ||
3491 | } | 3637 | } |
@@ -3503,7 +3649,7 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, | |||
3503 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3649 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3504 | return -EINVAL; | 3650 | return -EINVAL; |
3505 | 3651 | ||
3506 | mutex_lock(&dev->mode_config.mutex); | 3652 | drm_modeset_lock_all(dev); |
3507 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); | 3653 | obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
3508 | if (!obj) { | 3654 | if (!obj) { |
3509 | ret = -EINVAL; | 3655 | ret = -EINVAL; |
@@ -3536,7 +3682,7 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, | |||
3536 | goto out; | 3682 | goto out; |
3537 | } | 3683 | } |
3538 | out: | 3684 | out: |
3539 | mutex_unlock(&dev->mode_config.mutex); | 3685 | drm_modeset_unlock_all(dev); |
3540 | return ret; | 3686 | return ret; |
3541 | } | 3687 | } |
3542 | 3688 | ||
@@ -3546,7 +3692,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3546 | struct drm_mode_crtc_page_flip *page_flip = data; | 3692 | struct drm_mode_crtc_page_flip *page_flip = data; |
3547 | struct drm_mode_object *obj; | 3693 | struct drm_mode_object *obj; |
3548 | struct drm_crtc *crtc; | 3694 | struct drm_crtc *crtc; |
3549 | struct drm_framebuffer *fb; | 3695 | struct drm_framebuffer *fb = NULL, *old_fb = NULL; |
3550 | struct drm_pending_vblank_event *e = NULL; | 3696 | struct drm_pending_vblank_event *e = NULL; |
3551 | unsigned long flags; | 3697 | unsigned long flags; |
3552 | int hdisplay, vdisplay; | 3698 | int hdisplay, vdisplay; |
@@ -3556,12 +3702,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3556 | page_flip->reserved != 0) | 3702 | page_flip->reserved != 0) |
3557 | return -EINVAL; | 3703 | return -EINVAL; |
3558 | 3704 | ||
3559 | mutex_lock(&dev->mode_config.mutex); | ||
3560 | obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); | 3705 | obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); |
3561 | if (!obj) | 3706 | if (!obj) |
3562 | goto out; | 3707 | return -EINVAL; |
3563 | crtc = obj_to_crtc(obj); | 3708 | crtc = obj_to_crtc(obj); |
3564 | 3709 | ||
3710 | mutex_lock(&crtc->mutex); | ||
3565 | if (crtc->fb == NULL) { | 3711 | if (crtc->fb == NULL) { |
3566 | /* The framebuffer is currently unbound, presumably | 3712 | /* The framebuffer is currently unbound, presumably |
3567 | * due to a hotplug event, that userspace has not | 3713 | * due to a hotplug event, that userspace has not |
@@ -3574,10 +3720,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3574 | if (crtc->funcs->page_flip == NULL) | 3720 | if (crtc->funcs->page_flip == NULL) |
3575 | goto out; | 3721 | goto out; |
3576 | 3722 | ||
3577 | obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); | 3723 | fb = drm_framebuffer_lookup(dev, page_flip->fb_id); |
3578 | if (!obj) | 3724 | if (!fb) |
3579 | goto out; | 3725 | goto out; |
3580 | fb = obj_to_fb(obj); | ||
3581 | 3726 | ||
3582 | hdisplay = crtc->mode.hdisplay; | 3727 | hdisplay = crtc->mode.hdisplay; |
3583 | vdisplay = crtc->mode.vdisplay; | 3728 | vdisplay = crtc->mode.vdisplay; |
@@ -3623,6 +3768,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3623 | (void (*) (struct drm_pending_event *)) kfree; | 3768 | (void (*) (struct drm_pending_event *)) kfree; |
3624 | } | 3769 | } |
3625 | 3770 | ||
3771 | old_fb = crtc->fb; | ||
3626 | ret = crtc->funcs->page_flip(crtc, fb, e); | 3772 | ret = crtc->funcs->page_flip(crtc, fb, e); |
3627 | if (ret) { | 3773 | if (ret) { |
3628 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { | 3774 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { |
@@ -3631,10 +3777,27 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
3631 | spin_unlock_irqrestore(&dev->event_lock, flags); | 3777 | spin_unlock_irqrestore(&dev->event_lock, flags); |
3632 | kfree(e); | 3778 | kfree(e); |
3633 | } | 3779 | } |
3780 | /* Keep the old fb, don't unref it. */ | ||
3781 | old_fb = NULL; | ||
3782 | } else { | ||
3783 | /* | ||
3784 | * Warn if the driver hasn't properly updated the crtc->fb | ||
3785 | * field to reflect that the new framebuffer is now used. | ||
3786 | * Failing to do so will screw with the reference counting | ||
3787 | * on framebuffers. | ||
3788 | */ | ||
3789 | WARN_ON(crtc->fb != fb); | ||
3790 | /* Unref only the old framebuffer. */ | ||
3791 | fb = NULL; | ||
3634 | } | 3792 | } |
3635 | 3793 | ||
3636 | out: | 3794 | out: |
3637 | mutex_unlock(&dev->mode_config.mutex); | 3795 | if (fb) |
3796 | drm_framebuffer_unreference(fb); | ||
3797 | if (old_fb) | ||
3798 | drm_framebuffer_unreference(old_fb); | ||
3799 | mutex_unlock(&crtc->mutex); | ||
3800 | |||
3638 | return ret; | 3801 | return ret; |
3639 | } | 3802 | } |
3640 | 3803 | ||
@@ -3702,6 +3865,7 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, | |||
3702 | int *bpp) | 3865 | int *bpp) |
3703 | { | 3866 | { |
3704 | switch (format) { | 3867 | switch (format) { |
3868 | case DRM_FORMAT_C8: | ||
3705 | case DRM_FORMAT_RGB332: | 3869 | case DRM_FORMAT_RGB332: |
3706 | case DRM_FORMAT_BGR233: | 3870 | case DRM_FORMAT_BGR233: |
3707 | *depth = 8; | 3871 | *depth = 8; |