static const struct ttm_place vram_placement_flags = {
.fpfn = 0,
.lpfn = 0,
- .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED
-};
-
-static const struct ttm_place vram_ne_placement_flags = {
- .fpfn = 0,
- .lpfn = 0,
- .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT
+ .mem_type = TTM_PL_VRAM,
+ .flags = TTM_PL_FLAG_CACHED
};
static const struct ttm_place sys_placement_flags = {
.fpfn = 0,
.lpfn = 0,
- .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED
-};
-
-static const struct ttm_place sys_ne_placement_flags = {
- .fpfn = 0,
- .lpfn = 0,
- .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT
+ .mem_type = TTM_PL_SYSTEM,
+ .flags = TTM_PL_FLAG_CACHED
};
static const struct ttm_place gmr_placement_flags = {
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
-};
-
-static const struct ttm_place gmr_ne_placement_flags = {
- .fpfn = 0,
- .lpfn = 0,
- .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT
+ .mem_type = VMW_PL_GMR,
+ .flags = TTM_PL_FLAG_CACHED
};
static const struct ttm_place mob_placement_flags = {
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED
-};
-
-static const struct ttm_place mob_ne_placement_flags = {
- .fpfn = 0,
- .lpfn = 0,
- .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT
+ .mem_type = VMW_PL_MOB,
+ .flags = TTM_PL_FLAG_CACHED
};
struct ttm_placement vmw_vram_placement = {
{
.fpfn = 0,
.lpfn = 0,
- .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED
+ .mem_type = TTM_PL_VRAM,
+ .flags = TTM_PL_FLAG_CACHED
}, {
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+ .mem_type = VMW_PL_GMR,
+ .flags = TTM_PL_FLAG_CACHED
}
};
{
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+ .mem_type = VMW_PL_GMR,
+ .flags = TTM_PL_FLAG_CACHED
}, {
.fpfn = 0,
.lpfn = 0,
- .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED
+ .mem_type = TTM_PL_VRAM,
+ .flags = TTM_PL_FLAG_CACHED
}
};
.busy_placement = &gmr_placement_flags
};
-static const struct ttm_place vram_gmr_ne_placement_flags[] = {
- {
- .fpfn = 0,
- .lpfn = 0,
- .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED |
- TTM_PL_FLAG_NO_EVICT
- }, {
- .fpfn = 0,
- .lpfn = 0,
- .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED |
- TTM_PL_FLAG_NO_EVICT
- }
-};
-
-struct ttm_placement vmw_vram_gmr_ne_placement = {
- .num_placement = 2,
- .placement = vram_gmr_ne_placement_flags,
- .num_busy_placement = 1,
- .busy_placement = &gmr_ne_placement_flags
-};
-
struct ttm_placement vmw_vram_sys_placement = {
.num_placement = 1,
.placement = &vram_placement_flags,
.busy_placement = &sys_placement_flags
};
-struct ttm_placement vmw_vram_ne_placement = {
- .num_placement = 1,
- .placement = &vram_ne_placement_flags,
- .num_busy_placement = 1,
- .busy_placement = &vram_ne_placement_flags
-};
-
struct ttm_placement vmw_sys_placement = {
.num_placement = 1,
.placement = &sys_placement_flags,
.busy_placement = &sys_placement_flags
};
-struct ttm_placement vmw_sys_ne_placement = {
- .num_placement = 1,
- .placement = &sys_ne_placement_flags,
- .num_busy_placement = 1,
- .busy_placement = &sys_ne_placement_flags
-};
-
static const struct ttm_place evictable_placement_flags[] = {
{
.fpfn = 0,
.lpfn = 0,
- .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED
+ .mem_type = TTM_PL_SYSTEM,
+ .flags = TTM_PL_FLAG_CACHED
}, {
.fpfn = 0,
.lpfn = 0,
- .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED
+ .mem_type = TTM_PL_VRAM,
+ .flags = TTM_PL_FLAG_CACHED
}, {
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+ .mem_type = VMW_PL_GMR,
+ .flags = TTM_PL_FLAG_CACHED
}, {
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED
+ .mem_type = VMW_PL_MOB,
+ .flags = TTM_PL_FLAG_CACHED
}
};
{
.fpfn = 0,
.lpfn = 0,
- .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED
+ .mem_type = TTM_PL_SYSTEM,
+ .flags = TTM_PL_FLAG_CACHED
}, {
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+ .mem_type = VMW_PL_GMR,
+ .flags = TTM_PL_FLAG_CACHED
}, {
.fpfn = 0,
.lpfn = 0,
- .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED
+ .mem_type = VMW_PL_MOB,
+ .flags = TTM_PL_FLAG_CACHED
}
};
.busy_placement = &mob_placement_flags
};
-struct ttm_placement vmw_mob_ne_placement = {
- .num_placement = 1,
- .num_busy_placement = 1,
- .placement = &mob_ne_placement_flags,
- .busy_placement = &mob_ne_placement_flags
-};
-
struct ttm_placement vmw_nonfixed_placement = {
.num_placement = 3,
.placement = nonfixed_placement_flags,
struct vmw_sg_table vsgt;
uint64_t sg_alloc_size;
bool mapped;
+ bool bound;
};
const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
vmw_tt->mapped = false;
}
-
-/**
- * vmw_bo_map_dma - Make sure buffer object pages are visible to the device
- *
- * @bo: Pointer to a struct ttm_buffer_object
- *
- * Wrapper around vmw_ttm_map_dma, that takes a TTM buffer object pointer
- * instead of a pointer to a struct vmw_ttm_backend as argument.
- * Note that the buffer object must be either pinned or reserved before
- * calling this function.
- */
-int vmw_bo_map_dma(struct ttm_buffer_object *bo)
-{
- struct vmw_ttm_tt *vmw_tt =
- container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
-
- return vmw_ttm_map_dma(vmw_tt);
-}
-
-
-/**
- * vmw_bo_unmap_dma - Make sure buffer object pages are visible to the device
- *
- * @bo: Pointer to a struct ttm_buffer_object
- *
- * Wrapper around vmw_ttm_unmap_dma, that takes a TTM buffer object pointer
- * instead of a pointer to a struct vmw_ttm_backend as argument.
- */
-void vmw_bo_unmap_dma(struct ttm_buffer_object *bo)
-{
- struct vmw_ttm_tt *vmw_tt =
- container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
-
- vmw_ttm_unmap_dma(vmw_tt);
-}
-
-
/**
* vmw_bo_sg_table - Return a struct vmw_sg_table object for a
* TTM buffer object
}
-static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
+static int vmw_ttm_bind(struct ttm_bo_device *bdev,
+ struct ttm_tt *ttm, struct ttm_resource *bo_mem)
{
struct vmw_ttm_tt *vmw_be =
container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
- int ret;
+ int ret = 0;
+
+ if (!bo_mem)
+ return -EINVAL;
+
+ if (vmw_be->bound)
+ return 0;
ret = vmw_ttm_map_dma(vmw_be);
if (unlikely(ret != 0))
switch (bo_mem->mem_type) {
case VMW_PL_GMR:
- return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
+ ret = vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
ttm->num_pages, vmw_be->gmr_id);
+ break;
case VMW_PL_MOB:
if (unlikely(vmw_be->mob == NULL)) {
vmw_be->mob =
return -ENOMEM;
}
- return vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob,
+ ret = vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob,
&vmw_be->vsgt, ttm->num_pages,
vmw_be->gmr_id);
+ break;
default:
BUG();
}
- return 0;
+ vmw_be->bound = true;
+ return ret;
}
-static void vmw_ttm_unbind(struct ttm_tt *ttm)
+static void vmw_ttm_unbind(struct ttm_bo_device *bdev,
+ struct ttm_tt *ttm)
{
struct vmw_ttm_tt *vmw_be =
container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+ if (!vmw_be->bound)
+ return;
+
switch (vmw_be->mem_type) {
case VMW_PL_GMR:
vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind)
vmw_ttm_unmap_dma(vmw_be);
+ vmw_be->bound = false;
}
-static void vmw_ttm_destroy(struct ttm_tt *ttm)
+static void vmw_ttm_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
{
struct vmw_ttm_tt *vmw_be =
container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+ vmw_ttm_unbind(bdev, ttm);
+ ttm_tt_destroy_common(bdev, ttm);
vmw_ttm_unmap_dma(vmw_be);
if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
ttm_dma_tt_fini(&vmw_be->dma_ttm);
}
-static int vmw_ttm_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
+static int vmw_ttm_populate(struct ttm_bo_device *bdev,
+ struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
{
struct vmw_ttm_tt *vmw_tt =
container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
struct ttm_mem_global *glob = vmw_mem_glob(dev_priv);
int ret;
- if (ttm->state != tt_unpopulated)
+ if (ttm_tt_is_populated(ttm))
return 0;
if (dev_priv->map_mode == vmw_dma_alloc_coherent) {
return ret;
}
-static void vmw_ttm_unpopulate(struct ttm_tt *ttm)
+static void vmw_ttm_unpopulate(struct ttm_bo_device *bdev,
+ struct ttm_tt *ttm)
{
struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,
dma_ttm.ttm);
ttm_pool_unpopulate(ttm);
}
-static struct ttm_backend_func vmw_ttm_func = {
- .bind = vmw_ttm_bind,
- .unbind = vmw_ttm_unbind,
- .destroy = vmw_ttm_destroy,
-};
-
static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
{
if (!vmw_be)
return NULL;
- vmw_be->dma_ttm.ttm.func = &vmw_ttm_func;
vmw_be->dev_priv = container_of(bo->bdev, struct vmw_private, bdev);
vmw_be->mob = NULL;
if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
- ret = ttm_dma_tt_init(&vmw_be->dma_ttm, bo, page_flags);
+ ret = ttm_dma_tt_init(&vmw_be->dma_ttm, bo, page_flags,
+ ttm_cached);
else
- ret = ttm_tt_init(&vmw_be->dma_ttm.ttm, bo, page_flags);
+ ret = ttm_tt_init(&vmw_be->dma_ttm.ttm, bo, page_flags,
+ ttm_cached);
if (unlikely(ret != 0))
goto out_no_init;
return NULL;
}
-static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
- struct ttm_mem_type_manager *man)
-{
- switch (type) {
- case TTM_PL_SYSTEM:
- /* System memory */
- man->available_caching = TTM_PL_FLAG_CACHED;
- man->default_caching = TTM_PL_FLAG_CACHED;
- break;
- case TTM_PL_VRAM:
- /* "On-card" video ram */
- man->func = &vmw_thp_func;
- man->flags = TTM_MEMTYPE_FLAG_FIXED;
- man->available_caching = TTM_PL_FLAG_CACHED;
- man->default_caching = TTM_PL_FLAG_CACHED;
- break;
- case VMW_PL_GMR:
- case VMW_PL_MOB:
- /*
- * "Guest Memory Regions" is an aperture like feature with
- * one slot per bo. There is an upper limit of the number of
- * slots as well as the bo size.
- */
- man->func = &vmw_gmrid_manager_func;
- man->available_caching = TTM_PL_FLAG_CACHED;
- man->default_caching = TTM_PL_FLAG_CACHED;
- break;
- default:
- DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
- return -EINVAL;
- }
- return 0;
-}
-
static void vmw_evict_flags(struct ttm_buffer_object *bo,
struct ttm_placement *placement)
{
return vmw_user_bo_verify_access(bo, tfile);
}
-static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *mem)
{
struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev);
- mem->bus.addr = NULL;
- mem->bus.is_iomem = false;
- mem->bus.offset = 0;
- mem->bus.size = mem->num_pages << PAGE_SHIFT;
- mem->bus.base = 0;
-
switch (mem->mem_type) {
case TTM_PL_SYSTEM:
case VMW_PL_GMR:
case VMW_PL_MOB:
return 0;
case TTM_PL_VRAM:
- mem->bus.offset = mem->start << PAGE_SHIFT;
- mem->bus.base = dev_priv->vram_start;
+ mem->bus.offset = (mem->start << PAGE_SHIFT) +
+ dev_priv->vram_start;
mem->bus.is_iomem = true;
break;
default:
* vmw_move_notify - TTM move_notify_callback
*
* @bo: The TTM buffer object about to move.
- * @mem: The struct ttm_mem_reg indicating to what memory
+ * @mem: The struct ttm_resource indicating to what memory
* region the move is taking place.
*
* Calls move_notify for all subsystems needing it.
*/
static void vmw_move_notify(struct ttm_buffer_object *bo,
bool evict,
- struct ttm_mem_reg *mem)
+ struct ttm_resource *mem)
{
+ if (!mem)
+ return;
vmw_bo_move_notify(bo, mem);
vmw_query_move_notify(bo, mem);
}
(void) ttm_bo_wait(bo, false, false);
}
+static int vmw_move(struct ttm_buffer_object *bo,
+ bool evict,
+ struct ttm_operation_ctx *ctx,
+ struct ttm_resource *new_mem)
+{
+ struct ttm_resource_manager *old_man = ttm_manager_type(bo->bdev, bo->mem.mem_type);
+ struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type);
+
+ if (old_man->use_tt && new_man->use_tt) {
+ if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+ ttm_bo_assign_mem(bo, new_mem);
+ return 0;
+ }
+ return ttm_bo_move_ttm(bo, ctx, new_mem);
+ } else {
+ return ttm_bo_move_memcpy(bo, ctx, new_mem);
+ }
+}
struct ttm_bo_driver vmw_bo_driver = {
.ttm_tt_create = &vmw_ttm_tt_create,
.ttm_tt_populate = &vmw_ttm_populate,
.ttm_tt_unpopulate = &vmw_ttm_unpopulate,
- .init_mem_type = vmw_init_mem_type,
+ .ttm_tt_bind = &vmw_ttm_bind,
+ .ttm_tt_unbind = &vmw_ttm_unbind,
+ .ttm_tt_destroy = &vmw_ttm_destroy,
.eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = vmw_evict_flags,
- .move = NULL,
+ .move = vmw_move,
.verify_access = vmw_verify_access,
.move_notify = vmw_move_notify,
.swap_notify = vmw_swap_notify,
.io_mem_reserve = &vmw_ttm_io_mem_reserve,
};
+
+int vmw_bo_create_and_populate(struct vmw_private *dev_priv,
+ unsigned long bo_size,
+ struct ttm_buffer_object **bo_p)
+{
+ struct ttm_operation_ctx ctx = {
+ .interruptible = false,
+ .no_wait_gpu = false
+ };
+ struct ttm_buffer_object *bo;
+ int ret;
+
+ ret = vmw_bo_create_kernel(dev_priv, bo_size,
+ &vmw_sys_placement,
+ &bo);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ret = ttm_bo_reserve(bo, false, true, NULL);
+ BUG_ON(ret != 0);
+ ret = vmw_ttm_populate(bo->bdev, bo->ttm, &ctx);
+ if (likely(ret == 0)) {
+ struct vmw_ttm_tt *vmw_tt =
+ container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+ ret = vmw_ttm_map_dma(vmw_tt);
+ }
+
+ ttm_bo_unreserve(bo);
+
+ if (likely(ret == 0))
+ *bo_p = bo;
+ return ret;
+}