aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c394
1 files changed, 227 insertions, 167 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 90e773019eac..e79c8d3700d8 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -40,106 +40,12 @@
40#include <drm/drm_modeset_lock.h> 40#include <drm/drm_modeset_lock.h>
41 41
42#include "drm_crtc_internal.h" 42#include "drm_crtc_internal.h"
43#include "drm_internal.h"
43 44
44static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, 45static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
45 struct drm_mode_fb_cmd2 *r, 46 struct drm_mode_fb_cmd2 *r,
46 struct drm_file *file_priv); 47 struct drm_file *file_priv);
47 48
48/**
49 * drm_modeset_lock_all - take all modeset locks
50 * @dev: drm device
51 *
52 * This function takes all modeset locks, suitable where a more fine-grained
53 * scheme isn't (yet) implemented. Locks must be dropped with
54 * drm_modeset_unlock_all.
55 */
56void drm_modeset_lock_all(struct drm_device *dev)
57{
58 struct drm_mode_config *config = &dev->mode_config;
59 struct drm_modeset_acquire_ctx *ctx;
60 int ret;
61
62 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
63 if (WARN_ON(!ctx))
64 return;
65
66 mutex_lock(&config->mutex);
67
68 drm_modeset_acquire_init(ctx, 0);
69
70retry:
71 ret = drm_modeset_lock(&config->connection_mutex, ctx);
72 if (ret)
73 goto fail;
74 ret = drm_modeset_lock_all_crtcs(dev, ctx);
75 if (ret)
76 goto fail;
77
78 WARN_ON(config->acquire_ctx);
79
80 /* now we hold the locks, so now that it is safe, stash the
81 * ctx for drm_modeset_unlock_all():
82 */
83 config->acquire_ctx = ctx;
84
85 drm_warn_on_modeset_not_all_locked(dev);
86
87 return;
88
89fail:
90 if (ret == -EDEADLK) {
91 drm_modeset_backoff(ctx);
92 goto retry;
93 }
94}
95EXPORT_SYMBOL(drm_modeset_lock_all);
96
97/**
98 * drm_modeset_unlock_all - drop all modeset locks
99 * @dev: device
100 *
101 * This function drop all modeset locks taken by drm_modeset_lock_all.
102 */
103void drm_modeset_unlock_all(struct drm_device *dev)
104{
105 struct drm_mode_config *config = &dev->mode_config;
106 struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
107
108 if (WARN_ON(!ctx))
109 return;
110
111 config->acquire_ctx = NULL;
112 drm_modeset_drop_locks(ctx);
113 drm_modeset_acquire_fini(ctx);
114
115 kfree(ctx);
116
117 mutex_unlock(&dev->mode_config.mutex);
118}
119EXPORT_SYMBOL(drm_modeset_unlock_all);
120
121/**
122 * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
123 * @dev: device
124 *
125 * Useful as a debug assert.
126 */
127void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
128{
129 struct drm_crtc *crtc;
130
131 /* Locking is currently fubar in the panic handler. */
132 if (oops_in_progress)
133 return;
134
135 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
136 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
137
138 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
139 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
140}
141EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
142
143/* Avoid boilerplate. I'm tired of typing. */ 49/* Avoid boilerplate. I'm tired of typing. */
144#define DRM_ENUM_NAME_FN(fnname, list) \ 50#define DRM_ENUM_NAME_FN(fnname, list) \
145 const char *fnname(int val) \ 51 const char *fnname(int val) \
@@ -515,9 +421,6 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
515 if (ret) 421 if (ret)
516 goto out; 422 goto out;
517 423
518 /* Grab the idr reference. */
519 drm_framebuffer_reference(fb);
520
521 dev->mode_config.num_fb++; 424 dev->mode_config.num_fb++;
522 list_add(&fb->head, &dev->mode_config.fb_list); 425 list_add(&fb->head, &dev->mode_config.fb_list);
523out: 426out:
@@ -527,10 +430,34 @@ out:
527} 430}
528EXPORT_SYMBOL(drm_framebuffer_init); 431EXPORT_SYMBOL(drm_framebuffer_init);
529 432
433/* dev->mode_config.fb_lock must be held! */
434static void __drm_framebuffer_unregister(struct drm_device *dev,
435 struct drm_framebuffer *fb)
436{
437 mutex_lock(&dev->mode_config.idr_mutex);
438 idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
439 mutex_unlock(&dev->mode_config.idr_mutex);
440
441 fb->base.id = 0;
442}
443
530static void drm_framebuffer_free(struct kref *kref) 444static void drm_framebuffer_free(struct kref *kref)
531{ 445{
532 struct drm_framebuffer *fb = 446 struct drm_framebuffer *fb =
533 container_of(kref, struct drm_framebuffer, refcount); 447 container_of(kref, struct drm_framebuffer, refcount);
448 struct drm_device *dev = fb->dev;
449
450 /*
451 * The lookup idr holds a weak reference, which has not necessarily been
452 * removed at this point. Check for that.
453 */
454 mutex_lock(&dev->mode_config.fb_lock);
455 if (fb->base.id) {
456 /* Mark fb as reaped and drop idr ref. */
457 __drm_framebuffer_unregister(dev, fb);
458 }
459 mutex_unlock(&dev->mode_config.fb_lock);
460
534 fb->funcs->destroy(fb); 461 fb->funcs->destroy(fb);
535} 462}
536 463
@@ -567,8 +494,10 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
567 494
568 mutex_lock(&dev->mode_config.fb_lock); 495 mutex_lock(&dev->mode_config.fb_lock);
569 fb = __drm_framebuffer_lookup(dev, id); 496 fb = __drm_framebuffer_lookup(dev, id);
570 if (fb) 497 if (fb) {
571 drm_framebuffer_reference(fb); 498 if (!kref_get_unless_zero(&fb->refcount))
499 fb = NULL;
500 }
572 mutex_unlock(&dev->mode_config.fb_lock); 501 mutex_unlock(&dev->mode_config.fb_lock);
573 502
574 return fb; 503 return fb;
@@ -612,19 +541,6 @@ static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
612 kref_put(&fb->refcount, drm_framebuffer_free_bug); 541 kref_put(&fb->refcount, drm_framebuffer_free_bug);
613} 542}
614 543
615/* dev->mode_config.fb_lock must be held! */
616static void __drm_framebuffer_unregister(struct drm_device *dev,
617 struct drm_framebuffer *fb)
618{
619 mutex_lock(&dev->mode_config.idr_mutex);
620 idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
621 mutex_unlock(&dev->mode_config.idr_mutex);
622
623 fb->base.id = 0;
624
625 __drm_framebuffer_unreference(fb);
626}
627
628/** 544/**
629 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr 545 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
630 * @fb: fb to unregister 546 * @fb: fb to unregister
@@ -764,11 +680,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
764 crtc->funcs = funcs; 680 crtc->funcs = funcs;
765 crtc->invert_dimensions = false; 681 crtc->invert_dimensions = false;
766 682
767 drm_modeset_lock_all(dev);
768 drm_modeset_lock_init(&crtc->mutex); 683 drm_modeset_lock_init(&crtc->mutex);
769 /* dropped by _unlock_all(): */
770 drm_modeset_lock(&crtc->mutex, config->acquire_ctx);
771
772 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); 684 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
773 if (ret) 685 if (ret)
774 goto out; 686 goto out;
@@ -786,7 +698,6 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
786 cursor->possible_crtcs = 1 << drm_crtc_index(crtc); 698 cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
787 699
788 out: 700 out:
789 drm_modeset_unlock_all(dev);
790 701
791 return ret; 702 return ret;
792} 703}
@@ -853,6 +764,59 @@ static void drm_mode_remove(struct drm_connector *connector,
853} 764}
854 765
855/** 766/**
767 * drm_connector_get_cmdline_mode - reads the user's cmdline mode
768 * @connector: connector to quwery
769 * @mode: returned mode
770 *
771 * The kernel supports per-connector configration of its consoles through
772 * use of the video= parameter. This function parses that option and
773 * extracts the user's specified mode (or enable/disable status) for a
774 * particular connector. This is typically only used during the early fbdev
775 * setup.
776 */
777static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
778{
779 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
780 char *option = NULL;
781
782 if (fb_get_options(connector->name, &option))
783 return;
784
785 if (!drm_mode_parse_command_line_for_connector(option,
786 connector,
787 mode))
788 return;
789
790 if (mode->force) {
791 const char *s;
792
793 switch (mode->force) {
794 case DRM_FORCE_OFF:
795 s = "OFF";
796 break;
797 case DRM_FORCE_ON_DIGITAL:
798 s = "ON - dig";
799 break;
800 default:
801 case DRM_FORCE_ON:
802 s = "ON";
803 break;
804 }
805
806 DRM_INFO("forcing %s connector %s\n", connector->name, s);
807 connector->force = mode->force;
808 }
809
810 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
811 connector->name,
812 mode->xres, mode->yres,
813 mode->refresh_specified ? mode->refresh : 60,
814 mode->rb ? " reduced blanking" : "",
815 mode->margins ? " with margins" : "",
816 mode->interlace ? " interlaced" : "");
817}
818
819/**
856 * drm_connector_init - Init a preallocated connector 820 * drm_connector_init - Init a preallocated connector
857 * @dev: DRM device 821 * @dev: DRM device
858 * @connector: the connector to init 822 * @connector: the connector to init
@@ -904,6 +868,8 @@ int drm_connector_init(struct drm_device *dev,
904 connector->edid_blob_ptr = NULL; 868 connector->edid_blob_ptr = NULL;
905 connector->status = connector_status_unknown; 869 connector->status = connector_status_unknown;
906 870
871 drm_connector_get_cmdline_mode(connector);
872
907 list_add_tail(&connector->head, &dev->mode_config.connector_list); 873 list_add_tail(&connector->head, &dev->mode_config.connector_list);
908 dev->mode_config.num_connector++; 874 dev->mode_config.num_connector++;
909 875
@@ -957,6 +923,29 @@ void drm_connector_cleanup(struct drm_connector *connector)
957EXPORT_SYMBOL(drm_connector_cleanup); 923EXPORT_SYMBOL(drm_connector_cleanup);
958 924
959/** 925/**
926 * drm_connector_index - find the index of a registered connector
927 * @connector: connector to find index for
928 *
929 * Given a registered connector, return the index of that connector within a DRM
930 * device's list of connectors.
931 */
932unsigned int drm_connector_index(struct drm_connector *connector)
933{
934 unsigned int index = 0;
935 struct drm_connector *tmp;
936
937 list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
938 if (tmp == connector)
939 return index;
940
941 index++;
942 }
943
944 BUG();
945}
946EXPORT_SYMBOL(drm_connector_index);
947
948/**
960 * drm_connector_register - register a connector 949 * drm_connector_register - register a connector
961 * @connector: the connector to register 950 * @connector: the connector to register
962 * 951 *
@@ -1261,6 +1250,29 @@ void drm_plane_cleanup(struct drm_plane *plane)
1261EXPORT_SYMBOL(drm_plane_cleanup); 1250EXPORT_SYMBOL(drm_plane_cleanup);
1262 1251
1263/** 1252/**
1253 * drm_plane_index - find the index of a registered plane
1254 * @plane: plane to find index for
1255 *
1256 * Given a registered plane, return the index of that CRTC within a DRM
1257 * device's list of planes.
1258 */
1259unsigned int drm_plane_index(struct drm_plane *plane)
1260{
1261 unsigned int index = 0;
1262 struct drm_plane *tmp;
1263
1264 list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
1265 if (tmp == plane)
1266 return index;
1267
1268 index++;
1269 }
1270
1271 BUG();
1272}
1273EXPORT_SYMBOL(drm_plane_index);
1274
1275/**
1264 * drm_plane_force_disable - Forcibly disable a plane 1276 * drm_plane_force_disable - Forcibly disable a plane
1265 * @plane: plane to disable 1277 * @plane: plane to disable
1266 * 1278 *
@@ -1271,19 +1283,21 @@ EXPORT_SYMBOL(drm_plane_cleanup);
1271 */ 1283 */
1272void drm_plane_force_disable(struct drm_plane *plane) 1284void drm_plane_force_disable(struct drm_plane *plane)
1273{ 1285{
1274 struct drm_framebuffer *old_fb = plane->fb;
1275 int ret; 1286 int ret;
1276 1287
1277 if (!old_fb) 1288 if (!plane->fb)
1278 return; 1289 return;
1279 1290
1291 plane->old_fb = plane->fb;
1280 ret = plane->funcs->disable_plane(plane); 1292 ret = plane->funcs->disable_plane(plane);
1281 if (ret) { 1293 if (ret) {
1282 DRM_ERROR("failed to disable plane with busy fb\n"); 1294 DRM_ERROR("failed to disable plane with busy fb\n");
1295 plane->old_fb = NULL;
1283 return; 1296 return;
1284 } 1297 }
1285 /* disconnect the plane from the fb and crtc: */ 1298 /* disconnect the plane from the fb and crtc: */
1286 __drm_framebuffer_unreference(old_fb); 1299 __drm_framebuffer_unreference(plane->old_fb);
1300 plane->old_fb = NULL;
1287 plane->fb = NULL; 1301 plane->fb = NULL;
1288 plane->crtc = NULL; 1302 plane->crtc = NULL;
1289} 1303}
@@ -2249,33 +2263,29 @@ out:
2249 * 2263 *
2250 * src_{x,y,w,h} are provided in 16.16 fixed point format 2264 * src_{x,y,w,h} are provided in 16.16 fixed point format
2251 */ 2265 */
2252static int setplane_internal(struct drm_plane *plane, 2266static int __setplane_internal(struct drm_plane *plane,
2253 struct drm_crtc *crtc, 2267 struct drm_crtc *crtc,
2254 struct drm_framebuffer *fb, 2268 struct drm_framebuffer *fb,
2255 int32_t crtc_x, int32_t crtc_y, 2269 int32_t crtc_x, int32_t crtc_y,
2256 uint32_t crtc_w, uint32_t crtc_h, 2270 uint32_t crtc_w, uint32_t crtc_h,
2257 /* src_{x,y,w,h} values are 16.16 fixed point */ 2271 /* src_{x,y,w,h} values are 16.16 fixed point */
2258 uint32_t src_x, uint32_t src_y, 2272 uint32_t src_x, uint32_t src_y,
2259 uint32_t src_w, uint32_t src_h) 2273 uint32_t src_w, uint32_t src_h)
2260{ 2274{
2261 struct drm_device *dev = plane->dev;
2262 struct drm_framebuffer *old_fb = NULL;
2263 int ret = 0; 2275 int ret = 0;
2264 unsigned int fb_width, fb_height; 2276 unsigned int fb_width, fb_height;
2265 int i; 2277 int i;
2266 2278
2267 /* No fb means shut it down */ 2279 /* No fb means shut it down */
2268 if (!fb) { 2280 if (!fb) {
2269 drm_modeset_lock_all(dev); 2281 plane->old_fb = plane->fb;
2270 old_fb = plane->fb;
2271 ret = plane->funcs->disable_plane(plane); 2282 ret = plane->funcs->disable_plane(plane);
2272 if (!ret) { 2283 if (!ret) {
2273 plane->crtc = NULL; 2284 plane->crtc = NULL;
2274 plane->fb = NULL; 2285 plane->fb = NULL;
2275 } else { 2286 } else {
2276 old_fb = NULL; 2287 plane->old_fb = NULL;
2277 } 2288 }
2278 drm_modeset_unlock_all(dev);
2279 goto out; 2289 goto out;
2280 } 2290 }
2281 2291
@@ -2315,8 +2325,7 @@ static int setplane_internal(struct drm_plane *plane,
2315 goto out; 2325 goto out;
2316 } 2326 }
2317 2327
2318 drm_modeset_lock_all(dev); 2328 plane->old_fb = plane->fb;
2319 old_fb = plane->fb;
2320 ret = plane->funcs->update_plane(plane, crtc, fb, 2329 ret = plane->funcs->update_plane(plane, crtc, fb,
2321 crtc_x, crtc_y, crtc_w, crtc_h, 2330 crtc_x, crtc_y, crtc_w, crtc_h,
2322 src_x, src_y, src_w, src_h); 2331 src_x, src_y, src_w, src_h);
@@ -2325,18 +2334,37 @@ static int setplane_internal(struct drm_plane *plane,
2325 plane->fb = fb; 2334 plane->fb = fb;
2326 fb = NULL; 2335 fb = NULL;
2327 } else { 2336 } else {
2328 old_fb = NULL; 2337 plane->old_fb = NULL;
2329 } 2338 }
2330 drm_modeset_unlock_all(dev);
2331 2339
2332out: 2340out:
2333 if (fb) 2341 if (fb)
2334 drm_framebuffer_unreference(fb); 2342 drm_framebuffer_unreference(fb);
2335 if (old_fb) 2343 if (plane->old_fb)
2336 drm_framebuffer_unreference(old_fb); 2344 drm_framebuffer_unreference(plane->old_fb);
2345 plane->old_fb = NULL;
2337 2346
2338 return ret; 2347 return ret;
2348}
2349
2350static int setplane_internal(struct drm_plane *plane,
2351 struct drm_crtc *crtc,
2352 struct drm_framebuffer *fb,
2353 int32_t crtc_x, int32_t crtc_y,
2354 uint32_t crtc_w, uint32_t crtc_h,
2355 /* src_{x,y,w,h} values are 16.16 fixed point */
2356 uint32_t src_x, uint32_t src_y,
2357 uint32_t src_w, uint32_t src_h)
2358{
2359 int ret;
2360
2361 drm_modeset_lock_all(plane->dev);
2362 ret = __setplane_internal(plane, crtc, fb,
2363 crtc_x, crtc_y, crtc_w, crtc_h,
2364 src_x, src_y, src_w, src_h);
2365 drm_modeset_unlock_all(plane->dev);
2339 2366
2367 return ret;
2340} 2368}
2341 2369
2342/** 2370/**
@@ -2440,7 +2468,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2440 * crtcs. Atomic modeset will have saner semantics ... 2468 * crtcs. Atomic modeset will have saner semantics ...
2441 */ 2469 */
2442 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) 2470 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
2443 tmp->old_fb = tmp->primary->fb; 2471 tmp->primary->old_fb = tmp->primary->fb;
2444 2472
2445 fb = set->fb; 2473 fb = set->fb;
2446 2474
@@ -2453,8 +2481,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2453 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { 2481 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
2454 if (tmp->primary->fb) 2482 if (tmp->primary->fb)
2455 drm_framebuffer_reference(tmp->primary->fb); 2483 drm_framebuffer_reference(tmp->primary->fb);
2456 if (tmp->old_fb) 2484 if (tmp->primary->old_fb)
2457 drm_framebuffer_unreference(tmp->old_fb); 2485 drm_framebuffer_unreference(tmp->primary->old_fb);
2486 tmp->primary->old_fb = NULL;
2458 } 2487 }
2459 2488
2460 return ret; 2489 return ret;
@@ -2701,6 +2730,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2701 int ret = 0; 2730 int ret = 0;
2702 2731
2703 BUG_ON(!crtc->cursor); 2732 BUG_ON(!crtc->cursor);
2733 WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
2704 2734
2705 /* 2735 /*
2706 * Obtain fb we'll be using (either new or existing) and take an extra 2736 * Obtain fb we'll be using (either new or existing) and take an extra
@@ -2720,11 +2750,9 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2720 fb = NULL; 2750 fb = NULL;
2721 } 2751 }
2722 } else { 2752 } else {
2723 mutex_lock(&dev->mode_config.mutex);
2724 fb = crtc->cursor->fb; 2753 fb = crtc->cursor->fb;
2725 if (fb) 2754 if (fb)
2726 drm_framebuffer_reference(fb); 2755 drm_framebuffer_reference(fb);
2727 mutex_unlock(&dev->mode_config.mutex);
2728 } 2756 }
2729 2757
2730 if (req->flags & DRM_MODE_CURSOR_MOVE) { 2758 if (req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -2746,7 +2774,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2746 * setplane_internal will take care of deref'ing either the old or new 2774 * setplane_internal will take care of deref'ing either the old or new
2747 * framebuffer depending on success. 2775 * framebuffer depending on success.
2748 */ 2776 */
2749 ret = setplane_internal(crtc->cursor, crtc, fb, 2777 ret = __setplane_internal(crtc->cursor, crtc, fb,
2750 crtc_x, crtc_y, crtc_w, crtc_h, 2778 crtc_x, crtc_y, crtc_w, crtc_h,
2751 0, 0, src_w, src_h); 2779 0, 0, src_w, src_h);
2752 2780
@@ -2782,10 +2810,12 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2782 * If this crtc has a universal cursor plane, call that plane's update 2810 * If this crtc has a universal cursor plane, call that plane's update
2783 * handler rather than using legacy cursor handlers. 2811 * handler rather than using legacy cursor handlers.
2784 */ 2812 */
2785 if (crtc->cursor) 2813 drm_modeset_lock_crtc(crtc);
2786 return drm_mode_cursor_universal(crtc, req, file_priv); 2814 if (crtc->cursor) {
2815 ret = drm_mode_cursor_universal(crtc, req, file_priv);
2816 goto out;
2817 }
2787 2818
2788 drm_modeset_lock(&crtc->mutex, NULL);
2789 if (req->flags & DRM_MODE_CURSOR_BO) { 2819 if (req->flags & DRM_MODE_CURSOR_BO) {
2790 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 2820 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
2791 ret = -ENXIO; 2821 ret = -ENXIO;
@@ -2809,7 +2839,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2809 } 2839 }
2810 } 2840 }
2811out: 2841out:
2812 drm_modeset_unlock(&crtc->mutex); 2842 drm_modeset_unlock_crtc(crtc);
2813 2843
2814 return ret; 2844 return ret;
2815 2845
@@ -3370,7 +3400,16 @@ void drm_fb_release(struct drm_file *priv)
3370 struct drm_device *dev = priv->minor->dev; 3400 struct drm_device *dev = priv->minor->dev;
3371 struct drm_framebuffer *fb, *tfb; 3401 struct drm_framebuffer *fb, *tfb;
3372 3402
3373 mutex_lock(&priv->fbs_lock); 3403 /*
3404 * When the file gets released that means no one else can access the fb
3405 * list any more, so no need to grab fpriv->fbs_lock. And we need to to
3406 * avoid upsetting lockdep since the universal cursor code adds a
3407 * framebuffer while holding mutex locks.
3408 *
3409 * Note that a real deadlock between fpriv->fbs_lock and the modeset
3410 * locks is impossible here since no one else but this function can get
3411 * at it any more.
3412 */
3374 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 3413 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
3375 3414
3376 mutex_lock(&dev->mode_config.fb_lock); 3415 mutex_lock(&dev->mode_config.fb_lock);
@@ -3383,7 +3422,6 @@ void drm_fb_release(struct drm_file *priv)
3383 /* This will also drop the fpriv->fbs reference. */ 3422 /* This will also drop the fpriv->fbs reference. */
3384 drm_framebuffer_remove(fb); 3423 drm_framebuffer_remove(fb);
3385 } 3424 }
3386 mutex_unlock(&priv->fbs_lock);
3387} 3425}
3388 3426
3389/** 3427/**
@@ -3495,9 +3533,10 @@ EXPORT_SYMBOL(drm_property_create_enum);
3495 * @flags: flags specifying the property type 3533 * @flags: flags specifying the property type
3496 * @name: name of the property 3534 * @name: name of the property
3497 * @props: enumeration lists with property bitflags 3535 * @props: enumeration lists with property bitflags
3498 * @num_values: number of pre-defined values 3536 * @num_props: size of the @props array
3537 * @supported_bits: bitmask of all supported enumeration values
3499 * 3538 *
3500 * This creates a new generic drm property which can then be attached to a drm 3539 * This creates a new bitmask drm property which can then be attached to a drm
3501 * object with drm_object_attach_property. The returned property object must be 3540 * object with drm_object_attach_property. The returned property object must be
3502 * freed with drm_property_destroy. 3541 * freed with drm_property_destroy.
3503 * 3542 *
@@ -4157,12 +4196,25 @@ static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
4157 return ret; 4196 return ret;
4158} 4197}
4159 4198
4160static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj, 4199/**
4161 struct drm_property *property, 4200 * drm_mode_plane_set_obj_prop - set the value of a property
4162 uint64_t value) 4201 * @plane: drm plane object to set property value for
4202 * @property: property to set
4203 * @value: value the property should be set to
4204 *
4205 * This functions sets a given property on a given plane object. This function
4206 * calls the driver's ->set_property callback and changes the software state of
4207 * the property if the callback succeeds.
4208 *
4209 * Returns:
4210 * Zero on success, error code on failure.
4211 */
4212int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
4213 struct drm_property *property,
4214 uint64_t value)
4163{ 4215{
4164 int ret = -EINVAL; 4216 int ret = -EINVAL;
4165 struct drm_plane *plane = obj_to_plane(obj); 4217 struct drm_mode_object *obj = &plane->base;
4166 4218
4167 if (plane->funcs->set_property) 4219 if (plane->funcs->set_property)
4168 ret = plane->funcs->set_property(plane, property, value); 4220 ret = plane->funcs->set_property(plane, property, value);
@@ -4171,6 +4223,7 @@ static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
4171 4223
4172 return ret; 4224 return ret;
4173} 4225}
4226EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
4174 4227
4175/** 4228/**
4176 * drm_mode_getproperty_ioctl - get the current value of a object's property 4229 * drm_mode_getproperty_ioctl - get the current value of a object's property
@@ -4309,7 +4362,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
4309 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); 4362 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
4310 break; 4363 break;
4311 case DRM_MODE_OBJECT_PLANE: 4364 case DRM_MODE_OBJECT_PLANE:
4312 ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value); 4365 ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
4366 property, arg->value);
4313 break; 4367 break;
4314 } 4368 }
4315 4369
@@ -4529,7 +4583,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4529{ 4583{
4530 struct drm_mode_crtc_page_flip *page_flip = data; 4584 struct drm_mode_crtc_page_flip *page_flip = data;
4531 struct drm_crtc *crtc; 4585 struct drm_crtc *crtc;
4532 struct drm_framebuffer *fb = NULL, *old_fb = NULL; 4586 struct drm_framebuffer *fb = NULL;
4533 struct drm_pending_vblank_event *e = NULL; 4587 struct drm_pending_vblank_event *e = NULL;
4534 unsigned long flags; 4588 unsigned long flags;
4535 int ret = -EINVAL; 4589 int ret = -EINVAL;
@@ -4545,7 +4599,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4545 if (!crtc) 4599 if (!crtc)
4546 return -ENOENT; 4600 return -ENOENT;
4547 4601
4548 drm_modeset_lock(&crtc->mutex, NULL); 4602 drm_modeset_lock_crtc(crtc);
4549 if (crtc->primary->fb == NULL) { 4603 if (crtc->primary->fb == NULL) {
4550 /* The framebuffer is currently unbound, presumably 4604 /* The framebuffer is currently unbound, presumably
4551 * due to a hotplug event, that userspace has not 4605 * due to a hotplug event, that userspace has not
@@ -4601,7 +4655,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4601 (void (*) (struct drm_pending_event *)) kfree; 4655 (void (*) (struct drm_pending_event *)) kfree;
4602 } 4656 }
4603 4657
4604 old_fb = crtc->primary->fb; 4658 crtc->primary->old_fb = crtc->primary->fb;
4605 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); 4659 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
4606 if (ret) { 4660 if (ret) {
4607 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 4661 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4611,7 +4665,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4611 kfree(e); 4665 kfree(e);
4612 } 4666 }
4613 /* Keep the old fb, don't unref it. */ 4667 /* Keep the old fb, don't unref it. */
4614 old_fb = NULL; 4668 crtc->primary->old_fb = NULL;
4615 } else { 4669 } else {
4616 /* 4670 /*
4617 * Warn if the driver hasn't properly updated the crtc->fb 4671 * Warn if the driver hasn't properly updated the crtc->fb
@@ -4627,9 +4681,10 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4627out: 4681out:
4628 if (fb) 4682 if (fb)
4629 drm_framebuffer_unreference(fb); 4683 drm_framebuffer_unreference(fb);
4630 if (old_fb) 4684 if (crtc->primary->old_fb)
4631 drm_framebuffer_unreference(old_fb); 4685 drm_framebuffer_unreference(crtc->primary->old_fb);
4632 drm_modeset_unlock(&crtc->mutex); 4686 crtc->primary->old_fb = NULL;
4687 drm_modeset_unlock_crtc(crtc);
4633 4688
4634 return ret; 4689 return ret;
4635} 4690}
@@ -4645,9 +4700,14 @@ out:
4645void drm_mode_config_reset(struct drm_device *dev) 4700void drm_mode_config_reset(struct drm_device *dev)
4646{ 4701{
4647 struct drm_crtc *crtc; 4702 struct drm_crtc *crtc;
4703 struct drm_plane *plane;
4648 struct drm_encoder *encoder; 4704 struct drm_encoder *encoder;
4649 struct drm_connector *connector; 4705 struct drm_connector *connector;
4650 4706
4707 list_for_each_entry(plane, &dev->mode_config.plane_list, head)
4708 if (plane->funcs->reset)
4709 plane->funcs->reset(plane);
4710
4651 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 4711 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
4652 if (crtc->funcs->reset) 4712 if (crtc->funcs->reset)
4653 crtc->funcs->reset(crtc); 4713 crtc->funcs->reset(crtc);