Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6da768aa authored by Thomas Hellstrom's avatar Thomas Hellstrom
Browse files

drm/vmwgfx: Hook up MOBs to TTM as a separate memory type



To bind a buffer object as a MOB, just validate it as a MOB
memory type. We are reusing the GMRID manager, although we create a new
instance of it to manage MOB ids and tomake sure we don't exceed
the maximum amount of MOB pages.

Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarBrian Paul <brianp@vmware.com>
parent 3530bdc3
Loading
Loading
Loading
Loading
+95 −7
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@ static uint32_t gmr_ne_placement_flags = VMW_PL_FLAG_GMR |
	TTM_PL_FLAG_CACHED |
	TTM_PL_FLAG_NO_EVICT;

static uint32_t mob_placement_flags = VMW_PL_FLAG_MOB |
	TTM_PL_FLAG_CACHED;

struct ttm_placement vmw_vram_placement = {
	.fpfn = 0,
	.lpfn = 0,
@@ -132,13 +135,14 @@ struct ttm_placement vmw_sys_ne_placement = {
static uint32_t evictable_placement_flags[] = {
	TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED,
	TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED,
	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED,
	VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED
};

struct ttm_placement vmw_evictable_placement = {
	.fpfn = 0,
	.lpfn = 0,
	.num_placement = 3,
	.num_placement = 4,
	.placement = evictable_placement_flags,
	.num_busy_placement = 1,
	.busy_placement = &sys_placement_flags
@@ -153,10 +157,21 @@ struct ttm_placement vmw_srf_placement = {
	.busy_placement = gmr_vram_placement_flags
};

struct ttm_placement vmw_mob_placement = {
	.fpfn = 0,
	.lpfn = 0,
	.num_placement = 1,
	.num_busy_placement = 1,
	.placement = &mob_placement_flags,
	.busy_placement = &mob_placement_flags
};

struct vmw_ttm_tt {
	struct ttm_dma_tt dma_ttm;
	struct vmw_private *dev_priv;
	int gmr_id;
	struct vmw_mob *mob;
	int mem_type;
	struct sg_table sgt;
	struct vmw_sg_table vsgt;
	uint64_t sg_alloc_size;
@@ -448,9 +463,27 @@ static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
		return ret;

	vmw_be->gmr_id = bo_mem->start;
	vmw_be->mem_type = bo_mem->mem_type;

	switch (bo_mem->mem_type) {
	case VMW_PL_GMR:
		return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
				    ttm->num_pages, vmw_be->gmr_id);
	case VMW_PL_MOB:
		if (unlikely(vmw_be->mob == NULL)) {
			vmw_be->mob =
				vmw_mob_create(ttm->num_pages);
			if (unlikely(vmw_be->mob == NULL))
				return -ENOMEM;
		}

		return vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob,
				    ttm->pages, ttm->num_pages,
				    vmw_be->gmr_id);
	default:
		BUG();
	}
	return 0;
}

static int vmw_ttm_unbind(struct ttm_tt *ttm)
@@ -458,7 +491,16 @@ static int vmw_ttm_unbind(struct ttm_tt *ttm)
	struct vmw_ttm_tt *vmw_be =
		container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);

	switch (vmw_be->mem_type) {
	case VMW_PL_GMR:
		vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
		break;
	case VMW_PL_MOB:
		vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob);
		break;
	default:
		BUG();
	}

	if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind)
		vmw_ttm_unmap_dma(vmw_be);
@@ -466,6 +508,7 @@ static int vmw_ttm_unbind(struct ttm_tt *ttm)
	return 0;
}


static void vmw_ttm_destroy(struct ttm_tt *ttm)
{
	struct vmw_ttm_tt *vmw_be =
@@ -476,6 +519,10 @@ static void vmw_ttm_destroy(struct ttm_tt *ttm)
		ttm_dma_tt_fini(&vmw_be->dma_ttm);
	else
		ttm_tt_fini(ttm);

	if (vmw_be->mob)
		vmw_mob_destroy(vmw_be->mob);

	kfree(vmw_be);
}

@@ -513,6 +560,12 @@ static void vmw_ttm_unpopulate(struct ttm_tt *ttm)
	struct vmw_private *dev_priv = vmw_tt->dev_priv;
	struct ttm_mem_global *glob = vmw_mem_glob(dev_priv);


	if (vmw_tt->mob) {
		vmw_mob_destroy(vmw_tt->mob);
		vmw_tt->mob = NULL;
	}

	vmw_ttm_unmap_dma(vmw_tt);
	if (dev_priv->map_mode == vmw_dma_alloc_coherent) {
		size_t size =
@@ -543,6 +596,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,

	vmw_be->dma_ttm.ttm.func = &vmw_ttm_func;
	vmw_be->dev_priv = container_of(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, bdev, size, page_flags,
@@ -584,6 +638,7 @@ static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
		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
@@ -631,6 +686,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg
	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;
@@ -690,6 +746,38 @@ static int vmw_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible)
				  VMW_FENCE_WAIT_TIMEOUT);
}

/**
 * vmw_move_notify - TTM move_notify_callback
 *
 * @bo:             The TTM buffer object about to move.
 * @mem:            The truct ttm_mem_reg indicating to what memory
 *                  region the move is taking place.
 *
 * Calls move_notify for all subsystems needing it.
 * (currently only resources).
 */
