]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
drm/vmwgfx: Hook up MOBs to TTM as a separate memory type
[~andy/linux] / drivers / gpu / drm / vmwgfx / vmwgfx_buffer.c
index 92ae4c5894c5248159a042089e5dcd0e1fc15000..e4f5b926b67ec9f3aa644cad94f2636d3eefa219 100644 (file)
@@ -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;
 
-       return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
-                           ttm->num_pages, vmw_be->gmr_id);
+       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);
 
-       vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
+       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,