From 966a6a13c6660b499caf2932de22ae70c1317786 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 29 Nov 2016 12:02:15 +0000 Subject: drm: Hold mode_config.lock to prevent hotplug whilst setting up crtcs The fb_helper->connector_count is modified when a new connector is constructed following a hotplug event (e.g. DP-MST). This causes trouble for drm_setup_crtcs() and friends that assume that fb_helper is constant: [ 1250.872997] BUG: KASAN: slab-out-of-bounds in drm_setup_crtcs+0x320/0xf80 at addr ffff88074cdd2608 [ 1250.873020] Write of size 40 by task kworker/u8:3/480 [ 1250.873039] CPU: 2 PID: 480 Comm: kworker/u8:3 Tainted: G U 4.9.0-rc6+ #285 [ 1250.873043] Hardware name: /NUC6i3SYB, BIOS SYSKLi35.86A.0024.2015.1027.2142 10/27/2015 [ 1250.873050] Workqueue: events_unbound async_run_entry_fn [ 1250.873056] ffff88070f9d78f0 ffffffff814b72aa ffff88074e40c5c0 ffff88074cdd2608 [ 1250.873067] ffff88070f9d7918 ffffffff8124ff3c ffff88070f9d79b0 ffff88074cdd2600 [ 1250.873079] ffff88074e40c5c0 ffff88070f9d79a0 ffffffff812501e4 0000000000000005 [ 1250.873090] Call Trace: [ 1250.873099] [] dump_stack+0x67/0x9d [ 1250.873106] [] kasan_object_err+0x1c/0x70 [ 1250.873113] [] kasan_report_error+0x204/0x4f0 [ 1250.873120] [] ? drm_dev_printk+0x140/0x140 [ 1250.873127] [] kasan_report+0x53/0x60 [ 1250.873134] [] ? drm_setup_crtcs+0x320/0xf80 [ 1250.873142] [] check_memory_region+0x13e/0x1a0 [ 1250.873147] [] memset+0x23/0x40 [ 1250.873154] [] drm_setup_crtcs+0x320/0xf80 [ 1250.873161] [] ? wake_up_q+0x45/0x80 [ 1250.873169] [] ? mutex_lock_nested+0x5a0/0x5a0 [ 1250.873176] [] drm_fb_helper_initial_config+0x206/0x7a0 [ 1250.873183] [] ? drm_fb_helper_set_par+0x90/0x90 [ 1250.873303] [] ? intel_fbdev_fini+0x140/0x140 [i915] [ 1250.873387] [] intel_fbdev_initial_config+0x22/0x40 [i915] [ 1250.873391] [] async_run_entry_fn+0x7f/0x270 [ 1250.873394] [] process_one_work+0x3d0/0x960 [ 1250.873398] [] ? process_one_work+0x33d/0x960 [ 1250.873401] [] ? max_active_store+0xf0/0xf0 [ 1250.873406] [] ? do_raw_spin_lock+0x10d/0x1a0 [ 1250.873413] [] worker_thread+0x8d/0x840 [ 1250.873419] [] ? create_worker+0x2e0/0x2e0 [ 1250.873426] [] kthread+0x194/0x1c0 [ 1250.873432] [] ? kthread_park+0x60/0x60 [ 1250.873438] [] ? trace_hardirqs_on+0xd/0x10 [ 1250.873446] [] ? kthread_park+0x60/0x60 [ 1250.873453] [] ? kthread_park+0x60/0x60 [ 1250.873457] [] ret_from_fork+0x27/0x40 [ 1250.873460] Object at ffff88074cdd2608, in cache kmalloc-32 size: 32 However, when holding the mode_config.lock around the fb_helper, we have to be careful of any callbacks that may reenter the fb_helper and so try to reacquire the mode_config.lock (e.g. register_framebuffer). To avoid the mutex recursion, we have to rearrange the sequence to move the registration into the caller outside of the mode_config.lock. v2: drop the 1; following the lockdep assertion inside the for(;;), I anticipated an error that doesn't happen! Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98826 Signed-off-by: Chris Wilson Cc: Daniel Vetter Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/20161129120217.7344-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_fb_helper.c | 73 ++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1f26634f53d8..380a0ec01033 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -97,6 +97,10 @@ static LIST_HEAD(kernel_fb_helper_list); * mmap page writes. */ +#define drm_fb_helper_for_each_connector(fbh, i__) \ + for (({ lockdep_assert_held(&(fbh)->dev->mode_config.mutex); }), \ + i__ = 0; i__ < (fbh)->connector_count; i__++) + /** * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev * emulation helper @@ -130,7 +134,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) mutex_unlock(&dev->mode_config.mutex); return 0; fail: - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_fb_helper_connector *fb_helper_connector = fb_helper->connector_info[i]; @@ -565,7 +569,7 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) continue; /* Walk the connectors & encoders on this fb turning them on/off */ - for (j = 0; j < fb_helper->connector_count; j++) { + drm_fb_helper_for_each_connector(fb_helper, j) { connector = fb_helper->connector_info[j]->connector; connector->funcs->dpms(connector, dpms_mode); drm_object_property_set_value(&connector->base, @@ -1469,7 +1473,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int ret = 0; int crtc_count = 0; int i; - struct fb_info *info; struct drm_fb_helper_surface_size sizes; int gamma_size = 0; @@ -1485,7 +1488,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, sizes.surface_depth = sizes.surface_bpp = preferred_bpp; /* first up get a count of crtcs now in use and new min/maxes width/heights */ - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; struct drm_cmdline_mode *cmdline_mode; @@ -1572,8 +1575,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, if (ret < 0) return ret; - info = fb_helper->fbdev; - /* * Set the fb pointer - usually drm_setup_crtcs does this for hotplug * events, but at init time drm_setup_crtcs needs to be called before @@ -1585,20 +1586,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, if (fb_helper->crtc_info[i].mode_set.num_connectors) fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; - - info->var.pixclock = 0; - if (register_framebuffer(info) < 0) - return -EINVAL; - - dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n", - info->node, info->fix.id); - - if (list_empty(&kernel_fb_helper_list)) { - register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); - } - - list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); - return 0; } @@ -1730,7 +1717,7 @@ static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper, int count = 0; int i; - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { connector = fb_helper->connector_info[i]->connector; count += connector->funcs->fill_modes(connector, maxX, maxY); } @@ -1830,7 +1817,7 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper, struct drm_connector *connector; int i = 0; - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { connector = fb_helper->connector_info[i]->connector; enabled[i] = drm_connector_enabled(connector, true); DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, @@ -1841,7 +1828,7 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper, if (any_enabled) return; - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { connector = fb_helper->connector_info[i]->connector; enabled[i] = drm_connector_enabled(connector, false); } @@ -1862,7 +1849,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, return false; count = 0; - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { if (enabled[i]) count++; } @@ -1873,7 +1860,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, /* check the command line or if nothing common pick 1024x768 */ can_clone = true; - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { if (!enabled[i]) continue; fb_helper_conn = fb_helper->connector_info[i]; @@ -1899,8 +1886,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, can_clone = true; dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false); - for (i = 0; i < fb_helper->connector_count; i++) { - + drm_fb_helper_for_each_connector(fb_helper, i) { if (!enabled[i]) continue; @@ -1931,7 +1917,7 @@ static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper, int i; int hoffset = 0, voffset = 0; - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { fb_helper_conn = fb_helper->connector_info[i]; if (!fb_helper_conn->connector->has_tile) continue; @@ -1965,7 +1951,7 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper, int i; retry: - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { fb_helper_conn = fb_helper->connector_info[i]; if (conn_configured & BIT_ULL(i)) @@ -2128,6 +2114,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) width = dev->mode_config.max_width; height = dev->mode_config.max_height; + /* prevent concurrent modification of connector_count by hotplug */ + lockdep_assert_held(&fb_helper->dev->mode_config.mutex); + crtcs = kcalloc(fb_helper->connector_count, sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); modes = kcalloc(fb_helper->connector_count, @@ -2141,7 +2130,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) goto out; } - drm_enable_connectors(fb_helper, enabled); if (!(fb_helper->funcs->initial_config && @@ -2170,7 +2158,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) drm_fb_helper_modeset_release(fb_helper, &fb_helper->crtc_info[i].mode_set); - for (i = 0; i < fb_helper->connector_count; i++) { + drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_display_mode *mode = modes[i]; struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; struct drm_fb_offset *offset = &offsets[i]; @@ -2247,7 +2235,9 @@ out: int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) { struct drm_device *dev = fb_helper->dev; + struct fb_info *info; int count = 0; + int ret; if (!drm_fbdev_emulation) return 0; @@ -2256,7 +2246,6 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) count = drm_fb_helper_probe_connector_modes(fb_helper, dev->mode_config.max_width, dev->mode_config.max_height); - mutex_unlock(&dev->mode_config.mutex); /* * we shouldn't end up with no modes here. */ @@ -2264,8 +2253,26 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n"); drm_setup_crtcs(fb_helper); + ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); + mutex_unlock(&dev->mode_config.mutex); + if (ret) + return ret; - return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); + info = fb_helper->fbdev; + info->var.pixclock = 0; + ret = register_framebuffer(info); + if (ret < 0) + return ret; + + dev_info(dev->dev, "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + + if (list_empty(&kernel_fb_helper_list)) + register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); + + list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); + + return 0; } EXPORT_SYMBOL(drm_fb_helper_initial_config); -- cgit v1.2.3 From 64e94407fb5a4128636c2b15b38fa6e71a427228 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 29 Nov 2016 12:02:16 +0000 Subject: drm: Pull together probe + setup for drm_fb_helper drm_fb_helper_probe_connector_modes() is always called before drm_setup_crtcs(), so just move the call into drm_setup_crtcs for a small bit of code compaction. Note that register_framebuffer will do a modeset (when fbcon is enabled) and hence must be moved out of the critical section. A follow-up patch will add new locking for the fb list, hence move all the related registration code together. Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/20161129120217.7344-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_fb_helper.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 380a0ec01033..90da28d2fcf3 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2099,20 +2099,19 @@ out: return best_score; } -static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) +static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, + u32 width, u32 height) { struct drm_device *dev = fb_helper->dev; struct drm_fb_helper_crtc **crtcs; struct drm_display_mode **modes; struct drm_fb_offset *offsets; bool *enabled; - int width, height; int i; DRM_DEBUG_KMS("\n"); - - width = dev->mode_config.max_width; - height = dev->mode_config.max_height; + if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) + DRM_DEBUG_KMS("No connectors reported connected with modes\n"); /* prevent concurrent modification of connector_count by hotplug */ lockdep_assert_held(&fb_helper->dev->mode_config.mutex); @@ -2236,23 +2235,15 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) { struct drm_device *dev = fb_helper->dev; struct fb_info *info; - int count = 0; int ret; if (!drm_fbdev_emulation) return 0; mutex_lock(&dev->mode_config.mutex); - count = drm_fb_helper_probe_connector_modes(fb_helper, - dev->mode_config.max_width, - dev->mode_config.max_height); - /* - * we shouldn't end up with no modes here. - */ - if (count == 0) - dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n"); - - drm_setup_crtcs(fb_helper); + drm_setup_crtcs(fb_helper, + dev->mode_config.max_width, + dev->mode_config.max_height); ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); mutex_unlock(&dev->mode_config.mutex); if (ret) @@ -2300,28 +2291,22 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; - u32 max_width, max_height; if (!drm_fbdev_emulation) return 0; - mutex_lock(&fb_helper->dev->mode_config.mutex); + mutex_lock(&dev->mode_config.mutex); if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { fb_helper->delayed_hotplug = true; - mutex_unlock(&fb_helper->dev->mode_config.mutex); + mutex_unlock(&dev->mode_config.mutex); return 0; } DRM_DEBUG_KMS("\n"); - max_width = fb_helper->fb->width; - max_height = fb_helper->fb->height; + drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height); - drm_fb_helper_probe_connector_modes(fb_helper, max_width, max_height); - mutex_unlock(&fb_helper->dev->mode_config.mutex); + mutex_unlock(&dev->mode_config.mutex); - drm_modeset_lock_all(dev); - drm_setup_crtcs(fb_helper); - drm_modeset_unlock_all(dev); drm_fb_helper_set_par(fb_helper->fbdev); return 0; -- cgit v1.2.3 From a53ca63502e62ca459de32821753c8227dc94197 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 29 Nov 2016 12:02:17 +0000 Subject: drm: Protect fb_helper list manipulation with a mutex Though we only walk the kernel_fb_helper_list inside a panic (or single thread debugging), we still need to protect the list manipulation on creating/removing a framebuffer device in order to prevent list corruption. Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/20161129120217.7344-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_fb_helper.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 90da28d2fcf3..e934b541feea 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -49,6 +49,7 @@ MODULE_PARM_DESC(fbdev_emulation, "Enable legacy fbdev emulation [default=true]"); static LIST_HEAD(kernel_fb_helper_list); +static DEFINE_MUTEX(kernel_fb_helper_lock); /** * DOC: fbdev helpers @@ -855,12 +856,14 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) if (!drm_fbdev_emulation) return; + mutex_lock(&kernel_fb_helper_lock); if (!list_empty(&fb_helper->kernel_fb_list)) { list_del(&fb_helper->kernel_fb_list); if (list_empty(&kernel_fb_helper_list)) { unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); } } + mutex_unlock(&kernel_fb_helper_lock); drm_fb_helper_crtc_free(fb_helper); @@ -2258,10 +2261,12 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) dev_info(dev->dev, "fb%d: %s frame buffer device\n", info->node, info->fix.id); + mutex_lock(&kernel_fb_helper_lock); if (list_empty(&kernel_fb_helper_list)) register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); + mutex_unlock(&kernel_fb_helper_lock); return 0; } -- cgit v1.2.3 From b07c42547b8253c806ae2d03c452b7d894672685 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 29 Nov 2016 10:24:40 +0100 Subject: drm/doc: Fix indenting in drm_modeset_lock.c comment This isn't part of the code snippet anymore ... Acked-by: Rob Clark Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161129092440.6940-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_modeset_lock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index 9059fe3145a1..3551ae31f143 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -52,12 +52,12 @@ * drm_modeset_drop_locks(&ctx); * drm_modeset_acquire_fini(&ctx); * - * On top of of these per-object locks using &ww_mutex there's also an overall - * dev->mode_config.lock, for protecting everything else. Mostly this means - * probe state of connectors, and preventing hotplug add/removal of connectors. + * On top of of these per-object locks using &ww_mutex there's also an overall + * dev->mode_config.lock, for protecting everything else. Mostly this means + * probe state of connectors, and preventing hotplug add/removal of connectors. * - * Finally there's a bunch of dedicated locks to protect drm core internal - * lists and lookup data structures. + * Finally there's a bunch of dedicated locks to protect drm core internal + * lists and lookup data structures. */ static DEFINE_WW_CLASS(crtc_ww_class); -- cgit v1.2.3 From 661a3755610ead153232011d22dc5c3688b24146 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 29 Nov 2016 10:45:38 +0100 Subject: drm: Fix locking cargo-cult in encoder/plane init/cleanup Encoders&planes can't be hotplugged, we dont need locking for this since it's all single-threaded driver setup/teardown code. CRTCs already don't grab locks. While at it I noticed that plane's are missing the drm_modeset_lock_fini() call, so add it. Reviewed-by: Frank Binns Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161129094538.9650-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_encoder.c | 9 +-------- drivers/gpu/drm/drm_plane.c | 4 ++-- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c index 5c067719164d..992879f15f23 100644 --- a/drivers/gpu/drm/drm_encoder.c +++ b/drivers/gpu/drm/drm_encoder.c @@ -110,11 +110,9 @@ int drm_encoder_init(struct drm_device *dev, { int ret; - drm_modeset_lock_all(dev); - ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); if (ret) - goto out_unlock; + return ret; encoder->dev = dev; encoder->encoder_type = encoder_type; @@ -142,9 +140,6 @@ out_put: if (ret) drm_mode_object_unregister(dev, &encoder->base); -out_unlock: - drm_modeset_unlock_all(dev); - return ret; } EXPORT_SYMBOL(drm_encoder_init); @@ -164,12 +159,10 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) * the indices on the drm_encoder after us in the encoder_list. */ - drm_modeset_lock_all(dev); drm_mode_object_unregister(dev, &encoder->base); kfree(encoder->name); list_del(&encoder->head); dev->mode_config.num_encoder--; - drm_modeset_unlock_all(dev); memset(encoder, 0, sizeof(*encoder)); } diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 419ac313c36f..9147aab182c4 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -221,7 +221,8 @@ void drm_plane_cleanup(struct drm_plane *plane) { struct drm_device *dev = plane->dev; - drm_modeset_lock_all(dev); + drm_modeset_lock_fini(&plane->mutex); + kfree(plane->format_types); drm_mode_object_unregister(dev, &plane->base); @@ -236,7 +237,6 @@ void drm_plane_cleanup(struct drm_plane *plane) dev->mode_config.num_total_plane--; if (plane->type == DRM_PLANE_TYPE_OVERLAY) dev->mode_config.num_overlay_plane--; - drm_modeset_unlock_all(dev); WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); if (plane->state && plane->funcs->atomic_destroy_state) -- cgit v1.2.3 From cc98e6ce6abe1c0103cbd7aff1ee586622a9361e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 30 Nov 2016 20:51:26 +0000 Subject: drm: Initialise drm_mm.head_node.allocated commit 202b52b7fbf7 ("drm: Track drm_mm nodes with an interval tree") introduced a requirement that the special drm_mm.head_node was initialised and marked as not being allocated. It is a very special node that has no side but has a hole that represents the drm_mm address space, and holds the list of nodes. Since it is not a real node, it is not part of the node rbtree and we detect this as it being unallocated. This presumed that drm_mm_init() was initialising it to zero. It happens that i915 kzallocs its objects and so it was accidentally setting it, but for generic use we cannot make that assumption. [ 22.981519] general protection fault: 0000 [#1] SMP [ 22.981521] Modules linked in: test_drm_mm(+) ctr ccm arc4 rt2800usb rt2x00usb rt2800lib rt2x00lib crc_ccitt mac80211 cmac rfcomm bnep snd_hda_codec_realtek snd_hda_codec_hdmi snd_hda_codec_generic snd_hda_intel dcdbas snd_hda_codec x86_pkg_temp_thermal intel_powerclamp btusb snd_hda_core coretemp crct10dif_pclmul cfg80211 btrtl btbcm btintel bluetooth crc32_pclmul ghash_clmulni_intel aesni_intel snd_pcm i2c_hid aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd snd_timer hid_multitouch snd joydev serio_raw lpc_ich mfd_core i2c_designware_platform i2c_designware_core 8250_dw binfmt_misc soundcore acpi_pad nls_iso8859_1 usbhid hid psmouse ahci libahci [last unloaded: test_drm_mm] [ 22.981544] CPU: 1 PID: 2088 Comm: drm_mm Tainted: G W 4.9.0-rc7+ #234 [ 22.981545] Hardware name: Dell Inc. XPS 13 9343/0310JH, BIOS A07 11/11/2015 [ 22.981546] task: ffff88020c971cc0 task.stack: ffffc90001728000 [ 22.981547] RIP: 0010:[] [] drm_mm_interval_tree_add_node+0xa0/0xd0 [ 22.981551] RSP: 0018:ffffc9000172ba98 EFLAGS: 00010202 [ 22.981552] RAX: 0f0000c69cf63d80 RBX: ffff88020be00000 RCX: ffff88020be00000 [ 22.981553] RDX: 0000000000000fff RSI: ffffc9000172bc48 RDI: ffffffff810ac4df [ 22.981553] RBP: ffffc9000172bb08 R08: ffffc9000172bc70 R09: 0000000000000fff [ 22.981554] R10: ffffffff810ac4d7 R11: 4dc04d8b4cffffe5 R12: 0000000000001000 [ 22.981555] R13: ffffc9000172bbd0 R14: ffffc9000172bbe0 R15: 0000000002000000 [ 22.981556] FS: 00007f80c9fab740(0000) GS:ffff88021f480000(0000) knlGS:0000000000000000 [ 22.981557] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 22.981558] CR2: 00007f80c9fd5000 CR3: 000000020c191000 CR4: 00000000003406e0 [ 22.981559] Stack: [ 22.981560] ffffffff81405d09 ffff88020be00000 ffffc9000172bbe0 000000000172bb08 [ 22.981562] ffffffffffffffff 0000000000000000 0000000000000000 0000000000000000 [ 22.981563] 0000000002000000 0000000002000000 ffffffffa02f3000 ffff88020be00000 [ 22.981565] Call Trace: [ 22.981568] [] ? drm_mm_insert_node_generic+0x229/0x310 [ 22.981570] [] ? 0xffffffffa02f3000 [ 22.981572] [] __subtest_insert_range.constprop.7+0xd1/0x5b0 [test_drm_mm] [ 22.981575] [] ? default_wake_function+0x12/0x20 [ 22.981576] [] ? __wake_up_common+0x55/0x90 [ 22.981578] [] ? sched_clock_cpu+0x72/0xa0 [ 22.981581] [] ? irq_work_queue+0xd/0x80 [ 22.981582] [] ? wake_up_klogd+0x34/0x40 [ 22.981584] [] ? console_unlock+0x4cd/0x530 [ 22.981585] [] ? vprintk_emit+0x2d7/0x490 [ 22.981587] [] ? vprintk_default+0x1f/0x30 [ 22.981589] [] ? printk+0x4d/0x4f [ 22.981590] [] ? 0xffffffffa02f3000 [ 22.981592] [] subtest_insert_range+0x15/0x80 [test_drm_mm] [ 22.981594] [] test_drm_mm_init+0x88/0x1000 [test_drm_mm] [ 22.981597] [] do_one_initcall+0x3d/0x150 [ 22.981600] [] ? kfree+0x13f/0x180 [ 22.981602] [] do_init_module+0x60/0x1f1 [ 22.981606] [] load_module+0x2228/0x2790 [ 22.981608] [] ? __symbol_put+0x40/0x40 [ 22.981612] [] ? kernel_read+0x41/0x60 [ 22.981614] [] SYSC_finit_module+0x96/0xd0 [ 22.981617] [] SyS_finit_module+0xe/0x10 [ 22.981620] [] entry_SYSCALL_64_fastpath+0x17/0x98 [ 22.981622] Code: c7 41 30 00 00 00 00 48 89 e5 48 89 3a 48 c7 c2 20 4e 40 81 e8 b2 a1 f0 ff 5d c3 48 8d 56 78 45 31 d2 48 89 d6 eb 25 48 8b 51 58 <48> 39 50 38 73 04 48 89 50 38 4c 8b 58 28 4c 39 59 48 48 8d 50 [ 22.981651] RIP [] drm_mm_interval_tree_add_node+0xa0/0xd0 [ 22.981655] RSP Testcase: igt/drm_mm Fixes: 202b52b7fbf7 ("drm: Track drm_mm nodes with an interval tree") Signed-off-by: Chris Wilson Cc: David Herrmann Cc: dri-devel@lists.freedesktop.org Cc: Daniel Vetter Cc: # v4.9-rc1+ Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161130205126.31106-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_mm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 025dcd8cadcb..ca1e344f318d 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -905,6 +905,7 @@ void drm_mm_init(struct drm_mm * mm, u64 start, u64 size) /* Clever trick to avoid a special case in the free hole tracking. */ INIT_LIST_HEAD(&mm->head_node.node_list); + mm->head_node.allocated = 0; mm->head_node.hole_follows = 1; mm->head_node.scanned_block = 0; mm->head_node.scanned_prev_free = 0; -- cgit v1.2.3 From 87291e5dbae94da1ddd3966272e0d7d6dc7232f1 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 30 Nov 2016 12:48:10 +0100 Subject: drm/bridge: tc358767: don't warn if display side ASSR enable fails ASSR is an optional feature, so it's a valid operating condition for the display to reject ASSR enable. Demote the warning to the debug level. Acked-by: Philipp Zabel Acked-by:Andrey Gusakov Signed-off-by: Lucas Stach Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/20161130114810.3245-1-l.stach@pengutronix.de --- drivers/gpu/drm/bridge/tc358767.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 44d476ea6d2e..a7872400eed8 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -908,7 +908,7 @@ static int tc_main_link_setup(struct tc_data *tc) goto err_dpcd_read; if (tmp[0] != tc->assr) { - dev_warn(dev, "Failed to switch display ASSR to %d, falling back to unscrambled mode\n", + dev_dbg(dev, "Failed to switch display ASSR to %d, falling back to unscrambled mode\n", tc->assr); /* trying with disabled scrambler */ tc->link.scrambler_dis = 1; -- cgit v1.2.3 From 949f08862d662f17b9d2929c6afb2d4e8f5d50cb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 29 Nov 2016 22:56:30 +0200 Subject: drm: Make the connector .detect() callback optional Many drivers (21 to be exact) create connectors that are always connected (for instance to an LVDS or DSI panel). Instead of forcing them to implement a dummy .detect() handler, make the callback optional and consider the connector as always connected in that case. Reviewed-by: Alex Deucher Acked-by: Maxime Ripard Acked-by: Jyri Sarha Acked-by: Jani Nikula Acked-by: Philipp Zabel Acked-by: Vincent Abriou Acked-by: Alexey Brodkin Signed-off-by: Laurent Pinchart [seanpaul fixed small conflict in rcar-du/rcar_du_lvdscon.c] Signed-off-by: Sean Paul --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 7 ------- drivers/gpu/drm/arc/arcpgu_sim.c | 7 ------- drivers/gpu/drm/ast/ast_mode.c | 7 ------- drivers/gpu/drm/bochs/bochs_kms.c | 7 ------- drivers/gpu/drm/bridge/nxp-ptn3460.c | 7 ------- drivers/gpu/drm/bridge/parade-ps8622.c | 7 ------- drivers/gpu/drm/bridge/tc358767.c | 7 ------- drivers/gpu/drm/cirrus/cirrus_mode.c | 7 ------- drivers/gpu/drm/drm_probe_helper.c | 14 +++++++++++--- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 7 ------- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 14 -------------- drivers/gpu/drm/gma500/psb_intel_lvds.c | 14 -------------- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 7 ------- drivers/gpu/drm/i915/intel_dsi.c | 7 ------- drivers/gpu/drm/imx/imx-ldb.c | 7 ------- drivers/gpu/drm/imx/imx-tve.c | 7 ------- drivers/gpu/drm/imx/parallel-display.c | 7 ------- drivers/gpu/drm/mediatek/mtk_dsi.c | 7 ------- drivers/gpu/drm/mgag200/mgag200_mode.c | 7 ------- drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 7 ------- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 7 ------- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 7 ------- drivers/gpu/drm/sti/sti_hda.c | 7 ------- drivers/gpu/drm/sun4i/sun4i_rgb.c | 7 ------- drivers/gpu/drm/sun4i/sun4i_tv.c | 7 ------- drivers/gpu/drm/tilcdc/tilcdc_panel.c | 8 -------- include/drm/drm_connector.h | 3 +++ 27 files changed, 14 insertions(+), 193 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 81cbf0b05dff..1d93e123532d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -429,12 +429,6 @@ dce_virtual_dpms(struct drm_connector *connector, int mode) return 0; } -static enum drm_connector_status -dce_virtual_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static int dce_virtual_set_property(struct drm_connector *connector, struct drm_property *property, @@ -463,7 +457,6 @@ static const struct drm_connector_helper_funcs dce_virtual_connector_helper_func static const struct drm_connector_funcs dce_virtual_connector_funcs = { .dpms = dce_virtual_dpms, - .detect = dce_virtual_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = dce_virtual_set_property, .destroy = dce_virtual_destroy, diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c index 2bf06d71556a..bca3a678c955 100644 --- a/drivers/gpu/drm/arc/arcpgu_sim.c +++ b/drivers/gpu/drm/arc/arcpgu_sim.c @@ -41,12 +41,6 @@ static int arcpgu_drm_connector_get_modes(struct drm_connector *connector) return count; } -static enum drm_connector_status -arcpgu_drm_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static void arcpgu_drm_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); @@ -61,7 +55,6 @@ arcpgu_drm_connector_helper_funcs = { static const struct drm_connector_funcs arcpgu_drm_connector_funcs = { .dpms = drm_helper_connector_dpms, .reset = drm_atomic_helper_connector_reset, - .detect = arcpgu_drm_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = arcpgu_drm_connector_destroy, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 5957c3e659fe..e26c98f51eb4 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -839,12 +839,6 @@ static void ast_connector_destroy(struct drm_connector *connector) kfree(connector); } -static enum drm_connector_status -ast_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { .mode_valid = ast_mode_valid, .get_modes = ast_get_modes, @@ -853,7 +847,6 @@ static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { static const struct drm_connector_funcs ast_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = ast_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = ast_connector_destroy, }; diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 0b4e5d117043..d5e63eff357b 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -216,12 +216,6 @@ bochs_connector_best_encoder(struct drm_connector *connector) return NULL; } -static enum drm_connector_status bochs_connector_detect(struct drm_connector - *connector, bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = { .get_modes = bochs_connector_get_modes, .mode_valid = bochs_connector_mode_valid, @@ -230,7 +224,6 @@ static const struct drm_connector_helper_funcs bochs_connector_connector_helper_ static const struct drm_connector_funcs bochs_connector_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = bochs_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = drm_connector_cleanup, }; diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index f1a99938e924..27f98c518dde 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -239,16 +239,9 @@ static const struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = .get_modes = ptn3460_get_modes, }; -static enum drm_connector_status ptn3460_detect(struct drm_connector *connector, - bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_funcs ptn3460_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = ptn3460_detect, .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index 6f7c2f9860d2..ac8cc5b50d9f 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -477,16 +477,9 @@ static const struct drm_connector_helper_funcs ps8622_connector_helper_funcs = { .get_modes = ps8622_get_modes, }; -static enum drm_connector_status ps8622_detect(struct drm_connector *connector, - bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_funcs ps8622_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = ps8622_detect, .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index a7872400eed8..de9ffb49e9f6 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1038,12 +1038,6 @@ err: return ret; } -static enum drm_connector_status -tc_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static void tc_bridge_pre_enable(struct drm_bridge *bridge) { struct tc_data *tc = bridge_to_tc(bridge); @@ -1168,7 +1162,6 @@ static const struct drm_connector_helper_funcs tc_connector_helper_funcs = { static const struct drm_connector_funcs tc_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = tc_connector_detect, .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 17c915d9a03e..9a4a27c1afd2 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -498,12 +498,6 @@ static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector return NULL; } -static enum drm_connector_status cirrus_vga_detect(struct drm_connector - *connector, bool force) -{ - return connector_status_connected; -} - static void cirrus_connector_destroy(struct drm_connector *connector) { drm_connector_cleanup(connector); @@ -517,7 +511,6 @@ static const struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs static const struct drm_connector_funcs cirrus_vga_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = cirrus_vga_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = cirrus_connector_destroy, }; diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index f6b64d7d3528..078d9703a4fe 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -152,6 +152,14 @@ void drm_kms_helper_poll_enable_locked(struct drm_device *dev) } EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked); +static enum drm_connector_status +drm_connector_detect(struct drm_connector *connector, bool force) +{ + return connector->funcs->detect ? + connector->funcs->detect(connector, force) : + connector_status_connected; +} + /** * drm_helper_probe_single_connector_modes - get complete set of display modes * @connector: connector to probe @@ -239,7 +247,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, if (connector->funcs->force) connector->funcs->force(connector); } else { - connector->status = connector->funcs->detect(connector, true); + connector->status = drm_connector_detect(connector, true); } /* @@ -405,7 +413,7 @@ static void output_poll_execute(struct work_struct *work) repoll = true; - connector->status = connector->funcs->detect(connector, false); + connector->status = drm_connector_detect(connector, false); if (old_status != connector->status) { const char *old, *new; @@ -565,7 +573,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) old_status = connector->status; - connector->status = connector->funcs->detect(connector, false); + connector->status = drm_connector_detect(connector, false); DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", connector->base.id, connector->name, diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index e1dd75b18118..05a8ee106879 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -58,17 +58,10 @@ static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector) drm_connector_cleanup(connector); } -static enum drm_connector_status -fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = { .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .destroy = fsl_dcu_drm_connector_destroy, - .detect = fsl_dcu_drm_connector_detect, .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .reset = drm_atomic_helper_connector_reset, diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index ea733ab5b1e0..5efdb7fbb7ee 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -386,19 +386,6 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder, REG_WRITE(PFIT_CONTROL, pfit_control); } -/** - * Detect the LVDS connection. - * - * This always returns CONNECTOR_STATUS_CONNECTED. - * This connector should only have - * been set up if the LVDS was actually connected anyway. - */ -static enum drm_connector_status cdv_intel_lvds_detect( - struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - /** * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. */ @@ -521,7 +508,6 @@ static const struct drm_connector_helper_funcs static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = cdv_intel_lvds_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = cdv_intel_lvds_set_property, .destroy = cdv_intel_lvds_destroy, diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index fd7c91254841..483fdce74e39 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -499,19 +499,6 @@ static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, REG_WRITE(PFIT_CONTROL, pfit_control); } -/* - * Detect the LVDS connection. - * - * This always returns CONNECTOR_STATUS_CONNECTED. - * This connector should only have - * been set up if the LVDS was actually connected anyway. - */ -static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector - *connector, bool force) -{ - return connector_status_connected; -} - /* * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. */ @@ -643,7 +630,6 @@ const struct drm_connector_helper_funcs const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = psb_intel_lvds_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = psb_intel_lvds_set_property, .destroy = psb_intel_lvds_destroy, diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index d1f67a9d4d86..12a18557c5fd 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -39,12 +39,6 @@ hibmc_connector_best_encoder(struct drm_connector *connector) return drm_encoder_find(connector->dev, connector->encoder_ids[0]); } -static enum drm_connector_status hibmc_connector_detect(struct drm_connector - *connector, bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_helper_funcs hibmc_connector_helper_funcs = { .get_modes = hibmc_connector_get_modes, @@ -54,7 +48,6 @@ static const struct drm_connector_helper_funcs static const struct drm_connector_funcs hibmc_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, - .detect = hibmc_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 4e0d025490a3..5b72c50d6f76 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1298,12 +1298,6 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, } } -static enum drm_connector_status -intel_dsi_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static int intel_dsi_get_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); @@ -1407,7 +1401,6 @@ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs static const struct drm_connector_funcs intel_dsi_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, - .detect = intel_dsi_detect, .late_register = intel_connector_register, .early_unregister = intel_connector_unregister, .destroy = intel_dsi_connector_destroy, diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index b300998dce7d..516d06490465 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -101,12 +101,6 @@ struct imx_ldb { const struct bus_mux *lvds_mux; }; -static enum drm_connector_status imx_ldb_connector_detect( - struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static void imx_ldb_ch_set_bus_format(struct imx_ldb_channel *imx_ldb_ch, u32 bus_format) { @@ -397,7 +391,6 @@ static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder, static const struct drm_connector_funcs imx_ldb_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = imx_ldb_connector_detect, .destroy = imx_drm_connector_destroy, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 8fc088843e55..3b602ee33c44 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -227,12 +227,6 @@ static int tve_setup_vga(struct imx_tve *tve) TVE_TVDAC_TEST_MODE_MASK, 1); } -static enum drm_connector_status imx_tve_connector_detect( - struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static int imx_tve_connector_get_modes(struct drm_connector *connector) { struct imx_tve *tve = con_to_tve(connector); @@ -352,7 +346,6 @@ static int imx_tve_atomic_check(struct drm_encoder *encoder, static const struct drm_connector_funcs imx_tve_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = imx_tve_connector_detect, .destroy = imx_drm_connector_destroy, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index d796ada2a47a..8582a83c0d9b 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -49,12 +49,6 @@ static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e) return container_of(e, struct imx_parallel_display, encoder); } -static enum drm_connector_status imx_pd_connector_detect( - struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static int imx_pd_connector_get_modes(struct drm_connector *connector) { struct imx_parallel_display *imxpd = con_to_imxpd(connector); @@ -143,7 +137,6 @@ static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder, static const struct drm_connector_funcs imx_pd_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = imx_pd_connector_detect, .destroy = imx_drm_connector_destroy, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 28b2044ed9f2..30027b26a59f 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -562,12 +562,6 @@ static void mtk_dsi_encoder_enable(struct drm_encoder *encoder) mtk_output_dsi_enable(dsi); } -static enum drm_connector_status mtk_dsi_connector_detect( - struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static int mtk_dsi_connector_get_modes(struct drm_connector *connector) { struct mtk_dsi *dsi = connector_to_dsi(connector); @@ -584,7 +578,6 @@ static const struct drm_encoder_helper_funcs mtk_dsi_encoder_helper_funcs = { static const struct drm_connector_funcs mtk_dsi_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, - .detect = mtk_dsi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 6b21cb27e1cc..3a03ac4045d8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1658,12 +1658,6 @@ static struct drm_encoder *mga_connector_best_encoder(struct drm_connector return NULL; } -static enum drm_connector_status mga_vga_detect(struct drm_connector - *connector, bool force) -{ - return connector_status_connected; -} - static void mga_connector_destroy(struct drm_connector *connector) { struct mga_connector *mga_connector = to_mga_connector(connector); @@ -1680,7 +1674,6 @@ static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = static const struct drm_connector_funcs mga_vga_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = mga_vga_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = mga_connector_destroy, }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c index 64e9f0b86e58..3bcfd161c53f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c @@ -61,16 +61,9 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { .get_modes = rcar_du_lvds_connector_get_modes, }; -static enum drm_connector_status -rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_funcs connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .reset = drm_atomic_helper_connector_reset, - .detect = rcar_du_lvds_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = drm_connector_cleanup, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index ca22e5ee89ca..d9aa382bb629 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -969,12 +969,6 @@ static struct drm_connector_helper_funcs dw_mipi_dsi_connector_helper_funcs = { .mode_valid = dw_mipi_dsi_mode_valid, }; -static enum drm_connector_status -dw_mipi_dsi_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); @@ -984,7 +978,6 @@ static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector) static struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = dw_mipi_dsi_detect, .destroy = dw_mipi_dsi_drm_connector_destroy, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 6547b1db460a..dddbdd62bed0 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -669,15 +669,8 @@ static void shmob_drm_connector_destroy(struct drm_connector *connector) drm_connector_cleanup(connector); } -static enum drm_connector_status -shmob_drm_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static const struct drm_connector_funcs connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = shmob_drm_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = shmob_drm_connector_destroy, }; diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index e7c243f70870..96f336dd0e29 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -642,12 +642,6 @@ struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = { .mode_valid = sti_hda_connector_mode_valid, }; -static enum drm_connector_status -sti_hda_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static int sti_hda_late_register(struct drm_connector *connector) { struct sti_hda_connector *hda_connector @@ -665,7 +659,6 @@ static int sti_hda_late_register(struct drm_connector *connector) static const struct drm_connector_funcs sti_hda_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = sti_hda_connector_detect, .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index c3ff10f559cc..5380085b3c06 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -110,12 +110,6 @@ static struct drm_connector_helper_funcs sun4i_rgb_con_helper_funcs = { .mode_valid = sun4i_rgb_mode_valid, }; -static enum drm_connector_status -sun4i_rgb_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static void sun4i_rgb_connector_destroy(struct drm_connector *connector) { @@ -129,7 +123,6 @@ sun4i_rgb_connector_destroy(struct drm_connector *connector) static struct drm_connector_funcs sun4i_rgb_con_funcs = { .dpms = drm_atomic_helper_connector_dpms, - .detect = sun4i_rgb_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = sun4i_rgb_connector_destroy, .reset = drm_atomic_helper_connector_reset, diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index d430b331fed5..c6f47222e8fc 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -537,12 +537,6 @@ static struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs = .mode_valid = sun4i_tv_comp_mode_valid, }; -static enum drm_connector_status -sun4i_tv_comp_connector_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - static void sun4i_tv_comp_connector_destroy(struct drm_connector *connector) { @@ -551,7 +545,6 @@ sun4i_tv_comp_connector_destroy(struct drm_connector *connector) static struct drm_connector_funcs sun4i_tv_comp_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, - .detect = sun4i_tv_comp_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = sun4i_tv_comp_connector_destroy, .reset = drm_atomic_helper_connector_reset, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 2134bb20fbe9..e634201db821 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -144,13 +144,6 @@ static void panel_connector_destroy(struct drm_connector *connector) drm_connector_cleanup(connector); } -static enum drm_connector_status panel_connector_detect( - struct drm_connector *connector, - bool force) -{ - return connector_status_connected; -} - static int panel_connector_get_modes(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -197,7 +190,6 @@ static struct drm_encoder *panel_connector_best_encoder( static const struct drm_connector_funcs panel_connector_funcs = { .destroy = panel_connector_destroy, .dpms = drm_atomic_helper_connector_dpms, - .detect = panel_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 34f9741ebb5b..1218a0c002c0 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -262,6 +262,9 @@ struct drm_connector_funcs { * connector due to a user request. force can be used by the driver to * avoid expensive, destructive operations during automated probing. * + * This callback is optional, if not implemented the connector will be + * considered as always being attached. + * * FIXME: * * Note that this hook is only called by the probe helper. It's not in -- cgit v1.2.3 From ad1231080be5a5cb34bbecf08fa3fea50209ef94 Mon Sep 17 00:00:00 2001 From: Nicolai Hähnle Date: Thu, 1 Dec 2016 15:06:44 +0100 Subject: drm/vgem: Use ww_mutex_(un)lock even with a NULL context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: use resv->lock instead of resv->lock.base (Christian König) Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Maarten Lankhorst Cc: Daniel Vetter Cc: Chris Wilson Cc: dri-devel@lists.freedesktop.org Signed-off-by: Nicolai Hähnle Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1480601214-26583-2-git-send-email-nhaehnle@gmail.com --- drivers/gpu/drm/vgem/vgem_fence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index 488909a21ed8..9cb00a5d5d08 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -191,12 +191,12 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, /* Expose the fence via the dma-buf */ ret = 0; - mutex_lock(&resv->lock.base); + ww_mutex_lock(&resv->lock, NULL); if (arg->flags & VGEM_FENCE_WRITE) reservation_object_add_excl_fence(resv, fence); else if ((ret = reservation_object_reserve_shared(resv)) == 0) reservation_object_add_shared_fence(resv, fence); - mutex_unlock(&resv->lock.base); + ww_mutex_unlock(&resv->lock); /* Record the fence in our idr for later signaling */ if (ret == 0) { -- cgit v1.2.3 From dabdcdc9822ae4e23cd7ff07090098d34f287b28 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 2 Dec 2016 08:07:40 +0100 Subject: drm/vmwgfx: Switch to mode_cmd2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surprisingly few changes needed to make it happen. Compile-tested only. The idea is that this replaces the 2 patches from Ville's big fb->format patch series as a prep patch. Only impact to later patches should be the one instace added in this patch where we look at fb->pixel_format (instead of fb->bpp and fb->depth), so minor adjustements in the cocci-generated patches needed. v2: Restore pitch computation in vmw_fb_kms_framebuffer (Sinclair). Cc: ville.syrjala@linux.intel.com Cc: Laurent Pinchart Cc: linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh Cc: Thomas Hellstrom Reviewed-by: Sinclair Yeh Acked-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161202070740.31689-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 19 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 116 +++++++++++++----------------------- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 +- 3 files changed, 53 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index d2d93959b119..723fd763da8e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -465,33 +465,34 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par, static int vmw_fb_kms_framebuffer(struct fb_info *info) { - struct drm_mode_fb_cmd mode_cmd; + struct drm_mode_fb_cmd2 mode_cmd; struct vmw_fb_par *par = info->par; struct fb_var_screeninfo *var = &info->var; struct drm_framebuffer *cur_fb; struct vmw_framebuffer *vfb; - int ret = 0; + int ret = 0, depth; size_t new_bo_size; - ret = vmw_fb_compute_depth(var, &mode_cmd.depth); + ret = vmw_fb_compute_depth(var, &depth); if (ret) return ret; mode_cmd.width = var->xres; mode_cmd.height = var->yres; - mode_cmd.bpp = var->bits_per_pixel; - mode_cmd.pitch = ((mode_cmd.bpp + 7) / 8) * mode_cmd.width; + mode_cmd.pitches[0] = ((var->bits_per_pixel + 7) / 8) * mode_cmd.width; + mode_cmd.pixel_format = + drm_mode_legacy_fb_format(var->bits_per_pixel, + ((var->bits_per_pixel + 7) / 8) * mode_cmd.width); cur_fb = par->set_fb; if (cur_fb && cur_fb->width == mode_cmd.width && cur_fb->height == mode_cmd.height && - cur_fb->bits_per_pixel == mode_cmd.bpp && - cur_fb->depth == mode_cmd.depth && - cur_fb->pitches[0] == mode_cmd.pitch) + cur_fb->pixel_format == mode_cmd.pixel_format && + cur_fb->pitches[0] == mode_cmd.pitches[0]) return 0; /* Need new buffer object ? */ - new_bo_size = (size_t) mode_cmd.pitch * (size_t) mode_cmd.height; + new_bo_size = (size_t) mode_cmd.pitches[0] * (size_t) mode_cmd.height; ret = vmw_fb_kms_detach(par, par->bo_size < new_bo_size || par->bo_size > 2*new_bo_size, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e3f68cc9bb4b..e7daf59bac80 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -516,7 +516,7 @@ static const struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = { static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, struct vmw_surface *surface, struct vmw_framebuffer **out, - const struct drm_mode_fb_cmd + const struct drm_mode_fb_cmd2 *mode_cmd, bool is_dmabuf_proxy) @@ -525,6 +525,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, struct vmw_framebuffer_surface *vfbs; enum SVGA3dSurfaceFormat format; int ret; + struct drm_format_name_buf format_name; /* 3D is only supported on HWv8 and newer hosts */ if (dev_priv->active_display_unit == vmw_du_legacy) @@ -548,21 +549,22 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, return -EINVAL; } - switch (mode_cmd->depth) { - case 32: + switch (mode_cmd->pixel_format) { + case DRM_FORMAT_ARGB8888: format = SVGA3D_A8R8G8B8; break; - case 24: + case DRM_FORMAT_XRGB8888: format = SVGA3D_X8R8G8B8; break; - case 16: + case DRM_FORMAT_RGB565: format = SVGA3D_R5G6B5; break; - case 15: + case DRM_FORMAT_XRGB1555: format = SVGA3D_A1R5G5B5; break; default: - DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth); + DRM_ERROR("Invalid pixel format: %s\n", + drm_get_format_name(mode_cmd->pixel_format, &format_name)); return -EINVAL; } @@ -581,14 +583,9 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, goto out_err1; } - /* XXX get the first 3 from the surface info */ - vfbs->base.base.bits_per_pixel = mode_cmd->bpp; - vfbs->base.base.pitches[0] = mode_cmd->pitch; - vfbs->base.base.depth = mode_cmd->depth; - vfbs->base.base.width = mode_cmd->width; - vfbs->base.base.height = mode_cmd->height; + drm_helper_mode_fill_fb_struct(&vfbs->base.base, mode_cmd); vfbs->surface = vmw_surface_reference(surface); - vfbs->base.user_handle = mode_cmd->handle; + vfbs->base.user_handle = mode_cmd->handles[0]; vfbs->is_dmabuf_proxy = is_dmabuf_proxy; *out = &vfbs->base; @@ -755,7 +752,7 @@ static int vmw_framebuffer_unpin(struct vmw_framebuffer *vfb) * 0 on success, error code otherwise */ static int vmw_create_dmabuf_proxy(struct drm_device *dev, - const struct drm_mode_fb_cmd *mode_cmd, + const struct drm_mode_fb_cmd2 *mode_cmd, struct vmw_dma_buffer *dmabuf_mob, struct vmw_surface **srf_out) { @@ -763,17 +760,18 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev, struct drm_vmw_size content_base_size; struct vmw_resource *res; unsigned int bytes_pp; + struct drm_format_name_buf format_name; int ret; - switch (mode_cmd->depth) { - case 32: - case 24: + switch (mode_cmd->pixel_format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: format = SVGA3D_X8R8G8B8; bytes_pp = 4; break; - case 16: - case 15: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_XRGB1555: format = SVGA3D_R5G6B5; bytes_pp = 2; break; @@ -784,11 +782,12 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev, break; default: - DRM_ERROR("Invalid framebuffer format %d\n", mode_cmd->depth); + DRM_ERROR("Invalid framebuffer format %s\n", + drm_get_format_name(mode_cmd->pixel_format, &format_name)); return -EINVAL; } - content_base_size.width = mode_cmd->pitch / bytes_pp; + content_base_size.width = mode_cmd->pitches[0] / bytes_pp; content_base_size.height = mode_cmd->height; content_base_size.depth = 1; @@ -826,16 +825,17 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev, static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, struct vmw_dma_buffer *dmabuf, struct vmw_framebuffer **out, - const struct drm_mode_fb_cmd + const struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_device *dev = dev_priv->dev; struct vmw_framebuffer_dmabuf *vfbd; unsigned int requested_size; + struct drm_format_name_buf format_name; int ret; - requested_size = mode_cmd->height * mode_cmd->pitch; + requested_size = mode_cmd->height * mode_cmd->pitches[0]; if (unlikely(requested_size > dmabuf->base.num_pages * PAGE_SIZE)) { DRM_ERROR("Screen buffer object size is too small " "for requested mode.\n"); @@ -844,27 +844,16 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, /* Limited framebuffer color depth support for screen objects */ if (dev_priv->active_display_unit == vmw_du_screen_object) { - switch (mode_cmd->depth) { - case 32: - case 24: - /* Only support 32 bpp for 32 and 24 depth fbs */ - if (mode_cmd->bpp == 32) - break; - - DRM_ERROR("Invalid color depth/bbp: %d %d\n", - mode_cmd->depth, mode_cmd->bpp); - return -EINVAL; - case 16: - case 15: - /* Only support 16 bpp for 16 and 15 depth fbs */ - if (mode_cmd->bpp == 16) - break; - - DRM_ERROR("Invalid color depth/bbp: %d %d\n", - mode_cmd->depth, mode_cmd->bpp); - return -EINVAL; + switch (mode_cmd->pixel_format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + break; + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_RGB565: + break; default: - DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth); + DRM_ERROR("Invalid pixel format: %s\n", + drm_get_format_name(mode_cmd->pixel_format, &format_name)); return -EINVAL; } } @@ -875,14 +864,10 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, goto out_err1; } - vfbd->base.base.bits_per_pixel = mode_cmd->bpp; - vfbd->base.base.pitches[0] = mode_cmd->pitch; - vfbd->base.base.depth = mode_cmd->depth; - vfbd->base.base.width = mode_cmd->width; - vfbd->base.base.height = mode_cmd->height; + drm_helper_mode_fill_fb_struct(&vfbd->base.base, mode_cmd); vfbd->base.dmabuf = true; vfbd->buffer = vmw_dmabuf_reference(dmabuf); - vfbd->base.user_handle = mode_cmd->handle; + vfbd->base.user_handle = mode_cmd->handles[0]; *out = &vfbd->base; ret = drm_framebuffer_init(dev, &vfbd->base.base, @@ -916,7 +901,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, struct vmw_dma_buffer *dmabuf, struct vmw_surface *surface, bool only_2d, - const struct drm_mode_fb_cmd *mode_cmd) + const struct drm_mode_fb_cmd2 *mode_cmd) { struct vmw_framebuffer *vfb = NULL; bool is_dmabuf_proxy = false; @@ -971,7 +956,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, struct drm_file *file_priv, - const struct drm_mode_fb_cmd2 *mode_cmd2) + const struct drm_mode_fb_cmd2 *mode_cmd) { struct vmw_private *dev_priv = vmw_priv(dev); struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; @@ -979,25 +964,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, struct vmw_surface *surface = NULL; struct vmw_dma_buffer *bo = NULL; struct ttm_base_object *user_obj; - struct drm_mode_fb_cmd mode_cmd; - const struct drm_format_info *info; int ret; - info = drm_format_info(mode_cmd2->pixel_format); - if (!info || !info->depth) { - struct drm_format_name_buf format_name; - DRM_ERROR("Unsupported framebuffer format %s\n", - drm_get_format_name(mode_cmd2->pixel_format, &format_name)); - return ERR_PTR(-EINVAL); - } - - mode_cmd.width = mode_cmd2->width; - mode_cmd.height = mode_cmd2->height; - mode_cmd.pitch = mode_cmd2->pitches[0]; - mode_cmd.handle = mode_cmd2->handles[0]; - mode_cmd.depth = info->depth; - mode_cmd.bpp = info->cpp[0] * 8; - /** * This code should be conditioned on Screen Objects not being used. * If screen objects are used, we can allocate a GMR to hold the @@ -1005,8 +973,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, */ if (!vmw_kms_validate_mode_vram(dev_priv, - mode_cmd.pitch, - mode_cmd.height)) { + mode_cmd->pitches[0], + mode_cmd->height)) { DRM_ERROR("Requested mode exceed bounding box limit.\n"); return ERR_PTR(-ENOMEM); } @@ -1020,7 +988,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, * command stream using user-space handles. */ - user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle); + user_obj = ttm_base_object_lookup(tfile, mode_cmd->handles[0]); if (unlikely(user_obj == NULL)) { DRM_ERROR("Could not locate requested kms frame buffer.\n"); return ERR_PTR(-ENOENT); @@ -1032,14 +1000,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, /* returns either a dmabuf or surface */ ret = vmw_user_lookup_handle(dev_priv, tfile, - mode_cmd.handle, + mode_cmd->handles[0], &surface, &bo); if (ret) goto err_out; vfb = vmw_kms_new_framebuffer(dev_priv, bo, surface, !(dev_priv->capabilities & SVGA_CAP_3D), - &mode_cmd); + mode_cmd); if (IS_ERR(vfb)) { ret = PTR_ERR(vfb); goto err_out; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index ff4803c107bc..f42ce9a1c3ac 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -248,7 +248,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, struct vmw_dma_buffer *dmabuf, struct vmw_surface *surface, bool only_2d, - const struct drm_mode_fb_cmd *mode_cmd); + const struct drm_mode_fb_cmd2 *mode_cmd); int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, unsigned unit, u32 max_width, -- cgit v1.2.3 From 1f32478f8fe5ac6f2f49670fc909f086c44a4b2f Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Sat, 3 Dec 2016 15:47:00 +0100 Subject: drm/radeon: don't add files at control minor debugfs directory Since commit 8a357d10043c ("drm: Nerf DRM_CONTROL nodes"), a struct drm_device's ->control member is always NULL. In the case of CONFIG_DEBUG_FS=y, radeon_debugfs_add_files() accesses ->control->debugfs_root though. This results in the following Oops: BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 IP: radeon_debugfs_add_files+0x90/0x100 [radeon] PGD 0 Oops: 0000 [#1] SMP [...] Call Trace: ? work_on_cpu+0xb0/0xb0 radeon_fence_driver_init+0x120/0x150 [radeon] si_init+0x122/0xd50 [radeon] ? _raw_spin_unlock_irq+0x2c/0x40 ? device_pm_check_callbacks+0xb3/0xc0 radeon_device_init+0x958/0xda0 [radeon] radeon_driver_load_kms+0x9a/0x210 [radeon] drm_dev_register+0xa9/0xd0 [drm] drm_get_pci_dev+0x9c/0x1e0 [drm] radeon_pci_probe+0xb8/0xe0 [radeon] [...] Fix this by omitting the drm_debugfs_create_files() call for the control minor debugfs directory which is now non-existent anyway. Fixes: 8a357d10043c ("drm: Nerf DRM_CONTROL nodes") Signed-off-by: Nicolai Stange Acked-by: Dave Airlie Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161203144700.2307-1-nicstange@gmail.com --- drivers/gpu/drm/radeon/radeon_device.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0be8d5cd7826..2ce5ace5008a 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1935,9 +1935,6 @@ int radeon_debugfs_add_files(struct radeon_device *rdev, rdev->debugfs[rdev->debugfs_count].num_files = nfiles; rdev->debugfs_count = i; #if defined(CONFIG_DEBUG_FS) - drm_debugfs_create_files(files, nfiles, - rdev->ddev->control->debugfs_root, - rdev->ddev->control); drm_debugfs_create_files(files, nfiles, rdev->ddev->primary->debugfs_root, rdev->ddev->primary); @@ -1951,9 +1948,6 @@ static void radeon_debugfs_remove_files(struct radeon_device *rdev) unsigned i; for (i = 0; i < rdev->debugfs_count; i++) { - drm_debugfs_remove_files(rdev->debugfs[i].files, - rdev->debugfs[i].num_files, - rdev->ddev->control); drm_debugfs_remove_files(rdev->debugfs[i].files, rdev->debugfs[i].num_files, rdev->ddev->primary); -- cgit v1.2.3 From 48d9831627c6a059946085ce42d2fd17fb365b8d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 5 Dec 2016 08:29:26 +0100 Subject: drm/qxl: Don't register debugfs for control minors They're gone since 8a357d10043c ("drm: Nerf DRM_CONTROL nodes"). Spotted while doing a full audit when revieng a similar patch from Nicolai for radeon. v2: Drink coffee first aka don't forget the unregister side. Cc: Dave Airlie Fixes: 8a357d10043c ("drm: Nerf DRM_CONTROL nodes") Cc: Nicolai Stange Acked-by: Dave Airlie Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161205072926.12546-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/qxl/qxl_debugfs.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index 6911b8c44492..241af9131dc8 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c @@ -122,9 +122,6 @@ int qxl_debugfs_add_files(struct qxl_device *qdev, qdev->debugfs[qdev->debugfs_count].num_files = nfiles; qdev->debugfs_count = i; #if defined(CONFIG_DEBUG_FS) - drm_debugfs_create_files(files, nfiles, - qdev->ddev->control->debugfs_root, - qdev->ddev->control); drm_debugfs_create_files(files, nfiles, qdev->ddev->primary->debugfs_root, qdev->ddev->primary); @@ -138,9 +135,6 @@ void qxl_debugfs_remove_files(struct qxl_device *qdev) unsigned i; for (i = 0; i < qdev->debugfs_count; i++) { - drm_debugfs_remove_files(qdev->debugfs[i].files, - qdev->debugfs[i].num_files, - qdev->ddev->control); drm_debugfs_remove_files(qdev->debugfs[i].files, qdev->debugfs[i].num_files, qdev->ddev->primary); -- cgit v1.2.3 From 16571a8a435abf73cde769918850ca76a471f14c Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Sat, 3 Dec 2016 23:11:42 +0800 Subject: drm/qxl: fix use of uninitialized variable In function qxl_release_alloc(), when kmalloc() returns a NULL pointer, it returns value 0 and parameter *ret is uninitialized. 0 means no error to the callers of qxl_release_alloc(). The callers keep going and will try to reference the uninitialized variable. This patch fixes the bug, returning "-ENOMEM" when kmalloc() fails. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188911 Signed-off-by: Pan Bian [seanpaul fixed up subject prefix] Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1480777902-7648-1-git-send-email-bianpan2016@163.com --- drivers/gpu/drm/qxl/qxl_release.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index 50b4e522f05f..e6ec845b5be0 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -134,7 +134,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type, release = kmalloc(size, GFP_KERNEL); if (!release) { DRM_ERROR("Out of memory\n"); - return 0; + return -ENOMEM; } release->base.ops = NULL; release->type = type; -- cgit v1.2.3 From 8f5040e421ca4bbd8cd5216dec509da188eb74bc Mon Sep 17 00:00:00 2001 From: Marta Lofstedt Date: Mon, 5 Dec 2016 14:04:08 +0200 Subject: drm: allow changing DPMS mode The drm_atomic_helper_connector_dpms will set the connector back the old DPMS state before returning. This makes it impossible to change DPMS state of the connector. Fixes: 0853695c3ba46f97dfc0b5885f7b7e640ca212dd v2: edit of commit message Cc: Chris Wilson Cc: Daniel Vetter Cc: Eric Engestrom Cc: Sean Paul Cc: dri-devel@lists.freedesktop.org Cc: Signed-off-by: Marta Lofstedt Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161205120408.13056-1-marta.lofstedt@intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 494680c9056e..6a5acb91fa7f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2885,8 +2885,8 @@ retry: fail: if (ret == -EDEADLK) goto backoff; - - connector->dpms = old_mode; + if (ret != 0) + connector->dpms = old_mode; drm_atomic_state_put(state); return ret; -- cgit v1.2.3 From 58309befa82d81f6e9dc36a92d2a339ef2144535 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Mon, 5 Dec 2016 21:30:22 +0100 Subject: drm/amdgpu: don't add files at control minor debugfs directory Since commit 8a357d10043c ("drm: Nerf DRM_CONTROL nodes"), a struct drm_device's ->control member is always NULL. In the case of CONFIG_DEBUG_FS=y, amdgpu_debugfs_add_files() accesses ->control->debugfs_root though. This results in a NULL pointer dereference. Fix this by omitting the drm_debugfs_create_files() call for the control minor debugfs directory which is now non-existent anyway. Fixes: 8a357d10043c ("drm: Nerf DRM_CONTROL nodes") Signed-off-by: Nicolai Stange Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98915 Reviewed-by: Alex Deucher Tested-by: Mike Lothian Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161205203022.11671-1-nicstange@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 9e16e975f31a..76cc47a9a7fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2505,9 +2505,6 @@ int amdgpu_debugfs_add_files(struct amdgpu_device *adev, adev->debugfs[adev->debugfs_count].num_files = nfiles; adev->debugfs_count = i; #if defined(CONFIG_DEBUG_FS) - drm_debugfs_create_files(files, nfiles, - adev->ddev->control->debugfs_root, - adev->ddev->control); drm_debugfs_create_files(files, nfiles, adev->ddev->primary->debugfs_root, adev->ddev->primary); @@ -2521,9 +2518,6 @@ static void amdgpu_debugfs_remove_files(struct amdgpu_device *adev) unsigned i; for (i = 0; i < adev->debugfs_count; i++) { - drm_debugfs_remove_files(adev->debugfs[i].files, - adev->debugfs[i].num_files, - adev->ddev->control); drm_debugfs_remove_files(adev->debugfs[i].files, adev->debugfs[i].num_files, adev->ddev->primary); -- cgit v1.2.3 From d5264ed3823abb0513cbdc5dd7444d4f61954409 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 1 Dec 2016 16:37:31 +0900 Subject: drm: Return -ENOTSUPP when called for KMS cap with a non-KMS driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an attempt to make the previous fix a bit more robust going forward. v2: * Only allow DRM_CAP_TIMESTAMP_MONOTONIC with UMS drivers (Daniel Vetter, Alex Deucher) * Different logic to keep DRM_CAP_TIMESTAMP_MONOTONIC separate from the other caps (Daniel Vetter) Signed-off-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161201073731.5716-1-michel@daenzer.net --- drivers/gpu/drm/drm_ioctl.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 71c3473476c7..706d5aaee7c3 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -229,6 +229,17 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ struct drm_crtc *crtc; req->value = 0; + + /* Only one cap makes sense with a UMS driver: */ + if (req->capability == DRM_CAP_TIMESTAMP_MONOTONIC) { + req->value = drm_timestamp_monotonic; + return 0; + } + + /* Other caps only work with KMS drivers */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -ENOTSUPP; + switch (req->capability) { case DRM_CAP_DUMB_BUFFER: if (dev->driver->dumb_create) @@ -247,19 +258,14 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0; break; - case DRM_CAP_TIMESTAMP_MONOTONIC: - req->value = drm_timestamp_monotonic; - break; case DRM_CAP_ASYNC_PAGE_FLIP: req->value = dev->mode_config.async_page_flip; break; case DRM_CAP_PAGE_FLIP_TARGET: - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - req->value = 1; - drm_for_each_crtc(crtc, dev) { - if (!crtc->funcs->page_flip_target) - req->value = 0; - } + req->value = 1; + drm_for_each_crtc(crtc, dev) { + if (!crtc->funcs->page_flip_target) + req->value = 0; } break; case DRM_CAP_CURSOR_WIDTH: -- cgit v1.2.3 From 1fe7841d892925aff10c3b070937e974d7835d2b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 6 Dec 2016 11:37:15 +0000 Subject: drm: Don't block the kworker waiting for mode_config.mutex in output_poll() If we cannot acquire the mode_config.mutex immediately, just back off and queue a new attempt after the poll interval. This is mostly to stop the hung task spam when the system is deadlocked, but it will also lessen the load (in such extreme cases). Signed-off-by: Chris Wilson Reviewed-by: Eric Engestrom [danvet:s/lock/mutex/ per Eric's comment.] Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161206113715.30382-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_probe_helper.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 078d9703a4fe..ac953f037be7 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -392,7 +392,11 @@ static void output_poll_execute(struct work_struct *work) if (!drm_kms_helper_poll) goto out; - mutex_lock(&dev->mode_config.mutex); + if (!mutex_trylock(&dev->mode_config.mutex)) { + repoll = true; + goto out; + } + drm_for_each_connector(connector, dev) { /* Ignore forced connectors. */ -- cgit v1.2.3 From db444e1344ddad60bc125717bb0bf3ebbb4c79c7 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 5 Dec 2016 12:03:46 -0200 Subject: drm/atomic: doc: remove old comment about nonblocking commits We now support nonblocking commits on drm_atomic_helper_commit() so the comment is not valid anymore. Signed-off-by: Gustavo Padovan Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1480946626-30917-1-git-send-email-gustavo@padovan.org --- drivers/gpu/drm/drm_atomic_helper.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 6a5acb91fa7f..583f47f27b36 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1234,9 +1234,6 @@ static void commit_work(struct work_struct *work) * function implements nonblocking commits, using * drm_atomic_helper_setup_commit() and related functions. * - * Note that right now this function does not support nonblocking commits, hence - * driver writers must implement their own version for now. - * * Committing the actual hardware state is done through the * ->atomic_commit_tail() callback of the &drm_mode_config_helper_funcs vtable, * or it's default implementation drm_atomic_helper_commit_tail(). -- cgit v1.2.3 From 8f34a548718ebb4becb4f829800552c48284ce9e Mon Sep 17 00:00:00 2001 From: zain wang Date: Wed, 7 Dec 2016 08:57:33 +0800 Subject: drm/bridge: analogix: Don't return -EINVAL when panel doesn't support PSR We will ignored PSR setting if panel not support it. So, in this case, we should return from analogix_dp_enable/disable_psr() without any error code. Let's retrun 0 instead of -EINVAL when panel not support PSR in analogix_dp_enable/disable_psr(). Signed-off-by: zain wang Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1481072253-8917-1-git-send-email-wzz@rock-chips.com --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 6e0447f329a2..eb9bf8786c24 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -112,7 +112,7 @@ int analogix_dp_enable_psr(struct device *dev) struct edp_vsc_psr psr_vsc; if (!dp->psr_support) - return -EINVAL; + return 0; /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(&psr_vsc, 0, sizeof(psr_vsc)); @@ -135,7 +135,7 @@ int analogix_dp_disable_psr(struct device *dev) struct edp_vsc_psr psr_vsc; if (!dp->psr_support) - return -EINVAL; + return 0; /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(&psr_vsc, 0, sizeof(psr_vsc)); -- cgit v1.2.3 From 35f8cc3b9a92c661e5331d64fdfdedb518891d5c Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 6 Dec 2016 15:47:17 -0200 Subject: drm/fence: add drm_crtc_create_fence() Instead of dealing with crtc details inside drm_atomic.c we should just export a function that creates a new crtc fence for us and use that. Suggested-by: Chris Wilson Signed-off-by: Gustavo Padovan Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1481046437-18778-1-git-send-email-gustavo@padovan.org --- drivers/gpu/drm/drm_atomic.c | 16 +--------------- drivers/gpu/drm/drm_crtc.c | 18 +++++++++++++++++- drivers/gpu/drm/drm_crtc_internal.h | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 19d7bcb88217..72fa5b20baf1 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1864,20 +1864,6 @@ EXPORT_SYMBOL(drm_atomic_clean_old_fb); * helpers and for the DRM event handling for existing userspace. */ -static struct dma_fence *get_crtc_fence(struct drm_crtc *crtc) -{ - struct dma_fence *fence; - - fence = kzalloc(sizeof(*fence), GFP_KERNEL); - if (!fence) - return NULL; - - dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock, - crtc->fence_context, ++crtc->fence_seqno); - - return fence; -} - struct drm_out_fence_state { s64 __user *out_fence_ptr; struct sync_file *sync_file; @@ -1959,7 +1945,7 @@ static int prepare_crtc_signaling(struct drm_device *dev, f[*num_fences].out_fence_ptr = fence_ptr; *fence_state = f; - fence = get_crtc_fence(crtc); + fence = drm_crtc_create_fence(crtc); if (!fence) return -ENOMEM; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 90931e039731..e75f62cd8a65 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -152,6 +152,8 @@ static void drm_crtc_crc_fini(struct drm_crtc *crtc) #endif } +static const struct dma_fence_ops drm_crtc_fence_ops; + static struct drm_crtc *fence_to_crtc(struct dma_fence *fence) { BUG_ON(fence->ops != &drm_crtc_fence_ops); @@ -177,13 +179,27 @@ static bool drm_crtc_fence_enable_signaling(struct dma_fence *fence) return true; } -const struct dma_fence_ops drm_crtc_fence_ops = { +static const struct dma_fence_ops drm_crtc_fence_ops = { .get_driver_name = drm_crtc_fence_get_driver_name, .get_timeline_name = drm_crtc_fence_get_timeline_name, .enable_signaling = drm_crtc_fence_enable_signaling, .wait = dma_fence_default_wait, }; +struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc) +{ + struct dma_fence *fence; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return NULL; + + dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock, + crtc->fence_context, ++crtc->fence_seqno); + + return fence; +} + /** * drm_crtc_init_with_planes - Initialise a new CRTC object with * specified primary and cursor planes. diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 33b17d0b127e..cdf6860c9d22 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -43,7 +43,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, int drm_crtc_register_all(struct drm_device *dev); void drm_crtc_unregister_all(struct drm_device *dev); -extern const struct dma_fence_ops drm_crtc_fence_ops; +struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc); /* IOCTLs */ int drm_mode_getcrtc(struct drm_device *dev, -- cgit v1.2.3 From f3f4c4d68a2862c361fd9890998275da5ef02724 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 7 Dec 2016 15:49:39 +0100 Subject: drm: Allow CAP_PRIME on !MODESET MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vgem (and our igt tests using vgem) need this. I suspect etnaviv will fare similarly. v2. Make it build. Oops. Fixes: d5264ed3823a ("drm: Return -ENOTSUPP when called for KMS cap with a non-KMS driver") Cc: Michel Dänzer Cc: Alex Deucher Cc: Chris Wilson Reviewed-by: Chris Wilson Reviewed-by: Michel Dänzer Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161207144939.22756-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_ioctl.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 706d5aaee7c3..fed22c2b98b6 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -230,10 +230,15 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ req->value = 0; - /* Only one cap makes sense with a UMS driver: */ - if (req->capability == DRM_CAP_TIMESTAMP_MONOTONIC) { + /* Only some caps make sense with UMS/render-only drivers. */ + switch (req->capability) { + case DRM_CAP_TIMESTAMP_MONOTONIC: req->value = drm_timestamp_monotonic; return 0; + case DRM_CAP_PRIME: + req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; + req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0; + return 0; } /* Other caps only work with KMS drivers */ @@ -254,10 +259,6 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_DUMB_PREFER_SHADOW: req->value = dev->mode_config.prefer_shadow; break; - case DRM_CAP_PRIME: - req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; - req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0; - break; case DRM_CAP_ASYNC_PAGE_FLIP: req->value = dev->mode_config.async_page_flip; break; -- cgit v1.2.3 From 72a93e8dd52c9feea42f1258d555e6070680a347 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Dec 2016 21:45:27 +0000 Subject: drm: Take ownership of the dmabuf->obj when exporting Currently the reference for the dmabuf->obj is incremented for the dmabuf in drm_gem_prime_handle_to_fd() (at the high level userspace interface), but is released in drm_gem_dmabuf_release() (the lowlevel handler). Improve the symmetry of the dmabuf->obj ownership by acquiring the reference in drm_gem_dmabuf_export(). This makes it easier to use the prime functions directly. Signed-off-by: Chris Wilson [danvet: Update kerneldoc.] Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161207214527.22533-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_prime.c | 12 +++++++----- drivers/gpu/drm/vgem/vgem_fence.c | 1 - 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index b22a94dd7b53..8d77b2462594 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -290,7 +290,8 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, * * This wraps dma_buf_export() for use by generic GEM drivers that are using * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take - * a reference to the drm_device which is released by drm_gem_dmabuf_release(). + * a reference to the &drm_device and the exported &drm_gem_object (stored in + * exp_info->priv) which is released by drm_gem_dmabuf_release(). * * Returns the new dmabuf. */ @@ -300,8 +301,11 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, struct dma_buf *dma_buf; dma_buf = dma_buf_export(exp_info); - if (!IS_ERR(dma_buf)) - drm_dev_ref(dev); + if (IS_ERR(dma_buf)) + return dma_buf; + + drm_dev_ref(dev); + drm_gem_object_reference(exp_info->priv); return dma_buf; } @@ -472,8 +476,6 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev, */ obj->dma_buf = dmabuf; get_dma_buf(obj->dma_buf); - /* Grab a new ref since the callers is now used by the dma-buf */ - drm_gem_object_reference(obj); return dmabuf; } diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index 9cb00a5d5d08..da25dfe7b80e 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -126,7 +126,6 @@ static int attach_dmabuf(struct drm_device *dev, return PTR_ERR(dmabuf); obj->dma_buf = dmabuf; - drm_gem_object_reference(obj); return 0; } -- cgit v1.2.3