On 1/30/23 19:35, Zack Rusin wrote: > From: Zack Rusin <zackr@xxxxxxxxxx> > > 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@xxxxxxxxxx> > --- > 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@xxxxxxxxxx> -- Maaz Mombasawala (VMware) <maazm@xxxxxxxxxxxx>