Message ID | 20230131033542.953249-8-zack@kde.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/vmwgfx: Refactor the buffer object code | expand |
From: Martin Krastev <krastevm@vmware.com> LGTM Reviewed-by: Martin Krastev <krastevm@vmware.com> Regards, Martin On 31.01.23 г. 5:35 ч., Zack Rusin wrote: > From: Zack Rusin <zackr@vmware.com> > > Problem with explicit placement selection in vmwgfx is that by the time > the buffer object needs to be validated the information about which > placement was supposed to be used is lost. To workaround this the driver > had a bunch of state in various places e.g. as_mob or cpu_blit to > somehow convey the information on which placement was intended. > > Fix it properly by allowing the buffer objects to hold their preferred > placement so it can be reused whenever needed. This makes the entire > validation pipeline a lot easier both to understand and maintain. > > Signed-off-by: Zack Rusin <zackr@vmware.com> > --- > drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 145 +++++++-- > drivers/gpu/drm/vmwgfx/vmwgfx_bo.h | 25 +- > drivers/gpu/drm/vmwgfx/vmwgfx_context.c | 9 +- > drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c | 11 +- > drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 3 +- > drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 - > drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 35 +- > drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 5 +- > drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 22 +- > drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 21 +- > drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 11 +- > drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h | 3 +- > drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 13 +- > drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 15 +- > drivers/gpu/drm/vmwgfx/vmwgfx_so.c | 4 +- > drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 304 ++---------------- > drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c | 3 +- > drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 6 +- > drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 47 --- > drivers/gpu/drm/vmwgfx/vmwgfx_va.c | 4 +- > drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 74 ++--- > drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 6 +- > 22 files changed, 312 insertions(+), 456 deletions(-) > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > index c6dc733f6d45..d8f6ccecf4bf 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > @@ -135,11 +135,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, > goto out_unreserve; > } > > - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > if (likely(ret == 0) || ret == -ERESTARTSYS) > goto out_unreserve; > > - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_VRAM); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > out_unreserve: > if (!ret) > @@ -190,17 +196,8 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, > { > struct ttm_operation_ctx ctx = {interruptible, false }; > struct ttm_buffer_object *bo = &buf->base; > - struct ttm_placement placement; > - struct ttm_place place; > int ret = 0; > > - place = vmw_vram_placement.placement[0]; > - place.lpfn = PFN_UP(bo->resource->size); > - placement.num_placement = 1; > - placement.placement = &place; > - placement.num_busy_placement = 1; > - placement.busy_placement = &place; > - > vmw_execbuf_release_pinned_bo(dev_priv); > ret = ttm_bo_reserve(bo, interruptible, false, NULL); > if (unlikely(ret != 0)) > @@ -216,14 +213,21 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, > bo->resource->start > 0 && > buf->base.pin_count == 0) { > ctx.interruptible = false; > - (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_SYS, > + VMW_BO_DOMAIN_SYS); > + (void)ttm_bo_validate(bo, &buf->placement, &ctx); > } > > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_VRAM); > + buf->places[0].lpfn = PFN_UP(bo->resource->size); > if (buf->base.pin_count > 0) > - ret = ttm_resource_compat(bo->resource, &placement) > + ret = ttm_resource_compat(bo->resource, &buf->placement) > ? 0 : -EINVAL; > else > - ret = ttm_bo_validate(bo, &placement, &ctx); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > /* For some reason we didn't end up at the start of vram */ > WARN_ON(ret == 0 && bo->resource->start != 0); > @@ -431,7 +435,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, > } > > int vmw_bo_create(struct vmw_private *vmw, > - size_t size, struct ttm_placement *placement, > + size_t size, u32 domain, u32 busy_domain, > bool interruptible, bool pin, > struct vmw_bo **p_bo) > { > @@ -444,7 +448,8 @@ int vmw_bo_create(struct vmw_private *vmw, > } > > ret = vmw_bo_init(vmw, *p_bo, size, > - placement, interruptible, pin); > + domain, busy_domain, > + interruptible, pin); > if (unlikely(ret != 0)) > goto out_error; > > @@ -461,7 +466,8 @@ int vmw_bo_create(struct vmw_private *vmw, > * @dev_priv: Pointer to the device private struct > * @vmw_bo: Pointer to the struct vmw_bo to initialize. > * @size: Buffer object size in bytes. > - * @placement: Initial placement. > + * @domain: Domain to put the bo in. > + * @busy_domain: Domain to put the bo if busy. > * @interruptible: Whether waits should be performed interruptible. > * @pin: If the BO should be created pinned at a fixed location. > * Returns: Zero on success, negative error code on error. > @@ -470,7 +476,9 @@ int vmw_bo_create(struct vmw_private *vmw, > */ > int vmw_bo_init(struct vmw_private *dev_priv, > struct vmw_bo *vmw_bo, > - size_t size, struct ttm_placement *placement, > + size_t size, > + u32 domain, > + u32 busy_domain, > bool interruptible, bool pin) > { > struct ttm_operation_ctx ctx = { > @@ -489,8 +497,9 @@ int vmw_bo_init(struct vmw_private *dev_priv, > size = ALIGN(size, PAGE_SIZE); > drm_gem_private_object_init(vdev, &vmw_bo->base.base, size); > > + vmw_bo_placement_set(vmw_bo, domain, busy_domain); > ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device, > - placement, 0, &ctx, NULL, NULL, vmw_bo_free); > + &vmw_bo->placement, 0, &ctx, NULL, NULL, vmw_bo_free); > if (unlikely(ret)) { > return ret; > } > @@ -825,3 +834,101 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, > if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) > vmw_resource_unbind_list(vbo); > } > + > +static u32 > +set_placement_list(struct ttm_place *pl, u32 domain) > +{ > + u32 n = 0; > + > + /* > + * The placements are ordered according to our preferences > + */ > + if (domain & VMW_BO_DOMAIN_MOB) { > + pl[n].mem_type = VMW_PL_MOB; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + if (domain & VMW_BO_DOMAIN_GMR) { > + pl[n].mem_type = VMW_PL_GMR; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + if (domain & VMW_BO_DOMAIN_VRAM) { > + pl[n].mem_type = TTM_PL_VRAM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + WARN_ON((domain & VMW_BO_DOMAIN_WAITABLE_SYS) != 0); > + if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) { > + pl[n].mem_type = VMW_PL_SYSTEM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + if (domain & VMW_BO_DOMAIN_SYS) { > + pl[n].mem_type = TTM_PL_SYSTEM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + > + WARN_ON(!n); > + if (!n) { > + pl[n].mem_type = TTM_PL_SYSTEM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + return n; > +} > + > +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain) > +{ > + struct ttm_device *bdev = bo->base.bdev; > + struct vmw_private *vmw = > + container_of(bdev, struct vmw_private, bdev); > + struct ttm_placement *pl = &bo->placement; > + bool mem_compatible = false; > + u32 i; > + > + pl->placement = bo->places; > + pl->num_placement = set_placement_list(bo->places, domain); > + > + if (drm_debug_enabled(DRM_UT_DRIVER) && bo->base.resource) { > + for (i = 0; i < pl->num_placement; ++i) { > + if (bo->base.resource->mem_type == TTM_PL_SYSTEM || > + bo->base.resource->mem_type == pl->placement[i].mem_type) > + mem_compatible = true; > + } > + if (!mem_compatible) > + drm_warn(&vmw->drm, > + "%s: Incompatible transition from " > + "bo->base.resource->mem_type = %u to domain = %u\n", > + __func__, bo->base.resource->mem_type, domain); > + } > + > + pl->busy_placement = bo->busy_places; > + pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain); > +} > + > +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo) > +{ > + struct ttm_device *bdev = bo->base.bdev; > + struct vmw_private *vmw = > + container_of(bdev, struct vmw_private, bdev); > + u32 domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM; > + > + if (vmw->has_mob) > + domain = VMW_BO_DOMAIN_MOB; > + > + vmw_bo_placement_set(bo, domain, domain); > +} > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > index 2ede1e28d7ce..538d8739d7a5 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > @@ -31,6 +31,7 @@ > #include "device_include/svga_reg.h" > > #include <drm/ttm/ttm_bo_api.h> > +#include <drm/ttm/ttm_placement.h> > > #include <linux/rbtree_types.h> > #include <linux/types.h> > @@ -40,6 +41,14 @@ struct vmw_fence_obj; > struct vmw_private; > struct vmw_resource; > > +enum vmw_bo_domain { > + VMW_BO_DOMAIN_SYS = BIT(0), > + VMW_BO_DOMAIN_WAITABLE_SYS = BIT(1), > + VMW_BO_DOMAIN_VRAM = BIT(2), > + VMW_BO_DOMAIN_GMR = BIT(3), > + VMW_BO_DOMAIN_MOB = BIT(4), > +}; > + > /** > * struct vmw_bo - TTM buffer object with vmwgfx additions > * @base: The TTM buffer object > @@ -53,6 +62,11 @@ struct vmw_resource; > */ > struct vmw_bo { > struct ttm_buffer_object base; > + > + struct ttm_placement placement; > + struct ttm_place places[5]; > + struct ttm_place busy_places[5]; > + > struct rb_root res_tree; > > atomic_t cpu_writers; > @@ -64,17 +78,24 @@ struct vmw_bo { > struct vmw_bo_dirty *dirty; > }; > > +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain); > +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo); > + > int vmw_bo_create_kernel(struct vmw_private *dev_priv, > unsigned long size, > struct ttm_placement *placement, > struct ttm_buffer_object **p_bo); > int vmw_bo_create(struct vmw_private *dev_priv, > - size_t size, struct ttm_placement *placement, > + size_t size, > + u32 domain, > + u32 busy_domain, > bool interruptible, bool pin, > struct vmw_bo **p_bo); > int vmw_bo_init(struct vmw_private *dev_priv, > struct vmw_bo *vmw_bo, > - size_t size, struct ttm_placement *placement, > + size_t size, > + u32 domain, > + u32 busy_domain, > bool interruptible, bool pin); > int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, > struct drm_file *file_priv); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > index cc02be6a9884..84ef5f0a785b 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > @@ -76,7 +76,8 @@ static const struct vmw_res_func vmw_legacy_context_func = { > .needs_backup = false, > .may_evict = false, > .type_name = "legacy contexts", > - .backup_placement = NULL, > + .domain = VMW_BO_DOMAIN_SYS, > + .busy_domain = VMW_BO_DOMAIN_SYS, > .create = NULL, > .destroy = NULL, > .bind = NULL, > @@ -90,7 +91,8 @@ static const struct vmw_res_func vmw_gb_context_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "guest backed contexts", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_gb_context_create, > .destroy = vmw_gb_context_destroy, > .bind = vmw_gb_context_bind, > @@ -104,7 +106,8 @@ static const struct vmw_res_func vmw_dx_context_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "dx contexts", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_dx_context_create, > .destroy = vmw_dx_context_destroy, > .bind = vmw_dx_context_bind, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > index 9193faae8dab..d49db8146df1 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > @@ -136,7 +136,8 @@ static const struct vmw_res_func vmw_cotable_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "context guest backed object tables", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_cotable_create, > .destroy = vmw_cotable_destroy, > .bind = vmw_cotable_bind, > @@ -424,7 +425,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) > * for the new COTable. Initially pin the buffer object to make sure > * we can use tryreserve without failure. > */ > - ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement, > + ret = vmw_bo_create(dev_priv, new_size, > + VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB, > true, true, &buf); > if (ret) { > DRM_ERROR("Failed initializing new cotable MOB.\n"); > @@ -465,7 +467,10 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) > } > > /* Unpin new buffer, and switch backup buffers. */ > - ret = ttm_bo_validate(bo, &vmw_mob_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_MOB, > + VMW_BO_DOMAIN_MOB); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > if (unlikely(ret != 0)) { > DRM_ERROR("Failed validating new COTable backup buffer.\n"); > goto out_wait; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > index 60d08185a71f..c12ad8264043 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > @@ -399,7 +399,8 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) > * user of the bo currently. > */ > ret = vmw_bo_create(dev_priv, PAGE_SIZE, > - &vmw_sys_placement, false, true, &vbo); > + VMW_BO_DOMAIN_SYS, VMW_BO_DOMAIN_SYS, > + false, true, &vbo); > if (unlikely(ret != 0)) > return ret; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > index e9a16a1e043d..5629a00039fe 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > @@ -930,9 +930,7 @@ extern struct ttm_placement vmw_vram_placement; > extern struct ttm_placement vmw_vram_sys_placement; > extern struct ttm_placement vmw_vram_gmr_placement; > extern struct ttm_placement vmw_sys_placement; > -extern struct ttm_placement vmw_srf_placement; > extern struct ttm_placement vmw_mob_placement; > -extern struct ttm_placement vmw_nonfixed_placement; > extern struct ttm_device_funcs vmw_bo_driver; > extern const struct vmw_sg_table * > vmw_bo_sg_table(struct ttm_buffer_object *bo); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > index 687c6926bc00..eda7f8471bcd 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > @@ -477,9 +477,13 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, > struct vmw_bo *dx_query_mob; > > dx_query_mob = vmw_context_get_dx_query_mob(ctx); > - if (dx_query_mob) > + if (dx_query_mob) { > + vmw_bo_placement_set(dx_query_mob, > + VMW_BO_DOMAIN_MOB, > + VMW_BO_DOMAIN_MOB); > ret = vmw_validation_add_bo(sw_context->ctx, > - dx_query_mob, true, false); > + dx_query_mob); > + } > } > > mutex_unlock(&dev_priv->binding_mutex); > @@ -1035,17 +1039,17 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, > > if (unlikely(sw_context->cur_query_bo != NULL)) { > sw_context->needs_post_query_barrier = true; > + vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo); > ret = vmw_validation_add_bo(sw_context->ctx, > - sw_context->cur_query_bo, > - dev_priv->has_mob, false); > + sw_context->cur_query_bo); > if (unlikely(ret != 0)) > return ret; > } > sw_context->cur_query_bo = new_query_bo; > > + vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo); > ret = vmw_validation_add_bo(sw_context->ctx, > - dev_priv->dummy_query_bo, > - dev_priv->has_mob, false); > + dev_priv->dummy_query_bo); > if (unlikely(ret != 0)) > return ret; > } > @@ -1157,7 +1161,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, > drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); > return PTR_ERR(vmw_bo); > } > - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); > + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); > + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); > ttm_bo_put(&vmw_bo->base); > if (unlikely(ret != 0)) > return ret; > @@ -1211,7 +1216,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, > drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); > return PTR_ERR(vmw_bo); > } > - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); > + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); > ttm_bo_put(&vmw_bo->base); > if (unlikely(ret != 0)) > return ret; > @@ -4361,13 +4368,17 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, > if (dev_priv->pinned_bo == NULL) > goto out_unlock; > > - ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, > - false); > + vmw_bo_placement_set(dev_priv->pinned_bo, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo); > if (ret) > goto out_no_reserve; > > - ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, > - false); > + vmw_bo_placement_set(dev_priv->dummy_query_bo, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo); > if (ret) > goto out_no_reserve; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > index c7ebcd4f3afa..5f383578a320 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > @@ -121,9 +121,8 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, > int ret; > > ret = vmw_bo_create(dev_priv, size, > - (dev_priv->has_mob) ? > - &vmw_sys_placement : > - &vmw_vram_sys_placement, > + (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_SYS, > true, false, p_vbo); > > (*p_vbo)->base.base.funcs = &vmw_gem_object_funcs; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > index e83286e08837..d975c0a818c7 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > @@ -1270,9 +1270,9 @@ int vmw_kms_readback(struct vmw_private *dev_priv, > user_fence_rep, vclips, num_clips, > NULL); > case vmw_du_screen_target: > - return vmw_kms_stdu_dma(dev_priv, file_priv, vfb, > - user_fence_rep, NULL, vclips, num_clips, > - 1, false, true, NULL); > + return vmw_kms_stdu_readback(dev_priv, file_priv, vfb, > + user_fence_rep, NULL, vclips, num_clips, > + 1, NULL); > default: > WARN_ONCE(true, > "Readback called with invalid display system.\n"); > @@ -2999,8 +2999,20 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) > struct vmw_framebuffer_bo *vfbbo = > container_of(update->vfb, typeof(*vfbbo), base); > > - ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false, > - update->cpu_blit); > + /* > + * For screen targets we want a mappable bo, for everything else we want > + * accelerated i.e. host backed (vram or gmr) bo. If the display unit > + * is not screen target then mob's shouldn't be available. > + */ > + if (update->dev_priv->active_display_unit == vmw_du_screen_target) { > + vmw_bo_placement_set(vfbbo->buffer, > + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR, > + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR); > + } else { > + WARN_ON(update->dev_priv->has_mob); > + vmw_bo_placement_set_default_accelerated(vfbbo->buffer); > + } > + ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer); > } else { > struct vmw_framebuffer_surface *vfbs = > container_of(update->vfb, typeof(*vfbs), base); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > index 7a97e53e8e51..1bdf601e7c35 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > @@ -126,7 +126,6 @@ struct vmw_du_update_plane { > struct vmw_framebuffer *vfb; > struct vmw_fence_obj **out_fence; > struct mutex *mutex; > - bool cpu_blit; > bool intr; > }; > > @@ -564,17 +563,15 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, > unsigned num_clips, int inc, > struct vmw_fence_obj **out_fence, > struct drm_crtc *crtc); > -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, > - struct drm_file *file_priv, > - struct vmw_framebuffer *vfb, > - struct drm_vmw_fence_rep __user *user_fence_rep, > - struct drm_clip_rect *clips, > - struct drm_vmw_rect *vclips, > - uint32_t num_clips, > - int increment, > - bool to_surface, > - bool interruptible, > - struct drm_crtc *crtc); > +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, > + struct drm_file *file_priv, > + struct vmw_framebuffer *vfb, > + struct drm_vmw_fence_rep __user *user_fence_rep, > + struct drm_clip_rect *clips, > + struct drm_vmw_rect *vclips, > + uint32_t num_clips, > + int increment, > + struct drm_crtc *crtc); > > int vmw_du_helper_plane_update(struct vmw_du_update_plane *update); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > index 54e412f8c2d1..6780a36e6171 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > @@ -332,7 +332,7 @@ static int vmw_resource_buf_alloc(struct vmw_resource *res, > } > > ret = vmw_bo_create(res->dev_priv, res->backup_size, > - res->func->backup_placement, > + res->func->domain, res->func->busy_domain, > interruptible, false, &backup); > if (unlikely(ret != 0)) > goto out_no_bo; > @@ -529,8 +529,10 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, > return 0; > > backup_dirty = res->backup_dirty; > + vmw_bo_placement_set(res->backup, res->func->domain, > + res->func->busy_domain); > ret = ttm_bo_validate(&res->backup->base, > - res->func->backup_placement, > + &res->backup->placement, > &ctx); > > if (unlikely(ret != 0)) > @@ -968,9 +970,12 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) > if (ret) > goto out_no_validate; > if (!vbo->base.pin_count) { > + vmw_bo_placement_set(vbo, > + res->func->domain, > + res->func->busy_domain); > ret = ttm_bo_validate > (&vbo->base, > - res->func->backup_placement, > + &vbo->placement, > &ctx); > if (ret) { > ttm_bo_unreserve(&vbo->base); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > index 3b7438b2d289..2c24e0929faa 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > @@ -83,7 +83,8 @@ struct vmw_res_func { > enum vmw_res_type res_type; > bool needs_backup; > const char *type_name; > - struct ttm_placement *backup_placement; > + u32 domain; > + u32 busy_domain; > bool may_evict; > u32 prio; > u32 dirty_prio; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > index a04897f04c13..e9d03ef98154 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > @@ -445,7 +445,8 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, > */ > vmw_overlay_pause_all(dev_priv); > ret = vmw_bo_create(dev_priv, size, > - &vmw_vram_placement, > + VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_VRAM, > false, true, &vps->bo); > vmw_overlay_resume_all(dev_priv); > if (ret) { > @@ -547,7 +548,6 @@ static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv, > bo_update.base.vfb = vfb; > bo_update.base.out_fence = out_fence; > bo_update.base.mutex = NULL; > - bo_update.base.cpu_blit = false; > bo_update.base.intr = true; > > bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size; > @@ -708,7 +708,6 @@ static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv, > srf_update.base.vfb = vfb; > srf_update.base.out_fence = out_fence; > srf_update.base.mutex = &dev_priv->cmdbuf_mutex; > - srf_update.base.cpu_blit = false; > srf_update.base.intr = true; > > srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size; > @@ -1224,7 +1223,9 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > int ret; > > - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); > + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, buf); > if (ret) > return ret; > > @@ -1330,7 +1331,9 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > int ret; > > - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); > + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, buf); > if (ret) > return ret; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > index b186d0993d83..9920c103bffb 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > @@ -94,7 +94,8 @@ static const struct vmw_res_func vmw_gb_shader_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "guest backed shaders", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_gb_shader_create, > .destroy = vmw_gb_shader_destroy, > .bind = vmw_gb_shader_bind, > @@ -108,7 +109,8 @@ static const struct vmw_res_func vmw_dx_shader_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "dx shaders", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_dx_shader_create, > /* > * The destroy callback is only called with a committed resource on > @@ -893,7 +895,9 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, > if (!vmw_shader_id_ok(user_key, shader_type)) > return -EINVAL; > > - ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement, > + ret = vmw_bo_create(dev_priv, size, > + VMW_BO_DOMAIN_SYS, > + VMW_BO_DOMAIN_SYS, > true, true, &buf); > if (unlikely(ret != 0)) > goto out; > @@ -913,7 +917,10 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, > WARN_ON(is_iomem); > > ttm_bo_kunmap(&map); > - ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_SYS, > + VMW_BO_DOMAIN_SYS); > + ret = ttm_bo_validate(&buf->base, &buf->placement, &ctx); > WARN_ON(ret != 0); > ttm_bo_unreserve(&buf->base); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > index 4ea32b01efc0..603175b8c97e 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > @@ -24,6 +24,7 @@ > * > **************************************************************************/ > > +#include "vmwgfx_bo.h" > #include "vmwgfx_drv.h" > #include "vmwgfx_resource_priv.h" > #include "vmwgfx_so.h" > @@ -84,7 +85,8 @@ static const struct vmw_res_func vmw_view_func = { > .needs_backup = false, > .may_evict = false, > .type_name = "DX view", > - .backup_placement = NULL, > + .domain = VMW_BO_DOMAIN_SYS, > + .busy_domain = VMW_BO_DOMAIN_SYS, > .create = vmw_view_create, > .commit_notify = vmw_view_commit_notify, > }; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > index 4745537fed25..0df86402e9ce 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > @@ -66,7 +66,6 @@ enum stdu_content_type { > */ > struct vmw_stdu_dirty { > struct vmw_kms_dirty base; > - SVGA3dTransferType transfer; > s32 left, right, top, bottom; > s32 fb_left, fb_top; > u32 pitch; > @@ -137,12 +136,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); > * Screen Target Display Unit CRTC Functions > *****************************************************************************/ > > -static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw) > -{ > - return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024); > -} > - > - > /** > * vmw_stdu_crtc_destroy - cleans up the STDU > * > @@ -451,93 +444,6 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, > } > } > > -/** > - * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect > - * > - * @dirty: The closure structure. > - * > - * Encodes a surface DMA command cliprect and updates the bounding box > - * for the DMA. > - */ > -static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty) > -{ > - struct vmw_stdu_dirty *ddirty = > - container_of(dirty, struct vmw_stdu_dirty, base); > - struct vmw_stdu_dma *cmd = dirty->cmd; > - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; > - > - blit += dirty->num_hits; > - blit->srcx = dirty->fb_x; > - blit->srcy = dirty->fb_y; > - blit->x = dirty->unit_x1; > - blit->y = dirty->unit_y1; > - blit->d = 1; > - blit->w = dirty->unit_x2 - dirty->unit_x1; > - blit->h = dirty->unit_y2 - dirty->unit_y1; > - dirty->num_hits++; > - > - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) > - return; > - > - /* Destination bounding box */ > - ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1); > - ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1); > - ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2); > - ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); > -} > - > -/** > - * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command. > - * > - * @dirty: The closure structure. > - * > - * Fills in the missing fields in a DMA command, and optionally encodes > - * a screen target update command, depending on transfer direction. > - */ > -static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty) > -{ > - struct vmw_stdu_dirty *ddirty = > - container_of(dirty, struct vmw_stdu_dirty, base); > - struct vmw_screen_target_display_unit *stdu = > - container_of(dirty->unit, typeof(*stdu), base); > - struct vmw_stdu_dma *cmd = dirty->cmd; > - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; > - SVGA3dCmdSurfaceDMASuffix *suffix = > - (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits]; > - size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix); > - > - if (!dirty->num_hits) { > - vmw_cmd_commit(dirty->dev_priv, 0); > - return; > - } > - > - cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; > - cmd->header.size = sizeof(cmd->body) + blit_size; > - vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr); > - cmd->body.guest.pitch = ddirty->pitch; > - cmd->body.host.sid = stdu->display_srf->res.id; > - cmd->body.host.face = 0; > - cmd->body.host.mipmap = 0; > - cmd->body.transfer = ddirty->transfer; > - suffix->suffixSize = sizeof(*suffix); > - suffix->maximumOffset = ddirty->buf->base.base.size; > - > - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { > - blit_size += sizeof(struct vmw_stdu_update); > - > - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, > - ddirty->left, ddirty->right, > - ddirty->top, ddirty->bottom); > - } > - > - vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size); > - > - stdu->display_srf->res.res_dirty = true; > - ddirty->left = ddirty->top = S32_MAX; > - ddirty->right = ddirty->bottom = S32_MIN; > -} > - > - > /** > * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit > * > @@ -598,62 +504,21 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > return; > > /* Assume we are blitting from Guest (bo) to Host (display_srf) */ > - dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; > - dst_bo = &stdu->display_srf->res.backup->base; > - dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; > - > - src_pitch = ddirty->pitch; > - src_bo = &ddirty->buf->base; > - src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; > + src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; > + src_bo = &stdu->display_srf->res.backup->base; > + src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; > > - /* Swap src and dst if the assumption was wrong. */ > - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) { > - swap(dst_pitch, src_pitch); > - swap(dst_bo, src_bo); > - swap(src_offset, dst_offset); > - } > + dst_pitch = ddirty->pitch; > + dst_bo = &ddirty->buf->base; > + dst_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; > > (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, > src_bo, src_offset, src_pitch, > width * stdu->cpp, height, &diff); > - > - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM && > - drm_rect_visible(&diff.rect)) { > - struct vmw_private *dev_priv; > - struct vmw_stdu_update *cmd; > - struct drm_clip_rect region; > - int ret; > - > - /* We are updating the actual surface, not a proxy */ > - region.x1 = diff.rect.x1; > - region.x2 = diff.rect.x2; > - region.y1 = diff.rect.y1; > - region.y2 = diff.rect.y2; > - ret = vmw_kms_update_proxy(&stdu->display_srf->res, ®ion, > - 1, 1); > - if (ret) > - goto out_cleanup; > - > - > - dev_priv = vmw_priv(stdu->base.crtc.dev); > - cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); > - if (!cmd) > - goto out_cleanup; > - > - vmw_stdu_populate_update(cmd, stdu->base.unit, > - region.x1, region.x2, > - region.y1, region.y2); > - > - vmw_cmd_commit(dev_priv, sizeof(*cmd)); > - } > - > -out_cleanup: > - ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; > - ddirty->right = ddirty->bottom = S32_MIN; > } > > /** > - * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed > + * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed > * framebuffer and the screen target system. > * > * @dev_priv: Pointer to the device private structure. > @@ -666,9 +531,6 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > * be NULL. > * @num_clips: Number of clip rects in @clips or @vclips. > * @increment: Increment to use when looping over @clips or @vclips. > - * @to_surface: Whether to DMA to the screen target system as opposed to > - * from the screen target system. > - * @interruptible: Whether to perform waits interruptible if possible. > * @crtc: If crtc is passed, perform stdu dma on that crtc only. > * > * If DMA-ing till the screen target system, the function will also notify > @@ -677,59 +539,49 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > * Returns 0 on success, negative error code on failure. -ERESTARTSYS if > * interrupted. > */ > -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, > - struct drm_file *file_priv, > - struct vmw_framebuffer *vfb, > - struct drm_vmw_fence_rep __user *user_fence_rep, > - struct drm_clip_rect *clips, > - struct drm_vmw_rect *vclips, > - uint32_t num_clips, > - int increment, > - bool to_surface, > - bool interruptible, > - struct drm_crtc *crtc) > +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, > + struct drm_file *file_priv, > + struct vmw_framebuffer *vfb, > + struct drm_vmw_fence_rep __user *user_fence_rep, > + struct drm_clip_rect *clips, > + struct drm_vmw_rect *vclips, > + uint32_t num_clips, > + int increment, > + struct drm_crtc *crtc) > { > struct vmw_bo *buf = > container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; > struct vmw_stdu_dirty ddirty; > int ret; > - bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > > /* > - * VMs without 3D support don't have the surface DMA command and > - * we'll be using a CPU blit, and the framebuffer should be moved out > - * of VRAM. > + * The GMR domain might seem confusing because it might seem like it should > + * never happen with screen targets but e.g. the xorg vmware driver issues > + * CMD_SURFACE_DMA for various pixmap updates which might transition our bo to > + * a GMR. Instead of forcing another transition we can optimize the readback > + * by reading directly from the GMR. > */ > - ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR, > + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR); > + ret = vmw_validation_add_bo(&val_ctx, buf); > if (ret) > return ret; > > - ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); > + ret = vmw_validation_prepare(&val_ctx, NULL, true); > if (ret) > goto out_unref; > > - ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM : > - SVGA3D_READ_HOST_VRAM; > ddirty.left = ddirty.top = S32_MAX; > ddirty.right = ddirty.bottom = S32_MIN; > ddirty.fb_left = ddirty.fb_top = S32_MAX; > ddirty.pitch = vfb->base.pitches[0]; > ddirty.buf = buf; > - ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit; > - ddirty.base.clip = vmw_stdu_bo_clip; > - ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) + > - num_clips * sizeof(SVGA3dCopyBox) + > - sizeof(SVGA3dCmdSurfaceDMASuffix); > - if (to_surface) > - ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update); > - > - > - if (cpu_blit) { > - ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; > - ddirty.base.clip = vmw_stdu_bo_cpu_clip; > - ddirty.base.fifo_reserve_size = 0; > - } > + > + ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; > + ddirty.base.clip = vmw_stdu_bo_cpu_clip; > + ddirty.base.fifo_reserve_size = 0; > > ddirty.base.crtc = crtc; > > @@ -1161,11 +1013,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, > /* > * This should only happen if the buffer object is too large to create a > * proxy surface for. > - * If we are a 2D VM with a buffer object then we have to use CPU blit > - * so cache these mappings > */ > - if (vps->content_fb_type == SEPARATE_BO && > - vmw_stdu_use_cpu_blit(dev_priv)) > + if (vps->content_fb_type == SEPARATE_BO) > vps->cpp = new_fb->pitches[0] / new_fb->width; > > return 0; > @@ -1175,14 +1024,6 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, > return ret; > } > > -static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update, > - uint32_t num_hits) > -{ > - return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits + > - sizeof(SVGA3dCmdSurfaceDMASuffix) + > - sizeof(struct vmw_stdu_update); > -} > - > static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, > uint32_t num_hits) > { > @@ -1190,68 +1031,6 @@ static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, > sizeof(struct vmw_stdu_update); > } > > -static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update, > - void *cmd, uint32_t num_hits) > -{ > - struct vmw_screen_target_display_unit *stdu; > - struct vmw_framebuffer_bo *vfbbo; > - struct vmw_stdu_dma *cmd_dma = cmd; > - > - stdu = container_of(update->du, typeof(*stdu), base); > - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); > - > - cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA; > - cmd_dma->header.size = sizeof(cmd_dma->body) + > - sizeof(struct SVGA3dCopyBox) * num_hits + > - sizeof(SVGA3dCmdSurfaceDMASuffix); > - vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr); > - cmd_dma->body.guest.pitch = update->vfb->base.pitches[0]; > - cmd_dma->body.host.sid = stdu->display_srf->res.id; > - cmd_dma->body.host.face = 0; > - cmd_dma->body.host.mipmap = 0; > - cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM; > - > - return sizeof(*cmd_dma); > -} > - > -static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update, > - void *cmd, struct drm_rect *clip, > - uint32_t fb_x, uint32_t fb_y) > -{ > - struct SVGA3dCopyBox *box = cmd; > - > - box->srcx = fb_x; > - box->srcy = fb_y; > - box->srcz = 0; > - box->x = clip->x1; > - box->y = clip->y1; > - box->z = 0; > - box->w = drm_rect_width(clip); > - box->h = drm_rect_height(clip); > - box->d = 1; > - > - return sizeof(*box); > -} > - > -static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update, > - void *cmd, struct drm_rect *bb) > -{ > - struct vmw_screen_target_display_unit *stdu; > - struct vmw_framebuffer_bo *vfbbo; > - SVGA3dCmdSurfaceDMASuffix *suffix = cmd; > - > - stdu = container_of(update->du, typeof(*stdu), base); > - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); > - > - suffix->suffixSize = sizeof(*suffix); > - suffix->maximumOffset = vfbbo->buffer->base.base.size; > - > - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2, > - bb->y1, bb->y2); > - > - return sizeof(*suffix) + sizeof(struct vmw_stdu_update); > -} > - > static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, > void *cmd, uint32_t num_hits) > { > @@ -1369,24 +1148,12 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, > bo_update.base.vfb = vfb; > bo_update.base.out_fence = out_fence; > bo_update.base.mutex = NULL; > - bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); > bo_update.base.intr = false; > > - /* > - * VM without 3D support don't have surface DMA command and framebuffer > - * should be moved out of VRAM. > - */ > - if (bo_update.base.cpu_blit) { > - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; > - bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; > - bo_update.base.clip = vmw_stdu_bo_clip_cpu; > - bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; > - } else { > - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size; > - bo_update.base.pre_clip = vmw_stdu_bo_populate_dma; > - bo_update.base.clip = vmw_stdu_bo_populate_clip; > - bo_update.base.post_clip = vmw_stdu_bo_populate_update; > - } > + bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; > + bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; > + bo_update.base.clip = vmw_stdu_bo_clip_cpu; > + bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; > > return vmw_du_helper_plane_update(&bo_update.base); > } > @@ -1549,7 +1316,6 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, > srf_update.vfb = vfb; > srf_update.out_fence = out_fence; > srf_update.mutex = &dev_priv->cmdbuf_mutex; > - srf_update.cpu_blit = false; > srf_update.intr = true; > > if (vfbs->is_bo_proxy) > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > index 71ce89150ba7..b35ac195285d 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > @@ -66,7 +66,8 @@ static const struct vmw_res_func vmw_dx_streamoutput_func = { > .needs_backup = true, > .may_evict = false, > .type_name = "DX streamoutput", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_dx_streamoutput_create, > .destroy = NULL, /* Command buffer managed resource. */ > .bind = vmw_dx_streamoutput_bind, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > index 296d903c5acb..9c6a691b005e 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > @@ -131,7 +131,8 @@ static const struct vmw_res_func vmw_legacy_surface_func = { > .prio = 1, > .dirty_prio = 1, > .type_name = "legacy surfaces", > - .backup_placement = &vmw_srf_placement, > + .domain = VMW_BO_DOMAIN_GMR, > + .busy_domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > .create = &vmw_legacy_srf_create, > .destroy = &vmw_legacy_srf_destroy, > .bind = &vmw_legacy_srf_bind, > @@ -145,7 +146,8 @@ static const struct vmw_res_func vmw_gb_surface_func = { > .prio = 1, > .dirty_prio = 2, > .type_name = "guest backed surfaces", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_gb_surface_create, > .destroy = vmw_gb_surface_destroy, > .bind = vmw_gb_surface_bind, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > index 41480af87255..c43df4109613 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > @@ -79,20 +79,6 @@ static const struct ttm_place vram_gmr_placement_flags[] = { > } > }; > > -static const struct ttm_place gmr_vram_placement_flags[] = { > - { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = VMW_PL_GMR, > - .flags = 0 > - }, { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = TTM_PL_VRAM, > - .flags = 0 > - } > -}; > - > static const struct ttm_place vmw_sys_placement_flags = { > .fpfn = 0, > .lpfn = 0, > @@ -128,32 +114,6 @@ struct ttm_placement vmw_pt_sys_placement = { > .busy_placement = &vmw_sys_placement_flags > }; > > -static const struct ttm_place nonfixed_placement_flags[] = { > - { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = TTM_PL_SYSTEM, > - .flags = 0 > - }, { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = VMW_PL_GMR, > - .flags = 0 > - }, { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = VMW_PL_MOB, > - .flags = 0 > - } > -}; > - > -struct ttm_placement vmw_srf_placement = { > - .num_placement = 1, > - .num_busy_placement = 2, > - .placement = &gmr_placement_flags, > - .busy_placement = gmr_vram_placement_flags > -}; > - > struct ttm_placement vmw_mob_placement = { > .num_placement = 1, > .num_busy_placement = 1, > @@ -161,13 +121,6 @@ struct ttm_placement vmw_mob_placement = { > .busy_placement = &mob_placement_flags > }; > > -struct ttm_placement vmw_nonfixed_placement = { > - .num_placement = 3, > - .placement = nonfixed_placement_flags, > - .num_busy_placement = 1, > - .busy_placement = &sys_placement_flags > -}; > - > const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); > > /** > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > index 6ad744ae07f5..c968180c9769 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > @@ -25,6 +25,7 @@ > * > **************************************************************************/ > > +#include "vmwgfx_bo.h" > #include "vmwgfx_drv.h" > #include "vmwgfx_resource_priv.h" > > @@ -83,7 +84,8 @@ static const struct vmw_simple_resource_func va_stream_func = { > .needs_backup = false, > .may_evict = false, > .type_name = "overlay stream", > - .backup_placement = NULL, > + .domain = VMW_BO_DOMAIN_SYS, > + .busy_domain = VMW_BO_DOMAIN_SYS, > .create = NULL, > .destroy = NULL, > .bind = NULL, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > index 770b1b53bde7..05f0909ff1dd 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > @@ -27,6 +27,7 @@ > **************************************************************************/ > #include "vmwgfx_bo.h" > #include "vmwgfx_drv.h" > +#include "vmwgfx_resource_priv.h" > #include "vmwgfx_validation.h" > > #include <linux/slab.h> > @@ -40,8 +41,6 @@ > * @hash: A hash entry used for the duplicate detection hash table. > * @coherent_count: If switching backup buffers, number of new coherent > * resources that will have this buffer as a backup buffer. > - * @as_mob: Validate as mob. > - * @cpu_blit: Validate for cpu blit access. > * > * Bit fields are used since these structures are allocated and freed in > * large numbers and space conservation is desired. > @@ -50,8 +49,6 @@ struct vmw_validation_bo_node { > struct ttm_validate_buffer base; > struct vmwgfx_hash_item hash; > unsigned int coherent_count; > - u32 as_mob : 1; > - u32 cpu_blit : 1; > }; > /** > * struct vmw_validation_res_node - Resource validation metadata. > @@ -260,26 +257,16 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx, > * vmw_validation_add_bo - Add a buffer object to the validation context. > * @ctx: The validation context. > * @vbo: The buffer object. > - * @as_mob: Validate as mob, otherwise suitable for GMR operations. > - * @cpu_blit: Validate in a page-mappable location. > * > * Return: Zero on success, negative error code otherwise. > */ > int vmw_validation_add_bo(struct vmw_validation_context *ctx, > - struct vmw_bo *vbo, > - bool as_mob, > - bool cpu_blit) > + struct vmw_bo *vbo) > { > struct vmw_validation_bo_node *bo_node; > > bo_node = vmw_validation_find_bo_dup(ctx, vbo); > - if (bo_node) { > - if (bo_node->as_mob != as_mob || > - bo_node->cpu_blit != cpu_blit) { > - DRM_ERROR("Inconsistent buffer usage.\n"); > - return -EINVAL; > - } > - } else { > + if (!bo_node) { > struct ttm_validate_buffer *val_buf; > > bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node)); > @@ -297,8 +284,6 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, > return -ESRCH; > val_buf->num_shared = 0; > list_add_tail(&val_buf->head, &ctx->bo_list); > - bo_node->as_mob = as_mob; > - bo_node->cpu_blit = cpu_blit; > } > > return 0; > @@ -455,9 +440,10 @@ int vmw_validation_res_reserve(struct vmw_validation_context *ctx, > if (res->backup) { > struct vmw_bo *vbo = res->backup; > > - ret = vmw_validation_add_bo > - (ctx, vbo, vmw_resource_needs_backup(res), > - false); > + vmw_bo_placement_set(vbo, > + res->func->domain, > + res->func->busy_domain); > + ret = vmw_validation_add_bo(ctx, vbo); > if (ret) > goto out_unreserve; > } > @@ -519,14 +505,12 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, > * vmw_validation_bo_validate_single - Validate a single buffer object. > * @bo: The TTM buffer object base. > * @interruptible: Whether to perform waits interruptible if possible. > - * @validate_as_mob: Whether to validate in MOB memory. > * > * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error > * code on failure. > */ > -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > - bool interruptible, > - bool validate_as_mob) > +static int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > + bool interruptible) > { > struct vmw_bo *vbo = > container_of(bo, struct vmw_bo, base); > @@ -542,27 +526,17 @@ int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > if (vbo->base.pin_count > 0) > return 0; > > - if (validate_as_mob) > - return ttm_bo_validate(bo, &vmw_mob_placement, &ctx); > - > - /** > - * Put BO in VRAM if there is space, otherwise as a GMR. > - * If there is no space in VRAM and GMR ids are all used up, > - * start evicting GMRs to make room. If the DMA buffer can't be > - * used as a GMR, this will return -ENOMEM. > - */ > - > - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); > + ret = ttm_bo_validate(bo, &vbo->placement, &ctx); > if (ret == 0 || ret == -ERESTARTSYS) > return ret; > > - /** > - * If that failed, try VRAM again, this time evicting > + /* > + * If that failed, try again, this time evicting > * previous contents. > */ > + ctx.allow_res_evict = true; > > - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); > - return ret; > + return ttm_bo_validate(bo, &vbo->placement, &ctx); > } > > /** > @@ -583,18 +557,8 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) > struct vmw_bo *vbo = > container_of(entry->base.bo, typeof(*vbo), base); > > - if (entry->cpu_blit) { > - struct ttm_operation_ctx ttm_ctx = { > - .interruptible = intr, > - .no_wait_gpu = false > - }; > - > - ret = ttm_bo_validate(entry->base.bo, > - &vmw_nonfixed_placement, &ttm_ctx); > - } else { > - ret = vmw_validation_bo_validate_single > - (entry->base.bo, intr, entry->as_mob); > - } > + ret = vmw_validation_bo_validate_single(entry->base.bo, intr); > + > if (ret) > return ret; > > @@ -655,9 +619,9 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) > if (backup && res->backup && (backup != res->backup)) { > struct vmw_bo *vbo = res->backup; > > - ret = vmw_validation_add_bo > - (ctx, vbo, vmw_resource_needs_backup(res), > - false); > + vmw_bo_placement_set(vbo, res->func->domain, > + res->func->busy_domain); > + ret = vmw_validation_add_bo(ctx, vbo); > if (ret) > return ret; > } > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > index 4aa4f700c65e..240ee0c4ebfd 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > @@ -159,11 +159,7 @@ static inline unsigned int vmw_validation_align(unsigned int val) > } > > int vmw_validation_add_bo(struct vmw_validation_context *ctx, > - struct vmw_bo *vbo, > - bool as_mob, bool cpu_blit); > -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > - bool interruptible, > - bool validate_as_mob); > + struct vmw_bo *vbo); > int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); > void vmw_validation_unref_lists(struct vmw_validation_context *ctx); > int vmw_validation_add_resource(struct vmw_validation_context *ctx,
On 1/30/23 19:35, Zack Rusin wrote: > From: Zack Rusin <zackr@vmware.com> > > Problem with explicit placement selection in vmwgfx is that by the time > the buffer object needs to be validated the information about which > placement was supposed to be used is lost. To workaround this the driver > had a bunch of state in various places e.g. as_mob or cpu_blit to > somehow convey the information on which placement was intended. > > Fix it properly by allowing the buffer objects to hold their preferred > placement so it can be reused whenever needed. This makes the entire > validation pipeline a lot easier both to understand and maintain. > > Signed-off-by: Zack Rusin <zackr@vmware.com> > --- > drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 145 +++++++-- > drivers/gpu/drm/vmwgfx/vmwgfx_bo.h | 25 +- > drivers/gpu/drm/vmwgfx/vmwgfx_context.c | 9 +- > drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c | 11 +- > drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 3 +- > drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 - > drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 35 +- > drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 5 +- > drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 22 +- > drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 21 +- > drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 11 +- > drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h | 3 +- > drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 13 +- > drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 15 +- > drivers/gpu/drm/vmwgfx/vmwgfx_so.c | 4 +- > drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 304 ++---------------- > drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c | 3 +- > drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 6 +- > drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 47 --- > drivers/gpu/drm/vmwgfx/vmwgfx_va.c | 4 +- > drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 74 ++--- > drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 6 +- > 22 files changed, 312 insertions(+), 456 deletions(-) > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > index c6dc733f6d45..d8f6ccecf4bf 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > @@ -135,11 +135,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, > goto out_unreserve; > } > > - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > if (likely(ret == 0) || ret == -ERESTARTSYS) > goto out_unreserve; > > - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_VRAM); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > out_unreserve: > if (!ret) > @@ -190,17 +196,8 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, > { > struct ttm_operation_ctx ctx = {interruptible, false }; > struct ttm_buffer_object *bo = &buf->base; > - struct ttm_placement placement; > - struct ttm_place place; > int ret = 0; > > - place = vmw_vram_placement.placement[0]; > - place.lpfn = PFN_UP(bo->resource->size); > - placement.num_placement = 1; > - placement.placement = &place; > - placement.num_busy_placement = 1; > - placement.busy_placement = &place; > - > vmw_execbuf_release_pinned_bo(dev_priv); > ret = ttm_bo_reserve(bo, interruptible, false, NULL); > if (unlikely(ret != 0)) > @@ -216,14 +213,21 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, > bo->resource->start > 0 && > buf->base.pin_count == 0) { > ctx.interruptible = false; > - (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_SYS, > + VMW_BO_DOMAIN_SYS); > + (void)ttm_bo_validate(bo, &buf->placement, &ctx); > } > > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_VRAM); > + buf->places[0].lpfn = PFN_UP(bo->resource->size); > if (buf->base.pin_count > 0) > - ret = ttm_resource_compat(bo->resource, &placement) > + ret = ttm_resource_compat(bo->resource, &buf->placement) > ? 0 : -EINVAL; > else > - ret = ttm_bo_validate(bo, &placement, &ctx); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > /* For some reason we didn't end up at the start of vram */ > WARN_ON(ret == 0 && bo->resource->start != 0); > @@ -431,7 +435,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, > } > > int vmw_bo_create(struct vmw_private *vmw, > - size_t size, struct ttm_placement *placement, > + size_t size, u32 domain, u32 busy_domain, > bool interruptible, bool pin, > struct vmw_bo **p_bo) > { > @@ -444,7 +448,8 @@ int vmw_bo_create(struct vmw_private *vmw, > } > > ret = vmw_bo_init(vmw, *p_bo, size, > - placement, interruptible, pin); > + domain, busy_domain, > + interruptible, pin); > if (unlikely(ret != 0)) > goto out_error; > > @@ -461,7 +466,8 @@ int vmw_bo_create(struct vmw_private *vmw, > * @dev_priv: Pointer to the device private struct > * @vmw_bo: Pointer to the struct vmw_bo to initialize. > * @size: Buffer object size in bytes. > - * @placement: Initial placement. > + * @domain: Domain to put the bo in. > + * @busy_domain: Domain to put the bo if busy. > * @interruptible: Whether waits should be performed interruptible. > * @pin: If the BO should be created pinned at a fixed location. > * Returns: Zero on success, negative error code on error. > @@ -470,7 +476,9 @@ int vmw_bo_create(struct vmw_private *vmw, > */ > int vmw_bo_init(struct vmw_private *dev_priv, > struct vmw_bo *vmw_bo, > - size_t size, struct ttm_placement *placement, > + size_t size, > + u32 domain, > + u32 busy_domain, > bool interruptible, bool pin) > { > struct ttm_operation_ctx ctx = { > @@ -489,8 +497,9 @@ int vmw_bo_init(struct vmw_private *dev_priv, > size = ALIGN(size, PAGE_SIZE); > drm_gem_private_object_init(vdev, &vmw_bo->base.base, size); > > + vmw_bo_placement_set(vmw_bo, domain, busy_domain); > ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device, > - placement, 0, &ctx, NULL, NULL, vmw_bo_free); > + &vmw_bo->placement, 0, &ctx, NULL, NULL, vmw_bo_free); > if (unlikely(ret)) { > return ret; > } > @@ -825,3 +834,101 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, > if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) > vmw_resource_unbind_list(vbo); > } > + > +static u32 > +set_placement_list(struct ttm_place *pl, u32 domain) > +{ > + u32 n = 0; > + > + /* > + * The placements are ordered according to our preferences > + */ > + if (domain & VMW_BO_DOMAIN_MOB) { > + pl[n].mem_type = VMW_PL_MOB; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + if (domain & VMW_BO_DOMAIN_GMR) { > + pl[n].mem_type = VMW_PL_GMR; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + if (domain & VMW_BO_DOMAIN_VRAM) { > + pl[n].mem_type = TTM_PL_VRAM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + WARN_ON((domain & VMW_BO_DOMAIN_WAITABLE_SYS) != 0); > + if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) { > + pl[n].mem_type = VMW_PL_SYSTEM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + if (domain & VMW_BO_DOMAIN_SYS) { > + pl[n].mem_type = TTM_PL_SYSTEM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + > + WARN_ON(!n); > + if (!n) { > + pl[n].mem_type = TTM_PL_SYSTEM; > + pl[n].flags = 0; > + pl[n].fpfn = 0; > + pl[n].lpfn = 0; > + n++; > + } > + return n; > +} > + > +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain) > +{ > + struct ttm_device *bdev = bo->base.bdev; > + struct vmw_private *vmw = > + container_of(bdev, struct vmw_private, bdev); > + struct ttm_placement *pl = &bo->placement; > + bool mem_compatible = false; > + u32 i; > + > + pl->placement = bo->places; > + pl->num_placement = set_placement_list(bo->places, domain); > + > + if (drm_debug_enabled(DRM_UT_DRIVER) && bo->base.resource) { > + for (i = 0; i < pl->num_placement; ++i) { > + if (bo->base.resource->mem_type == TTM_PL_SYSTEM || > + bo->base.resource->mem_type == pl->placement[i].mem_type) > + mem_compatible = true; > + } > + if (!mem_compatible) > + drm_warn(&vmw->drm, > + "%s: Incompatible transition from " > + "bo->base.resource->mem_type = %u to domain = %u\n", > + __func__, bo->base.resource->mem_type, domain); > + } > + > + pl->busy_placement = bo->busy_places; > + pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain); > +} > + > +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo) > +{ > + struct ttm_device *bdev = bo->base.bdev; > + struct vmw_private *vmw = > + container_of(bdev, struct vmw_private, bdev); > + u32 domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM; > + > + if (vmw->has_mob) > + domain = VMW_BO_DOMAIN_MOB; > + > + vmw_bo_placement_set(bo, domain, domain); > +} > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > index 2ede1e28d7ce..538d8739d7a5 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > @@ -31,6 +31,7 @@ > #include "device_include/svga_reg.h" > > #include <drm/ttm/ttm_bo_api.h> > +#include <drm/ttm/ttm_placement.h> > > #include <linux/rbtree_types.h> > #include <linux/types.h> > @@ -40,6 +41,14 @@ struct vmw_fence_obj; > struct vmw_private; > struct vmw_resource; > > +enum vmw_bo_domain { > + VMW_BO_DOMAIN_SYS = BIT(0), > + VMW_BO_DOMAIN_WAITABLE_SYS = BIT(1), > + VMW_BO_DOMAIN_VRAM = BIT(2), > + VMW_BO_DOMAIN_GMR = BIT(3), > + VMW_BO_DOMAIN_MOB = BIT(4), > +}; > + > /** > * struct vmw_bo - TTM buffer object with vmwgfx additions > * @base: The TTM buffer object > @@ -53,6 +62,11 @@ struct vmw_resource; > */ > struct vmw_bo { > struct ttm_buffer_object base; > + > + struct ttm_placement placement; > + struct ttm_place places[5]; > + struct ttm_place busy_places[5]; > + > struct rb_root res_tree; > > atomic_t cpu_writers; > @@ -64,17 +78,24 @@ struct vmw_bo { > struct vmw_bo_dirty *dirty; > }; > > +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain); > +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo); > + > int vmw_bo_create_kernel(struct vmw_private *dev_priv, > unsigned long size, > struct ttm_placement *placement, > struct ttm_buffer_object **p_bo); > int vmw_bo_create(struct vmw_private *dev_priv, > - size_t size, struct ttm_placement *placement, > + size_t size, > + u32 domain, > + u32 busy_domain, > bool interruptible, bool pin, > struct vmw_bo **p_bo); > int vmw_bo_init(struct vmw_private *dev_priv, > struct vmw_bo *vmw_bo, > - size_t size, struct ttm_placement *placement, > + size_t size, > + u32 domain, > + u32 busy_domain, > bool interruptible, bool pin); > int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, > struct drm_file *file_priv); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > index cc02be6a9884..84ef5f0a785b 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > @@ -76,7 +76,8 @@ static const struct vmw_res_func vmw_legacy_context_func = { > .needs_backup = false, > .may_evict = false, > .type_name = "legacy contexts", > - .backup_placement = NULL, > + .domain = VMW_BO_DOMAIN_SYS, > + .busy_domain = VMW_BO_DOMAIN_SYS, > .create = NULL, > .destroy = NULL, > .bind = NULL, > @@ -90,7 +91,8 @@ static const struct vmw_res_func vmw_gb_context_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "guest backed contexts", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_gb_context_create, > .destroy = vmw_gb_context_destroy, > .bind = vmw_gb_context_bind, > @@ -104,7 +106,8 @@ static const struct vmw_res_func vmw_dx_context_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "dx contexts", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_dx_context_create, > .destroy = vmw_dx_context_destroy, > .bind = vmw_dx_context_bind, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > index 9193faae8dab..d49db8146df1 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > @@ -136,7 +136,8 @@ static const struct vmw_res_func vmw_cotable_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "context guest backed object tables", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_cotable_create, > .destroy = vmw_cotable_destroy, > .bind = vmw_cotable_bind, > @@ -424,7 +425,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) > * for the new COTable. Initially pin the buffer object to make sure > * we can use tryreserve without failure. > */ > - ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement, > + ret = vmw_bo_create(dev_priv, new_size, > + VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB, > true, true, &buf); > if (ret) { > DRM_ERROR("Failed initializing new cotable MOB.\n"); > @@ -465,7 +467,10 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) > } > > /* Unpin new buffer, and switch backup buffers. */ > - ret = ttm_bo_validate(bo, &vmw_mob_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_MOB, > + VMW_BO_DOMAIN_MOB); > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > if (unlikely(ret != 0)) { > DRM_ERROR("Failed validating new COTable backup buffer.\n"); > goto out_wait; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > index 60d08185a71f..c12ad8264043 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > @@ -399,7 +399,8 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) > * user of the bo currently. > */ > ret = vmw_bo_create(dev_priv, PAGE_SIZE, > - &vmw_sys_placement, false, true, &vbo); > + VMW_BO_DOMAIN_SYS, VMW_BO_DOMAIN_SYS, > + false, true, &vbo); > if (unlikely(ret != 0)) > return ret; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > index e9a16a1e043d..5629a00039fe 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > @@ -930,9 +930,7 @@ extern struct ttm_placement vmw_vram_placement; > extern struct ttm_placement vmw_vram_sys_placement; > extern struct ttm_placement vmw_vram_gmr_placement; > extern struct ttm_placement vmw_sys_placement; > -extern struct ttm_placement vmw_srf_placement; > extern struct ttm_placement vmw_mob_placement; > -extern struct ttm_placement vmw_nonfixed_placement; > extern struct ttm_device_funcs vmw_bo_driver; > extern const struct vmw_sg_table * > vmw_bo_sg_table(struct ttm_buffer_object *bo); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > index 687c6926bc00..eda7f8471bcd 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > @@ -477,9 +477,13 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, > struct vmw_bo *dx_query_mob; > > dx_query_mob = vmw_context_get_dx_query_mob(ctx); > - if (dx_query_mob) > + if (dx_query_mob) { > + vmw_bo_placement_set(dx_query_mob, > + VMW_BO_DOMAIN_MOB, > + VMW_BO_DOMAIN_MOB); > ret = vmw_validation_add_bo(sw_context->ctx, > - dx_query_mob, true, false); > + dx_query_mob); > + } > } > > mutex_unlock(&dev_priv->binding_mutex); > @@ -1035,17 +1039,17 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, > > if (unlikely(sw_context->cur_query_bo != NULL)) { > sw_context->needs_post_query_barrier = true; > + vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo); > ret = vmw_validation_add_bo(sw_context->ctx, > - sw_context->cur_query_bo, > - dev_priv->has_mob, false); > + sw_context->cur_query_bo); > if (unlikely(ret != 0)) > return ret; > } > sw_context->cur_query_bo = new_query_bo; > > + vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo); > ret = vmw_validation_add_bo(sw_context->ctx, > - dev_priv->dummy_query_bo, > - dev_priv->has_mob, false); > + dev_priv->dummy_query_bo); > if (unlikely(ret != 0)) > return ret; > } > @@ -1157,7 +1161,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, > drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); > return PTR_ERR(vmw_bo); > } > - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); > + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); > + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); > ttm_bo_put(&vmw_bo->base); > if (unlikely(ret != 0)) > return ret; > @@ -1211,7 +1216,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, > drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); > return PTR_ERR(vmw_bo); > } > - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); > + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); > ttm_bo_put(&vmw_bo->base); > if (unlikely(ret != 0)) > return ret; > @@ -4361,13 +4368,17 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, > if (dev_priv->pinned_bo == NULL) > goto out_unlock; > > - ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, > - false); > + vmw_bo_placement_set(dev_priv->pinned_bo, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo); > if (ret) > goto out_no_reserve; > > - ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, > - false); > + vmw_bo_placement_set(dev_priv->dummy_query_bo, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo); > if (ret) > goto out_no_reserve; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > index c7ebcd4f3afa..5f383578a320 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > @@ -121,9 +121,8 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, > int ret; > > ret = vmw_bo_create(dev_priv, size, > - (dev_priv->has_mob) ? > - &vmw_sys_placement : > - &vmw_vram_sys_placement, > + (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_SYS, > true, false, p_vbo); > > (*p_vbo)->base.base.funcs = &vmw_gem_object_funcs; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > index e83286e08837..d975c0a818c7 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > @@ -1270,9 +1270,9 @@ int vmw_kms_readback(struct vmw_private *dev_priv, > user_fence_rep, vclips, num_clips, > NULL); > case vmw_du_screen_target: > - return vmw_kms_stdu_dma(dev_priv, file_priv, vfb, > - user_fence_rep, NULL, vclips, num_clips, > - 1, false, true, NULL); > + return vmw_kms_stdu_readback(dev_priv, file_priv, vfb, > + user_fence_rep, NULL, vclips, num_clips, > + 1, NULL); > default: > WARN_ONCE(true, > "Readback called with invalid display system.\n"); > @@ -2999,8 +2999,20 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) > struct vmw_framebuffer_bo *vfbbo = > container_of(update->vfb, typeof(*vfbbo), base); > > - ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false, > - update->cpu_blit); > + /* > + * For screen targets we want a mappable bo, for everything else we want > + * accelerated i.e. host backed (vram or gmr) bo. If the display unit > + * is not screen target then mob's shouldn't be available. > + */ > + if (update->dev_priv->active_display_unit == vmw_du_screen_target) { > + vmw_bo_placement_set(vfbbo->buffer, > + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR, > + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR); > + } else { > + WARN_ON(update->dev_priv->has_mob); > + vmw_bo_placement_set_default_accelerated(vfbbo->buffer); > + } > + ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer); > } else { > struct vmw_framebuffer_surface *vfbs = > container_of(update->vfb, typeof(*vfbs), base); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > index 7a97e53e8e51..1bdf601e7c35 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > @@ -126,7 +126,6 @@ struct vmw_du_update_plane { > struct vmw_framebuffer *vfb; > struct vmw_fence_obj **out_fence; > struct mutex *mutex; > - bool cpu_blit; > bool intr; > }; > > @@ -564,17 +563,15 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, > unsigned num_clips, int inc, > struct vmw_fence_obj **out_fence, > struct drm_crtc *crtc); > -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, > - struct drm_file *file_priv, > - struct vmw_framebuffer *vfb, > - struct drm_vmw_fence_rep __user *user_fence_rep, > - struct drm_clip_rect *clips, > - struct drm_vmw_rect *vclips, > - uint32_t num_clips, > - int increment, > - bool to_surface, > - bool interruptible, > - struct drm_crtc *crtc); > +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, > + struct drm_file *file_priv, > + struct vmw_framebuffer *vfb, > + struct drm_vmw_fence_rep __user *user_fence_rep, > + struct drm_clip_rect *clips, > + struct drm_vmw_rect *vclips, > + uint32_t num_clips, > + int increment, > + struct drm_crtc *crtc); > > int vmw_du_helper_plane_update(struct vmw_du_update_plane *update); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > index 54e412f8c2d1..6780a36e6171 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > @@ -332,7 +332,7 @@ static int vmw_resource_buf_alloc(struct vmw_resource *res, > } > > ret = vmw_bo_create(res->dev_priv, res->backup_size, > - res->func->backup_placement, > + res->func->domain, res->func->busy_domain, > interruptible, false, &backup); > if (unlikely(ret != 0)) > goto out_no_bo; > @@ -529,8 +529,10 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, > return 0; > > backup_dirty = res->backup_dirty; > + vmw_bo_placement_set(res->backup, res->func->domain, > + res->func->busy_domain); > ret = ttm_bo_validate(&res->backup->base, > - res->func->backup_placement, > + &res->backup->placement, > &ctx); > > if (unlikely(ret != 0)) > @@ -968,9 +970,12 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) > if (ret) > goto out_no_validate; > if (!vbo->base.pin_count) { > + vmw_bo_placement_set(vbo, > + res->func->domain, > + res->func->busy_domain); > ret = ttm_bo_validate > (&vbo->base, > - res->func->backup_placement, > + &vbo->placement, > &ctx); > if (ret) { > ttm_bo_unreserve(&vbo->base); > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > index 3b7438b2d289..2c24e0929faa 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > @@ -83,7 +83,8 @@ struct vmw_res_func { > enum vmw_res_type res_type; > bool needs_backup; > const char *type_name; > - struct ttm_placement *backup_placement; > + u32 domain; > + u32 busy_domain; > bool may_evict; > u32 prio; > u32 dirty_prio; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > index a04897f04c13..e9d03ef98154 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > @@ -445,7 +445,8 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, > */ > vmw_overlay_pause_all(dev_priv); > ret = vmw_bo_create(dev_priv, size, > - &vmw_vram_placement, > + VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_VRAM, > false, true, &vps->bo); > vmw_overlay_resume_all(dev_priv); > if (ret) { > @@ -547,7 +548,6 @@ static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv, > bo_update.base.vfb = vfb; > bo_update.base.out_fence = out_fence; > bo_update.base.mutex = NULL; > - bo_update.base.cpu_blit = false; > bo_update.base.intr = true; > > bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size; > @@ -708,7 +708,6 @@ static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv, > srf_update.base.vfb = vfb; > srf_update.base.out_fence = out_fence; > srf_update.base.mutex = &dev_priv->cmdbuf_mutex; > - srf_update.base.cpu_blit = false; > srf_update.base.intr = true; > > srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size; > @@ -1224,7 +1223,9 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > int ret; > > - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); > + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, buf); > if (ret) > return ret; > > @@ -1330,7 +1331,9 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > int ret; > > - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); > + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > + ret = vmw_validation_add_bo(&val_ctx, buf); > if (ret) > return ret; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > index b186d0993d83..9920c103bffb 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > @@ -94,7 +94,8 @@ static const struct vmw_res_func vmw_gb_shader_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "guest backed shaders", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_gb_shader_create, > .destroy = vmw_gb_shader_destroy, > .bind = vmw_gb_shader_bind, > @@ -108,7 +109,8 @@ static const struct vmw_res_func vmw_dx_shader_func = { > .prio = 3, > .dirty_prio = 3, > .type_name = "dx shaders", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_dx_shader_create, > /* > * The destroy callback is only called with a committed resource on > @@ -893,7 +895,9 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, > if (!vmw_shader_id_ok(user_key, shader_type)) > return -EINVAL; > > - ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement, > + ret = vmw_bo_create(dev_priv, size, > + VMW_BO_DOMAIN_SYS, > + VMW_BO_DOMAIN_SYS, > true, true, &buf); > if (unlikely(ret != 0)) > goto out; > @@ -913,7 +917,10 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, > WARN_ON(is_iomem); > > ttm_bo_kunmap(&map); > - ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_SYS, > + VMW_BO_DOMAIN_SYS); > + ret = ttm_bo_validate(&buf->base, &buf->placement, &ctx); > WARN_ON(ret != 0); > ttm_bo_unreserve(&buf->base); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > index 4ea32b01efc0..603175b8c97e 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > @@ -24,6 +24,7 @@ > * > **************************************************************************/ > > +#include "vmwgfx_bo.h" > #include "vmwgfx_drv.h" > #include "vmwgfx_resource_priv.h" > #include "vmwgfx_so.h" > @@ -84,7 +85,8 @@ static const struct vmw_res_func vmw_view_func = { > .needs_backup = false, > .may_evict = false, > .type_name = "DX view", > - .backup_placement = NULL, > + .domain = VMW_BO_DOMAIN_SYS, > + .busy_domain = VMW_BO_DOMAIN_SYS, > .create = vmw_view_create, > .commit_notify = vmw_view_commit_notify, > }; > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > index 4745537fed25..0df86402e9ce 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > @@ -66,7 +66,6 @@ enum stdu_content_type { > */ > struct vmw_stdu_dirty { > struct vmw_kms_dirty base; > - SVGA3dTransferType transfer; > s32 left, right, top, bottom; > s32 fb_left, fb_top; > u32 pitch; > @@ -137,12 +136,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); > * Screen Target Display Unit CRTC Functions > *****************************************************************************/ > > -static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw) > -{ > - return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024); > -} > - > - > /** > * vmw_stdu_crtc_destroy - cleans up the STDU > * > @@ -451,93 +444,6 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, > } > } > > -/** > - * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect > - * > - * @dirty: The closure structure. > - * > - * Encodes a surface DMA command cliprect and updates the bounding box > - * for the DMA. > - */ > -static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty) > -{ > - struct vmw_stdu_dirty *ddirty = > - container_of(dirty, struct vmw_stdu_dirty, base); > - struct vmw_stdu_dma *cmd = dirty->cmd; > - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; > - > - blit += dirty->num_hits; > - blit->srcx = dirty->fb_x; > - blit->srcy = dirty->fb_y; > - blit->x = dirty->unit_x1; > - blit->y = dirty->unit_y1; > - blit->d = 1; > - blit->w = dirty->unit_x2 - dirty->unit_x1; > - blit->h = dirty->unit_y2 - dirty->unit_y1; > - dirty->num_hits++; > - > - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) > - return; > - > - /* Destination bounding box */ > - ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1); > - ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1); > - ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2); > - ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); > -} > - > -/** > - * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command. > - * > - * @dirty: The closure structure. > - * > - * Fills in the missing fields in a DMA command, and optionally encodes > - * a screen target update command, depending on transfer direction. > - */ > -static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty) > -{ > - struct vmw_stdu_dirty *ddirty = > - container_of(dirty, struct vmw_stdu_dirty, base); > - struct vmw_screen_target_display_unit *stdu = > - container_of(dirty->unit, typeof(*stdu), base); > - struct vmw_stdu_dma *cmd = dirty->cmd; > - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; > - SVGA3dCmdSurfaceDMASuffix *suffix = > - (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits]; > - size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix); > - > - if (!dirty->num_hits) { > - vmw_cmd_commit(dirty->dev_priv, 0); > - return; > - } > - > - cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; > - cmd->header.size = sizeof(cmd->body) + blit_size; > - vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr); > - cmd->body.guest.pitch = ddirty->pitch; > - cmd->body.host.sid = stdu->display_srf->res.id; > - cmd->body.host.face = 0; > - cmd->body.host.mipmap = 0; > - cmd->body.transfer = ddirty->transfer; > - suffix->suffixSize = sizeof(*suffix); > - suffix->maximumOffset = ddirty->buf->base.base.size; > - > - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { > - blit_size += sizeof(struct vmw_stdu_update); > - > - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, > - ddirty->left, ddirty->right, > - ddirty->top, ddirty->bottom); > - } > - > - vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size); > - > - stdu->display_srf->res.res_dirty = true; > - ddirty->left = ddirty->top = S32_MAX; > - ddirty->right = ddirty->bottom = S32_MIN; > -} > - > - > /** > * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit > * > @@ -598,62 +504,21 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > return; > > /* Assume we are blitting from Guest (bo) to Host (display_srf) */ > - dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; > - dst_bo = &stdu->display_srf->res.backup->base; > - dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; > - > - src_pitch = ddirty->pitch; > - src_bo = &ddirty->buf->base; > - src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; > + src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; > + src_bo = &stdu->display_srf->res.backup->base; > + src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; > > - /* Swap src and dst if the assumption was wrong. */ > - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) { > - swap(dst_pitch, src_pitch); > - swap(dst_bo, src_bo); > - swap(src_offset, dst_offset); > - } > + dst_pitch = ddirty->pitch; > + dst_bo = &ddirty->buf->base; > + dst_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; > > (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, > src_bo, src_offset, src_pitch, > width * stdu->cpp, height, &diff); > - > - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM && > - drm_rect_visible(&diff.rect)) { > - struct vmw_private *dev_priv; > - struct vmw_stdu_update *cmd; > - struct drm_clip_rect region; > - int ret; > - > - /* We are updating the actual surface, not a proxy */ > - region.x1 = diff.rect.x1; > - region.x2 = diff.rect.x2; > - region.y1 = diff.rect.y1; > - region.y2 = diff.rect.y2; > - ret = vmw_kms_update_proxy(&stdu->display_srf->res, ®ion, > - 1, 1); > - if (ret) > - goto out_cleanup; > - > - > - dev_priv = vmw_priv(stdu->base.crtc.dev); > - cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); > - if (!cmd) > - goto out_cleanup; > - > - vmw_stdu_populate_update(cmd, stdu->base.unit, > - region.x1, region.x2, > - region.y1, region.y2); > - > - vmw_cmd_commit(dev_priv, sizeof(*cmd)); > - } > - > -out_cleanup: > - ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; > - ddirty->right = ddirty->bottom = S32_MIN; > } > > /** > - * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed > + * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed > * framebuffer and the screen target system. > * > * @dev_priv: Pointer to the device private structure. > @@ -666,9 +531,6 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > * be NULL. > * @num_clips: Number of clip rects in @clips or @vclips. > * @increment: Increment to use when looping over @clips or @vclips. > - * @to_surface: Whether to DMA to the screen target system as opposed to > - * from the screen target system. > - * @interruptible: Whether to perform waits interruptible if possible. > * @crtc: If crtc is passed, perform stdu dma on that crtc only. > * > * If DMA-ing till the screen target system, the function will also notify > @@ -677,59 +539,49 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > * Returns 0 on success, negative error code on failure. -ERESTARTSYS if > * interrupted. > */ > -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, > - struct drm_file *file_priv, > - struct vmw_framebuffer *vfb, > - struct drm_vmw_fence_rep __user *user_fence_rep, > - struct drm_clip_rect *clips, > - struct drm_vmw_rect *vclips, > - uint32_t num_clips, > - int increment, > - bool to_surface, > - bool interruptible, > - struct drm_crtc *crtc) > +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, > + struct drm_file *file_priv, > + struct vmw_framebuffer *vfb, > + struct drm_vmw_fence_rep __user *user_fence_rep, > + struct drm_clip_rect *clips, > + struct drm_vmw_rect *vclips, > + uint32_t num_clips, > + int increment, > + struct drm_crtc *crtc) > { > struct vmw_bo *buf = > container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; > struct vmw_stdu_dirty ddirty; > int ret; > - bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > > /* > - * VMs without 3D support don't have the surface DMA command and > - * we'll be using a CPU blit, and the framebuffer should be moved out > - * of VRAM. > + * The GMR domain might seem confusing because it might seem like it should > + * never happen with screen targets but e.g. the xorg vmware driver issues > + * CMD_SURFACE_DMA for various pixmap updates which might transition our bo to > + * a GMR. Instead of forcing another transition we can optimize the readback > + * by reading directly from the GMR. > */ > - ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit); > + vmw_bo_placement_set(buf, > + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR, > + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR); > + ret = vmw_validation_add_bo(&val_ctx, buf); > if (ret) > return ret; > > - ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); > + ret = vmw_validation_prepare(&val_ctx, NULL, true); > if (ret) > goto out_unref; > > - ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM : > - SVGA3D_READ_HOST_VRAM; > ddirty.left = ddirty.top = S32_MAX; > ddirty.right = ddirty.bottom = S32_MIN; > ddirty.fb_left = ddirty.fb_top = S32_MAX; > ddirty.pitch = vfb->base.pitches[0]; > ddirty.buf = buf; > - ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit; > - ddirty.base.clip = vmw_stdu_bo_clip; > - ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) + > - num_clips * sizeof(SVGA3dCopyBox) + > - sizeof(SVGA3dCmdSurfaceDMASuffix); > - if (to_surface) > - ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update); > - > - > - if (cpu_blit) { > - ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; > - ddirty.base.clip = vmw_stdu_bo_cpu_clip; > - ddirty.base.fifo_reserve_size = 0; > - } > + > + ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; > + ddirty.base.clip = vmw_stdu_bo_cpu_clip; > + ddirty.base.fifo_reserve_size = 0; > > ddirty.base.crtc = crtc; > > @@ -1161,11 +1013,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, > /* > * This should only happen if the buffer object is too large to create a > * proxy surface for. > - * If we are a 2D VM with a buffer object then we have to use CPU blit > - * so cache these mappings > */ > - if (vps->content_fb_type == SEPARATE_BO && > - vmw_stdu_use_cpu_blit(dev_priv)) > + if (vps->content_fb_type == SEPARATE_BO) > vps->cpp = new_fb->pitches[0] / new_fb->width; > > return 0; > @@ -1175,14 +1024,6 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, > return ret; > } > > -static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update, > - uint32_t num_hits) > -{ > - return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits + > - sizeof(SVGA3dCmdSurfaceDMASuffix) + > - sizeof(struct vmw_stdu_update); > -} > - > static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, > uint32_t num_hits) > { > @@ -1190,68 +1031,6 @@ static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, > sizeof(struct vmw_stdu_update); > } > > -static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update, > - void *cmd, uint32_t num_hits) > -{ > - struct vmw_screen_target_display_unit *stdu; > - struct vmw_framebuffer_bo *vfbbo; > - struct vmw_stdu_dma *cmd_dma = cmd; > - > - stdu = container_of(update->du, typeof(*stdu), base); > - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); > - > - cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA; > - cmd_dma->header.size = sizeof(cmd_dma->body) + > - sizeof(struct SVGA3dCopyBox) * num_hits + > - sizeof(SVGA3dCmdSurfaceDMASuffix); > - vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr); > - cmd_dma->body.guest.pitch = update->vfb->base.pitches[0]; > - cmd_dma->body.host.sid = stdu->display_srf->res.id; > - cmd_dma->body.host.face = 0; > - cmd_dma->body.host.mipmap = 0; > - cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM; > - > - return sizeof(*cmd_dma); > -} > - > -static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update, > - void *cmd, struct drm_rect *clip, > - uint32_t fb_x, uint32_t fb_y) > -{ > - struct SVGA3dCopyBox *box = cmd; > - > - box->srcx = fb_x; > - box->srcy = fb_y; > - box->srcz = 0; > - box->x = clip->x1; > - box->y = clip->y1; > - box->z = 0; > - box->w = drm_rect_width(clip); > - box->h = drm_rect_height(clip); > - box->d = 1; > - > - return sizeof(*box); > -} > - > -static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update, > - void *cmd, struct drm_rect *bb) > -{ > - struct vmw_screen_target_display_unit *stdu; > - struct vmw_framebuffer_bo *vfbbo; > - SVGA3dCmdSurfaceDMASuffix *suffix = cmd; > - > - stdu = container_of(update->du, typeof(*stdu), base); > - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); > - > - suffix->suffixSize = sizeof(*suffix); > - suffix->maximumOffset = vfbbo->buffer->base.base.size; > - > - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2, > - bb->y1, bb->y2); > - > - return sizeof(*suffix) + sizeof(struct vmw_stdu_update); > -} > - > static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, > void *cmd, uint32_t num_hits) > { > @@ -1369,24 +1148,12 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, > bo_update.base.vfb = vfb; > bo_update.base.out_fence = out_fence; > bo_update.base.mutex = NULL; > - bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); > bo_update.base.intr = false; > > - /* > - * VM without 3D support don't have surface DMA command and framebuffer > - * should be moved out of VRAM. > - */ > - if (bo_update.base.cpu_blit) { > - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; > - bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; > - bo_update.base.clip = vmw_stdu_bo_clip_cpu; > - bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; > - } else { > - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size; > - bo_update.base.pre_clip = vmw_stdu_bo_populate_dma; > - bo_update.base.clip = vmw_stdu_bo_populate_clip; > - bo_update.base.post_clip = vmw_stdu_bo_populate_update; > - } > + bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; > + bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; > + bo_update.base.clip = vmw_stdu_bo_clip_cpu; > + bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; > > return vmw_du_helper_plane_update(&bo_update.base); > } > @@ -1549,7 +1316,6 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, > srf_update.vfb = vfb; > srf_update.out_fence = out_fence; > srf_update.mutex = &dev_priv->cmdbuf_mutex; > - srf_update.cpu_blit = false; > srf_update.intr = true; > > if (vfbs->is_bo_proxy) > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > index 71ce89150ba7..b35ac195285d 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > @@ -66,7 +66,8 @@ static const struct vmw_res_func vmw_dx_streamoutput_func = { > .needs_backup = true, > .may_evict = false, > .type_name = "DX streamoutput", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_dx_streamoutput_create, > .destroy = NULL, /* Command buffer managed resource. */ > .bind = vmw_dx_streamoutput_bind, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > index 296d903c5acb..9c6a691b005e 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > @@ -131,7 +131,8 @@ static const struct vmw_res_func vmw_legacy_surface_func = { > .prio = 1, > .dirty_prio = 1, > .type_name = "legacy surfaces", > - .backup_placement = &vmw_srf_placement, > + .domain = VMW_BO_DOMAIN_GMR, > + .busy_domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > .create = &vmw_legacy_srf_create, > .destroy = &vmw_legacy_srf_destroy, > .bind = &vmw_legacy_srf_bind, > @@ -145,7 +146,8 @@ static const struct vmw_res_func vmw_gb_surface_func = { > .prio = 1, > .dirty_prio = 2, > .type_name = "guest backed surfaces", > - .backup_placement = &vmw_mob_placement, > + .domain = VMW_BO_DOMAIN_MOB, > + .busy_domain = VMW_BO_DOMAIN_MOB, > .create = vmw_gb_surface_create, > .destroy = vmw_gb_surface_destroy, > .bind = vmw_gb_surface_bind, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > index 41480af87255..c43df4109613 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > @@ -79,20 +79,6 @@ static const struct ttm_place vram_gmr_placement_flags[] = { > } > }; > > -static const struct ttm_place gmr_vram_placement_flags[] = { > - { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = VMW_PL_GMR, > - .flags = 0 > - }, { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = TTM_PL_VRAM, > - .flags = 0 > - } > -}; > - > static const struct ttm_place vmw_sys_placement_flags = { > .fpfn = 0, > .lpfn = 0, > @@ -128,32 +114,6 @@ struct ttm_placement vmw_pt_sys_placement = { > .busy_placement = &vmw_sys_placement_flags > }; > > -static const struct ttm_place nonfixed_placement_flags[] = { > - { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = TTM_PL_SYSTEM, > - .flags = 0 > - }, { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = VMW_PL_GMR, > - .flags = 0 > - }, { > - .fpfn = 0, > - .lpfn = 0, > - .mem_type = VMW_PL_MOB, > - .flags = 0 > - } > -}; > - > -struct ttm_placement vmw_srf_placement = { > - .num_placement = 1, > - .num_busy_placement = 2, > - .placement = &gmr_placement_flags, > - .busy_placement = gmr_vram_placement_flags > -}; > - > struct ttm_placement vmw_mob_placement = { > .num_placement = 1, > .num_busy_placement = 1, > @@ -161,13 +121,6 @@ struct ttm_placement vmw_mob_placement = { > .busy_placement = &mob_placement_flags > }; > > -struct ttm_placement vmw_nonfixed_placement = { > - .num_placement = 3, > - .placement = nonfixed_placement_flags, > - .num_busy_placement = 1, > - .busy_placement = &sys_placement_flags > -}; > - > const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); > > /** > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > index 6ad744ae07f5..c968180c9769 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > @@ -25,6 +25,7 @@ > * > **************************************************************************/ > > +#include "vmwgfx_bo.h" > #include "vmwgfx_drv.h" > #include "vmwgfx_resource_priv.h" > > @@ -83,7 +84,8 @@ static const struct vmw_simple_resource_func va_stream_func = { > .needs_backup = false, > .may_evict = false, > .type_name = "overlay stream", > - .backup_placement = NULL, > + .domain = VMW_BO_DOMAIN_SYS, > + .busy_domain = VMW_BO_DOMAIN_SYS, > .create = NULL, > .destroy = NULL, > .bind = NULL, > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > index 770b1b53bde7..05f0909ff1dd 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > @@ -27,6 +27,7 @@ > **************************************************************************/ > #include "vmwgfx_bo.h" > #include "vmwgfx_drv.h" > +#include "vmwgfx_resource_priv.h" > #include "vmwgfx_validation.h" > > #include <linux/slab.h> > @@ -40,8 +41,6 @@ > * @hash: A hash entry used for the duplicate detection hash table. > * @coherent_count: If switching backup buffers, number of new coherent > * resources that will have this buffer as a backup buffer. > - * @as_mob: Validate as mob. > - * @cpu_blit: Validate for cpu blit access. > * > * Bit fields are used since these structures are allocated and freed in > * large numbers and space conservation is desired. > @@ -50,8 +49,6 @@ struct vmw_validation_bo_node { > struct ttm_validate_buffer base; > struct vmwgfx_hash_item hash; > unsigned int coherent_count; > - u32 as_mob : 1; > - u32 cpu_blit : 1; > }; > /** > * struct vmw_validation_res_node - Resource validation metadata. > @@ -260,26 +257,16 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx, > * vmw_validation_add_bo - Add a buffer object to the validation context. > * @ctx: The validation context. > * @vbo: The buffer object. > - * @as_mob: Validate as mob, otherwise suitable for GMR operations. > - * @cpu_blit: Validate in a page-mappable location. > * > * Return: Zero on success, negative error code otherwise. > */ > int vmw_validation_add_bo(struct vmw_validation_context *ctx, > - struct vmw_bo *vbo, > - bool as_mob, > - bool cpu_blit) > + struct vmw_bo *vbo) > { > struct vmw_validation_bo_node *bo_node; > > bo_node = vmw_validation_find_bo_dup(ctx, vbo); > - if (bo_node) { > - if (bo_node->as_mob != as_mob || > - bo_node->cpu_blit != cpu_blit) { > - DRM_ERROR("Inconsistent buffer usage.\n"); > - return -EINVAL; > - } > - } else { > + if (!bo_node) { > struct ttm_validate_buffer *val_buf; > > bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node)); > @@ -297,8 +284,6 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, > return -ESRCH; > val_buf->num_shared = 0; > list_add_tail(&val_buf->head, &ctx->bo_list); > - bo_node->as_mob = as_mob; > - bo_node->cpu_blit = cpu_blit; > } > > return 0; > @@ -455,9 +440,10 @@ int vmw_validation_res_reserve(struct vmw_validation_context *ctx, > if (res->backup) { > struct vmw_bo *vbo = res->backup; > > - ret = vmw_validation_add_bo > - (ctx, vbo, vmw_resource_needs_backup(res), > - false); > + vmw_bo_placement_set(vbo, > + res->func->domain, > + res->func->busy_domain); > + ret = vmw_validation_add_bo(ctx, vbo); > if (ret) > goto out_unreserve; > } > @@ -519,14 +505,12 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, > * vmw_validation_bo_validate_single - Validate a single buffer object. > * @bo: The TTM buffer object base. > * @interruptible: Whether to perform waits interruptible if possible. > - * @validate_as_mob: Whether to validate in MOB memory. > * > * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error > * code on failure. > */ > -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > - bool interruptible, > - bool validate_as_mob) > +static int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > + bool interruptible) > { > struct vmw_bo *vbo = > container_of(bo, struct vmw_bo, base); > @@ -542,27 +526,17 @@ int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > if (vbo->base.pin_count > 0) > return 0; > > - if (validate_as_mob) > - return ttm_bo_validate(bo, &vmw_mob_placement, &ctx); > - > - /** > - * Put BO in VRAM if there is space, otherwise as a GMR. > - * If there is no space in VRAM and GMR ids are all used up, > - * start evicting GMRs to make room. If the DMA buffer can't be > - * used as a GMR, this will return -ENOMEM. > - */ > - > - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); > + ret = ttm_bo_validate(bo, &vbo->placement, &ctx); > if (ret == 0 || ret == -ERESTARTSYS) > return ret; > > - /** > - * If that failed, try VRAM again, this time evicting > + /* > + * If that failed, try again, this time evicting > * previous contents. > */ > + ctx.allow_res_evict = true; > > - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); > - return ret; > + return ttm_bo_validate(bo, &vbo->placement, &ctx); > } > > /** > @@ -583,18 +557,8 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) > struct vmw_bo *vbo = > container_of(entry->base.bo, typeof(*vbo), base); > > - if (entry->cpu_blit) { > - struct ttm_operation_ctx ttm_ctx = { > - .interruptible = intr, > - .no_wait_gpu = false > - }; > - > - ret = ttm_bo_validate(entry->base.bo, > - &vmw_nonfixed_placement, &ttm_ctx); > - } else { > - ret = vmw_validation_bo_validate_single > - (entry->base.bo, intr, entry->as_mob); > - } > + ret = vmw_validation_bo_validate_single(entry->base.bo, intr); > + > if (ret) > return ret; > > @@ -655,9 +619,9 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) > if (backup && res->backup && (backup != res->backup)) { > struct vmw_bo *vbo = res->backup; > > - ret = vmw_validation_add_bo > - (ctx, vbo, vmw_resource_needs_backup(res), > - false); > + vmw_bo_placement_set(vbo, res->func->domain, > + res->func->busy_domain); > + ret = vmw_validation_add_bo(ctx, vbo); > if (ret) > return ret; > } > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > index 4aa4f700c65e..240ee0c4ebfd 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > @@ -159,11 +159,7 @@ static inline unsigned int vmw_validation_align(unsigned int val) > } > > int vmw_validation_add_bo(struct vmw_validation_context *ctx, > - struct vmw_bo *vbo, > - bool as_mob, bool cpu_blit); > -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > - bool interruptible, > - bool validate_as_mob); > + struct vmw_bo *vbo); > int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); > void vmw_validation_unref_lists(struct vmw_validation_context *ctx); > int vmw_validation_add_resource(struct vmw_validation_context *ctx, LGTM! Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com>
> > > > Problem with explicit placement selection in vmwgfx is that by the time > > the buffer object needs to be validated the information about which > > placement was supposed to be used is lost. To workaround this the driver > > had a bunch of state in various places e.g. as_mob or cpu_blit to > > somehow convey the information on which placement was intended. > > > > Fix it properly by allowing the buffer objects to hold their preferred > > placement so it can be reused whenever needed. This makes the entire > > validation pipeline a lot easier both to understand and maintain. I think this patch mixes up src/dst_pitch in the stdu code. CC [M] drivers/gpu/drm/etnaviv/etnaviv_gem_submit.o /home/airlied/devel/kernel/dim/src/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c:509:29: error: variable 'dst_pitch' is uninitialized when used here [-Werror,-Wuninitialized] src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; ^~~~~~~~~ /home/airlied/devel/kernel/dim/src/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c:492:26: note: initialize the variable 'dst_pitch' to silence this warning s32 src_pitch, dst_pitch; ^ = 0 Dave. > > > > Signed-off-by: Zack Rusin <zackr@vmware.com> > > --- > > drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 145 +++++++-- > > drivers/gpu/drm/vmwgfx/vmwgfx_bo.h | 25 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_context.c | 9 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c | 11 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 3 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 - > > drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 35 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 5 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 22 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 21 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 11 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h | 3 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 13 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 15 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_so.c | 4 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 304 ++---------------- > > drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c | 3 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 6 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 47 --- > > drivers/gpu/drm/vmwgfx/vmwgfx_va.c | 4 +- > > drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 74 ++--- > > drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 6 +- > > 22 files changed, 312 insertions(+), 456 deletions(-) > > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > > index c6dc733f6d45..d8f6ccecf4bf 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c > > @@ -135,11 +135,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, > > goto out_unreserve; > > } > > > > - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); > > + vmw_bo_placement_set(buf, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_GMR); > > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > if (likely(ret == 0) || ret == -ERESTARTSYS) > > goto out_unreserve; > > > > - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); > > + vmw_bo_placement_set(buf, > > + VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_VRAM); > > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > > > out_unreserve: > > if (!ret) > > @@ -190,17 +196,8 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, > > { > > struct ttm_operation_ctx ctx = {interruptible, false }; > > struct ttm_buffer_object *bo = &buf->base; > > - struct ttm_placement placement; > > - struct ttm_place place; > > int ret = 0; > > > > - place = vmw_vram_placement.placement[0]; > > - place.lpfn = PFN_UP(bo->resource->size); > > - placement.num_placement = 1; > > - placement.placement = &place; > > - placement.num_busy_placement = 1; > > - placement.busy_placement = &place; > > - > > vmw_execbuf_release_pinned_bo(dev_priv); > > ret = ttm_bo_reserve(bo, interruptible, false, NULL); > > if (unlikely(ret != 0)) > > @@ -216,14 +213,21 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, > > bo->resource->start > 0 && > > buf->base.pin_count == 0) { > > ctx.interruptible = false; > > - (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx); > > + vmw_bo_placement_set(buf, > > + VMW_BO_DOMAIN_SYS, > > + VMW_BO_DOMAIN_SYS); > > + (void)ttm_bo_validate(bo, &buf->placement, &ctx); > > } > > > > + vmw_bo_placement_set(buf, > > + VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_VRAM); > > + buf->places[0].lpfn = PFN_UP(bo->resource->size); > > if (buf->base.pin_count > 0) > > - ret = ttm_resource_compat(bo->resource, &placement) > > + ret = ttm_resource_compat(bo->resource, &buf->placement) > > ? 0 : -EINVAL; > > else > > - ret = ttm_bo_validate(bo, &placement, &ctx); > > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > > > /* For some reason we didn't end up at the start of vram */ > > WARN_ON(ret == 0 && bo->resource->start != 0); > > @@ -431,7 +435,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, > > } > > > > int vmw_bo_create(struct vmw_private *vmw, > > - size_t size, struct ttm_placement *placement, > > + size_t size, u32 domain, u32 busy_domain, > > bool interruptible, bool pin, > > struct vmw_bo **p_bo) > > { > > @@ -444,7 +448,8 @@ int vmw_bo_create(struct vmw_private *vmw, > > } > > > > ret = vmw_bo_init(vmw, *p_bo, size, > > - placement, interruptible, pin); > > + domain, busy_domain, > > + interruptible, pin); > > if (unlikely(ret != 0)) > > goto out_error; > > > > @@ -461,7 +466,8 @@ int vmw_bo_create(struct vmw_private *vmw, > > * @dev_priv: Pointer to the device private struct > > * @vmw_bo: Pointer to the struct vmw_bo to initialize. > > * @size: Buffer object size in bytes. > > - * @placement: Initial placement. > > + * @domain: Domain to put the bo in. > > + * @busy_domain: Domain to put the bo if busy. > > * @interruptible: Whether waits should be performed interruptible. > > * @pin: If the BO should be created pinned at a fixed location. > > * Returns: Zero on success, negative error code on error. > > @@ -470,7 +476,9 @@ int vmw_bo_create(struct vmw_private *vmw, > > */ > > int vmw_bo_init(struct vmw_private *dev_priv, > > struct vmw_bo *vmw_bo, > > - size_t size, struct ttm_placement *placement, > > + size_t size, > > + u32 domain, > > + u32 busy_domain, > > bool interruptible, bool pin) > > { > > struct ttm_operation_ctx ctx = { > > @@ -489,8 +497,9 @@ int vmw_bo_init(struct vmw_private *dev_priv, > > size = ALIGN(size, PAGE_SIZE); > > drm_gem_private_object_init(vdev, &vmw_bo->base.base, size); > > > > + vmw_bo_placement_set(vmw_bo, domain, busy_domain); > > ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device, > > - placement, 0, &ctx, NULL, NULL, vmw_bo_free); > > + &vmw_bo->placement, 0, &ctx, NULL, NULL, vmw_bo_free); > > if (unlikely(ret)) { > > return ret; > > } > > @@ -825,3 +834,101 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, > > if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) > > vmw_resource_unbind_list(vbo); > > } > > + > > +static u32 > > +set_placement_list(struct ttm_place *pl, u32 domain) > > +{ > > + u32 n = 0; > > + > > + /* > > + * The placements are ordered according to our preferences > > + */ > > + if (domain & VMW_BO_DOMAIN_MOB) { > > + pl[n].mem_type = VMW_PL_MOB; > > + pl[n].flags = 0; > > + pl[n].fpfn = 0; > > + pl[n].lpfn = 0; > > + n++; > > + } > > + if (domain & VMW_BO_DOMAIN_GMR) { > > + pl[n].mem_type = VMW_PL_GMR; > > + pl[n].flags = 0; > > + pl[n].fpfn = 0; > > + pl[n].lpfn = 0; > > + n++; > > + } > > + if (domain & VMW_BO_DOMAIN_VRAM) { > > + pl[n].mem_type = TTM_PL_VRAM; > > + pl[n].flags = 0; > > + pl[n].fpfn = 0; > > + pl[n].lpfn = 0; > > + n++; > > + } > > + WARN_ON((domain & VMW_BO_DOMAIN_WAITABLE_SYS) != 0); > > + if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) { > > + pl[n].mem_type = VMW_PL_SYSTEM; > > + pl[n].flags = 0; > > + pl[n].fpfn = 0; > > + pl[n].lpfn = 0; > > + n++; > > + } > > + if (domain & VMW_BO_DOMAIN_SYS) { > > + pl[n].mem_type = TTM_PL_SYSTEM; > > + pl[n].flags = 0; > > + pl[n].fpfn = 0; > > + pl[n].lpfn = 0; > > + n++; > > + } > > + > > + WARN_ON(!n); > > + if (!n) { > > + pl[n].mem_type = TTM_PL_SYSTEM; > > + pl[n].flags = 0; > > + pl[n].fpfn = 0; > > + pl[n].lpfn = 0; > > + n++; > > + } > > + return n; > > +} > > + > > +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain) > > +{ > > + struct ttm_device *bdev = bo->base.bdev; > > + struct vmw_private *vmw = > > + container_of(bdev, struct vmw_private, bdev); > > + struct ttm_placement *pl = &bo->placement; > > + bool mem_compatible = false; > > + u32 i; > > + > > + pl->placement = bo->places; > > + pl->num_placement = set_placement_list(bo->places, domain); > > + > > + if (drm_debug_enabled(DRM_UT_DRIVER) && bo->base.resource) { > > + for (i = 0; i < pl->num_placement; ++i) { > > + if (bo->base.resource->mem_type == TTM_PL_SYSTEM || > > + bo->base.resource->mem_type == pl->placement[i].mem_type) > > + mem_compatible = true; > > + } > > + if (!mem_compatible) > > + drm_warn(&vmw->drm, > > + "%s: Incompatible transition from " > > + "bo->base.resource->mem_type = %u to domain = %u\n", > > + __func__, bo->base.resource->mem_type, domain); > > + } > > + > > + pl->busy_placement = bo->busy_places; > > + pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain); > > +} > > + > > +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo) > > +{ > > + struct ttm_device *bdev = bo->base.bdev; > > + struct vmw_private *vmw = > > + container_of(bdev, struct vmw_private, bdev); > > + u32 domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM; > > + > > + if (vmw->has_mob) > > + domain = VMW_BO_DOMAIN_MOB; > > + > > + vmw_bo_placement_set(bo, domain, domain); > > +} > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > > index 2ede1e28d7ce..538d8739d7a5 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h > > @@ -31,6 +31,7 @@ > > #include "device_include/svga_reg.h" > > > > #include <drm/ttm/ttm_bo_api.h> > > +#include <drm/ttm/ttm_placement.h> > > > > #include <linux/rbtree_types.h> > > #include <linux/types.h> > > @@ -40,6 +41,14 @@ struct vmw_fence_obj; > > struct vmw_private; > > struct vmw_resource; > > > > +enum vmw_bo_domain { > > + VMW_BO_DOMAIN_SYS = BIT(0), > > + VMW_BO_DOMAIN_WAITABLE_SYS = BIT(1), > > + VMW_BO_DOMAIN_VRAM = BIT(2), > > + VMW_BO_DOMAIN_GMR = BIT(3), > > + VMW_BO_DOMAIN_MOB = BIT(4), > > +}; > > + > > /** > > * struct vmw_bo - TTM buffer object with vmwgfx additions > > * @base: The TTM buffer object > > @@ -53,6 +62,11 @@ struct vmw_resource; > > */ > > struct vmw_bo { > > struct ttm_buffer_object base; > > + > > + struct ttm_placement placement; > > + struct ttm_place places[5]; > > + struct ttm_place busy_places[5]; > > + > > struct rb_root res_tree; > > > > atomic_t cpu_writers; > > @@ -64,17 +78,24 @@ struct vmw_bo { > > struct vmw_bo_dirty *dirty; > > }; > > > > +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain); > > +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo); > > + > > int vmw_bo_create_kernel(struct vmw_private *dev_priv, > > unsigned long size, > > struct ttm_placement *placement, > > struct ttm_buffer_object **p_bo); > > int vmw_bo_create(struct vmw_private *dev_priv, > > - size_t size, struct ttm_placement *placement, > > + size_t size, > > + u32 domain, > > + u32 busy_domain, > > bool interruptible, bool pin, > > struct vmw_bo **p_bo); > > int vmw_bo_init(struct vmw_private *dev_priv, > > struct vmw_bo *vmw_bo, > > - size_t size, struct ttm_placement *placement, > > + size_t size, > > + u32 domain, > > + u32 busy_domain, > > bool interruptible, bool pin); > > int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, > > struct drm_file *file_priv); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > > index cc02be6a9884..84ef5f0a785b 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c > > @@ -76,7 +76,8 @@ static const struct vmw_res_func vmw_legacy_context_func = { > > .needs_backup = false, > > .may_evict = false, > > .type_name = "legacy contexts", > > - .backup_placement = NULL, > > + .domain = VMW_BO_DOMAIN_SYS, > > + .busy_domain = VMW_BO_DOMAIN_SYS, > > .create = NULL, > > .destroy = NULL, > > .bind = NULL, > > @@ -90,7 +91,8 @@ static const struct vmw_res_func vmw_gb_context_func = { > > .prio = 3, > > .dirty_prio = 3, > > .type_name = "guest backed contexts", > > - .backup_placement = &vmw_mob_placement, > > + .domain = VMW_BO_DOMAIN_MOB, > > + .busy_domain = VMW_BO_DOMAIN_MOB, > > .create = vmw_gb_context_create, > > .destroy = vmw_gb_context_destroy, > > .bind = vmw_gb_context_bind, > > @@ -104,7 +106,8 @@ static const struct vmw_res_func vmw_dx_context_func = { > > .prio = 3, > > .dirty_prio = 3, > > .type_name = "dx contexts", > > - .backup_placement = &vmw_mob_placement, > > + .domain = VMW_BO_DOMAIN_MOB, > > + .busy_domain = VMW_BO_DOMAIN_MOB, > > .create = vmw_dx_context_create, > > .destroy = vmw_dx_context_destroy, > > .bind = vmw_dx_context_bind, > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > > index 9193faae8dab..d49db8146df1 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c > > @@ -136,7 +136,8 @@ static const struct vmw_res_func vmw_cotable_func = { > > .prio = 3, > > .dirty_prio = 3, > > .type_name = "context guest backed object tables", > > - .backup_placement = &vmw_mob_placement, > > + .domain = VMW_BO_DOMAIN_MOB, > > + .busy_domain = VMW_BO_DOMAIN_MOB, > > .create = vmw_cotable_create, > > .destroy = vmw_cotable_destroy, > > .bind = vmw_cotable_bind, > > @@ -424,7 +425,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) > > * for the new COTable. Initially pin the buffer object to make sure > > * we can use tryreserve without failure. > > */ > > - ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement, > > + ret = vmw_bo_create(dev_priv, new_size, > > + VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB, > > true, true, &buf); > > if (ret) { > > DRM_ERROR("Failed initializing new cotable MOB.\n"); > > @@ -465,7 +467,10 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) > > } > > > > /* Unpin new buffer, and switch backup buffers. */ > > - ret = ttm_bo_validate(bo, &vmw_mob_placement, &ctx); > > + vmw_bo_placement_set(buf, > > + VMW_BO_DOMAIN_MOB, > > + VMW_BO_DOMAIN_MOB); > > + ret = ttm_bo_validate(bo, &buf->placement, &ctx); > > if (unlikely(ret != 0)) { > > DRM_ERROR("Failed validating new COTable backup buffer.\n"); > > goto out_wait; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > > index 60d08185a71f..c12ad8264043 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c > > @@ -399,7 +399,8 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) > > * user of the bo currently. > > */ > > ret = vmw_bo_create(dev_priv, PAGE_SIZE, > > - &vmw_sys_placement, false, true, &vbo); > > + VMW_BO_DOMAIN_SYS, VMW_BO_DOMAIN_SYS, > > + false, true, &vbo); > > if (unlikely(ret != 0)) > > return ret; > > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > > index e9a16a1e043d..5629a00039fe 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h > > @@ -930,9 +930,7 @@ extern struct ttm_placement vmw_vram_placement; > > extern struct ttm_placement vmw_vram_sys_placement; > > extern struct ttm_placement vmw_vram_gmr_placement; > > extern struct ttm_placement vmw_sys_placement; > > -extern struct ttm_placement vmw_srf_placement; > > extern struct ttm_placement vmw_mob_placement; > > -extern struct ttm_placement vmw_nonfixed_placement; > > extern struct ttm_device_funcs vmw_bo_driver; > > extern const struct vmw_sg_table * > > vmw_bo_sg_table(struct ttm_buffer_object *bo); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > > index 687c6926bc00..eda7f8471bcd 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > > @@ -477,9 +477,13 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, > > struct vmw_bo *dx_query_mob; > > > > dx_query_mob = vmw_context_get_dx_query_mob(ctx); > > - if (dx_query_mob) > > + if (dx_query_mob) { > > + vmw_bo_placement_set(dx_query_mob, > > + VMW_BO_DOMAIN_MOB, > > + VMW_BO_DOMAIN_MOB); > > ret = vmw_validation_add_bo(sw_context->ctx, > > - dx_query_mob, true, false); > > + dx_query_mob); > > + } > > } > > > > mutex_unlock(&dev_priv->binding_mutex); > > @@ -1035,17 +1039,17 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, > > > > if (unlikely(sw_context->cur_query_bo != NULL)) { > > sw_context->needs_post_query_barrier = true; > > + vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo); > > ret = vmw_validation_add_bo(sw_context->ctx, > > - sw_context->cur_query_bo, > > - dev_priv->has_mob, false); > > + sw_context->cur_query_bo); > > if (unlikely(ret != 0)) > > return ret; > > } > > sw_context->cur_query_bo = new_query_bo; > > > > + vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo); > > ret = vmw_validation_add_bo(sw_context->ctx, > > - dev_priv->dummy_query_bo, > > - dev_priv->has_mob, false); > > + dev_priv->dummy_query_bo); > > if (unlikely(ret != 0)) > > return ret; > > } > > @@ -1157,7 +1161,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, > > drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); > > return PTR_ERR(vmw_bo); > > } > > - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); > > + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); > > + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); > > ttm_bo_put(&vmw_bo->base); > > if (unlikely(ret != 0)) > > return ret; > > @@ -1211,7 +1216,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, > > drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); > > return PTR_ERR(vmw_bo); > > } > > - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); > > + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > > + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); > > ttm_bo_put(&vmw_bo->base); > > if (unlikely(ret != 0)) > > return ret; > > @@ -4361,13 +4368,17 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, > > if (dev_priv->pinned_bo == NULL) > > goto out_unlock; > > > > - ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, > > - false); > > + vmw_bo_placement_set(dev_priv->pinned_bo, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > > + ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo); > > if (ret) > > goto out_no_reserve; > > > > - ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, > > - false); > > + vmw_bo_placement_set(dev_priv->dummy_query_bo, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > > + ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo); > > if (ret) > > goto out_no_reserve; > > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > > index c7ebcd4f3afa..5f383578a320 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c > > @@ -121,9 +121,8 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, > > int ret; > > > > ret = vmw_bo_create(dev_priv, size, > > - (dev_priv->has_mob) ? > > - &vmw_sys_placement : > > - &vmw_vram_sys_placement, > > + (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_SYS, > > true, false, p_vbo); > > > > (*p_vbo)->base.base.funcs = &vmw_gem_object_funcs; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > > index e83286e08837..d975c0a818c7 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c > > @@ -1270,9 +1270,9 @@ int vmw_kms_readback(struct vmw_private *dev_priv, > > user_fence_rep, vclips, num_clips, > > NULL); > > case vmw_du_screen_target: > > - return vmw_kms_stdu_dma(dev_priv, file_priv, vfb, > > - user_fence_rep, NULL, vclips, num_clips, > > - 1, false, true, NULL); > > + return vmw_kms_stdu_readback(dev_priv, file_priv, vfb, > > + user_fence_rep, NULL, vclips, num_clips, > > + 1, NULL); > > default: > > WARN_ONCE(true, > > "Readback called with invalid display system.\n"); > > @@ -2999,8 +2999,20 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) > > struct vmw_framebuffer_bo *vfbbo = > > container_of(update->vfb, typeof(*vfbbo), base); > > > > - ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false, > > - update->cpu_blit); > > + /* > > + * For screen targets we want a mappable bo, for everything else we want > > + * accelerated i.e. host backed (vram or gmr) bo. If the display unit > > + * is not screen target then mob's shouldn't be available. > > + */ > > + if (update->dev_priv->active_display_unit == vmw_du_screen_target) { > > + vmw_bo_placement_set(vfbbo->buffer, > > + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR, > > + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR); > > + } else { > > + WARN_ON(update->dev_priv->has_mob); > > + vmw_bo_placement_set_default_accelerated(vfbbo->buffer); > > + } > > + ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer); > > } else { > > struct vmw_framebuffer_surface *vfbs = > > container_of(update->vfb, typeof(*vfbs), base); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > > index 7a97e53e8e51..1bdf601e7c35 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h > > @@ -126,7 +126,6 @@ struct vmw_du_update_plane { > > struct vmw_framebuffer *vfb; > > struct vmw_fence_obj **out_fence; > > struct mutex *mutex; > > - bool cpu_blit; > > bool intr; > > }; > > > > @@ -564,17 +563,15 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, > > unsigned num_clips, int inc, > > struct vmw_fence_obj **out_fence, > > struct drm_crtc *crtc); > > -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, > > - struct drm_file *file_priv, > > - struct vmw_framebuffer *vfb, > > - struct drm_vmw_fence_rep __user *user_fence_rep, > > - struct drm_clip_rect *clips, > > - struct drm_vmw_rect *vclips, > > - uint32_t num_clips, > > - int increment, > > - bool to_surface, > > - bool interruptible, > > - struct drm_crtc *crtc); > > +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, > > + struct drm_file *file_priv, > > + struct vmw_framebuffer *vfb, > > + struct drm_vmw_fence_rep __user *user_fence_rep, > > + struct drm_clip_rect *clips, > > + struct drm_vmw_rect *vclips, > > + uint32_t num_clips, > > + int increment, > > + struct drm_crtc *crtc); > > > > int vmw_du_helper_plane_update(struct vmw_du_update_plane *update); > > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > > index 54e412f8c2d1..6780a36e6171 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c > > @@ -332,7 +332,7 @@ static int vmw_resource_buf_alloc(struct vmw_resource *res, > > } > > > > ret = vmw_bo_create(res->dev_priv, res->backup_size, > > - res->func->backup_placement, > > + res->func->domain, res->func->busy_domain, > > interruptible, false, &backup); > > if (unlikely(ret != 0)) > > goto out_no_bo; > > @@ -529,8 +529,10 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, > > return 0; > > > > backup_dirty = res->backup_dirty; > > + vmw_bo_placement_set(res->backup, res->func->domain, > > + res->func->busy_domain); > > ret = ttm_bo_validate(&res->backup->base, > > - res->func->backup_placement, > > + &res->backup->placement, > > &ctx); > > > > if (unlikely(ret != 0)) > > @@ -968,9 +970,12 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) > > if (ret) > > goto out_no_validate; > > if (!vbo->base.pin_count) { > > + vmw_bo_placement_set(vbo, > > + res->func->domain, > > + res->func->busy_domain); > > ret = ttm_bo_validate > > (&vbo->base, > > - res->func->backup_placement, > > + &vbo->placement, > > &ctx); > > if (ret) { > > ttm_bo_unreserve(&vbo->base); > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > > index 3b7438b2d289..2c24e0929faa 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h > > @@ -83,7 +83,8 @@ struct vmw_res_func { > > enum vmw_res_type res_type; > > bool needs_backup; > > const char *type_name; > > - struct ttm_placement *backup_placement; > > + u32 domain; > > + u32 busy_domain; > > bool may_evict; > > u32 prio; > > u32 dirty_prio; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > > index a04897f04c13..e9d03ef98154 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c > > @@ -445,7 +445,8 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, > > */ > > vmw_overlay_pause_all(dev_priv); > > ret = vmw_bo_create(dev_priv, size, > > - &vmw_vram_placement, > > + VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_VRAM, > > false, true, &vps->bo); > > vmw_overlay_resume_all(dev_priv); > > if (ret) { > > @@ -547,7 +548,6 @@ static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv, > > bo_update.base.vfb = vfb; > > bo_update.base.out_fence = out_fence; > > bo_update.base.mutex = NULL; > > - bo_update.base.cpu_blit = false; > > bo_update.base.intr = true; > > > > bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size; > > @@ -708,7 +708,6 @@ static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv, > > srf_update.base.vfb = vfb; > > srf_update.base.out_fence = out_fence; > > srf_update.base.mutex = &dev_priv->cmdbuf_mutex; > > - srf_update.base.cpu_blit = false; > > srf_update.base.intr = true; > > > > srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size; > > @@ -1224,7 +1223,9 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, > > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > > int ret; > > > > - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); > > + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > > + ret = vmw_validation_add_bo(&val_ctx, buf); > > if (ret) > > return ret; > > > > @@ -1330,7 +1331,9 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, > > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > > int ret; > > > > - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); > > + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > > + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); > > + ret = vmw_validation_add_bo(&val_ctx, buf); > > if (ret) > > return ret; > > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > > index b186d0993d83..9920c103bffb 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c > > @@ -94,7 +94,8 @@ static const struct vmw_res_func vmw_gb_shader_func = { > > .prio = 3, > > .dirty_prio = 3, > > .type_name = "guest backed shaders", > > - .backup_placement = &vmw_mob_placement, > > + .domain = VMW_BO_DOMAIN_MOB, > > + .busy_domain = VMW_BO_DOMAIN_MOB, > > .create = vmw_gb_shader_create, > > .destroy = vmw_gb_shader_destroy, > > .bind = vmw_gb_shader_bind, > > @@ -108,7 +109,8 @@ static const struct vmw_res_func vmw_dx_shader_func = { > > .prio = 3, > > .dirty_prio = 3, > > .type_name = "dx shaders", > > - .backup_placement = &vmw_mob_placement, > > + .domain = VMW_BO_DOMAIN_MOB, > > + .busy_domain = VMW_BO_DOMAIN_MOB, > > .create = vmw_dx_shader_create, > > /* > > * The destroy callback is only called with a committed resource on > > @@ -893,7 +895,9 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, > > if (!vmw_shader_id_ok(user_key, shader_type)) > > return -EINVAL; > > > > - ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement, > > + ret = vmw_bo_create(dev_priv, size, > > + VMW_BO_DOMAIN_SYS, > > + VMW_BO_DOMAIN_SYS, > > true, true, &buf); > > if (unlikely(ret != 0)) > > goto out; > > @@ -913,7 +917,10 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, > > WARN_ON(is_iomem); > > > > ttm_bo_kunmap(&map); > > - ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx); > > + vmw_bo_placement_set(buf, > > + VMW_BO_DOMAIN_SYS, > > + VMW_BO_DOMAIN_SYS); > > + ret = ttm_bo_validate(&buf->base, &buf->placement, &ctx); > > WARN_ON(ret != 0); > > ttm_bo_unreserve(&buf->base); > > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > > index 4ea32b01efc0..603175b8c97e 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c > > @@ -24,6 +24,7 @@ > > * > > **************************************************************************/ > > > > +#include "vmwgfx_bo.h" > > #include "vmwgfx_drv.h" > > #include "vmwgfx_resource_priv.h" > > #include "vmwgfx_so.h" > > @@ -84,7 +85,8 @@ static const struct vmw_res_func vmw_view_func = { > > .needs_backup = false, > > .may_evict = false, > > .type_name = "DX view", > > - .backup_placement = NULL, > > + .domain = VMW_BO_DOMAIN_SYS, > > + .busy_domain = VMW_BO_DOMAIN_SYS, > > .create = vmw_view_create, > > .commit_notify = vmw_view_commit_notify, > > }; > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > > index 4745537fed25..0df86402e9ce 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c > > @@ -66,7 +66,6 @@ enum stdu_content_type { > > */ > > struct vmw_stdu_dirty { > > struct vmw_kms_dirty base; > > - SVGA3dTransferType transfer; > > s32 left, right, top, bottom; > > s32 fb_left, fb_top; > > u32 pitch; > > @@ -137,12 +136,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); > > * Screen Target Display Unit CRTC Functions > > *****************************************************************************/ > > > > -static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw) > > -{ > > - return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024); > > -} > > - > > - > > /** > > * vmw_stdu_crtc_destroy - cleans up the STDU > > * > > @@ -451,93 +444,6 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, > > } > > } > > > > -/** > > - * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect > > - * > > - * @dirty: The closure structure. > > - * > > - * Encodes a surface DMA command cliprect and updates the bounding box > > - * for the DMA. > > - */ > > -static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty) > > -{ > > - struct vmw_stdu_dirty *ddirty = > > - container_of(dirty, struct vmw_stdu_dirty, base); > > - struct vmw_stdu_dma *cmd = dirty->cmd; > > - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; > > - > > - blit += dirty->num_hits; > > - blit->srcx = dirty->fb_x; > > - blit->srcy = dirty->fb_y; > > - blit->x = dirty->unit_x1; > > - blit->y = dirty->unit_y1; > > - blit->d = 1; > > - blit->w = dirty->unit_x2 - dirty->unit_x1; > > - blit->h = dirty->unit_y2 - dirty->unit_y1; > > - dirty->num_hits++; > > - > > - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) > > - return; > > - > > - /* Destination bounding box */ > > - ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1); > > - ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1); > > - ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2); > > - ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); > > -} > > - > > -/** > > - * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command. > > - * > > - * @dirty: The closure structure. > > - * > > - * Fills in the missing fields in a DMA command, and optionally encodes > > - * a screen target update command, depending on transfer direction. > > - */ > > -static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty) > > -{ > > - struct vmw_stdu_dirty *ddirty = > > - container_of(dirty, struct vmw_stdu_dirty, base); > > - struct vmw_screen_target_display_unit *stdu = > > - container_of(dirty->unit, typeof(*stdu), base); > > - struct vmw_stdu_dma *cmd = dirty->cmd; > > - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; > > - SVGA3dCmdSurfaceDMASuffix *suffix = > > - (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits]; > > - size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix); > > - > > - if (!dirty->num_hits) { > > - vmw_cmd_commit(dirty->dev_priv, 0); > > - return; > > - } > > - > > - cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; > > - cmd->header.size = sizeof(cmd->body) + blit_size; > > - vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr); > > - cmd->body.guest.pitch = ddirty->pitch; > > - cmd->body.host.sid = stdu->display_srf->res.id; > > - cmd->body.host.face = 0; > > - cmd->body.host.mipmap = 0; > > - cmd->body.transfer = ddirty->transfer; > > - suffix->suffixSize = sizeof(*suffix); > > - suffix->maximumOffset = ddirty->buf->base.base.size; > > - > > - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { > > - blit_size += sizeof(struct vmw_stdu_update); > > - > > - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, > > - ddirty->left, ddirty->right, > > - ddirty->top, ddirty->bottom); > > - } > > - > > - vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size); > > - > > - stdu->display_srf->res.res_dirty = true; > > - ddirty->left = ddirty->top = S32_MAX; > > - ddirty->right = ddirty->bottom = S32_MIN; > > -} > > - > > - > > /** > > * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit > > * > > @@ -598,62 +504,21 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > > return; > > > > /* Assume we are blitting from Guest (bo) to Host (display_srf) */ > > - dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; > > - dst_bo = &stdu->display_srf->res.backup->base; > > - dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; > > - > > - src_pitch = ddirty->pitch; > > - src_bo = &ddirty->buf->base; > > - src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; > > + src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; > > + src_bo = &stdu->display_srf->res.backup->base; > > + src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; > > > > - /* Swap src and dst if the assumption was wrong. */ > > - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) { > > - swap(dst_pitch, src_pitch); > > - swap(dst_bo, src_bo); > > - swap(src_offset, dst_offset); > > - } > > + dst_pitch = ddirty->pitch; > > + dst_bo = &ddirty->buf->base; > > + dst_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; > > > > (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, > > src_bo, src_offset, src_pitch, > > width * stdu->cpp, height, &diff); > > - > > - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM && > > - drm_rect_visible(&diff.rect)) { > > - struct vmw_private *dev_priv; > > - struct vmw_stdu_update *cmd; > > - struct drm_clip_rect region; > > - int ret; > > - > > - /* We are updating the actual surface, not a proxy */ > > - region.x1 = diff.rect.x1; > > - region.x2 = diff.rect.x2; > > - region.y1 = diff.rect.y1; > > - region.y2 = diff.rect.y2; > > - ret = vmw_kms_update_proxy(&stdu->display_srf->res, ®ion, > > - 1, 1); > > - if (ret) > > - goto out_cleanup; > > - > > - > > - dev_priv = vmw_priv(stdu->base.crtc.dev); > > - cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); > > - if (!cmd) > > - goto out_cleanup; > > - > > - vmw_stdu_populate_update(cmd, stdu->base.unit, > > - region.x1, region.x2, > > - region.y1, region.y2); > > - > > - vmw_cmd_commit(dev_priv, sizeof(*cmd)); > > - } > > - > > -out_cleanup: > > - ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; > > - ddirty->right = ddirty->bottom = S32_MIN; > > } > > > > /** > > - * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed > > + * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed > > * framebuffer and the screen target system. > > * > > * @dev_priv: Pointer to the device private structure. > > @@ -666,9 +531,6 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > > * be NULL. > > * @num_clips: Number of clip rects in @clips or @vclips. > > * @increment: Increment to use when looping over @clips or @vclips. > > - * @to_surface: Whether to DMA to the screen target system as opposed to > > - * from the screen target system. > > - * @interruptible: Whether to perform waits interruptible if possible. > > * @crtc: If crtc is passed, perform stdu dma on that crtc only. > > * > > * If DMA-ing till the screen target system, the function will also notify > > @@ -677,59 +539,49 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) > > * Returns 0 on success, negative error code on failure. -ERESTARTSYS if > > * interrupted. > > */ > > -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, > > - struct drm_file *file_priv, > > - struct vmw_framebuffer *vfb, > > - struct drm_vmw_fence_rep __user *user_fence_rep, > > - struct drm_clip_rect *clips, > > - struct drm_vmw_rect *vclips, > > - uint32_t num_clips, > > - int increment, > > - bool to_surface, > > - bool interruptible, > > - struct drm_crtc *crtc) > > +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, > > + struct drm_file *file_priv, > > + struct vmw_framebuffer *vfb, > > + struct drm_vmw_fence_rep __user *user_fence_rep, > > + struct drm_clip_rect *clips, > > + struct drm_vmw_rect *vclips, > > + uint32_t num_clips, > > + int increment, > > + struct drm_crtc *crtc) > > { > > struct vmw_bo *buf = > > container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; > > struct vmw_stdu_dirty ddirty; > > int ret; > > - bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); > > DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); > > > > /* > > - * VMs without 3D support don't have the surface DMA command and > > - * we'll be using a CPU blit, and the framebuffer should be moved out > > - * of VRAM. > > + * The GMR domain might seem confusing because it might seem like it should > > + * never happen with screen targets but e.g. the xorg vmware driver issues > > + * CMD_SURFACE_DMA for various pixmap updates which might transition our bo to > > + * a GMR. Instead of forcing another transition we can optimize the readback > > + * by reading directly from the GMR. > > */ > > - ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit); > > + vmw_bo_placement_set(buf, > > + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR, > > + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR); > > + ret = vmw_validation_add_bo(&val_ctx, buf); > > if (ret) > > return ret; > > > > - ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); > > + ret = vmw_validation_prepare(&val_ctx, NULL, true); > > if (ret) > > goto out_unref; > > > > - ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM : > > - SVGA3D_READ_HOST_VRAM; > > ddirty.left = ddirty.top = S32_MAX; > > ddirty.right = ddirty.bottom = S32_MIN; > > ddirty.fb_left = ddirty.fb_top = S32_MAX; > > ddirty.pitch = vfb->base.pitches[0]; > > ddirty.buf = buf; > > - ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit; > > - ddirty.base.clip = vmw_stdu_bo_clip; > > - ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) + > > - num_clips * sizeof(SVGA3dCopyBox) + > > - sizeof(SVGA3dCmdSurfaceDMASuffix); > > - if (to_surface) > > - ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update); > > - > > - > > - if (cpu_blit) { > > - ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; > > - ddirty.base.clip = vmw_stdu_bo_cpu_clip; > > - ddirty.base.fifo_reserve_size = 0; > > - } > > + > > + ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; > > + ddirty.base.clip = vmw_stdu_bo_cpu_clip; > > + ddirty.base.fifo_reserve_size = 0; > > > > ddirty.base.crtc = crtc; > > > > @@ -1161,11 +1013,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, > > /* > > * This should only happen if the buffer object is too large to create a > > * proxy surface for. > > - * If we are a 2D VM with a buffer object then we have to use CPU blit > > - * so cache these mappings > > */ > > - if (vps->content_fb_type == SEPARATE_BO && > > - vmw_stdu_use_cpu_blit(dev_priv)) > > + if (vps->content_fb_type == SEPARATE_BO) > > vps->cpp = new_fb->pitches[0] / new_fb->width; > > > > return 0; > > @@ -1175,14 +1024,6 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, > > return ret; > > } > > > > -static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update, > > - uint32_t num_hits) > > -{ > > - return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits + > > - sizeof(SVGA3dCmdSurfaceDMASuffix) + > > - sizeof(struct vmw_stdu_update); > > -} > > - > > static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, > > uint32_t num_hits) > > { > > @@ -1190,68 +1031,6 @@ static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, > > sizeof(struct vmw_stdu_update); > > } > > > > -static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update, > > - void *cmd, uint32_t num_hits) > > -{ > > - struct vmw_screen_target_display_unit *stdu; > > - struct vmw_framebuffer_bo *vfbbo; > > - struct vmw_stdu_dma *cmd_dma = cmd; > > - > > - stdu = container_of(update->du, typeof(*stdu), base); > > - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); > > - > > - cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA; > > - cmd_dma->header.size = sizeof(cmd_dma->body) + > > - sizeof(struct SVGA3dCopyBox) * num_hits + > > - sizeof(SVGA3dCmdSurfaceDMASuffix); > > - vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr); > > - cmd_dma->body.guest.pitch = update->vfb->base.pitches[0]; > > - cmd_dma->body.host.sid = stdu->display_srf->res.id; > > - cmd_dma->body.host.face = 0; > > - cmd_dma->body.host.mipmap = 0; > > - cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM; > > - > > - return sizeof(*cmd_dma); > > -} > > - > > -static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update, > > - void *cmd, struct drm_rect *clip, > > - uint32_t fb_x, uint32_t fb_y) > > -{ > > - struct SVGA3dCopyBox *box = cmd; > > - > > - box->srcx = fb_x; > > - box->srcy = fb_y; > > - box->srcz = 0; > > - box->x = clip->x1; > > - box->y = clip->y1; > > - box->z = 0; > > - box->w = drm_rect_width(clip); > > - box->h = drm_rect_height(clip); > > - box->d = 1; > > - > > - return sizeof(*box); > > -} > > - > > -static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update, > > - void *cmd, struct drm_rect *bb) > > -{ > > - struct vmw_screen_target_display_unit *stdu; > > - struct vmw_framebuffer_bo *vfbbo; > > - SVGA3dCmdSurfaceDMASuffix *suffix = cmd; > > - > > - stdu = container_of(update->du, typeof(*stdu), base); > > - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); > > - > > - suffix->suffixSize = sizeof(*suffix); > > - suffix->maximumOffset = vfbbo->buffer->base.base.size; > > - > > - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2, > > - bb->y1, bb->y2); > > - > > - return sizeof(*suffix) + sizeof(struct vmw_stdu_update); > > -} > > - > > static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, > > void *cmd, uint32_t num_hits) > > { > > @@ -1369,24 +1148,12 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, > > bo_update.base.vfb = vfb; > > bo_update.base.out_fence = out_fence; > > bo_update.base.mutex = NULL; > > - bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); > > bo_update.base.intr = false; > > > > - /* > > - * VM without 3D support don't have surface DMA command and framebuffer > > - * should be moved out of VRAM. > > - */ > > - if (bo_update.base.cpu_blit) { > > - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; > > - bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; > > - bo_update.base.clip = vmw_stdu_bo_clip_cpu; > > - bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; > > - } else { > > - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size; > > - bo_update.base.pre_clip = vmw_stdu_bo_populate_dma; > > - bo_update.base.clip = vmw_stdu_bo_populate_clip; > > - bo_update.base.post_clip = vmw_stdu_bo_populate_update; > > - } > > + bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; > > + bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; > > + bo_update.base.clip = vmw_stdu_bo_clip_cpu; > > + bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; > > > > return vmw_du_helper_plane_update(&bo_update.base); > > } > > @@ -1549,7 +1316,6 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, > > srf_update.vfb = vfb; > > srf_update.out_fence = out_fence; > > srf_update.mutex = &dev_priv->cmdbuf_mutex; > > - srf_update.cpu_blit = false; > > srf_update.intr = true; > > > > if (vfbs->is_bo_proxy) > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > > index 71ce89150ba7..b35ac195285d 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c > > @@ -66,7 +66,8 @@ static const struct vmw_res_func vmw_dx_streamoutput_func = { > > .needs_backup = true, > > .may_evict = false, > > .type_name = "DX streamoutput", > > - .backup_placement = &vmw_mob_placement, > > + .domain = VMW_BO_DOMAIN_MOB, > > + .busy_domain = VMW_BO_DOMAIN_MOB, > > .create = vmw_dx_streamoutput_create, > > .destroy = NULL, /* Command buffer managed resource. */ > > .bind = vmw_dx_streamoutput_bind, > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > > index 296d903c5acb..9c6a691b005e 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > > @@ -131,7 +131,8 @@ static const struct vmw_res_func vmw_legacy_surface_func = { > > .prio = 1, > > .dirty_prio = 1, > > .type_name = "legacy surfaces", > > - .backup_placement = &vmw_srf_placement, > > + .domain = VMW_BO_DOMAIN_GMR, > > + .busy_domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, > > .create = &vmw_legacy_srf_create, > > .destroy = &vmw_legacy_srf_destroy, > > .bind = &vmw_legacy_srf_bind, > > @@ -145,7 +146,8 @@ static const struct vmw_res_func vmw_gb_surface_func = { > > .prio = 1, > > .dirty_prio = 2, > > .type_name = "guest backed surfaces", > > - .backup_placement = &vmw_mob_placement, > > + .domain = VMW_BO_DOMAIN_MOB, > > + .busy_domain = VMW_BO_DOMAIN_MOB, > > .create = vmw_gb_surface_create, > > .destroy = vmw_gb_surface_destroy, > > .bind = vmw_gb_surface_bind, > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > > index 41480af87255..c43df4109613 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c > > @@ -79,20 +79,6 @@ static const struct ttm_place vram_gmr_placement_flags[] = { > > } > > }; > > > > -static const struct ttm_place gmr_vram_placement_flags[] = { > > - { > > - .fpfn = 0, > > - .lpfn = 0, > > - .mem_type = VMW_PL_GMR, > > - .flags = 0 > > - }, { > > - .fpfn = 0, > > - .lpfn = 0, > > - .mem_type = TTM_PL_VRAM, > > - .flags = 0 > > - } > > -}; > > - > > static const struct ttm_place vmw_sys_placement_flags = { > > .fpfn = 0, > > .lpfn = 0, > > @@ -128,32 +114,6 @@ struct ttm_placement vmw_pt_sys_placement = { > > .busy_placement = &vmw_sys_placement_flags > > }; > > > > -static const struct ttm_place nonfixed_placement_flags[] = { > > - { > > - .fpfn = 0, > > - .lpfn = 0, > > - .mem_type = TTM_PL_SYSTEM, > > - .flags = 0 > > - }, { > > - .fpfn = 0, > > - .lpfn = 0, > > - .mem_type = VMW_PL_GMR, > > - .flags = 0 > > - }, { > > - .fpfn = 0, > > - .lpfn = 0, > > - .mem_type = VMW_PL_MOB, > > - .flags = 0 > > - } > > -}; > > - > > -struct ttm_placement vmw_srf_placement = { > > - .num_placement = 1, > > - .num_busy_placement = 2, > > - .placement = &gmr_placement_flags, > > - .busy_placement = gmr_vram_placement_flags > > -}; > > - > > struct ttm_placement vmw_mob_placement = { > > .num_placement = 1, > > .num_busy_placement = 1, > > @@ -161,13 +121,6 @@ struct ttm_placement vmw_mob_placement = { > > .busy_placement = &mob_placement_flags > > }; > > > > -struct ttm_placement vmw_nonfixed_placement = { > > - .num_placement = 3, > > - .placement = nonfixed_placement_flags, > > - .num_busy_placement = 1, > > - .busy_placement = &sys_placement_flags > > -}; > > - > > const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); > > > > /** > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > > index 6ad744ae07f5..c968180c9769 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c > > @@ -25,6 +25,7 @@ > > * > > **************************************************************************/ > > > > +#include "vmwgfx_bo.h" > > #include "vmwgfx_drv.h" > > #include "vmwgfx_resource_priv.h" > > > > @@ -83,7 +84,8 @@ static const struct vmw_simple_resource_func va_stream_func = { > > .needs_backup = false, > > .may_evict = false, > > .type_name = "overlay stream", > > - .backup_placement = NULL, > > + .domain = VMW_BO_DOMAIN_SYS, > > + .busy_domain = VMW_BO_DOMAIN_SYS, > > .create = NULL, > > .destroy = NULL, > > .bind = NULL, > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > > index 770b1b53bde7..05f0909ff1dd 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c > > @@ -27,6 +27,7 @@ > > **************************************************************************/ > > #include "vmwgfx_bo.h" > > #include "vmwgfx_drv.h" > > +#include "vmwgfx_resource_priv.h" > > #include "vmwgfx_validation.h" > > > > #include <linux/slab.h> > > @@ -40,8 +41,6 @@ > > * @hash: A hash entry used for the duplicate detection hash table. > > * @coherent_count: If switching backup buffers, number of new coherent > > * resources that will have this buffer as a backup buffer. > > - * @as_mob: Validate as mob. > > - * @cpu_blit: Validate for cpu blit access. > > * > > * Bit fields are used since these structures are allocated and freed in > > * large numbers and space conservation is desired. > > @@ -50,8 +49,6 @@ struct vmw_validation_bo_node { > > struct ttm_validate_buffer base; > > struct vmwgfx_hash_item hash; > > unsigned int coherent_count; > > - u32 as_mob : 1; > > - u32 cpu_blit : 1; > > }; > > /** > > * struct vmw_validation_res_node - Resource validation metadata. > > @@ -260,26 +257,16 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx, > > * vmw_validation_add_bo - Add a buffer object to the validation context. > > * @ctx: The validation context. > > * @vbo: The buffer object. > > - * @as_mob: Validate as mob, otherwise suitable for GMR operations. > > - * @cpu_blit: Validate in a page-mappable location. > > * > > * Return: Zero on success, negative error code otherwise. > > */ > > int vmw_validation_add_bo(struct vmw_validation_context *ctx, > > - struct vmw_bo *vbo, > > - bool as_mob, > > - bool cpu_blit) > > + struct vmw_bo *vbo) > > { > > struct vmw_validation_bo_node *bo_node; > > > > bo_node = vmw_validation_find_bo_dup(ctx, vbo); > > - if (bo_node) { > > - if (bo_node->as_mob != as_mob || > > - bo_node->cpu_blit != cpu_blit) { > > - DRM_ERROR("Inconsistent buffer usage.\n"); > > - return -EINVAL; > > - } > > - } else { > > + if (!bo_node) { > > struct ttm_validate_buffer *val_buf; > > > > bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node)); > > @@ -297,8 +284,6 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, > > return -ESRCH; > > val_buf->num_shared = 0; > > list_add_tail(&val_buf->head, &ctx->bo_list); > > - bo_node->as_mob = as_mob; > > - bo_node->cpu_blit = cpu_blit; > > } > > > > return 0; > > @@ -455,9 +440,10 @@ int vmw_validation_res_reserve(struct vmw_validation_context *ctx, > > if (res->backup) { > > struct vmw_bo *vbo = res->backup; > > > > - ret = vmw_validation_add_bo > > - (ctx, vbo, vmw_resource_needs_backup(res), > > - false); > > + vmw_bo_placement_set(vbo, > > + res->func->domain, > > + res->func->busy_domain); > > + ret = vmw_validation_add_bo(ctx, vbo); > > if (ret) > > goto out_unreserve; > > } > > @@ -519,14 +505,12 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, > > * vmw_validation_bo_validate_single - Validate a single buffer object. > > * @bo: The TTM buffer object base. > > * @interruptible: Whether to perform waits interruptible if possible. > > - * @validate_as_mob: Whether to validate in MOB memory. > > * > > * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error > > * code on failure. > > */ > > -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > > - bool interruptible, > > - bool validate_as_mob) > > +static int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > > + bool interruptible) > > { > > struct vmw_bo *vbo = > > container_of(bo, struct vmw_bo, base); > > @@ -542,27 +526,17 @@ int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > > if (vbo->base.pin_count > 0) > > return 0; > > > > - if (validate_as_mob) > > - return ttm_bo_validate(bo, &vmw_mob_placement, &ctx); > > - > > - /** > > - * Put BO in VRAM if there is space, otherwise as a GMR. > > - * If there is no space in VRAM and GMR ids are all used up, > > - * start evicting GMRs to make room. If the DMA buffer can't be > > - * used as a GMR, this will return -ENOMEM. > > - */ > > - > > - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); > > + ret = ttm_bo_validate(bo, &vbo->placement, &ctx); > > if (ret == 0 || ret == -ERESTARTSYS) > > return ret; > > > > - /** > > - * If that failed, try VRAM again, this time evicting > > + /* > > + * If that failed, try again, this time evicting > > * previous contents. > > */ > > + ctx.allow_res_evict = true; > > > > - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); > > - return ret; > > + return ttm_bo_validate(bo, &vbo->placement, &ctx); > > } > > > > /** > > @@ -583,18 +557,8 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) > > struct vmw_bo *vbo = > > container_of(entry->base.bo, typeof(*vbo), base); > > > > - if (entry->cpu_blit) { > > - struct ttm_operation_ctx ttm_ctx = { > > - .interruptible = intr, > > - .no_wait_gpu = false > > - }; > > - > > - ret = ttm_bo_validate(entry->base.bo, > > - &vmw_nonfixed_placement, &ttm_ctx); > > - } else { > > - ret = vmw_validation_bo_validate_single > > - (entry->base.bo, intr, entry->as_mob); > > - } > > + ret = vmw_validation_bo_validate_single(entry->base.bo, intr); > > + > > if (ret) > > return ret; > > > > @@ -655,9 +619,9 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) > > if (backup && res->backup && (backup != res->backup)) { > > struct vmw_bo *vbo = res->backup; > > > > - ret = vmw_validation_add_bo > > - (ctx, vbo, vmw_resource_needs_backup(res), > > - false); > > + vmw_bo_placement_set(vbo, res->func->domain, > > + res->func->busy_domain); > > + ret = vmw_validation_add_bo(ctx, vbo); > > if (ret) > > return ret; > > } > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > > index 4aa4f700c65e..240ee0c4ebfd 100644 > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h > > @@ -159,11 +159,7 @@ static inline unsigned int vmw_validation_align(unsigned int val) > > } > > > > int vmw_validation_add_bo(struct vmw_validation_context *ctx, > > - struct vmw_bo *vbo, > > - bool as_mob, bool cpu_blit); > > -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, > > - bool interruptible, > > - bool validate_as_mob); > > + struct vmw_bo *vbo); > > int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); > > void vmw_validation_unref_lists(struct vmw_validation_context *ctx); > > int vmw_validation_add_resource(struct vmw_validation_context *ctx, > > LGTM! > > Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com> > > -- > Maaz Mombasawala (VMware) <maazm@fastmail.com> >
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index c6dc733f6d45..d8f6ccecf4bf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -135,11 +135,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, goto out_unreserve; } - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); + vmw_bo_placement_set(buf, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_GMR); + ret = ttm_bo_validate(bo, &buf->placement, &ctx); if (likely(ret == 0) || ret == -ERESTARTSYS) goto out_unreserve; - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); + vmw_bo_placement_set(buf, + VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_VRAM); + ret = ttm_bo_validate(bo, &buf->placement, &ctx); out_unreserve: if (!ret) @@ -190,17 +196,8 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, { struct ttm_operation_ctx ctx = {interruptible, false }; struct ttm_buffer_object *bo = &buf->base; - struct ttm_placement placement; - struct ttm_place place; int ret = 0; - place = vmw_vram_placement.placement[0]; - place.lpfn = PFN_UP(bo->resource->size); - placement.num_placement = 1; - placement.placement = &place; - placement.num_busy_placement = 1; - placement.busy_placement = &place; - vmw_execbuf_release_pinned_bo(dev_priv); ret = ttm_bo_reserve(bo, interruptible, false, NULL); if (unlikely(ret != 0)) @@ -216,14 +213,21 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, bo->resource->start > 0 && buf->base.pin_count == 0) { ctx.interruptible = false; - (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx); + vmw_bo_placement_set(buf, + VMW_BO_DOMAIN_SYS, + VMW_BO_DOMAIN_SYS); + (void)ttm_bo_validate(bo, &buf->placement, &ctx); } + vmw_bo_placement_set(buf, + VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_VRAM); + buf->places[0].lpfn = PFN_UP(bo->resource->size); if (buf->base.pin_count > 0) - ret = ttm_resource_compat(bo->resource, &placement) + ret = ttm_resource_compat(bo->resource, &buf->placement) ? 0 : -EINVAL; else - ret = ttm_bo_validate(bo, &placement, &ctx); + ret = ttm_bo_validate(bo, &buf->placement, &ctx); /* For some reason we didn't end up at the start of vram */ WARN_ON(ret == 0 && bo->resource->start != 0); @@ -431,7 +435,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, } int vmw_bo_create(struct vmw_private *vmw, - size_t size, struct ttm_placement *placement, + size_t size, u32 domain, u32 busy_domain, bool interruptible, bool pin, struct vmw_bo **p_bo) { @@ -444,7 +448,8 @@ int vmw_bo_create(struct vmw_private *vmw, } ret = vmw_bo_init(vmw, *p_bo, size, - placement, interruptible, pin); + domain, busy_domain, + interruptible, pin); if (unlikely(ret != 0)) goto out_error; @@ -461,7 +466,8 @@ int vmw_bo_create(struct vmw_private *vmw, * @dev_priv: Pointer to the device private struct * @vmw_bo: Pointer to the struct vmw_bo to initialize. * @size: Buffer object size in bytes. - * @placement: Initial placement. + * @domain: Domain to put the bo in. + * @busy_domain: Domain to put the bo if busy. * @interruptible: Whether waits should be performed interruptible. * @pin: If the BO should be created pinned at a fixed location. * Returns: Zero on success, negative error code on error. @@ -470,7 +476,9 @@ int vmw_bo_create(struct vmw_private *vmw, */ int vmw_bo_init(struct vmw_private *dev_priv, struct vmw_bo *vmw_bo, - size_t size, struct ttm_placement *placement, + size_t size, + u32 domain, + u32 busy_domain, bool interruptible, bool pin) { struct ttm_operation_ctx ctx = { @@ -489,8 +497,9 @@ int vmw_bo_init(struct vmw_private *dev_priv, size = ALIGN(size, PAGE_SIZE); drm_gem_private_object_init(vdev, &vmw_bo->base.base, size); + vmw_bo_placement_set(vmw_bo, domain, busy_domain); ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device, - placement, 0, &ctx, NULL, NULL, vmw_bo_free); + &vmw_bo->placement, 0, &ctx, NULL, NULL, vmw_bo_free); if (unlikely(ret)) { return ret; } @@ -825,3 +834,101 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) vmw_resource_unbind_list(vbo); } + +static u32 +set_placement_list(struct ttm_place *pl, u32 domain) +{ + u32 n = 0; + + /* + * The placements are ordered according to our preferences + */ + if (domain & VMW_BO_DOMAIN_MOB) { + pl[n].mem_type = VMW_PL_MOB; + pl[n].flags = 0; + pl[n].fpfn = 0; + pl[n].lpfn = 0; + n++; + } + if (domain & VMW_BO_DOMAIN_GMR) { + pl[n].mem_type = VMW_PL_GMR; + pl[n].flags = 0; + pl[n].fpfn = 0; + pl[n].lpfn = 0; + n++; + } + if (domain & VMW_BO_DOMAIN_VRAM) { + pl[n].mem_type = TTM_PL_VRAM; + pl[n].flags = 0; + pl[n].fpfn = 0; + pl[n].lpfn = 0; + n++; + } + WARN_ON((domain & VMW_BO_DOMAIN_WAITABLE_SYS) != 0); + if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) { + pl[n].mem_type = VMW_PL_SYSTEM; + pl[n].flags = 0; + pl[n].fpfn = 0; + pl[n].lpfn = 0; + n++; + } + if (domain & VMW_BO_DOMAIN_SYS) { + pl[n].mem_type = TTM_PL_SYSTEM; + pl[n].flags = 0; + pl[n].fpfn = 0; + pl[n].lpfn = 0; + n++; + } + + WARN_ON(!n); + if (!n) { + pl[n].mem_type = TTM_PL_SYSTEM; + pl[n].flags = 0; + pl[n].fpfn = 0; + pl[n].lpfn = 0; + n++; + } + return n; +} + +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain) +{ + struct ttm_device *bdev = bo->base.bdev; + struct vmw_private *vmw = + container_of(bdev, struct vmw_private, bdev); + struct ttm_placement *pl = &bo->placement; + bool mem_compatible = false; + u32 i; + + pl->placement = bo->places; + pl->num_placement = set_placement_list(bo->places, domain); + + if (drm_debug_enabled(DRM_UT_DRIVER) && bo->base.resource) { + for (i = 0; i < pl->num_placement; ++i) { + if (bo->base.resource->mem_type == TTM_PL_SYSTEM || + bo->base.resource->mem_type == pl->placement[i].mem_type) + mem_compatible = true; + } + if (!mem_compatible) + drm_warn(&vmw->drm, + "%s: Incompatible transition from " + "bo->base.resource->mem_type = %u to domain = %u\n", + __func__, bo->base.resource->mem_type, domain); + } + + pl->busy_placement = bo->busy_places; + pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain); +} + +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo) +{ + struct ttm_device *bdev = bo->base.bdev; + struct vmw_private *vmw = + container_of(bdev, struct vmw_private, bdev); + u32 domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM; + + if (vmw->has_mob) + domain = VMW_BO_DOMAIN_MOB; + + vmw_bo_placement_set(bo, domain, domain); +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h index 2ede1e28d7ce..538d8739d7a5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h @@ -31,6 +31,7 @@ #include "device_include/svga_reg.h" #include <drm/ttm/ttm_bo_api.h> +#include <drm/ttm/ttm_placement.h> #include <linux/rbtree_types.h> #include <linux/types.h> @@ -40,6 +41,14 @@ struct vmw_fence_obj; struct vmw_private; struct vmw_resource; +enum vmw_bo_domain { + VMW_BO_DOMAIN_SYS = BIT(0), + VMW_BO_DOMAIN_WAITABLE_SYS = BIT(1), + VMW_BO_DOMAIN_VRAM = BIT(2), + VMW_BO_DOMAIN_GMR = BIT(3), + VMW_BO_DOMAIN_MOB = BIT(4), +}; + /** * struct vmw_bo - TTM buffer object with vmwgfx additions * @base: The TTM buffer object @@ -53,6 +62,11 @@ struct vmw_resource; */ struct vmw_bo { struct ttm_buffer_object base; + + struct ttm_placement placement; + struct ttm_place places[5]; + struct ttm_place busy_places[5]; + struct rb_root res_tree; atomic_t cpu_writers; @@ -64,17 +78,24 @@ struct vmw_bo { struct vmw_bo_dirty *dirty; }; +void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain); +void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo); + int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size, struct ttm_placement *placement, struct ttm_buffer_object **p_bo); int vmw_bo_create(struct vmw_private *dev_priv, - size_t size, struct ttm_placement *placement, + size_t size, + u32 domain, + u32 busy_domain, bool interruptible, bool pin, struct vmw_bo **p_bo); int vmw_bo_init(struct vmw_private *dev_priv, struct vmw_bo *vmw_bo, - size_t size, struct ttm_placement *placement, + size_t size, + u32 domain, + u32 busy_domain, bool interruptible, bool pin); int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c index cc02be6a9884..84ef5f0a785b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c @@ -76,7 +76,8 @@ static const struct vmw_res_func vmw_legacy_context_func = { .needs_backup = false, .may_evict = false, .type_name = "legacy contexts", - .backup_placement = NULL, + .domain = VMW_BO_DOMAIN_SYS, + .busy_domain = VMW_BO_DOMAIN_SYS, .create = NULL, .destroy = NULL, .bind = NULL, @@ -90,7 +91,8 @@ static const struct vmw_res_func vmw_gb_context_func = { .prio = 3, .dirty_prio = 3, .type_name = "guest backed contexts", - .backup_placement = &vmw_mob_placement, + .domain = VMW_BO_DOMAIN_MOB, + .busy_domain = VMW_BO_DOMAIN_MOB, .create = vmw_gb_context_create, .destroy = vmw_gb_context_destroy, .bind = vmw_gb_context_bind, @@ -104,7 +106,8 @@ static const struct vmw_res_func vmw_dx_context_func = { .prio = 3, .dirty_prio = 3, .type_name = "dx contexts", - .backup_placement = &vmw_mob_placement, + .domain = VMW_BO_DOMAIN_MOB, + .busy_domain = VMW_BO_DOMAIN_MOB, .create = vmw_dx_context_create, .destroy = vmw_dx_context_destroy, .bind = vmw_dx_context_bind, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c index 9193faae8dab..d49db8146df1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c @@ -136,7 +136,8 @@ static const struct vmw_res_func vmw_cotable_func = { .prio = 3, .dirty_prio = 3, .type_name = "context guest backed object tables", - .backup_placement = &vmw_mob_placement, + .domain = VMW_BO_DOMAIN_MOB, + .busy_domain = VMW_BO_DOMAIN_MOB, .create = vmw_cotable_create, .destroy = vmw_cotable_destroy, .bind = vmw_cotable_bind, @@ -424,7 +425,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) * for the new COTable. Initially pin the buffer object to make sure * we can use tryreserve without failure. */ - ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement, + ret = vmw_bo_create(dev_priv, new_size, + VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB, true, true, &buf); if (ret) { DRM_ERROR("Failed initializing new cotable MOB.\n"); @@ -465,7 +467,10 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) } /* Unpin new buffer, and switch backup buffers. */ - ret = ttm_bo_validate(bo, &vmw_mob_placement, &ctx); + vmw_bo_placement_set(buf, + VMW_BO_DOMAIN_MOB, + VMW_BO_DOMAIN_MOB); + ret = ttm_bo_validate(bo, &buf->placement, &ctx); if (unlikely(ret != 0)) { DRM_ERROR("Failed validating new COTable backup buffer.\n"); goto out_wait; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 60d08185a71f..c12ad8264043 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -399,7 +399,8 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) * user of the bo currently. */ ret = vmw_bo_create(dev_priv, PAGE_SIZE, - &vmw_sys_placement, false, true, &vbo); + VMW_BO_DOMAIN_SYS, VMW_BO_DOMAIN_SYS, + false, true, &vbo); if (unlikely(ret != 0)) return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index e9a16a1e043d..5629a00039fe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -930,9 +930,7 @@ extern struct ttm_placement vmw_vram_placement; extern struct ttm_placement vmw_vram_sys_placement; extern struct ttm_placement vmw_vram_gmr_placement; extern struct ttm_placement vmw_sys_placement; -extern struct ttm_placement vmw_srf_placement; extern struct ttm_placement vmw_mob_placement; -extern struct ttm_placement vmw_nonfixed_placement; extern struct ttm_device_funcs vmw_bo_driver; extern const struct vmw_sg_table * vmw_bo_sg_table(struct ttm_buffer_object *bo); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 687c6926bc00..eda7f8471bcd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -477,9 +477,13 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, struct vmw_bo *dx_query_mob; dx_query_mob = vmw_context_get_dx_query_mob(ctx); - if (dx_query_mob) + if (dx_query_mob) { + vmw_bo_placement_set(dx_query_mob, + VMW_BO_DOMAIN_MOB, + VMW_BO_DOMAIN_MOB); ret = vmw_validation_add_bo(sw_context->ctx, - dx_query_mob, true, false); + dx_query_mob); + } } mutex_unlock(&dev_priv->binding_mutex); @@ -1035,17 +1039,17 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, if (unlikely(sw_context->cur_query_bo != NULL)) { sw_context->needs_post_query_barrier = true; + vmw_bo_placement_set_default_accelerated(sw_context->cur_query_bo); ret = vmw_validation_add_bo(sw_context->ctx, - sw_context->cur_query_bo, - dev_priv->has_mob, false); + sw_context->cur_query_bo); if (unlikely(ret != 0)) return ret; } sw_context->cur_query_bo = new_query_bo; + vmw_bo_placement_set_default_accelerated(dev_priv->dummy_query_bo); ret = vmw_validation_add_bo(sw_context->ctx, - dev_priv->dummy_query_bo, - dev_priv->has_mob, false); + dev_priv->dummy_query_bo); if (unlikely(ret != 0)) return ret; } @@ -1157,7 +1161,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n"); return PTR_ERR(vmw_bo); } - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); ttm_bo_put(&vmw_bo->base); if (unlikely(ret != 0)) return ret; @@ -1211,7 +1216,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n"); return PTR_ERR(vmw_bo); } - ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); + vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); ttm_bo_put(&vmw_bo->base); if (unlikely(ret != 0)) return ret; @@ -4361,13 +4368,17 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, if (dev_priv->pinned_bo == NULL) goto out_unlock; - ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, - false); + vmw_bo_placement_set(dev_priv->pinned_bo, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); + ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo); if (ret) goto out_no_reserve; - ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, - false); + vmw_bo_placement_set(dev_priv->dummy_query_bo, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); + ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo); if (ret) goto out_no_reserve; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c index c7ebcd4f3afa..5f383578a320 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c @@ -121,9 +121,8 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, int ret; ret = vmw_bo_create(dev_priv, size, - (dev_priv->has_mob) ? - &vmw_sys_placement : - &vmw_vram_sys_placement, + (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_SYS, true, false, p_vbo); (*p_vbo)->base.base.funcs = &vmw_gem_object_funcs; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e83286e08837..d975c0a818c7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1270,9 +1270,9 @@ int vmw_kms_readback(struct vmw_private *dev_priv, user_fence_rep, vclips, num_clips, NULL); case vmw_du_screen_target: - return vmw_kms_stdu_dma(dev_priv, file_priv, vfb, - user_fence_rep, NULL, vclips, num_clips, - 1, false, true, NULL); + return vmw_kms_stdu_readback(dev_priv, file_priv, vfb, + user_fence_rep, NULL, vclips, num_clips, + 1, NULL); default: WARN_ONCE(true, "Readback called with invalid display system.\n"); @@ -2999,8 +2999,20 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) struct vmw_framebuffer_bo *vfbbo = container_of(update->vfb, typeof(*vfbbo), base); - ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false, - update->cpu_blit); + /* + * For screen targets we want a mappable bo, for everything else we want + * accelerated i.e. host backed (vram or gmr) bo. If the display unit + * is not screen target then mob's shouldn't be available. + */ + if (update->dev_priv->active_display_unit == vmw_du_screen_target) { + vmw_bo_placement_set(vfbbo->buffer, + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR, + VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR); + } else { + WARN_ON(update->dev_priv->has_mob); + vmw_bo_placement_set_default_accelerated(vfbbo->buffer); + } + ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer); } else { struct vmw_framebuffer_surface *vfbs = container_of(update->vfb, typeof(*vfbs), base); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 7a97e53e8e51..1bdf601e7c35 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -126,7 +126,6 @@ struct vmw_du_update_plane { struct vmw_framebuffer *vfb; struct vmw_fence_obj **out_fence; struct mutex *mutex; - bool cpu_blit; bool intr; }; @@ -564,17 +563,15 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, unsigned num_clips, int inc, struct vmw_fence_obj **out_fence, struct drm_crtc *crtc); -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, - struct drm_file *file_priv, - struct vmw_framebuffer *vfb, - struct drm_vmw_fence_rep __user *user_fence_rep, - struct drm_clip_rect *clips, - struct drm_vmw_rect *vclips, - uint32_t num_clips, - int increment, - bool to_surface, - bool interruptible, - struct drm_crtc *crtc); +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, + struct drm_file *file_priv, + struct vmw_framebuffer *vfb, + struct drm_vmw_fence_rep __user *user_fence_rep, + struct drm_clip_rect *clips, + struct drm_vmw_rect *vclips, + uint32_t num_clips, + int increment, + struct drm_crtc *crtc); int vmw_du_helper_plane_update(struct vmw_du_update_plane *update); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 54e412f8c2d1..6780a36e6171 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -332,7 +332,7 @@ static int vmw_resource_buf_alloc(struct vmw_resource *res, } ret = vmw_bo_create(res->dev_priv, res->backup_size, - res->func->backup_placement, + res->func->domain, res->func->busy_domain, interruptible, false, &backup); if (unlikely(ret != 0)) goto out_no_bo; @@ -529,8 +529,10 @@ vmw_resource_check_buffer(struct ww_acquire_ctx *ticket, return 0; backup_dirty = res->backup_dirty; + vmw_bo_placement_set(res->backup, res->func->domain, + res->func->busy_domain); ret = ttm_bo_validate(&res->backup->base, - res->func->backup_placement, + &res->backup->placement, &ctx); if (unlikely(ret != 0)) @@ -968,9 +970,12 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) if (ret) goto out_no_validate; if (!vbo->base.pin_count) { + vmw_bo_placement_set(vbo, + res->func->domain, + res->func->busy_domain); ret = ttm_bo_validate (&vbo->base, - res->func->backup_placement, + &vbo->placement, &ctx); if (ret) { ttm_bo_unreserve(&vbo->base); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h index 3b7438b2d289..2c24e0929faa 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h @@ -83,7 +83,8 @@ struct vmw_res_func { enum vmw_res_type res_type; bool needs_backup; const char *type_name; - struct ttm_placement *backup_placement; + u32 domain; + u32 busy_domain; bool may_evict; u32 prio; u32 dirty_prio; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index a04897f04c13..e9d03ef98154 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -445,7 +445,8 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, */ vmw_overlay_pause_all(dev_priv); ret = vmw_bo_create(dev_priv, size, - &vmw_vram_placement, + VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_VRAM, false, true, &vps->bo); vmw_overlay_resume_all(dev_priv); if (ret) { @@ -547,7 +548,6 @@ static int vmw_sou_plane_update_bo(struct vmw_private *dev_priv, bo_update.base.vfb = vfb; bo_update.base.out_fence = out_fence; bo_update.base.mutex = NULL; - bo_update.base.cpu_blit = false; bo_update.base.intr = true; bo_update.base.calc_fifo_size = vmw_sou_bo_fifo_size; @@ -708,7 +708,6 @@ static int vmw_sou_plane_update_surface(struct vmw_private *dev_priv, srf_update.base.vfb = vfb; srf_update.base.out_fence = out_fence; srf_update.base.mutex = &dev_priv->cmdbuf_mutex; - srf_update.base.cpu_blit = false; srf_update.base.intr = true; srf_update.base.calc_fifo_size = vmw_sou_surface_fifo_size; @@ -1224,7 +1223,9 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); int ret; - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); + ret = vmw_validation_add_bo(&val_ctx, buf); if (ret) return ret; @@ -1330,7 +1331,9 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); int ret; - ret = vmw_validation_add_bo(&val_ctx, buf, false, false); + vmw_bo_placement_set(buf, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, + VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); + ret = vmw_validation_add_bo(&val_ctx, buf); if (ret) return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index b186d0993d83..9920c103bffb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -94,7 +94,8 @@ static const struct vmw_res_func vmw_gb_shader_func = { .prio = 3, .dirty_prio = 3, .type_name = "guest backed shaders", - .backup_placement = &vmw_mob_placement, + .domain = VMW_BO_DOMAIN_MOB, + .busy_domain = VMW_BO_DOMAIN_MOB, .create = vmw_gb_shader_create, .destroy = vmw_gb_shader_destroy, .bind = vmw_gb_shader_bind, @@ -108,7 +109,8 @@ static const struct vmw_res_func vmw_dx_shader_func = { .prio = 3, .dirty_prio = 3, .type_name = "dx shaders", - .backup_placement = &vmw_mob_placement, + .domain = VMW_BO_DOMAIN_MOB, + .busy_domain = VMW_BO_DOMAIN_MOB, .create = vmw_dx_shader_create, /* * The destroy callback is only called with a committed resource on @@ -893,7 +895,9 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, if (!vmw_shader_id_ok(user_key, shader_type)) return -EINVAL; - ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement, + ret = vmw_bo_create(dev_priv, size, + VMW_BO_DOMAIN_SYS, + VMW_BO_DOMAIN_SYS, true, true, &buf); if (unlikely(ret != 0)) goto out; @@ -913,7 +917,10 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, WARN_ON(is_iomem); ttm_bo_kunmap(&map); - ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx); + vmw_bo_placement_set(buf, + VMW_BO_DOMAIN_SYS, + VMW_BO_DOMAIN_SYS); + ret = ttm_bo_validate(&buf->base, &buf->placement, &ctx); WARN_ON(ret != 0); ttm_bo_unreserve(&buf->base); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c index 4ea32b01efc0..603175b8c97e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c @@ -24,6 +24,7 @@ * **************************************************************************/ +#include "vmwgfx_bo.h" #include "vmwgfx_drv.h" #include "vmwgfx_resource_priv.h" #include "vmwgfx_so.h" @@ -84,7 +85,8 @@ static const struct vmw_res_func vmw_view_func = { .needs_backup = false, .may_evict = false, .type_name = "DX view", - .backup_placement = NULL, + .domain = VMW_BO_DOMAIN_SYS, + .busy_domain = VMW_BO_DOMAIN_SYS, .create = vmw_view_create, .commit_notify = vmw_view_commit_notify, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 4745537fed25..0df86402e9ce 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -66,7 +66,6 @@ enum stdu_content_type { */ struct vmw_stdu_dirty { struct vmw_kms_dirty base; - SVGA3dTransferType transfer; s32 left, right, top, bottom; s32 fb_left, fb_top; u32 pitch; @@ -137,12 +136,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); * Screen Target Display Unit CRTC Functions *****************************************************************************/ -static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw) -{ - return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024); -} - - /** * vmw_stdu_crtc_destroy - cleans up the STDU * @@ -451,93 +444,6 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, } } -/** - * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect - * - * @dirty: The closure structure. - * - * Encodes a surface DMA command cliprect and updates the bounding box - * for the DMA. - */ -static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty) -{ - struct vmw_stdu_dirty *ddirty = - container_of(dirty, struct vmw_stdu_dirty, base); - struct vmw_stdu_dma *cmd = dirty->cmd; - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; - - blit += dirty->num_hits; - blit->srcx = dirty->fb_x; - blit->srcy = dirty->fb_y; - blit->x = dirty->unit_x1; - blit->y = dirty->unit_y1; - blit->d = 1; - blit->w = dirty->unit_x2 - dirty->unit_x1; - blit->h = dirty->unit_y2 - dirty->unit_y1; - dirty->num_hits++; - - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) - return; - - /* Destination bounding box */ - ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1); - ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1); - ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2); - ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); -} - -/** - * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command. - * - * @dirty: The closure structure. - * - * Fills in the missing fields in a DMA command, and optionally encodes - * a screen target update command, depending on transfer direction. - */ -static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty) -{ - struct vmw_stdu_dirty *ddirty = - container_of(dirty, struct vmw_stdu_dirty, base); - struct vmw_screen_target_display_unit *stdu = - container_of(dirty->unit, typeof(*stdu), base); - struct vmw_stdu_dma *cmd = dirty->cmd; - struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; - SVGA3dCmdSurfaceDMASuffix *suffix = - (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits]; - size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix); - - if (!dirty->num_hits) { - vmw_cmd_commit(dirty->dev_priv, 0); - return; - } - - cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; - cmd->header.size = sizeof(cmd->body) + blit_size; - vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr); - cmd->body.guest.pitch = ddirty->pitch; - cmd->body.host.sid = stdu->display_srf->res.id; - cmd->body.host.face = 0; - cmd->body.host.mipmap = 0; - cmd->body.transfer = ddirty->transfer; - suffix->suffixSize = sizeof(*suffix); - suffix->maximumOffset = ddirty->buf->base.base.size; - - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { - blit_size += sizeof(struct vmw_stdu_update); - - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, - ddirty->left, ddirty->right, - ddirty->top, ddirty->bottom); - } - - vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size); - - stdu->display_srf->res.res_dirty = true; - ddirty->left = ddirty->top = S32_MAX; - ddirty->right = ddirty->bottom = S32_MIN; -} - - /** * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit * @@ -598,62 +504,21 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) return; /* Assume we are blitting from Guest (bo) to Host (display_srf) */ - dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; - dst_bo = &stdu->display_srf->res.backup->base; - dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; - - src_pitch = ddirty->pitch; - src_bo = &ddirty->buf->base; - src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; + src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; + src_bo = &stdu->display_srf->res.backup->base; + src_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; - /* Swap src and dst if the assumption was wrong. */ - if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) { - swap(dst_pitch, src_pitch); - swap(dst_bo, src_bo); - swap(src_offset, dst_offset); - } + dst_pitch = ddirty->pitch; + dst_bo = &ddirty->buf->base; + dst_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, src_bo, src_offset, src_pitch, width * stdu->cpp, height, &diff); - - if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM && - drm_rect_visible(&diff.rect)) { - struct vmw_private *dev_priv; - struct vmw_stdu_update *cmd; - struct drm_clip_rect region; - int ret; - - /* We are updating the actual surface, not a proxy */ - region.x1 = diff.rect.x1; - region.x2 = diff.rect.x2; - region.y1 = diff.rect.y1; - region.y2 = diff.rect.y2; - ret = vmw_kms_update_proxy(&stdu->display_srf->res, ®ion, - 1, 1); - if (ret) - goto out_cleanup; - - - dev_priv = vmw_priv(stdu->base.crtc.dev); - cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); - if (!cmd) - goto out_cleanup; - - vmw_stdu_populate_update(cmd, stdu->base.unit, - region.x1, region.x2, - region.y1, region.y2); - - vmw_cmd_commit(dev_priv, sizeof(*cmd)); - } - -out_cleanup: - ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; - ddirty->right = ddirty->bottom = S32_MIN; } /** - * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed + * vmw_kms_stdu_readback - Perform a readback from a buffer-object backed * framebuffer and the screen target system. * * @dev_priv: Pointer to the device private structure. @@ -666,9 +531,6 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) * be NULL. * @num_clips: Number of clip rects in @clips or @vclips. * @increment: Increment to use when looping over @clips or @vclips. - * @to_surface: Whether to DMA to the screen target system as opposed to - * from the screen target system. - * @interruptible: Whether to perform waits interruptible if possible. * @crtc: If crtc is passed, perform stdu dma on that crtc only. * * If DMA-ing till the screen target system, the function will also notify @@ -677,59 +539,49 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) * Returns 0 on success, negative error code on failure. -ERESTARTSYS if * interrupted. */ -int vmw_kms_stdu_dma(struct vmw_private *dev_priv, - struct drm_file *file_priv, - struct vmw_framebuffer *vfb, - struct drm_vmw_fence_rep __user *user_fence_rep, - struct drm_clip_rect *clips, - struct drm_vmw_rect *vclips, - uint32_t num_clips, - int increment, - bool to_surface, - bool interruptible, - struct drm_crtc *crtc) +int vmw_kms_stdu_readback(struct vmw_private *dev_priv, + struct drm_file *file_priv, + struct vmw_framebuffer *vfb, + struct drm_vmw_fence_rep __user *user_fence_rep, + struct drm_clip_rect *clips, + struct drm_vmw_rect *vclips, + uint32_t num_clips, + int increment, + struct drm_crtc *crtc) { struct vmw_bo *buf = container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; struct vmw_stdu_dirty ddirty; int ret; - bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); /* - * VMs without 3D support don't have the surface DMA command and - * we'll be using a CPU blit, and the framebuffer should be moved out - * of VRAM. + * The GMR domain might seem confusing because it might seem like it should + * never happen with screen targets but e.g. the xorg vmware driver issues + * CMD_SURFACE_DMA for various pixmap updates which might transition our bo to + * a GMR. Instead of forcing another transition we can optimize the readback + * by reading directly from the GMR. */ - ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit); + vmw_bo_placement_set(buf, + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR, + VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_GMR); + ret = vmw_validation_add_bo(&val_ctx, buf); if (ret) return ret; - ret = vmw_validation_prepare(&val_ctx, NULL, interruptible); + ret = vmw_validation_prepare(&val_ctx, NULL, true); if (ret) goto out_unref; - ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM : - SVGA3D_READ_HOST_VRAM; ddirty.left = ddirty.top = S32_MAX; ddirty.right = ddirty.bottom = S32_MIN; ddirty.fb_left = ddirty.fb_top = S32_MAX; ddirty.pitch = vfb->base.pitches[0]; ddirty.buf = buf; - ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit; - ddirty.base.clip = vmw_stdu_bo_clip; - ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) + - num_clips * sizeof(SVGA3dCopyBox) + - sizeof(SVGA3dCmdSurfaceDMASuffix); - if (to_surface) - ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update); - - - if (cpu_blit) { - ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; - ddirty.base.clip = vmw_stdu_bo_cpu_clip; - ddirty.base.fifo_reserve_size = 0; - } + + ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; + ddirty.base.clip = vmw_stdu_bo_cpu_clip; + ddirty.base.fifo_reserve_size = 0; ddirty.base.crtc = crtc; @@ -1161,11 +1013,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, /* * This should only happen if the buffer object is too large to create a * proxy surface for. - * If we are a 2D VM with a buffer object then we have to use CPU blit - * so cache these mappings */ - if (vps->content_fb_type == SEPARATE_BO && - vmw_stdu_use_cpu_blit(dev_priv)) + if (vps->content_fb_type == SEPARATE_BO) vps->cpp = new_fb->pitches[0] / new_fb->width; return 0; @@ -1175,14 +1024,6 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, return ret; } -static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update, - uint32_t num_hits) -{ - return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits + - sizeof(SVGA3dCmdSurfaceDMASuffix) + - sizeof(struct vmw_stdu_update); -} - static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, uint32_t num_hits) { @@ -1190,68 +1031,6 @@ static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update, sizeof(struct vmw_stdu_update); } -static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update, - void *cmd, uint32_t num_hits) -{ - struct vmw_screen_target_display_unit *stdu; - struct vmw_framebuffer_bo *vfbbo; - struct vmw_stdu_dma *cmd_dma = cmd; - - stdu = container_of(update->du, typeof(*stdu), base); - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); - - cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA; - cmd_dma->header.size = sizeof(cmd_dma->body) + - sizeof(struct SVGA3dCopyBox) * num_hits + - sizeof(SVGA3dCmdSurfaceDMASuffix); - vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr); - cmd_dma->body.guest.pitch = update->vfb->base.pitches[0]; - cmd_dma->body.host.sid = stdu->display_srf->res.id; - cmd_dma->body.host.face = 0; - cmd_dma->body.host.mipmap = 0; - cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM; - - return sizeof(*cmd_dma); -} - -static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update, - void *cmd, struct drm_rect *clip, - uint32_t fb_x, uint32_t fb_y) -{ - struct SVGA3dCopyBox *box = cmd; - - box->srcx = fb_x; - box->srcy = fb_y; - box->srcz = 0; - box->x = clip->x1; - box->y = clip->y1; - box->z = 0; - box->w = drm_rect_width(clip); - box->h = drm_rect_height(clip); - box->d = 1; - - return sizeof(*box); -} - -static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update, - void *cmd, struct drm_rect *bb) -{ - struct vmw_screen_target_display_unit *stdu; - struct vmw_framebuffer_bo *vfbbo; - SVGA3dCmdSurfaceDMASuffix *suffix = cmd; - - stdu = container_of(update->du, typeof(*stdu), base); - vfbbo = container_of(update->vfb, typeof(*vfbbo), base); - - suffix->suffixSize = sizeof(*suffix); - suffix->maximumOffset = vfbbo->buffer->base.base.size; - - vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2, - bb->y1, bb->y2); - - return sizeof(*suffix) + sizeof(struct vmw_stdu_update); -} - static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update, void *cmd, uint32_t num_hits) { @@ -1369,24 +1148,12 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, bo_update.base.vfb = vfb; bo_update.base.out_fence = out_fence; bo_update.base.mutex = NULL; - bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); bo_update.base.intr = false; - /* - * VM without 3D support don't have surface DMA command and framebuffer - * should be moved out of VRAM. - */ - if (bo_update.base.cpu_blit) { - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; - bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; - bo_update.base.clip = vmw_stdu_bo_clip_cpu; - bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; - } else { - bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size; - bo_update.base.pre_clip = vmw_stdu_bo_populate_dma; - bo_update.base.clip = vmw_stdu_bo_populate_clip; - bo_update.base.post_clip = vmw_stdu_bo_populate_update; - } + bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu; + bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu; + bo_update.base.clip = vmw_stdu_bo_clip_cpu; + bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu; return vmw_du_helper_plane_update(&bo_update.base); } @@ -1549,7 +1316,6 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, srf_update.vfb = vfb; srf_update.out_fence = out_fence; srf_update.mutex = &dev_priv->cmdbuf_mutex; - srf_update.cpu_blit = false; srf_update.intr = true; if (vfbs->is_bo_proxy) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c index 71ce89150ba7..b35ac195285d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c @@ -66,7 +66,8 @@ static const struct vmw_res_func vmw_dx_streamoutput_func = { .needs_backup = true, .may_evict = false, .type_name = "DX streamoutput", - .backup_placement = &vmw_mob_placement, + .domain = VMW_BO_DOMAIN_MOB, + .busy_domain = VMW_BO_DOMAIN_MOB, .create = vmw_dx_streamoutput_create, .destroy = NULL, /* Command buffer managed resource. */ .bind = vmw_dx_streamoutput_bind, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 296d903c5acb..9c6a691b005e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -131,7 +131,8 @@ static const struct vmw_res_func vmw_legacy_surface_func = { .prio = 1, .dirty_prio = 1, .type_name = "legacy surfaces", - .backup_placement = &vmw_srf_placement, + .domain = VMW_BO_DOMAIN_GMR, + .busy_domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, .create = &vmw_legacy_srf_create, .destroy = &vmw_legacy_srf_destroy, .bind = &vmw_legacy_srf_bind, @@ -145,7 +146,8 @@ static const struct vmw_res_func vmw_gb_surface_func = { .prio = 1, .dirty_prio = 2, .type_name = "guest backed surfaces", - .backup_placement = &vmw_mob_placement, + .domain = VMW_BO_DOMAIN_MOB, + .busy_domain = VMW_BO_DOMAIN_MOB, .create = vmw_gb_surface_create, .destroy = vmw_gb_surface_destroy, .bind = vmw_gb_surface_bind, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 41480af87255..c43df4109613 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -79,20 +79,6 @@ static const struct ttm_place vram_gmr_placement_flags[] = { } }; -static const struct ttm_place gmr_vram_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .mem_type = VMW_PL_GMR, - .flags = 0 - }, { - .fpfn = 0, - .lpfn = 0, - .mem_type = TTM_PL_VRAM, - .flags = 0 - } -}; - static const struct ttm_place vmw_sys_placement_flags = { .fpfn = 0, .lpfn = 0, @@ -128,32 +114,6 @@ struct ttm_placement vmw_pt_sys_placement = { .busy_placement = &vmw_sys_placement_flags }; -static const struct ttm_place nonfixed_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .mem_type = TTM_PL_SYSTEM, - .flags = 0 - }, { - .fpfn = 0, - .lpfn = 0, - .mem_type = VMW_PL_GMR, - .flags = 0 - }, { - .fpfn = 0, - .lpfn = 0, - .mem_type = VMW_PL_MOB, - .flags = 0 - } -}; - -struct ttm_placement vmw_srf_placement = { - .num_placement = 1, - .num_busy_placement = 2, - .placement = &gmr_placement_flags, - .busy_placement = gmr_vram_placement_flags -}; - struct ttm_placement vmw_mob_placement = { .num_placement = 1, .num_busy_placement = 1, @@ -161,13 +121,6 @@ struct ttm_placement vmw_mob_placement = { .busy_placement = &mob_placement_flags }; -struct ttm_placement vmw_nonfixed_placement = { - .num_placement = 3, - .placement = nonfixed_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_placement_flags -}; - const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c index 6ad744ae07f5..c968180c9769 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_va.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_va.c @@ -25,6 +25,7 @@ * **************************************************************************/ +#include "vmwgfx_bo.h" #include "vmwgfx_drv.h" #include "vmwgfx_resource_priv.h" @@ -83,7 +84,8 @@ static const struct vmw_simple_resource_func va_stream_func = { .needs_backup = false, .may_evict = false, .type_name = "overlay stream", - .backup_placement = NULL, + .domain = VMW_BO_DOMAIN_SYS, + .busy_domain = VMW_BO_DOMAIN_SYS, .create = NULL, .destroy = NULL, .bind = NULL, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c index 770b1b53bde7..05f0909ff1dd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c @@ -27,6 +27,7 @@ **************************************************************************/ #include "vmwgfx_bo.h" #include "vmwgfx_drv.h" +#include "vmwgfx_resource_priv.h" #include "vmwgfx_validation.h" #include <linux/slab.h> @@ -40,8 +41,6 @@ * @hash: A hash entry used for the duplicate detection hash table. * @coherent_count: If switching backup buffers, number of new coherent * resources that will have this buffer as a backup buffer. - * @as_mob: Validate as mob. - * @cpu_blit: Validate for cpu blit access. * * Bit fields are used since these structures are allocated and freed in * large numbers and space conservation is desired. @@ -50,8 +49,6 @@ struct vmw_validation_bo_node { struct ttm_validate_buffer base; struct vmwgfx_hash_item hash; unsigned int coherent_count; - u32 as_mob : 1; - u32 cpu_blit : 1; }; /** * struct vmw_validation_res_node - Resource validation metadata. @@ -260,26 +257,16 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx, * vmw_validation_add_bo - Add a buffer object to the validation context. * @ctx: The validation context. * @vbo: The buffer object. - * @as_mob: Validate as mob, otherwise suitable for GMR operations. - * @cpu_blit: Validate in a page-mappable location. * * Return: Zero on success, negative error code otherwise. */ int vmw_validation_add_bo(struct vmw_validation_context *ctx, - struct vmw_bo *vbo, - bool as_mob, - bool cpu_blit) + struct vmw_bo *vbo) { struct vmw_validation_bo_node *bo_node; bo_node = vmw_validation_find_bo_dup(ctx, vbo); - if (bo_node) { - if (bo_node->as_mob != as_mob || - bo_node->cpu_blit != cpu_blit) { - DRM_ERROR("Inconsistent buffer usage.\n"); - return -EINVAL; - } - } else { + if (!bo_node) { struct ttm_validate_buffer *val_buf; bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node)); @@ -297,8 +284,6 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx, return -ESRCH; val_buf->num_shared = 0; list_add_tail(&val_buf->head, &ctx->bo_list); - bo_node->as_mob = as_mob; - bo_node->cpu_blit = cpu_blit; } return 0; @@ -455,9 +440,10 @@ int vmw_validation_res_reserve(struct vmw_validation_context *ctx, if (res->backup) { struct vmw_bo *vbo = res->backup; - ret = vmw_validation_add_bo - (ctx, vbo, vmw_resource_needs_backup(res), - false); + vmw_bo_placement_set(vbo, + res->func->domain, + res->func->busy_domain); + ret = vmw_validation_add_bo(ctx, vbo); if (ret) goto out_unreserve; } @@ -519,14 +505,12 @@ void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, * vmw_validation_bo_validate_single - Validate a single buffer object. * @bo: The TTM buffer object base. * @interruptible: Whether to perform waits interruptible if possible. - * @validate_as_mob: Whether to validate in MOB memory. * * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error * code on failure. */ -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, - bool interruptible, - bool validate_as_mob) +static int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, + bool interruptible) { struct vmw_bo *vbo = container_of(bo, struct vmw_bo, base); @@ -542,27 +526,17 @@ int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, if (vbo->base.pin_count > 0) return 0; - if (validate_as_mob) - return ttm_bo_validate(bo, &vmw_mob_placement, &ctx); - - /** - * Put BO in VRAM if there is space, otherwise as a GMR. - * If there is no space in VRAM and GMR ids are all used up, - * start evicting GMRs to make room. If the DMA buffer can't be - * used as a GMR, this will return -ENOMEM. - */ - - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); + ret = ttm_bo_validate(bo, &vbo->placement, &ctx); if (ret == 0 || ret == -ERESTARTSYS) return ret; - /** - * If that failed, try VRAM again, this time evicting + /* + * If that failed, try again, this time evicting * previous contents. */ + ctx.allow_res_evict = true; - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); - return ret; + return ttm_bo_validate(bo, &vbo->placement, &ctx); } /** @@ -583,18 +557,8 @@ int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) struct vmw_bo *vbo = container_of(entry->base.bo, typeof(*vbo), base); - if (entry->cpu_blit) { - struct ttm_operation_ctx ttm_ctx = { - .interruptible = intr, - .no_wait_gpu = false - }; - - ret = ttm_bo_validate(entry->base.bo, - &vmw_nonfixed_placement, &ttm_ctx); - } else { - ret = vmw_validation_bo_validate_single - (entry->base.bo, intr, entry->as_mob); - } + ret = vmw_validation_bo_validate_single(entry->base.bo, intr); + if (ret) return ret; @@ -655,9 +619,9 @@ int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) if (backup && res->backup && (backup != res->backup)) { struct vmw_bo *vbo = res->backup; - ret = vmw_validation_add_bo - (ctx, vbo, vmw_resource_needs_backup(res), - false); + vmw_bo_placement_set(vbo, res->func->domain, + res->func->busy_domain); + ret = vmw_validation_add_bo(ctx, vbo); if (ret) return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h index 4aa4f700c65e..240ee0c4ebfd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h @@ -159,11 +159,7 @@ static inline unsigned int vmw_validation_align(unsigned int val) } int vmw_validation_add_bo(struct vmw_validation_context *ctx, - struct vmw_bo *vbo, - bool as_mob, bool cpu_blit); -int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, - bool interruptible, - bool validate_as_mob); + struct vmw_bo *vbo); int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); void vmw_validation_unref_lists(struct vmw_validation_context *ctx); int vmw_validation_add_resource(struct vmw_validation_context *ctx,