aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-08-25 19:04:03 -0400
committerDave Airlie <airlied@redhat.com>2014-08-25 19:04:03 -0400
commitc0ee755fc57319a623e0d9ef839cf8fb26ce8d60 (patch)
tree727fe78a158757f75b54d7e037b383ad6a39843c /drivers
parent52addcf9d6669fa439387610bc65c92fa0980cef (diff)
parent14f476fa24e81d0beea1aa14d763102958518d60 (diff)
Merge tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel into drm-next
So small drm stuff all over for 3.18. Biggest one is the cmdline parsing from Chris with a few fixes from me to make it work for stupid kernel configs. Plus the atomic prep series. Tested for more than a week in -nightly and Ville/Imre indeed discovered some fun which is now fixed (and i915 vblank patches postponed since the fixups need this branch plus drm-intel-next merged together). * tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel: drm: Use the type of the array element when reallocating drm: Don't return 0 for a value used as a denominator drm: Docbook fixes drm/irq: Implement a generic vblank_wait function drm: Add a plane->reset hook drm: trylock modest locking for fbdev panics drm: Move ->old_fb from crtc to plane drm: Handle legacy per-crtc locking with full acquire ctx drm: Move modeset_lock_all helpers to drm_modeset_lock.[hc] drm: Add drm_plane/connector_index drm: idiot-proof vblank drm: Warn when leaking flip events on close drm: Perform cmdline mode parsing during connector initialisation video/fbdev: Always built-in video= cmdline parsing drm: Don't grab an fb reference for the idr
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/Kconfig1
-rw-r--r--drivers/gpu/drm/drm_crtc.c306
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c3
-rw-r--r--drivers/gpu/drm/drm_edid.c2
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c76
-rw-r--r--drivers/gpu/drm/drm_fops.c2
-rw-r--r--drivers/gpu/drm/drm_irq.c68
-rw-r--r--drivers/gpu/drm/drm_modes.c1
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c213
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c17
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c21
-rw-r--r--drivers/video/fbdev/Kconfig4
-rw-r--r--drivers/video/fbdev/core/Makefile1
-rw-r--r--drivers/video/fbdev/core/fb_cmdline.c110
-rw-r--r--drivers/video/fbdev/core/fbmem.c92
-rw-r--r--drivers/video/fbdev/core/modedb.c3
16 files changed, 598 insertions, 322 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index b066bb3ca01a..e251ecce4ed2 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -8,6 +8,7 @@ menuconfig DRM
8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" 8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
9 depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA 9 depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
10 select HDMI 10 select HDMI
11 select FB_CMDLINE
11 select I2C 12 select I2C
12 select I2C_ALGOBIT 13 select I2C_ALGOBIT
13 select DMA_SHARED_BUFFER 14 select DMA_SHARED_BUFFER
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index fa2be249999c..f09b75212081 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -45,101 +45,6 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
45 struct drm_mode_fb_cmd2 *r, 45 struct drm_mode_fb_cmd2 *r,
46 struct drm_file *file_priv); 46 struct drm_file *file_priv);
47 47
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. */ 48/* Avoid boilerplate. I'm tired of typing. */
144#define DRM_ENUM_NAME_FN(fnname, list) \ 49#define DRM_ENUM_NAME_FN(fnname, list) \
145 const char *fnname(int val) \ 50 const char *fnname(int val) \
@@ -515,9 +420,6 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
515 if (ret) 420 if (ret)
516 goto out; 421 goto out;
517 422
518 /* Grab the idr reference. */
519 drm_framebuffer_reference(fb);
520
521 dev->mode_config.num_fb++; 423 dev->mode_config.num_fb++;
522 list_add(&fb->head, &dev->mode_config.fb_list); 424 list_add(&fb->head, &dev->mode_config.fb_list);
523out: 425out:
@@ -527,10 +429,34 @@ out:
527} 429}
528EXPORT_SYMBOL(drm_framebuffer_init); 430EXPORT_SYMBOL(drm_framebuffer_init);
529 431
432/* dev->mode_config.fb_lock must be held! */
433static void __drm_framebuffer_unregister(struct drm_device *dev,
434 struct drm_framebuffer *fb)
435{
436 mutex_lock(&dev->mode_config.idr_mutex);
437 idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
438 mutex_unlock(&dev->mode_config.idr_mutex);
439
440 fb->base.id = 0;
441}
442
530static void drm_framebuffer_free(struct kref *kref) 443static void drm_framebuffer_free(struct kref *kref)
531{ 444{
532 struct drm_framebuffer *fb = 445 struct drm_framebuffer *fb =
533 container_of(kref, struct drm_framebuffer, refcount); 446 container_of(kref, struct drm_framebuffer, refcount);
447 struct drm_device *dev = fb->dev;
448
449 /*
450 * The lookup idr holds a weak reference, which has not necessarily been
451 * removed at this point. Check for that.
452 */
453 mutex_lock(&dev->mode_config.fb_lock);
454 if (fb->base.id) {
455 /* Mark fb as reaped and drop idr ref. */
456 __drm_framebuffer_unregister(dev, fb);
457 }
458 mutex_unlock(&dev->mode_config.fb_lock);
459
534 fb->funcs->destroy(fb); 460 fb->funcs->destroy(fb);
535} 461}
536 462
@@ -567,8 +493,10 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
567 493
568 mutex_lock(&dev->mode_config.fb_lock); 494 mutex_lock(&dev->mode_config.fb_lock);
569 fb = __drm_framebuffer_lookup(dev, id); 495 fb = __drm_framebuffer_lookup(dev, id);
570 if (fb) 496 if (fb) {
571 drm_framebuffer_reference(fb); 497 if (!kref_get_unless_zero(&fb->refcount))
498 fb = NULL;
499 }
572 mutex_unlock(&dev->mode_config.fb_lock); 500 mutex_unlock(&dev->mode_config.fb_lock);
573 501
574 return fb; 502 return fb;
@@ -612,19 +540,6 @@ static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
612 kref_put(&fb->refcount, drm_framebuffer_free_bug); 540 kref_put(&fb->refcount, drm_framebuffer_free_bug);
613} 541}
614 542
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/** 543/**
629 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr 544 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
630 * @fb: fb to unregister 545 * @fb: fb to unregister
@@ -853,6 +768,59 @@ static void drm_mode_remove(struct drm_connector *connector,
853} 768}
854 769
855/** 770/**
771 * drm_connector_get_cmdline_mode - reads the user's cmdline mode
772 * @connector: connector to quwery
773 * @mode: returned mode
774 *
775 * The kernel supports per-connector configration of its consoles through
776 * use of the video= parameter. This function parses that option and
777 * extracts the user's specified mode (or enable/disable status) for a
778 * particular connector. This is typically only used during the early fbdev
779 * setup.
780 */
781static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
782{
783 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
784 char *option = NULL;
785
786 if (fb_get_options(connector->name, &option))
787 return;
788
789 if (!drm_mode_parse_command_line_for_connector(option,
790 connector,
791 mode))
792 return;
793
794 if (mode->force) {
795 const char *s;
796
797 switch (mode->force) {
798 case DRM_FORCE_OFF:
799 s = "OFF";
800 break;
801 case DRM_FORCE_ON_DIGITAL:
802 s = "ON - dig";
803 break;
804 default:
805 case DRM_FORCE_ON:
806 s = "ON";
807 break;
808 }
809
810 DRM_INFO("forcing %s connector %s\n", connector->name, s);
811 connector->force = mode->force;
812 }
813
814 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
815 connector->name,
816 mode->xres, mode->yres,
817 mode->refresh_specified ? mode->refresh : 60,
818 mode->rb ? " reduced blanking" : "",
819 mode->margins ? " with margins" : "",
820 mode->interlace ? " interlaced" : "");
821}
822
823/**
856 * drm_connector_init - Init a preallocated connector 824 * drm_connector_init - Init a preallocated connector
857 * @dev: DRM device 825 * @dev: DRM device
858 * @connector: the connector to init 826 * @connector: the connector to init
@@ -904,6 +872,8 @@ int drm_connector_init(struct drm_device *dev,
904 connector->edid_blob_ptr = NULL; 872 connector->edid_blob_ptr = NULL;
905 connector->status = connector_status_unknown; 873 connector->status = connector_status_unknown;
906 874
875 drm_connector_get_cmdline_mode(connector);
876
907 list_add_tail(&connector->head, &dev->mode_config.connector_list); 877 list_add_tail(&connector->head, &dev->mode_config.connector_list);
908 dev->mode_config.num_connector++; 878 dev->mode_config.num_connector++;
909 879
@@ -957,6 +927,29 @@ void drm_connector_cleanup(struct drm_connector *connector)
957EXPORT_SYMBOL(drm_connector_cleanup); 927EXPORT_SYMBOL(drm_connector_cleanup);
958 928
959/** 929/**
930 * drm_connector_index - find the index of a registered connector
931 * @connector: connector to find index for
932 *
933 * Given a registered connector, return the index of that connector within a DRM
934 * device's list of connectors.
935 */
936unsigned int drm_connector_index(struct drm_connector *connector)
937{
938 unsigned int index = 0;
939 struct drm_connector *tmp;
940
941 list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
942 if (tmp == connector)
943 return index;
944
945 index++;
946 }
947
948 BUG();
949}
950EXPORT_SYMBOL(drm_connector_index);
951
952/**
960 * drm_connector_register - register a connector 953 * drm_connector_register - register a connector
961 * @connector: the connector to register 954 * @connector: the connector to register
962 * 955 *
@@ -1261,6 +1254,29 @@ void drm_plane_cleanup(struct drm_plane *plane)
1261EXPORT_SYMBOL(drm_plane_cleanup); 1254EXPORT_SYMBOL(drm_plane_cleanup);
1262 1255
1263/** 1256/**
1257 * drm_plane_index - find the index of a registered plane
1258 * @plane: plane to find index for
1259 *
1260 * Given a registered plane, return the index of that CRTC within a DRM
1261 * device's list of planes.
1262 */
1263unsigned int drm_plane_index(struct drm_plane *plane)
1264{
1265 unsigned int index = 0;
1266 struct drm_plane *tmp;
1267
1268 list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
1269 if (tmp == plane)
1270 return index;
1271
1272 index++;
1273 }
1274
1275 BUG();
1276}
1277EXPORT_SYMBOL(drm_plane_index);
1278
1279/**
1264 * drm_plane_force_disable - Forcibly disable a plane 1280 * drm_plane_force_disable - Forcibly disable a plane
1265 * @plane: plane to disable 1281 * @plane: plane to disable
1266 * 1282 *
@@ -1271,19 +1287,21 @@ EXPORT_SYMBOL(drm_plane_cleanup);
1271 */ 1287 */
1272void drm_plane_force_disable(struct drm_plane *plane) 1288void drm_plane_force_disable(struct drm_plane *plane)
1273{ 1289{
1274 struct drm_framebuffer *old_fb = plane->fb;
1275 int ret; 1290 int ret;
1276 1291
1277 if (!old_fb) 1292 if (!plane->fb)
1278 return; 1293 return;
1279 1294
1295 plane->old_fb = plane->fb;
1280 ret = plane->funcs->disable_plane(plane); 1296 ret = plane->funcs->disable_plane(plane);
1281 if (ret) { 1297 if (ret) {
1282 DRM_ERROR("failed to disable plane with busy fb\n"); 1298 DRM_ERROR("failed to disable plane with busy fb\n");
1299 plane->old_fb = NULL;
1283 return; 1300 return;
1284 } 1301 }
1285 /* disconnect the plane from the fb and crtc: */ 1302 /* disconnect the plane from the fb and crtc: */
1286 __drm_framebuffer_unreference(old_fb); 1303 __drm_framebuffer_unreference(plane->old_fb);
1304 plane->old_fb = NULL;
1287 plane->fb = NULL; 1305 plane->fb = NULL;
1288 plane->crtc = NULL; 1306 plane->crtc = NULL;
1289} 1307}
@@ -2259,23 +2277,21 @@ static int setplane_internal(struct drm_plane *plane,
2259 uint32_t src_w, uint32_t src_h) 2277 uint32_t src_w, uint32_t src_h)
2260{ 2278{
2261 struct drm_device *dev = plane->dev; 2279 struct drm_device *dev = plane->dev;
2262 struct drm_framebuffer *old_fb = NULL;
2263 int ret = 0; 2280 int ret = 0;
2264 unsigned int fb_width, fb_height; 2281 unsigned int fb_width, fb_height;
2265 int i; 2282 int i;
2266 2283
2284 drm_modeset_lock_all(dev);
2267 /* No fb means shut it down */ 2285 /* No fb means shut it down */
2268 if (!fb) { 2286 if (!fb) {
2269 drm_modeset_lock_all(dev); 2287 plane->old_fb = plane->fb;
2270 old_fb = plane->fb;
2271 ret = plane->funcs->disable_plane(plane); 2288 ret = plane->funcs->disable_plane(plane);
2272 if (!ret) { 2289 if (!ret) {
2273 plane->crtc = NULL; 2290 plane->crtc = NULL;
2274 plane->fb = NULL; 2291 plane->fb = NULL;
2275 } else { 2292 } else {
2276 old_fb = NULL; 2293 plane->old_fb = NULL;
2277 } 2294 }
2278 drm_modeset_unlock_all(dev);
2279 goto out; 2295 goto out;
2280 } 2296 }
2281 2297
@@ -2315,8 +2331,7 @@ static int setplane_internal(struct drm_plane *plane,
2315 goto out; 2331 goto out;
2316 } 2332 }
2317 2333
2318 drm_modeset_lock_all(dev); 2334 plane->old_fb = plane->fb;
2319 old_fb = plane->fb;
2320 ret = plane->funcs->update_plane(plane, crtc, fb, 2335 ret = plane->funcs->update_plane(plane, crtc, fb,
2321 crtc_x, crtc_y, crtc_w, crtc_h, 2336 crtc_x, crtc_y, crtc_w, crtc_h,
2322 src_x, src_y, src_w, src_h); 2337 src_x, src_y, src_w, src_h);
@@ -2325,15 +2340,16 @@ static int setplane_internal(struct drm_plane *plane,
2325 plane->fb = fb; 2340 plane->fb = fb;
2326 fb = NULL; 2341 fb = NULL;
2327 } else { 2342 } else {
2328 old_fb = NULL; 2343 plane->old_fb = NULL;
2329 } 2344 }
2330 drm_modeset_unlock_all(dev);
2331 2345
2332out: 2346out:
2333 if (fb) 2347 if (fb)
2334 drm_framebuffer_unreference(fb); 2348 drm_framebuffer_unreference(fb);
2335 if (old_fb) 2349 if (plane->old_fb)
2336 drm_framebuffer_unreference(old_fb); 2350 drm_framebuffer_unreference(plane->old_fb);
2351 plane->old_fb = NULL;
2352 drm_modeset_unlock_all(dev);
2337 2353
2338 return ret; 2354 return ret;
2339 2355
@@ -2440,7 +2456,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2440 * crtcs. Atomic modeset will have saner semantics ... 2456 * crtcs. Atomic modeset will have saner semantics ...
2441 */ 2457 */
2442 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) 2458 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
2443 tmp->old_fb = tmp->primary->fb; 2459 tmp->primary->old_fb = tmp->primary->fb;
2444 2460
2445 fb = set->fb; 2461 fb = set->fb;
2446 2462
@@ -2453,8 +2469,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) { 2469 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
2454 if (tmp->primary->fb) 2470 if (tmp->primary->fb)
2455 drm_framebuffer_reference(tmp->primary->fb); 2471 drm_framebuffer_reference(tmp->primary->fb);
2456 if (tmp->old_fb) 2472 if (tmp->primary->old_fb)
2457 drm_framebuffer_unreference(tmp->old_fb); 2473 drm_framebuffer_unreference(tmp->primary->old_fb);
2474 tmp->primary->old_fb = NULL;
2458 } 2475 }
2459 2476
2460 return ret; 2477 return ret;
@@ -2785,7 +2802,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2785 if (crtc->cursor) 2802 if (crtc->cursor)
2786 return drm_mode_cursor_universal(crtc, req, file_priv); 2803 return drm_mode_cursor_universal(crtc, req, file_priv);
2787 2804
2788 drm_modeset_lock(&crtc->mutex, NULL); 2805 drm_modeset_lock_crtc(crtc);
2789 if (req->flags & DRM_MODE_CURSOR_BO) { 2806 if (req->flags & DRM_MODE_CURSOR_BO) {
2790 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 2807 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
2791 ret = -ENXIO; 2808 ret = -ENXIO;
@@ -2809,7 +2826,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2809 } 2826 }
2810 } 2827 }
2811out: 2828out:
2812 drm_modeset_unlock(&crtc->mutex); 2829 drm_modeset_unlock_crtc(crtc);
2813 2830
2814 return ret; 2831 return ret;
2815 2832
@@ -3495,9 +3512,10 @@ EXPORT_SYMBOL(drm_property_create_enum);
3495 * @flags: flags specifying the property type 3512 * @flags: flags specifying the property type
3496 * @name: name of the property 3513 * @name: name of the property
3497 * @props: enumeration lists with property bitflags 3514 * @props: enumeration lists with property bitflags
3498 * @num_values: number of pre-defined values 3515 * @num_props: size of the @props array
3516 * @supported_bits: bitmask of all supported enumeration values
3499 * 3517 *
3500 * This creates a new generic drm property which can then be attached to a drm 3518 * 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 3519 * object with drm_object_attach_property. The returned property object must be
3502 * freed with drm_property_destroy. 3520 * freed with drm_property_destroy.
3503 * 3521 *
@@ -4529,7 +4547,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4529{ 4547{
4530 struct drm_mode_crtc_page_flip *page_flip = data; 4548 struct drm_mode_crtc_page_flip *page_flip = data;
4531 struct drm_crtc *crtc; 4549 struct drm_crtc *crtc;
4532 struct drm_framebuffer *fb = NULL, *old_fb = NULL; 4550 struct drm_framebuffer *fb = NULL;
4533 struct drm_pending_vblank_event *e = NULL; 4551 struct drm_pending_vblank_event *e = NULL;
4534 unsigned long flags; 4552 unsigned long flags;
4535 int ret = -EINVAL; 4553 int ret = -EINVAL;
@@ -4545,7 +4563,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4545 if (!crtc) 4563 if (!crtc)
4546 return -ENOENT; 4564 return -ENOENT;
4547 4565
4548 drm_modeset_lock(&crtc->mutex, NULL); 4566 drm_modeset_lock_crtc(crtc);
4549 if (crtc->primary->fb == NULL) { 4567 if (crtc->primary->fb == NULL) {
4550 /* The framebuffer is currently unbound, presumably 4568 /* The framebuffer is currently unbound, presumably
4551 * due to a hotplug event, that userspace has not 4569 * due to a hotplug event, that userspace has not
@@ -4601,7 +4619,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4601 (void (*) (struct drm_pending_event *)) kfree; 4619 (void (*) (struct drm_pending_event *)) kfree;
4602 } 4620 }
4603 4621
4604 old_fb = crtc->primary->fb; 4622 crtc->primary->old_fb = crtc->primary->fb;
4605 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); 4623 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
4606 if (ret) { 4624 if (ret) {
4607 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 4625 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4611,7 +4629,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4611 kfree(e); 4629 kfree(e);
4612 } 4630 }
4613 /* Keep the old fb, don't unref it. */ 4631 /* Keep the old fb, don't unref it. */
4614 old_fb = NULL; 4632 crtc->primary->old_fb = NULL;
4615 } else { 4633 } else {
4616 /* 4634 /*
4617 * Warn if the driver hasn't properly updated the crtc->fb 4635 * Warn if the driver hasn't properly updated the crtc->fb
@@ -4627,9 +4645,10 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4627out: 4645out:
4628 if (fb) 4646 if (fb)
4629 drm_framebuffer_unreference(fb); 4647 drm_framebuffer_unreference(fb);
4630 if (old_fb) 4648 if (crtc->primary->old_fb)
4631 drm_framebuffer_unreference(old_fb); 4649 drm_framebuffer_unreference(crtc->primary->old_fb);
4632 drm_modeset_unlock(&crtc->mutex); 4650 crtc->primary->old_fb = NULL;
4651 drm_modeset_unlock_crtc(crtc);
4633 4652
4634 return ret; 4653 return ret;
4635} 4654}
@@ -4645,9 +4664,14 @@ out:
4645void drm_mode_config_reset(struct drm_device *dev) 4664void drm_mode_config_reset(struct drm_device *dev)
4646{ 4665{
4647 struct drm_crtc *crtc; 4666 struct drm_crtc *crtc;
4667 struct drm_plane *plane;
4648 struct drm_encoder *encoder; 4668 struct drm_encoder *encoder;
4649 struct drm_connector *connector; 4669 struct drm_connector *connector;
4650 4670
4671 list_for_each_entry(plane, &dev->mode_config.plane_list, head)
4672 if (plane->funcs->reset)
4673 plane->funcs->reset(plane);
4674
4651 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 4675 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
4652 if (crtc->funcs->reset) 4676 if (crtc->funcs->reset)
4653 crtc->funcs->reset(crtc); 4677 crtc->funcs->reset(crtc);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index ac3c2738db94..b3adf1445020 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1772,7 +1772,7 @@ static int drm_dp_get_vc_payload_bw(int dp_link_bw, int dp_link_count)
1772 case DP_LINK_BW_5_4: 1772 case DP_LINK_BW_5_4:
1773 return 10 * dp_link_count; 1773 return 10 * dp_link_count;
1774 } 1774 }
1775 return 0; 1775 BUG();
1776} 1776}
1777 1777
1778/** 1778/**
@@ -2071,6 +2071,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
2071 * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify 2071 * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
2072 * @mgr: manager to notify irq for. 2072 * @mgr: manager to notify irq for.
2073 * @esi: 4 bytes from SINK_COUNT_ESI 2073 * @esi: 4 bytes from SINK_COUNT_ESI
2074 * @handled: whether the hpd interrupt was consumed or not
2074 * 2075 *
2075 * This should be called from the driver when it detects a short IRQ, 2076 * This should be called from the driver when it detects a short IRQ,
2076 * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The 2077 * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 1dbf3bc4c6a3..f905c63c0f68 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3433,10 +3433,10 @@ EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
3433/** 3433/**
3434 * drm_assign_hdmi_deep_color_info - detect whether monitor supports 3434 * drm_assign_hdmi_deep_color_info - detect whether monitor supports
3435 * hdmi deep color modes and update drm_display_info if so. 3435 * hdmi deep color modes and update drm_display_info if so.
3436 *
3437 * @edid: monitor EDID information 3436 * @edid: monitor EDID information
3438 * @info: Updated with maximum supported deep color bpc and color format 3437 * @info: Updated with maximum supported deep color bpc and color format
3439 * if deep color supported. 3438 * if deep color supported.
3439 * @connector: DRM connector, used only for debug output
3440 * 3440 *
3441 * Parse the CEA extension according to CEA-861-B. 3441 * Parse the CEA extension according to CEA-861-B.
3442 * Return true if HDMI deep color supported, false if not or unknown. 3442 * Return true if HDMI deep color supported, false if not or unknown.
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3144db9dc0f1..6019392b19cc 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -126,7 +126,7 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
126 126
127 WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex)); 127 WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
128 if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) { 128 if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
129 temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector) * (fb_helper->connector_count + 1), GFP_KERNEL); 129 temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL);
130 if (!temp) 130 if (!temp)
131 return -ENOMEM; 131 return -ENOMEM;
132 132
@@ -171,60 +171,6 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
171} 171}
172EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); 172EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
173 173
174static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
175{
176 struct drm_fb_helper_connector *fb_helper_conn;
177 int i;
178
179 for (i = 0; i < fb_helper->connector_count; i++) {
180 struct drm_cmdline_mode *mode;
181 struct drm_connector *connector;
182 char *option = NULL;
183
184 fb_helper_conn = fb_helper->connector_info[i];
185 connector = fb_helper_conn->connector;
186 mode = &fb_helper_conn->cmdline_mode;
187
188 /* do something on return - turn off connector maybe */
189 if (fb_get_options(connector->name, &option))
190 continue;
191
192 if (drm_mode_parse_command_line_for_connector(option,
193 connector,
194 mode)) {
195 if (mode->force) {
196 const char *s;
197 switch (mode->force) {
198 case DRM_FORCE_OFF:
199 s = "OFF";
200 break;
201 case DRM_FORCE_ON_DIGITAL:
202 s = "ON - dig";
203 break;
204 default:
205 case DRM_FORCE_ON:
206 s = "ON";
207 break;
208 }
209
210 DRM_INFO("forcing %s connector %s\n",
211 connector->name, s);
212 connector->force = mode->force;
213 }
214
215 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
216 connector->name,
217 mode->xres, mode->yres,
218 mode->refresh_specified ? mode->refresh : 60,
219 mode->rb ? " reduced blanking" : "",
220 mode->margins ? " with margins" : "",
221 mode->interlace ? " interlaced" : "");
222 }
223
224 }
225 return 0;
226}
227
228static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) 174static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
229{ 175{
230 uint16_t *r_base, *g_base, *b_base; 176 uint16_t *r_base, *g_base, *b_base;
@@ -419,11 +365,11 @@ static bool drm_fb_helper_force_kernel_mode(void)
419 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) 365 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
420 continue; 366 continue;
421 367
422 /* NOTE: we use lockless flag below to avoid grabbing other 368 /*
423 * modeset locks. So just trylock the underlying mutex 369 * NOTE: Use trylock mode to avoid deadlocks and sleeping in
424 * directly: 370 * panic context.
425 */ 371 */
426 if (!mutex_trylock(&dev->mode_config.mutex)) { 372 if (__drm_modeset_lock_all(dev, true) != 0) {
427 error = true; 373 error = true;
428 continue; 374 continue;
429 } 375 }
@@ -432,7 +378,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
432 if (ret) 378 if (ret)
433 error = true; 379 error = true;
434 380
435 mutex_unlock(&dev->mode_config.mutex); 381 drm_modeset_unlock_all(dev);
436 } 382 }
437 return error; 383 return error;
438} 384}
@@ -1013,7 +959,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
1013 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; 959 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
1014 struct drm_cmdline_mode *cmdline_mode; 960 struct drm_cmdline_mode *cmdline_mode;
1015 961
1016 cmdline_mode = &fb_helper_conn->cmdline_mode; 962 cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
1017 963
1018 if (cmdline_mode->bpp_specified) { 964 if (cmdline_mode->bpp_specified) {
1019 switch (cmdline_mode->bpp) { 965 switch (cmdline_mode->bpp) {
@@ -1260,9 +1206,7 @@ EXPORT_SYMBOL(drm_has_preferred_mode);
1260 1206
1261static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) 1207static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1262{ 1208{
1263 struct drm_cmdline_mode *cmdline_mode; 1209 return fb_connector->connector->cmdline_mode.specified;
1264 cmdline_mode = &fb_connector->cmdline_mode;
1265 return cmdline_mode->specified;
1266} 1210}
1267 1211
1268struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, 1212struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
@@ -1272,7 +1216,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
1272 struct drm_display_mode *mode = NULL; 1216 struct drm_display_mode *mode = NULL;
1273 bool prefer_non_interlace; 1217 bool prefer_non_interlace;
1274 1218
1275 cmdline_mode = &fb_helper_conn->cmdline_mode; 1219 cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
1276 if (cmdline_mode->specified == false) 1220 if (cmdline_mode->specified == false)
1277 return mode; 1221 return mode;
1278 1222
@@ -1657,8 +1601,6 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
1657 struct drm_device *dev = fb_helper->dev; 1601 struct drm_device *dev = fb_helper->dev;
1658 int count = 0; 1602 int count = 0;
1659 1603
1660 drm_fb_helper_parse_command_line(fb_helper);
1661
1662 mutex_lock(&dev->mode_config.mutex); 1604 mutex_lock(&dev->mode_config.mutex);
1663 count = drm_fb_helper_probe_connector_modes(fb_helper, 1605 count = drm_fb_helper_probe_connector_modes(fb_helper,
1664 dev->mode_config.max_width, 1606 dev->mode_config.max_width,
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 79d5221c6e41..6dbbb0fd54eb 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -464,6 +464,8 @@ int drm_release(struct inode *inode, struct file *filp)
464 if (drm_core_check_feature(dev, DRIVER_PRIME)) 464 if (drm_core_check_feature(dev, DRIVER_PRIME))
465 drm_prime_destroy_file_private(&file_priv->prime); 465 drm_prime_destroy_file_private(&file_priv->prime);
466 466
467 WARN_ON(!list_empty(&file_priv->event_list));
468
467 put_pid(file_priv->pid); 469 put_pid(file_priv->pid);
468 kfree(file_priv); 470 kfree(file_priv);
469 471
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 08ba1209228e..5708c056fa1b 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -720,6 +720,8 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp);
720 */ 720 */
721u32 drm_vblank_count(struct drm_device *dev, int crtc) 721u32 drm_vblank_count(struct drm_device *dev, int crtc)
722{ 722{
723 if (WARN_ON(crtc >= dev->num_crtcs))
724 return 0;
723 return atomic_read(&dev->vblank[crtc].count); 725 return atomic_read(&dev->vblank[crtc].count);
724} 726}
725EXPORT_SYMBOL(drm_vblank_count); 727EXPORT_SYMBOL(drm_vblank_count);
@@ -742,6 +744,9 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
742{ 744{
743 u32 cur_vblank; 745 u32 cur_vblank;
744 746
747 if (WARN_ON(crtc >= dev->num_crtcs))
748 return 0;
749
745 /* Read timestamp from slot of _vblank_time ringbuffer 750 /* Read timestamp from slot of _vblank_time ringbuffer
746 * that corresponds to current vblank count. Retry if 751 * that corresponds to current vblank count. Retry if
747 * count has incremented during readout. This works like 752 * count has incremented during readout. This works like
@@ -917,6 +922,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
917 unsigned long irqflags; 922 unsigned long irqflags;
918 int ret = 0; 923 int ret = 0;
919 924
925 if (WARN_ON(crtc >= dev->num_crtcs))
926 return -EINVAL;
927
920 spin_lock_irqsave(&dev->vbl_lock, irqflags); 928 spin_lock_irqsave(&dev->vbl_lock, irqflags);
921 /* Going from 0->1 means we have to enable interrupts again */ 929 /* Going from 0->1 means we have to enable interrupts again */
922 if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) { 930 if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) {
@@ -965,6 +973,9 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
965{ 973{
966 BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0); 974 BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
967 975
976 if (WARN_ON(crtc >= dev->num_crtcs))
977 return;
978
968 /* Last user schedules interrupt disable */ 979 /* Last user schedules interrupt disable */
969 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && 980 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
970 (drm_vblank_offdelay > 0)) 981 (drm_vblank_offdelay > 0))
@@ -989,6 +1000,50 @@ void drm_crtc_vblank_put(struct drm_crtc *crtc)
989EXPORT_SYMBOL(drm_crtc_vblank_put); 1000EXPORT_SYMBOL(drm_crtc_vblank_put);
990 1001
991/** 1002/**
1003 * drm_wait_one_vblank - wait for one vblank
1004 * @dev: DRM device
1005 * @crtc: crtc index
1006 *
1007 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1008 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1009 * due to lack of driver support or because the crtc is off.
1010 */
1011void drm_wait_one_vblank(struct drm_device *dev, int crtc)
1012{
1013 int ret;
1014 u32 last;
1015
1016 ret = drm_vblank_get(dev, crtc);
1017 if (WARN_ON(ret))
1018 return;
1019
1020 last = drm_vblank_count(dev, crtc);
1021
1022 ret = wait_event_timeout(dev->vblank[crtc].queue,
1023 last != drm_vblank_count(dev, crtc),
1024 msecs_to_jiffies(100));
1025
1026 WARN_ON(ret == 0);
1027
1028 drm_vblank_put(dev, crtc);
1029}
1030EXPORT_SYMBOL(drm_wait_one_vblank);
1031
1032/**
1033 * drm_crtc_wait_one_vblank - wait for one vblank
1034 * @crtc: DRM crtc
1035 *
1036 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1037 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1038 * due to lack of driver support or because the crtc is off.
1039 */
1040void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
1041{
1042 drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
1043}
1044EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
1045
1046/**
992 * drm_vblank_off - disable vblank events on a CRTC 1047 * drm_vblank_off - disable vblank events on a CRTC
993 * @dev: DRM device 1048 * @dev: DRM device
994 * @crtc: CRTC in question 1049 * @crtc: CRTC in question
@@ -1009,6 +1064,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
1009 unsigned long irqflags; 1064 unsigned long irqflags;
1010 unsigned int seq; 1065 unsigned int seq;
1011 1066
1067 if (WARN_ON(crtc >= dev->num_crtcs))
1068 return;
1069
1012 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1070 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1013 vblank_disable_and_save(dev, crtc); 1071 vblank_disable_and_save(dev, crtc);
1014 wake_up(&dev->vblank[crtc].queue); 1072 wake_up(&dev->vblank[crtc].queue);
@@ -1068,6 +1126,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
1068{ 1126{
1069 unsigned long irqflags; 1127 unsigned long irqflags;
1070 1128
1129 if (WARN_ON(crtc >= dev->num_crtcs))
1130 return;
1131
1071 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1132 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1072 /* re-enable interrupts if there's are users left */ 1133 /* re-enable interrupts if there's are users left */
1073 if (atomic_read(&dev->vblank[crtc].refcount) != 0) 1134 if (atomic_read(&dev->vblank[crtc].refcount) != 0)
@@ -1121,6 +1182,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
1121 /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1182 /* vblank is not initialized (IRQ not installed ?), or has been freed */
1122 if (!dev->num_crtcs) 1183 if (!dev->num_crtcs)
1123 return; 1184 return;
1185
1186 if (WARN_ON(crtc >= dev->num_crtcs))
1187 return;
1188
1124 /* 1189 /*
1125 * To avoid all the problems that might happen if interrupts 1190 * To avoid all the problems that might happen if interrupts
1126 * were enabled/disabled around or between these calls, we just 1191 * were enabled/disabled around or between these calls, we just
@@ -1429,6 +1494,9 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
1429 if (!dev->num_crtcs) 1494 if (!dev->num_crtcs)
1430 return false; 1495 return false;
1431 1496
1497 if (WARN_ON(crtc >= dev->num_crtcs))
1498 return false;
1499
1432 /* Need timestamp lock to prevent concurrent execution with 1500 /* Need timestamp lock to prevent concurrent execution with
1433 * vblank enable/disable, as this would cause inconsistent 1501 * vblank enable/disable, as this would cause inconsistent
1434 * or corrupted timestamps and vblank counts. 1502 * or corrupted timestamps and vblank counts.
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index bedf1894e17e..d1b7d2006529 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1259,6 +1259,7 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
1259 if (!mode) 1259 if (!mode)
1260 return NULL; 1260 return NULL;
1261 1261
1262 mode->type |= DRM_MODE_TYPE_USERDEF;
1262 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 1263 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1263 return mode; 1264 return mode;
1264} 1265}
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index 0dc57d5ecd10..8749fc06570e 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -57,6 +57,212 @@
57 57
58 58
59/** 59/**
60 * __drm_modeset_lock_all - internal helper to grab all modeset locks
61 * @dev: DRM device
62 * @trylock: trylock mode for atomic contexts
63 *
64 * This is a special version of drm_modeset_lock_all() which can also be used in
65 * atomic contexts. Then @trylock must be set to true.
66 *
67 * Returns:
68 * 0 on success or negative error code on failure.
69 */
70int __drm_modeset_lock_all(struct drm_device *dev,
71 bool trylock)
72{
73 struct drm_mode_config *config = &dev->mode_config;
74 struct drm_modeset_acquire_ctx *ctx;
75 int ret;
76
77 ctx = kzalloc(sizeof(*ctx),
78 trylock ? GFP_ATOMIC : GFP_KERNEL);
79 if (!ctx)
80 return -ENOMEM;
81
82 if (trylock) {
83 if (!mutex_trylock(&config->mutex))
84 return -EBUSY;
85 } else {
86 mutex_lock(&config->mutex);
87 }
88
89 drm_modeset_acquire_init(ctx, 0);
90 ctx->trylock_only = trylock;
91
92retry:
93 ret = drm_modeset_lock(&config->connection_mutex, ctx);
94 if (ret)
95 goto fail;
96 ret = drm_modeset_lock_all_crtcs(dev, ctx);
97 if (ret)
98 goto fail;
99
100 WARN_ON(config->acquire_ctx);
101
102 /* now we hold the locks, so now that it is safe, stash the
103 * ctx for drm_modeset_unlock_all():
104 */
105 config->acquire_ctx = ctx;
106
107 drm_warn_on_modeset_not_all_locked(dev);
108
109 return 0;
110
111fail:
112 if (ret == -EDEADLK) {
113 drm_modeset_backoff(ctx);
114 goto retry;
115 }
116
117 return ret;
118}
119EXPORT_SYMBOL(__drm_modeset_lock_all);
120
121/**
122 * drm_modeset_lock_all - take all modeset locks
123 * @dev: drm device
124 *
125 * This function takes all modeset locks, suitable where a more fine-grained
126 * scheme isn't (yet) implemented. Locks must be dropped with
127 * drm_modeset_unlock_all.
128 */
129void drm_modeset_lock_all(struct drm_device *dev)
130{
131 WARN_ON(__drm_modeset_lock_all(dev, false) != 0);
132}
133EXPORT_SYMBOL(drm_modeset_lock_all);
134
135/**
136 * drm_modeset_unlock_all - drop all modeset locks
137 * @dev: device
138 *
139 * This function drop all modeset locks taken by drm_modeset_lock_all.
140 */
141void drm_modeset_unlock_all(struct drm_device *dev)
142{
143 struct drm_mode_config *config = &dev->mode_config;
144 struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
145
146 if (WARN_ON(!ctx))
147 return;
148
149 config->acquire_ctx = NULL;
150 drm_modeset_drop_locks(ctx);
151 drm_modeset_acquire_fini(ctx);
152
153 kfree(ctx);
154
155 mutex_unlock(&dev->mode_config.mutex);
156}
157EXPORT_SYMBOL(drm_modeset_unlock_all);
158
159/**
160 * drm_modeset_lock_crtc - lock crtc with hidden acquire ctx
161 * @crtc: drm crtc
162 *
163 * This function locks the given crtc using a hidden acquire context. This is
164 * necessary so that drivers internally using the atomic interfaces can grab
165 * further locks with the lock acquire context.
166 */
167void drm_modeset_lock_crtc(struct drm_crtc *crtc)
168{
169 struct drm_modeset_acquire_ctx *ctx;
170 int ret;
171
172 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
173 if (WARN_ON(!ctx))
174 return;
175
176 drm_modeset_acquire_init(ctx, 0);
177
178retry:
179 ret = drm_modeset_lock(&crtc->mutex, ctx);
180 if (ret)
181 goto fail;
182
183 WARN_ON(crtc->acquire_ctx);
184
185 /* now we hold the locks, so now that it is safe, stash the
186 * ctx for drm_modeset_unlock_crtc():
187 */
188 crtc->acquire_ctx = ctx;
189
190 return;
191
192fail:
193 if (ret == -EDEADLK) {
194 drm_modeset_backoff(ctx);
195 goto retry;
196 }
197}
198EXPORT_SYMBOL(drm_modeset_lock_crtc);
199
200/**
201 * drm_modeset_legacy_acquire_ctx - find acquire ctx for legacy ioctls
202 * @crtc: drm crtc
203 *
204 * Legacy ioctl operations like cursor updates or page flips only have per-crtc
205 * locking, and store the acquire ctx in the corresponding crtc. All other
206 * legacy operations take all locks and use a global acquire context. This
207 * function grabs the right one.
208 */
209struct drm_modeset_acquire_ctx *
210drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc)
211{
212 if (crtc->acquire_ctx)
213 return crtc->acquire_ctx;
214
215 WARN_ON(!crtc->dev->mode_config.acquire_ctx);
216
217 return crtc->dev->mode_config.acquire_ctx;
218}
219EXPORT_SYMBOL(drm_modeset_legacy_acquire_ctx);
220
221/**
222 * drm_modeset_unlock_crtc - drop crtc lock
223 * @crtc: drm crtc
224 *
225 * This drops the crtc lock acquire with drm_modeset_lock_crtc() and all other
226 * locks acquired through the hidden context.
227 */
228void drm_modeset_unlock_crtc(struct drm_crtc *crtc)
229{
230 struct drm_modeset_acquire_ctx *ctx = crtc->acquire_ctx;
231
232 if (WARN_ON(!ctx))
233 return;
234
235 crtc->acquire_ctx = NULL;
236 drm_modeset_drop_locks(ctx);
237 drm_modeset_acquire_fini(ctx);
238
239 kfree(ctx);
240}
241EXPORT_SYMBOL(drm_modeset_unlock_crtc);
242
243/**
244 * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
245 * @dev: device
246 *
247 * Useful as a debug assert.
248 */
249void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
250{
251 struct drm_crtc *crtc;
252
253 /* Locking is currently fubar in the panic handler. */
254 if (oops_in_progress)
255 return;
256
257 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
258 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
259
260 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
261 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
262}
263EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
264
265/**
60 * drm_modeset_acquire_init - initialize acquire context 266 * drm_modeset_acquire_init - initialize acquire context
61 * @ctx: the acquire context 267 * @ctx: the acquire context
62 * @flags: for future 268 * @flags: for future
@@ -108,7 +314,12 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
108 314
109 WARN_ON(ctx->contended); 315 WARN_ON(ctx->contended);
110 316
111 if (interruptible && slow) { 317 if (ctx->trylock_only) {
318 if (!ww_mutex_trylock(&lock->mutex))
319 return -EBUSY;
320 else
321 return 0;
322 } else if (interruptible && slow) {
112 ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx); 323 ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx);
113 } else if (interruptible) { 324 } else if (interruptible) {
114 ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx); 325 ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx);
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index db7d250f7ac7..6857e9ad6339 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -82,6 +82,22 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
82 return; 82 return;
83} 83}
84 84
85static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
86{
87 struct drm_display_mode *mode;
88
89 if (!connector->cmdline_mode.specified)
90 return 0;
91
92 mode = drm_mode_create_from_cmdline_mode(connector->dev,
93 &connector->cmdline_mode);
94 if (mode == NULL)
95 return 0;
96
97 drm_mode_probed_add(connector, mode);
98 return 1;
99}
100
85static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector, 101static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
86 uint32_t maxX, uint32_t maxY, bool merge_type_bits) 102 uint32_t maxX, uint32_t maxY, bool merge_type_bits)
87{ 103{
@@ -141,6 +157,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
141 157
142 if (count == 0 && connector->status == connector_status_connected) 158 if (count == 0 && connector->status == connector_status_connected)
143 count = drm_add_modes_noedid(connector, 1024, 768); 159 count = drm_add_modes_noedid(connector, 1024, 768);
160 count += drm_helper_probe_add_cmdline_mode(connector);
144 if (count == 0) 161 if (count == 0)
145 goto prune; 162 goto prune;
146 163
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 45f04dea0ac2..83485ab81ce8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1483,11 +1483,7 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
1483{ 1483{
1484 struct drm_device *dev = connector->dev; 1484 struct drm_device *dev = connector->dev;
1485 struct mga_device *mdev = (struct mga_device*)dev->dev_private; 1485 struct mga_device *mdev = (struct mga_device*)dev->dev_private;
1486 struct mga_fbdev *mfbdev = mdev->mfbdev;
1487 struct drm_fb_helper *fb_helper = &mfbdev->helper;
1488 struct drm_fb_helper_connector *fb_helper_conn = NULL;
1489 int bpp = 32; 1486 int bpp = 32;
1490 int i = 0;
1491 1487
1492 if (IS_G200_SE(mdev)) { 1488 if (IS_G200_SE(mdev)) {
1493 if (mdev->unique_rev_id == 0x01) { 1489 if (mdev->unique_rev_id == 0x01) {
@@ -1537,21 +1533,14 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
1537 } 1533 }
1538 1534
1539 /* Validate the mode input by the user */ 1535 /* Validate the mode input by the user */
1540 for (i = 0; i < fb_helper->connector_count; i++) { 1536 if (connector->cmdline_mode.specified) {
1541 if (fb_helper->connector_info[i]->connector == connector) { 1537 if (connector->cmdline_mode.bpp_specified)
1542 /* Found the helper for this connector */ 1538 bpp = connector->cmdline_mode.bpp;
1543 fb_helper_conn = fb_helper->connector_info[i];
1544 if (fb_helper_conn->cmdline_mode.specified) {
1545 if (fb_helper_conn->cmdline_mode.bpp_specified) {
1546 bpp = fb_helper_conn->cmdline_mode.bpp;
1547 }
1548 }
1549 }
1550 } 1539 }
1551 1540
1552 if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) { 1541 if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
1553 if (fb_helper_conn) 1542 if (connector->cmdline_mode.specified)
1554 fb_helper_conn->cmdline_mode.specified = false; 1543 connector->cmdline_mode.specified = false;
1555 return MODE_BAD; 1544 return MODE_BAD;
1556 } 1545 }
1557 1546
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index e911b9c96e19..ccbe2ae22ac5 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -4,6 +4,7 @@
4 4
5menuconfig FB 5menuconfig FB
6 tristate "Support for frame buffer devices" 6 tristate "Support for frame buffer devices"
7 select FB_CMDLINE
7 ---help--- 8 ---help---
8 The frame buffer device provides an abstraction for the graphics 9 The frame buffer device provides an abstraction for the graphics
9 hardware. It represents the frame buffer of some video hardware and 10 hardware. It represents the frame buffer of some video hardware and
@@ -52,6 +53,9 @@ config FIRMWARE_EDID
52 combination with certain motherboards and monitors are known to 53 combination with certain motherboards and monitors are known to
53 suffer from this problem. 54 suffer from this problem.
54 55
56config FB_CMDLINE
57 bool
58
55config FB_DDC 59config FB_DDC
56 tristate 60 tristate
57 depends on FB 61 depends on FB
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
index fa306538dac2..67f28e20a892 100644
--- a/drivers/video/fbdev/core/Makefile
+++ b/drivers/video/fbdev/core/Makefile
@@ -1,4 +1,5 @@
1obj-y += fb_notify.o 1obj-y += fb_notify.o
2obj-$(CONFIG_FB_CMDLINE) += fb_cmdline.o
2obj-$(CONFIG_FB) += fb.o 3obj-$(CONFIG_FB) += fb.o
3fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ 4fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
4 modedb.o fbcvt.o 5 modedb.o fbcvt.o
diff --git a/drivers/video/fbdev/core/fb_cmdline.c b/drivers/video/fbdev/core/fb_cmdline.c
new file mode 100644
index 000000000000..39509ccd92f1
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_cmdline.c
@@ -0,0 +1,110 @@
1/*
2 * linux/drivers/video/fb_cmdline.c
3 *
4 * Copyright (C) 2014 Intel Corp
5 * Copyright (C) 1994 Martin Schaller
6 *
7 * 2001 - Documented with DocBook
8 * - Brad Douglas <brad@neruo.com>
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive
12 * for more details.
13 *
14 * Authors:
15 * Vetter <danie.vetter@ffwll.ch>
16 */
17#include <linux/init.h>
18#include <linux/fb.h>
19
20static char *video_options[FB_MAX] __read_mostly;
21static int ofonly __read_mostly;
22
23const char *fb_mode_option;
24EXPORT_SYMBOL_GPL(fb_mode_option);
25
26/**
27 * fb_get_options - get kernel boot parameters
28 * @name: framebuffer name as it would appear in
29 * the boot parameter line
30 * (video=<name>:<options>)
31 * @option: the option will be stored here
32 *
33 * NOTE: Needed to maintain backwards compatibility
34 */
35int fb_get_options(const char *name, char **option)
36{
37 char *opt, *options = NULL;
38 int retval = 0;
39 int name_len = strlen(name), i;
40
41 if (name_len && ofonly && strncmp(name, "offb", 4))
42 retval = 1;
43
44 if (name_len && !retval) {
45 for (i = 0; i < FB_MAX; i++) {
46 if (video_options[i] == NULL)
47 continue;
48 if (!video_options[i][0])
49 continue;
50 opt = video_options[i];
51 if (!strncmp(name, opt, name_len) &&
52 opt[name_len] == ':')
53 options = opt + name_len + 1;
54 }
55 }
56 /* No match, pass global option */
57 if (!options && option && fb_mode_option)
58 options = kstrdup(fb_mode_option, GFP_KERNEL);
59 if (options && !strncmp(options, "off", 3))
60 retval = 1;
61
62 if (option)
63 *option = options;
64
65 return retval;
66}
67EXPORT_SYMBOL(fb_get_options);
68
69/**
70 * video_setup - process command line options
71 * @options: string of options
72 *
73 * Process command line options for frame buffer subsystem.
74 *
75 * NOTE: This function is a __setup and __init function.
76 * It only stores the options. Drivers have to call
77 * fb_get_options() as necessary.
78 *
79 * Returns zero.
80 *
81 */
82static int __init video_setup(char *options)
83{
84 int i, global = 0;
85
86 if (!options || !*options)
87 global = 1;
88
89 if (!global && !strncmp(options, "ofonly", 6)) {
90 ofonly = 1;
91 global = 1;
92 }
93
94 if (!global && !strchr(options, ':')) {
95 fb_mode_option = options;
96 global = 1;
97 }
98
99 if (!global) {
100 for (i = 0; i < FB_MAX; i++) {
101 if (video_options[i] == NULL) {
102 video_options[i] = options;
103 break;
104 }
105 }
106 }
107
108 return 1;
109}
110__setup("video=", video_setup);
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index b5e85f6c1c26..0705d8883ede 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1908,96 +1908,4 @@ int fb_new_modelist(struct fb_info *info)
1908 return err; 1908 return err;
1909} 1909}
1910 1910
1911static char *video_options[FB_MAX] __read_mostly;
1912static int ofonly __read_mostly;
1913
1914/**
1915 * fb_get_options - get kernel boot parameters
1916 * @name: framebuffer name as it would appear in
1917 * the boot parameter line
1918 * (video=<name>:<options>)
1919 * @option: the option will be stored here
1920 *
1921 * NOTE: Needed to maintain backwards compatibility
1922 */
1923int fb_get_options(const char *name, char **option)
1924{
1925 char *opt, *options = NULL;
1926 int retval = 0;
1927 int name_len = strlen(name), i;
1928
1929 if (name_len && ofonly && strncmp(name, "offb", 4))
1930 retval = 1;
1931
1932 if (name_len && !retval) {
1933 for (i = 0; i < FB_MAX; i++) {
1934 if (video_options[i] == NULL)
1935 continue;
1936 if (!video_options[i][0])
1937 continue;
1938 opt = video_options[i];
1939 if (!strncmp(name, opt, name_len) &&
1940 opt[name_len] == ':')
1941 options = opt + name_len + 1;
1942 }
1943 }
1944 /* No match, pass global option */
1945 if (!options && option && fb_mode_option)
1946 options = kstrdup(fb_mode_option, GFP_KERNEL);
1947 if (options && !strncmp(options, "off", 3))
1948 retval = 1;
1949
1950 if (option)
1951 *option = options;
1952
1953 return retval;
1954}
1955EXPORT_SYMBOL(fb_get_options);
1956
1957#ifndef MODULE
1958/**
1959 * video_setup - process command line options
1960 * @options: string of options
1961 *
1962 * Process command line options for frame buffer subsystem.
1963 *
1964 * NOTE: This function is a __setup and __init function.
1965 * It only stores the options. Drivers have to call
1966 * fb_get_options() as necessary.
1967 *
1968 * Returns zero.
1969 *
1970 */
1971static int __init video_setup(char *options)
1972{
1973 int i, global = 0;
1974
1975 if (!options || !*options)
1976 global = 1;
1977
1978 if (!global && !strncmp(options, "ofonly", 6)) {
1979 ofonly = 1;
1980 global = 1;
1981 }
1982
1983 if (!global && !strchr(options, ':')) {
1984 fb_mode_option = options;
1985 global = 1;
1986 }
1987
1988 if (!global) {
1989 for (i = 0; i < FB_MAX; i++) {
1990 if (video_options[i] == NULL) {
1991 video_options[i] = options;
1992 break;
1993 }
1994
1995 }
1996 }
1997
1998 return 1;
1999}
2000__setup("video=", video_setup);
2001#endif
2002
2003MODULE_LICENSE("GPL"); 1911MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c
index a9a907c440d7..388f7971494b 100644
--- a/drivers/video/fbdev/core/modedb.c
+++ b/drivers/video/fbdev/core/modedb.c
@@ -29,9 +29,6 @@
29#define DPRINTK(fmt, args...) 29#define DPRINTK(fmt, args...)
30#endif 30#endif
31 31
32const char *fb_mode_option;
33EXPORT_SYMBOL_GPL(fb_mode_option);
34
35/* 32/*
36 * Standard video mode definitions (taken from XFree86) 33 * Standard video mode definitions (taken from XFree86)
37 */ 34 */