static void vmw_move_notify(struct ttm_buffer_object *bo,
			    struct ttm_mem_reg *mem)
{
	vmw_resource_move_notify(bo, mem);
}


/**
 * vmw_swap_notify - TTM move_notify_callback
 *
 * @bo:             The TTM buffer object about to be swapped out.
 */
static void vmw_swap_notify(struct ttm_buffer_object *bo)
{
	struct ttm_bo_device *bdev = bo->bdev;

	spin_lock(&bdev->fence_lock);
	ttm_bo_wait(bo, false, false, false);
	spin_unlock(&bdev->fence_lock);
}


struct ttm_bo_driver vmw_bo_driver = {
	.ttm_tt_create = &vmw_ttm_tt_create,
	.ttm_tt_populate = &vmw_ttm_populate,
@@ -704,8 +792,8 @@ struct ttm_bo_driver vmw_bo_driver = {
	.sync_obj_flush = vmw_sync_obj_flush,
	.sync_obj_unref = vmw_sync_obj_unref,
	.sync_obj_ref = vmw_sync_obj_ref,
	.move_notify = NULL,
	.swap_notify = NULL,
	.move_notify = vmw_move_notify,
	.swap_notify = vmw_swap_notify,
	.fault_reserve_notify = &vmw_ttm_fault_reserve_notify,
	.io_mem_reserve = &vmw_ttm_io_mem_reserve,
	.io_mem_free = &vmw_ttm_io_mem_free,
+4 −2
Original line number Diff line number Diff line
@@ -304,9 +304,11 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)

	lockdep_assert_held(&bo->resv->lock.base);
	BUG_ON(old_mem_type != TTM_PL_VRAM &&
	       old_mem_type != VMW_PL_GMR);
	       old_mem_type != VMW_PL_GMR &&
	       old_mem_type != VMW_PL_MOB);

	pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
	pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB
		| TTM_PL_FLAG_CACHED;
	if (pin)
		pl_flags |= TTM_PL_FLAG_NO_EVICT;

+21 −2
Original line number Diff line number Diff line
@@ -643,6 +643,14 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
		 */
		dev_priv->memory_size = 512*1024*1024;
	}
	dev_priv->max_mob_pages = 0;
	if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
		uint64_t mem_size =
			vmw_read(dev_priv,
				 SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);

		dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
	}

	ret = vmw_dma_masks(dev_priv);
	if (unlikely(ret != 0))
@@ -698,14 +706,21 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
	dev_priv->has_gmr = true;
	if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
	    refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR,
					 dev_priv->max_gmr_ids) != 0) {
					 VMW_PL_GMR) != 0) {
		DRM_INFO("No GMR memory available. "
			 "Graphics memory resources are very limited.\n");
		dev_priv->has_gmr = false;
	}

	if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
	if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
		dev_priv->has_mob = true;
		if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB,
				   VMW_PL_MOB) != 0) {
			DRM_INFO("No MOB memory available. "
				 "3D will be disabled.\n");
			dev_priv->has_mob = false;
		}
	}

	dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
					       dev_priv->mmio_size);
@@ -809,6 +824,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
	iounmap(dev_priv->mmio_virt);
out_err3:
	arch_phys_wc_del(dev_priv->mmio_mtrr);
	if (dev_priv->has_mob)
		(void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
	if (dev_priv->has_gmr)
		(void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
@@ -853,6 +870,8 @@ static int vmw_driver_unload(struct drm_device *dev)
	ttm_object_device_release(&dev_priv->tdev);
	iounmap(dev_priv->mmio_virt);
	arch_phys_wc_del(dev_priv->mmio_mtrr);
	if (dev_priv->has_mob)
		(void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
	if (dev_priv->has_gmr)
		(void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
+3 −0
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@

#define VMW_PL_GMR TTM_PL_PRIV0
#define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0
#define VMW_PL_MOB TTM_PL_PRIV1
#define VMW_PL_FLAG_MOB TTM_PL_FLAG_PRIV1

#define VMW_RES_CONTEXT ttm_driver_type0
#define VMW_RES_SURFACE ttm_driver_type1
@@ -303,6 +305,7 @@ struct vmw_private {
	uint32_t capabilities;
	uint32_t max_gmr_ids;
	uint32_t max_gmr_pages;
	uint32_t max_mob_pages;
	uint32_t memory_size;
	bool has_gmr;
	bool has_mob;
+13 −2
Original line number Diff line number Diff line
@@ -125,10 +125,21 @@ static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man,
		return -ENOMEM;

	spin_lock_init(&gman->lock);
	gman->max_gmr_pages = dev_priv->max_gmr_pages;
	gman->used_gmr_pages = 0;
	ida_init(&gman->gmr_ida);
	gman->max_gmr_ids = p_size;

	switch (p_size) {
	case VMW_PL_GMR:
		gman->max_gmr_ids = dev_priv->max_gmr_ids;
		gman->max_gmr_pages = dev_priv->max_gmr_pages;
		break;
	case VMW_PL_MOB:
		gman->max_gmr_ids = VMWGFX_NUM_MOB;
		gman->max_gmr_pages = dev_priv->max_mob_pages;
		break;
	default:
		BUG();
	}
	man->priv = (void *) gman;
	return 0;
}