Commit 39985eea authored by Zack Rusin's avatar Zack Rusin

drm/vmwgfx: Abstract placement selection

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: default avatarZack Rusin <zackr@vmware.com>
Reviewed-by: default avatarMartin Krastev <krastevm@vmware.com>
Reviewed-by: default avatarMaaz Mombasawala <mombasawalam@vmware.com>
Acked-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20230131033542.953249-8-zack@kde.org
parent e0029da9
......@@ -124,11 +124,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
goto err;
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)
......@@ -179,17 +185,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))
......@@ -205,10 +202,17 @@ 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);
}
ret = ttm_bo_validate(bo, &placement, &ctx);
vmw_bo_placement_set(buf,
VMW_BO_DOMAIN_VRAM,
VMW_BO_DOMAIN_VRAM);
buf->places[0].lpfn = PFN_UP(bo->resource->size);
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);
......@@ -416,7 +420,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)
{
......@@ -429,7 +433,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;
......@@ -446,7 +451,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.
......@@ -455,7 +461,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 = {
......@@ -474,8 +482,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;
}
......@@ -810,3 +819,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);
}
......@@ -31,6 +31,7 @@
#include "device_include/svga_reg.h"
#include <drm/ttm/ttm_bo.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);
......
......@@ -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,
......
......@@ -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;
......
......@@ -398,7 +398,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;
......
......@@ -932,9 +932,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);
......
......@@ -478,9 +478,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);
......@@ -1036,17 +1040,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;
}
......@@ -1158,7 +1162,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;
......@@ -1212,7 +1217,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;
......@@ -4362,13 +4369,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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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,
};
......
This diff is collapsed.
......@@ -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,
......
......@@ -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,
......
......@@ -78,20 +78,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,
......@@ -127,32 +113,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,
......@@ -160,13 +120,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);
/**
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment