diff options
author | Dave Airlie <airlied@redhat.com> | 2023-01-30 11:26:08 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2023-01-30 11:26:16 +1000 |
commit | 2e2245efc1049d16379a8c627085659f9e207214 (patch) | |
tree | aec51d553fdf2db59cb86f767c43046d1156ea59 | |
parent | 68de345e101ce9a24e5c8849e69dd0dba2e8c9b2 (diff) | |
parent | 6ca80b9e5cc0120c37e2e7dd367b08e3e0eb8289 (diff) |
Merge tag 'drm-misc-next-2023-01-26' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v6.3:
UAPI Changes:
Cross-subsystem Changes:
Core Changes:
* fbdev-helper: Streamline code in generic fbdev and its helpers
* TTM: Fixes plus their reverts
Driver Changes:
* accel/ivpu: Typo fixes
* i915: TTM-related fixes
* nouveau: Remove unused return value from disable helper
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/Y9I2nOzHxTxPeTjg@linux-uq9g
26 files changed, 222 insertions, 167 deletions
diff --git a/drivers/accel/ivpu/ivpu_hw_mtl.c b/drivers/accel/ivpu/ivpu_hw_mtl.c index b59b1f472b40..62bfaa9081c4 100644 --- a/drivers/accel/ivpu/ivpu_hw_mtl.c +++ b/drivers/accel/ivpu/ivpu_hw_mtl.c @@ -608,7 +608,7 @@ static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable) ret = REGB_POLL_FLD(MTL_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); if (ret) { - ivpu_err(vdev, "Failed to sync before D0i3 tansition: %d\n", ret); + ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret); return ret; } @@ -621,7 +621,7 @@ static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable) ret = REGB_POLL_FLD(MTL_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); if (ret) - ivpu_err(vdev, "Failed to sync after D0i3 tansition: %d\n", ret); + ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret); return ret; } diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 584cee123bd8..07e410c62b7a 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -129,7 +129,7 @@ int armada_fbdev_init(struct drm_device *dev) priv->fbdev = fbh; - drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs); + drm_fb_helper_prepare(dev, fbh, 32, &armada_fb_helper_funcs); ret = drm_fb_helper_init(dev, fbh); if (ret) { @@ -137,7 +137,7 @@ int armada_fbdev_init(struct drm_device *dev) goto err_fb_helper; } - ret = drm_fb_helper_initial_config(fbh, 32); + ret = drm_fb_helper_initial_config(fbh); if (ret) { DRM_ERROR("failed to set initial config\n"); goto err_fb_setup; diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 262ec64d4397..009e7b10455c 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -198,13 +198,23 @@ void drm_client_dev_hotplug(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) return; + if (!dev->mode_config.num_connector) { + drm_dbg_kms(dev, "No connectors found, will not send hotplug events!\n"); + return; + } + mutex_lock(&dev->clientlist_mutex); list_for_each_entry(client, &dev->clientlist, list) { if (!client->funcs || !client->funcs->hotplug) continue; + if (client->hotplug_failed) + continue; + ret = client->funcs->hotplug(client); drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret); + if (ret) + client->hotplug_failed = true; } mutex_unlock(&dev->clientlist_mutex); } diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 367fb8b2d5fa..97b34f377fe8 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -414,14 +414,30 @@ static void drm_fb_helper_damage_work(struct work_struct *work) * drm_fb_helper_prepare - setup a drm_fb_helper structure * @dev: DRM device * @helper: driver-allocated fbdev helper structure to set up + * @preferred_bpp: Preferred bits per pixel for the device. * @funcs: pointer to structure of functions associate with this helper * * Sets up the bare minimum to make the framebuffer helper usable. This is * useful to implement race-free initialization of the polling helpers. */ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, + unsigned int preferred_bpp, const struct drm_fb_helper_funcs *funcs) { + /* + * Pick a preferred bpp of 32 if no value has been given. This + * will select XRGB8888 for the framebuffer formats. All drivers + * have to support XRGB8888 for backwards compatibility with legacy + * userspace, so it's the safe choice here. + * + * TODO: Replace struct drm_mode_config.preferred_depth and this + * bpp value with a preferred format that is given as struct + * drm_format_info. Then derive all other values from the + * format. + */ + if (!preferred_bpp) + preferred_bpp = 32; + INIT_LIST_HEAD(&helper->kernel_fb_list); spin_lock_init(&helper->damage_lock); INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker); @@ -430,10 +446,23 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, mutex_init(&helper->lock); helper->funcs = funcs; helper->dev = dev; + helper->preferred_bpp = preferred_bpp; } EXPORT_SYMBOL(drm_fb_helper_prepare); /** + * drm_fb_helper_unprepare - clean up a drm_fb_helper structure + * @fb_helper: driver-allocated fbdev helper structure to set up + * + * Cleans up the framebuffer helper. Inverse of drm_fb_helper_prepare(). + */ +void drm_fb_helper_unprepare(struct drm_fb_helper *fb_helper) +{ + mutex_destroy(&fb_helper->lock); +} +EXPORT_SYMBOL(drm_fb_helper_unprepare); + +/** * drm_fb_helper_init - initialize a &struct drm_fb_helper * @dev: drm device * @fb_helper: driver-allocated fbdev helper structure to initialize @@ -559,7 +588,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) } mutex_unlock(&kernel_fb_helper_lock); - mutex_destroy(&fb_helper->lock); + drm_fb_helper_unprepare(fb_helper); if (!fb_helper->client.funcs) drm_client_release(&fb_helper->client); @@ -1772,7 +1801,7 @@ static uint32_t drm_fb_helper_find_color_mode_format(struct drm_fb_helper *fb_he return drm_fb_helper_find_format(fb_helper, formats, format_count, bpp, depth); } -static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferred_bpp, +static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, struct drm_fb_helper_surface_size *sizes) { struct drm_client_dev *client = &fb_helper->client; @@ -1817,7 +1846,7 @@ static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int prefe surface_format = drm_fb_helper_find_color_mode_format(fb_helper, plane->format_types, plane->format_count, - preferred_bpp); + fb_helper->preferred_bpp); if (surface_format != DRM_FORMAT_INVALID) break; /* found supported format */ } @@ -1889,7 +1918,7 @@ static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int prefe return 0; } -static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferred_bpp, +static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, struct drm_fb_helper_surface_size *sizes) { struct drm_client_dev *client = &fb_helper->client; @@ -1898,7 +1927,7 @@ static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferr int ret; mutex_lock(&client->modeset_mutex); - ret = __drm_fb_helper_find_sizes(fb_helper, preferred_bpp, sizes); + ret = __drm_fb_helper_find_sizes(fb_helper, sizes); mutex_unlock(&client->modeset_mutex); if (ret) @@ -1920,14 +1949,13 @@ static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferr * Allocates the backing storage and sets up the fbdev info structure through * the ->fb_probe callback. */ -static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, - int preferred_bpp) +static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper) { struct drm_client_dev *client = &fb_helper->client; struct drm_fb_helper_surface_size sizes; int ret; - ret = drm_fb_helper_find_sizes(fb_helper, preferred_bpp, &sizes); + ret = drm_fb_helper_find_sizes(fb_helper, &sizes); if (ret) { /* First time: disable all crtc's.. */ if (!fb_helper->deferred_setup) @@ -2105,8 +2133,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) /* Note: Drops fb_helper->lock before returning. */ static int -__drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper, - int bpp_sel) +__drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; struct fb_info *info; @@ -2117,10 +2144,9 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper, height = dev->mode_config.max_height; drm_client_modeset_probe(&fb_helper->client, width, height); - ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); + ret = drm_fb_helper_single_fb_probe(fb_helper); if (ret < 0) { if (ret == -EAGAIN) { - fb_helper->preferred_bpp = bpp_sel; fb_helper->deferred_setup = true; ret = 0; } @@ -2166,7 +2192,6 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper, /** * drm_fb_helper_initial_config - setup a sane initial connector configuration * @fb_helper: fb_helper device struct - * @bpp_sel: bpp value to use for the framebuffer configuration * * Scans the CRTCs and connectors and tries to put together an initial setup. * At the moment, this is a cloned configuration across all heads with @@ -2204,7 +2229,7 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper, * RETURNS: * Zero if everything went ok, nonzero otherwise. */ -int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) +int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper) { int ret; @@ -2212,7 +2237,7 @@ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) return 0; mutex_lock(&fb_helper->lock); - ret = __drm_fb_helper_initial_config_and_unlock(fb_helper, bpp_sel); + ret = __drm_fb_helper_initial_config_and_unlock(fb_helper); return ret; } @@ -2248,8 +2273,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) mutex_lock(&fb_helper->lock); if (fb_helper->deferred_setup) { - err = __drm_fb_helper_initial_config_and_unlock(fb_helper, - fb_helper->preferred_bpp); + err = __drm_fb_helper_initial_config_and_unlock(fb_helper); return err; } diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c index 0a4c160e0e58..43f94aa9e015 100644 --- a/drivers/gpu/drm/drm_fbdev_generic.c +++ b/drivers/gpu/drm/drm_fbdev_generic.c @@ -43,20 +43,18 @@ static int drm_fbdev_fb_release(struct fb_info *info, int user) return 0; } -static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper) +static void drm_fbdev_fb_destroy(struct fb_info *info) { - struct fb_info *fbi = fb_helper->info; + struct drm_fb_helper *fb_helper = info->par; void *shadow = NULL; if (!fb_helper->dev) return; - if (fbi) { - if (fbi->fbdefio) - fb_deferred_io_cleanup(fbi); - if (drm_fbdev_use_shadow_fb(fb_helper)) - shadow = fbi->screen_buffer; - } + if (info->fbdefio) + fb_deferred_io_cleanup(info); + if (drm_fbdev_use_shadow_fb(fb_helper)) + shadow = info->screen_buffer; drm_fb_helper_fini(fb_helper); @@ -66,24 +64,10 @@ static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper) drm_client_buffer_vunmap(fb_helper->buffer); drm_client_framebuffer_delete(fb_helper->buffer); -} - -static void drm_fbdev_release(struct drm_fb_helper *fb_helper) -{ - drm_fbdev_cleanup(fb_helper); drm_client_release(&fb_helper->client); kfree(fb_helper); } -/* - * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of - * unregister_framebuffer() or fb_release(). - */ -static void drm_fbdev_fb_destroy(struct fb_info *info) -{ - drm_fbdev_release(info->par); -} - static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct drm_fb_helper *fb_helper = info->par; @@ -186,7 +170,7 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper, struct drm_device *dev = fb_helper->dev; struct drm_client_buffer *buffer; struct drm_framebuffer *fb; - struct fb_info *fbi; + struct fb_info *info; u32 format; struct iosys_map map; int ret; @@ -205,35 +189,35 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper, fb_helper->fb = buffer->fb; fb = buffer->fb; - fbi = drm_fb_helper_alloc_info(fb_helper); - if (IS_ERR(fbi)) - return PTR_ERR(fbi); + info = drm_fb_helper_alloc_info(fb_helper); + if (IS_ERR(info)) + return PTR_ERR(info); - fbi->fbops = &drm_fbdev_fb_ops; - fbi->screen_size = sizes->surface_height * fb->pitches[0]; - fbi->fix.smem_len = fbi->screen_size; - fbi->flags = FBINFO_DEFAULT; + info->fbops = &drm_fbdev_fb_ops; + info->screen_size = sizes->surface_height * fb->pitches[0]; + info->fix.smem_len = info->screen_size; + info->flags = FBINFO_DEFAULT; - drm_fb_helper_fill_info(fbi, fb_helper, sizes); + drm_fb_helper_fill_info(info, fb_helper, sizes); if (drm_fbdev_use_shadow_fb(fb_helper)) { - fbi->screen_buffer = vzalloc(fbi->screen_size); - if (!fbi->screen_buffer) + info->screen_buffer = vzalloc(info->screen_size); + if (!info->screen_buffer) return -ENOMEM; - fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST; + info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST; - fbi->fbdefio = &drm_fbdev_defio; - fb_deferred_io_init(fbi); + info->fbdefio = &drm_fbdev_defio; + fb_deferred_io_init(info); } else { /* buffer is mapped for HW framebuffer */ ret = drm_client_buffer_vmap(fb_helper->buffer, &map); if (ret) return ret; if (map.is_iomem) { - fbi->screen_base = map.vaddr_iomem; + info->screen_base = map.vaddr_iomem; } else { - fbi->screen_buffer = map.vaddr; - fbi->flags |= FBINFO_VIRTFB; + info->screen_buffer = map.vaddr; + info->flags |= FBINFO_VIRTFB; } /* @@ -242,10 +226,10 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper, * case. */ #if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM) - if (fb_helper->hint_leak_smem_start && fbi->fix.smem_start == 0 && + if (fb_helper->hint_leak_smem_start && info->fix.smem_start == 0 && !drm_WARN_ON_ONCE(dev, map.is_iomem)) - fbi->fix.smem_start = - page_to_phys(virt_to_page(fbi->screen_buffer)); + info->fix.smem_start = + page_to_phys(virt_to_page(info->screen_buffer)); #endif } @@ -362,11 +346,13 @@ static void drm_fbdev_client_unregister(struct drm_client_dev *client) { struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); - if (fb_helper->info) - /* drm_fbdev_fb_destroy() takes care of cleanup */ + if (fb_helper->info) { drm_fb_helper_unregister_info(fb_helper); - else - drm_fbdev_release(fb_helper); + } else { + drm_client_release(&fb_helper->client); + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); + } } static int drm_fbdev_client_restore(struct drm_client_dev *client) @@ -382,41 +368,26 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client) struct drm_device *dev = client->dev; int ret; - /* Setup is not retried if it has failed */ - if (!fb_helper->dev && fb_helper->funcs) - return 0; - if (dev->fb_helper) return drm_fb_helper_hotplug_event(dev->fb_helper); - if (!dev->mode_config.num_connector) { - drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n"); - return 0; - } - - drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs); - ret = drm_fb_helper_init(dev, fb_helper); if (ret) - goto err; + goto err_drm_err; if (!drm_drv_uses_atomic_modeset(dev)) drm_helper_disable_unused_functions(dev); - ret = drm_fb_helper_initial_config(fb_helper, fb_helper->preferred_bpp); + ret = drm_fb_helper_initial_config(fb_helper); if (ret) - goto err_cleanup; + goto err_drm_fb_helper_fini; return 0; -err_cleanup: - drm_fbdev_cleanup(fb_helper); -err: - fb_helper->dev = NULL; - fb_helper->info = NULL; - +err_drm_fb_helper_fini: + drm_fb_helper_fini(fb_helper); +err_drm_err: drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret); - return ret; } @@ -465,33 +436,25 @@ void drm_fbdev_generic_setup(struct drm_device *dev, fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); if (!fb_helper) return; + drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fb_helper_generic_funcs); ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs); if (ret) { - kfree(fb_helper); drm_err(dev, "Failed to register client: %d\n", ret); - return; + goto err_drm_client_init; } - /* - * Pick a preferred bpp of 32 if no value has been given. This - * will select XRGB8888 for the framebuffer formats. All drivers - * have to support XRGB8888 for backwards compatibility with legacy - * userspace, so it's the safe choice here. - * - * TODO: Replace struct drm_mode_config.preferred_depth and this - * bpp value with a preferred format that is given as struct - * drm_format_info. Then derive all other values from the - * format. - */ - if (!preferred_bpp) - preferred_bpp = 32; - fb_helper->preferred_bpp = preferred_bpp; - ret = drm_fbdev_client_hotplug(&fb_helper->client); if (ret) drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); drm_client_register(&fb_helper->client); + + return; + +err_drm_client_init: + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); + return; } EXPORT_SYMBOL(drm_fbdev_generic_setup); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 55c92372fca0..b89e33af8da8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -163,7 +163,7 @@ int exynos_drm_fbdev_init(struct drm_device *dev) private->fb_helper = helper = &fbdev->drm_fb_helper; - drm_fb_helper_prepare(dev, helper, &exynos_drm_fb_helper_funcs); + drm_fb_helper_prepare(dev, helper, PREFERRED_BPP, &exynos_drm_fb_helper_funcs); ret = drm_fb_helper_init(dev, helper); if (ret < 0) { @@ -172,7 +172,7 @@ int exynos_drm_fbdev_init(struct drm_device *dev) goto err_init; } - ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); + ret = drm_fb_helper_initial_config(helper); if (ret < 0) { DRM_DEV_ERROR(dev->dev, "failed to set up hw configuration.\n"); diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 52ae3ade9a61..1f04c07ee180 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -409,7 +409,7 @@ int psb_fbdev_init(struct drm_device *dev) dev_priv->fb_helper = fb_helper; - drm_fb_helper_prepare(dev, fb_helper, &psb_fb_helper_funcs); + drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fb_helper_funcs); ret = drm_fb_helper_init(dev, fb_helper); if (ret) @@ -418,7 +418,7 @@ int psb_fbdev_init(struct drm_device *dev) /* disable all the possible outputs/crtcs before entering KMS mode */ drm_helper_disable_unused_functions(dev); - ret = drm_fb_helper_initial_config(fb_helper, 32); + ret = drm_fb_helper_initial_config(fb_helper); if (ret) goto fini; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index bbdb98d7c96e..b6f5c554b50f 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -520,10 +520,12 @@ int intel_fbdev_init(struct drm_device *dev) return -ENOMEM; mutex_init(&ifbdev->hpd_lock); - drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs); + drm_fb_helper_prepare(dev, &ifbdev->helper, 32, &intel_fb_helper_funcs); - if (!intel_fbdev_init_bios(dev, ifbdev)) - ifbdev->preferred_bpp = 32; + if (intel_fbdev_init_bios(dev, ifbdev)) + ifbdev->helper.preferred_bpp = ifbdev->preferred_bpp; + else + ifbdev->preferred_bpp = ifbdev->helper.preferred_bpp; ret = drm_fb_helper_init(dev, &ifbdev->helper); if (ret) { @@ -542,8 +544,7 @@ static void intel_fbdev_initial_config(void *data, async_cookie_t cookie) struct intel_fbdev *ifbdev = data; /* Due to peculiar init order wrt to hpd handling this is separate. */ - if (drm_fb_helper_initial_config(&ifbdev->helper, - ifbdev->preferred_bpp)) + if (drm_fb_helper_initial_config(&ifbdev->helper)) intel_fbdev_unregister(to_i915(ifbdev->helper.dev)); } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 8cfed1bef629..7420276827a5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -274,8 +274,6 @@ static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo, { struct drm_i915_private *i915 = container_of(bo->bdev, typeof(*i915), bdev); - struct ttm_resource_manager *man = - ttm_manager_type(bo->bdev, bo->resource->mem_type); struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); unsigned long ccs_pages = 0; enum ttm_caching caching; @@ -289,8 +287,8 @@ static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo, if (!i915_tt) return NULL; - if (obj->flags & I915_BO_ALLOC_CPU_CLEAR && - man->use_tt) + if (obj->flags & I915_BO_ALLOC_CPU_CLEAR && (!bo->resource || + ttm_manager_type(bo->bdev, bo->resource->mem_type)->use_tt)) page_flags |= TTM_TT_FLAG_ZERO_ALLOC; caching = i915_ttm_select_tt_caching(obj); @@ -1058,7 +1056,26 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf) return VM_FAULT_SIGBUS; } - if (!i915_ttm_resource_mappable(bo->resource)) { + /* + * This must be swapped out with shmem ttm_tt (pipeline-gutting). + * Calling ttm_bo_validate() here with TTM_PL_SYSTEM should only go as + * far as far doing a ttm_bo_move_null(), which should skip all the + * other junk. + */ + if (!bo->resource) { + struct ttm_operation_ctx ctx = { + .interruptible = true, + .no_wait_gpu = true, /* should be idle already */ + }; + + GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED)); + + ret = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx); + if (ret) { + dma_resv_unlock(bo->base.resv); + return VM_FAULT_SIGBUS; + } + } else if (!i915_ttm_resource_mappable(bo->resource)) { int err = -ENODEV; int i; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c index 2ebaaf4d663c..76dd9e5e1a8b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c @@ -103,7 +103,27 @@ void i915_ttm_adjust_gem_after_move(struct drm_i915_gem_object *obj) { struct ttm_buffer_object *bo = i915_gem_to_ttm(obj); unsigned int cache_level; + unsigned int mem_flags; unsigned int i; + int mem_type; + + /* + * We might have been purged (or swapped out) if the resource is NULL, + * in which case the SYSTEM placement is the closest match to describe + * the current domain. If the object is ever used in this state then we + * will require moving it again. + */ + if (!bo->resource) { + mem_flags = I915_BO_FLAG_STRUCT_PAGE; + mem_type = I915_PL_SYSTEM; + cache_level = I915_CACHE_NONE; + } else { + mem_flags = i915_ttm_cpu_maps_iomem(bo->resource) ? I915_BO_FLAG_IOMEM : + I915_BO_FLAG_STRUCT_PAGE; + mem_type = bo->resource->mem_type; + cache_level = i915_ttm_cache_level(to_i915(bo->base.dev), bo->resource, + bo->ttm); + } /* * If object was moved to an allowable region, update the object @@ -111,11 +131,11 @@ void i915_ttm_adjust_gem_after_move(struct drm_i915_gem_object *obj) * in an allowable region, it's evicted and we don't update the * object region. */ - if (intel_region_to_ttm_type(obj->mm.region) != bo->resource->mem_type) { + if (intel_region_to_ttm_type(obj->mm.region) != mem_type) { for (i = 0; i < obj->mm.n_placements; ++i) { struct intel_memory_region *mr = obj->mm.placements[i]; - if (intel_region_to_ttm_type(mr) == bo->resource->mem_type && + if (intel_region_to_ttm_type(mr) == mem_type && mr != obj->mm.region) { i915_gem_object_release_memory_region(obj); i915_gem_object_init_memory_region(obj, mr); @@ -125,12 +145,8 @@ void i915_ttm_adjust_gem_after_move(struct drm_i915_gem_object *obj) } obj->mem_flags &= ~(I915_BO_FLAG_STRUCT_PAGE | I915_BO_FLAG_IOMEM); + obj->mem_flags |= mem_flags; - obj->mem_flags |= i915_ttm_cpu_maps_iomem(bo->resource) ? I915_BO_FLAG_IOMEM : - I915_BO_FLAG_STRUCT_PAGE; - - cache_level = i915_ttm_cache_level(to_i915(bo->base.dev), bo->resource, - bo->ttm); i915_gem_object_set_cache_coherency(obj, cache_level); } @@ -565,6 +581,32 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict, return 0; } + if (!bo->resource) { + if (dst_mem->mem_type != TTM_PL_SYSTEM) { + hop->mem_type = TTM_PL_SYSTEM; + hop->flags = TTM_PL_FLAG_TEMPORARY; + return -EMULTIHOP; + } + + /* + * This is only reached when first creating the object, or if + * the object was purged or swapped out (pipeline-gutting). For + * the former we can safely skip all of the below since we are + * only using a dummy SYSTEM placement here. And with the latter + * we will always re-enter here with bo->resource set correctly + * (as per the above), since this is part of a multi-hop + * sequence, where at the end we can do the move for real. + * + * The special case here is when the dst_mem is TTM_PL_SYSTEM, + * which doens't require any kind of move, so it should be safe + * to skip all the below and call ttm_bo_move_null() here, where + * the caller in __i915_ttm_get_pages() will take care of the + * rest, since we should have a valid ttm_tt. + */ + ttm_bo_move_null(bo, dst_mem); + return 0; + } + ret = i915_ttm_move_notify(bo); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 31e1e30cb52a..915b213f3a5c 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -146,7 +146,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev) helper = &fbdev->base; - drm_fb_helper_prepare(dev, helper, &msm_fb_helper_funcs); + drm_fb_helper_prepare(dev, helper, 32, &msm_fb_helper_funcs); ret = drm_fb_helper_init(dev, helper); if (ret) { @@ -159,7 +159,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev) if (ret) goto fini; - ret = drm_fb_helper_initial_config(helper, 32); + ret = drm_fb_helper_initial_config(helper); if (ret) goto fini; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c index dd4981708fe4..3d9319c319c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c @@ -51,7 +51,8 @@ u64 nvkm_devinit_disable(struct nvkm_devinit *init) { if (init && init->func->disable) - return init->func->disable(init); + init->func->disable(init); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c index c224702b7bed..00df7811dd10 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g84.c @@ -26,13 +26,12 @@ #include <subdev/bios.h> #include <subdev/bios/init.h> -static u64 +static void g84_devinit_disable(struct nvkm_devinit *init) { struct nvkm_device *device = init->subdev.device; u32 r001540 = nvkm_rd32(device, 0x001540); u32 r00154c = nvkm_rd32(device, 0x00154c); - u64 disable = 0ULL; if (!(r001540 & 0x40000000)) { nvkm_subdev_disable(device, NVKM_ENGINE_MPEG, 0); @@ -47,8 +46,6 @@ g84_devinit_disable(struct nvkm_devinit *init) nvkm_subdev_disable(device, NVKM_ENGINE_BSP, 0); if (!(r00154c & 0x00000040)) nvkm_subdev_disable(device, NVKM_ENGINE_CIPHER, 0); - - return disable; } static const struct nvkm_devinit_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c index 8977483a9f42..54bee499b982 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/g98.c @@ -26,7 +26,7 @@ #include <subdev/bios.h> #include <subdev/bios/init.h> -static u64 +static void g98_devinit_disable(struct nvkm_devinit *init) { struct nvkm_device *device = init->subdev.device; @@ -45,8 +45,6 @@ g98_devinit_disable(struct nvkm_devinit *init) nvkm_subdev_disable(device, NVKM_ENGINE_MSVLD, 0); if (!(r00154c & 0x00000040)) nvkm_subdev_disable(device, NVKM_ENGINE_SEC, 0); - - return 0ULL; } static const struct nvkm_devinit_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c index 5b7cb1fe7897..5368e705e7fd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c @@ -63,7 +63,7 @@ gf100_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) return ret; } -static u64 +static void gf100_devinit_disable(struct nvkm_devinit *init) { struct nvkm_device *device = init->subdev.device; @@ -85,8 +85,6 @@ gf100_devinit_disable(struct nvkm_devinit *init) nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); if (r022500 & 0x00000200) nvkm_subdev_disable(device, NVKM_ENGINE_CE, 1); - - return 0ULL; } void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c index 8955af2704c7..7bcbc4895ec2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c @@ -26,7 +26,7 @@ #include <subdev/bios.h> #include <subdev/bios/init.h> -u64 +void gm107_devinit_disable(struct nvkm_devinit *init) { struct nvkm_device *device = init->subdev.device; @@ -39,8 +39,6 @@ gm107_devinit_disable(struct nvkm_devinit *init) nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2); if (r021c04 & 0x00000001) nvkm_subdev_disable(device, NVKM_ENGINE_DISP, 0); - - return 0ULL; } static const struct nvkm_devinit_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c index 3d0ab86c3115..dbca92318baf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c @@ -62,7 +62,7 @@ gt215_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) return ret; } -static u64 +static void gt215_devinit_disable(struct nvkm_devinit *init) { struct nvkm_device *device = init->subdev.device; @@ -80,8 +80,6 @@ gt215_devinit_disable(struct nvkm_devinit *init) nvkm_subdev_disable(device, NVKM_ENGINE_MSVLD, 0); if (!(r00154c & 0x00000200)) nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); - - return 0ULL; } static u32 diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c index a9cdf2411187..a24bd2e7d7ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/mcp89.c @@ -26,7 +26,7 @@ #include <subdev/bios.h> #include <subdev/bios/init.h> -static u64 +static void mcp89_devinit_disable(struct nvkm_devinit *init) { struct nvkm_device *device = init->subdev.device; @@ -46,8 +46,6 @@ mcp89_devinit_disable(struct nvkm_devinit *init) nvkm_subdev_disable(device, NVKM_ENGINE_VIC, 0); if (!(r00154c & 0x00000200)) nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); - - return 0; } static const struct nvkm_devinit_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c index 380995d398b1..07ed8fd778b2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c @@ -77,17 +77,14 @@ nv50_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) return 0; } -static u64 +static void nv50_devinit_disable(struct nvkm_devinit *init) { struct nvkm_device *device = init->subdev.device; u32 r001540 = nvkm_rd32(device, 0x001540); - u64 disable = 0ULL; if (!(r001540 & 0x40000000)) nvkm_subdev_disable(device, NVKM_ENGINE_MPEG, 0); - - return disable; } void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h index 987a7f478b84..8de409c084c1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h @@ -23,7 +23,7 @@ int gf100_devinit_ctor(struct nvkm_object *, struct nvkm_object *, int gf100_devinit_pll_set(struct nvkm_devinit *, u32, u32); void gf100_devinit_preinit(struct nvkm_devinit *); -u64 gm107_devinit_disable(struct nvkm_devinit *); +void gm107_devinit_disable(struct nvkm_devinit *); int gm200_devinit_post(struct nvkm_devinit *, bool); void gm200_devinit_preos(struct nv50_devinit *, bool); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h index dd8b038a8cee..a648482d06e9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h @@ -12,7 +12,7 @@ struct nvkm_devinit_func { u32 (*mmio)(struct nvkm_devinit *, u32); void (*meminit)(struct nvkm_devinit *); int (*pll_set)(struct nvkm_devinit *, u32 type, u32 freq); - u64 (*disable)(struct nvkm_devinit *); + void (*disable)(struct nvkm_devinit *); }; void nvkm_devinit_ctor(const struct nvkm_devinit_func *, struct nvkm_device *, diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 98d8758048fc..fc5f52d567c6 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -239,13 +239,13 @@ void omap_fbdev_init(struct drm_device *dev) helper = &fbdev->base; - drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs); + drm_fb_helper_prepare(dev, helper, 32, &omap_fb_helper_funcs); ret = drm_fb_helper_init(dev, helper); if (ret) goto fail; - ret = drm_fb_helper_initial_config(helper, 32); + ret = drm_fb_helper_initial_config(helper); if (ret) goto fini; diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index fe4087bfdb3c..6e5eed0e157c 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -348,7 +348,7 @@ int radeon_fbdev_init(struct radeon_device *rdev) rfbdev->rdev = rdev; rdev->mode_info.rfbdev = rfbdev; - drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper, + drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper, bpp_sel, &radeon_fb_helper_funcs); ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper); @@ -358,7 +358,7 @@ int radeon_fbdev_init(struct radeon_device *rdev) /* disable all the possible outputs/crtcs before entering KMS mode */ drm_helper_disable_unused_functions(rdev->ddev); - ret = drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); + ret = drm_fb_helper_initial_config(&rfbdev->helper); if (ret) goto fini; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index a900300ae5bd..153c39c32c71 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -308,7 +308,7 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm) return ERR_PTR(-ENOMEM); } - drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs); + drm_fb_helper_prepare(drm, &fbdev->base, 32, &tegra_fb_helper_funcs); return fbdev; } @@ -319,7 +319,6 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev) } static int tegra_fbdev_init(struct tegra_fbdev *fbdev, - unsigned int preferred_bpp, unsigned int num_crtc, unsigned int max_connectors) { @@ -333,7 +332,7 @@ static int tegra_fbdev_init(struct tegra_fbdev *fbdev, return err; } - err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp); + err = drm_fb_helper_initial_config(&fbdev->base); if (err < 0) { dev_err(drm->dev, "failed to set initial configuration: %d\n", err); @@ -396,7 +395,7 @@ int tegra_drm_fb_init(struct drm_device *drm) struct tegra_drm *tegra = drm->dev_private; int err; - err = tegra_fbdev_init(tegra->fbdev, 32, drm->mode_config.num_crtc, + err = tegra_fbdev_init(tegra->fbdev, drm->mode_config.num_crtc, drm->mode_config.num_connector); if (err < 0) return err; diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 4fc8018eddda..39482527a775 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -106,6 +106,14 @@ struct drm_client_dev { * @modesets: CRTC configurations */ struct drm_mode_set *modesets; + + /** + * @hotplug failed: + * + * Set by client hotplug helpers if the hotplugging failed + * before. It is usually not tried again. + */ + bool hotplug_failed; }; int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index f443e1f11654..93bc8f29f5a4 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -229,7 +229,9 @@ drm_fb_helper_from_client(struct drm_client_dev *client) #ifdef CONFIG_DRM_FBDEV_EMULATION void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, + unsigned int preferred_bpp, const struct drm_fb_helper_funcs *funcs); +void drm_fb_helper_unprepare(struct drm_fb_helper *fb_helper); int drm_fb_helper_init(struct drm_device *dev, struct drm_fb_helper *helper); void drm_fb_helper_fini(struct drm_fb_helper *helper); int drm_fb_helper_blank(int blank, struct fb_info *info); @@ -283,7 +285,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); -int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); +int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper); int drm_fb_helper_debug_enter(struct fb_info *info); int drm_fb_helper_debug_leave(struct fb_info *info); @@ -291,8 +293,13 @@ void drm_fb_helper_lastclose(struct drm_device *dev); void drm_fb_helper_output_poll_changed(struct drm_device *dev); #else static inline void drm_fb_helper_prepare(struct drm_device *dev, - struct drm_fb_helper *helper, - const struct drm_fb_helper_funcs *funcs) + struct drm_fb_helper *helper, + unsigned int preferred_bpp, + const struct drm_fb_helper_funcs *funcs) +{ +} + +static inline void drm_fb_helper_unprepare(struct drm_fb_helper *fb_helper) { } @@ -450,8 +457,7 @@ static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) return 0; } -static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, - int bpp_sel) +static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper) { return 0; } |