Commit 2e2245ef authored by Dave Airlie's avatar Dave Airlie

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: default avatarDave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/Y9I2nOzHxTxPeTjg@linux-uq9g
parents 68de345e 6ca80b9e
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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,9 +446,22 @@ 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
......@@ -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;
}
......
......@@ -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);
......@@ -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");
......
......@@ -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;
......
......@@ -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));
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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 *,
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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,
......
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment