[PATCH 4/4] drm/ttm: move bo move logic inside driver to avoid callback
j.glisse at gmail.com
j.glisse at gmail.com
Thu Apr 5 11:44:26 PDT 2012
From: Jerome Glisse <jglisse at redhat.com>
Move buffer object move logic inside driver callback so we don't
have complex move_notify and cache_invalidate callback in error
path. This simplify driver at the expense of some code duplication
among drivers.
Signed-off-by: Jerome Glisse <jglisse at redhat.com>
---
drivers/gpu/drm/nouveau/nouveau_bo.c | 318 ++++++++++++++++++++------------
drivers/gpu/drm/radeon/radeon_ttm.c | 277 +++++++++++++++++-----------
drivers/gpu/drm/ttm/ttm_bo.c | 87 ++--------
drivers/gpu/drm/ttm/ttm_tt.c | 2 +
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 67 +++++++-
include/drm/ttm/ttm_bo_driver.h | 37 ++--
6 files changed, 472 insertions(+), 316 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 6f18c3b..2ddeb0f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -39,6 +39,18 @@
#include <linux/log2.h>
#include <linux/slab.h>
+/* gcc should kill that code */
+#if 1
+#define ASSERT(expr) \
+ if (!(expr)) { \
+ printk("radeon: assertion failed! %s[%d]: %s\n", \
+ __func__, __LINE__, #expr); \
+ panic("radeon: %s", __func__); \
+ }
+#else
+#define ASSERT(expr) do {} while (0)
+#endif
+
static void
nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
{
@@ -376,13 +388,6 @@ nouveau_ttm_tt_create(struct ttm_bo_device *bdev,
}
static int
-nouveau_bo_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
-{
- /* We'll do this from user space. */
- return 0;
-}
-
-static int
nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
struct ttm_mem_type_manager *man)
{
@@ -467,7 +472,6 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
static int
nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
struct nouveau_bo *nvbo, bool evict,
- bool no_wait_reserve, bool no_wait_gpu,
struct ttm_mem_reg *new_mem)
{
struct nouveau_fence *fence = NULL;
@@ -687,8 +691,7 @@ nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
}
static int
-nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
- bool no_wait_reserve, bool no_wait_gpu,
+nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
struct ttm_mem_reg *new_mem)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
@@ -727,9 +730,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
else
ret = nvc0_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
if (ret == 0) {
- ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict,
- no_wait_reserve,
- no_wait_gpu, new_mem);
+ ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict, new_mem);
}
out:
@@ -738,73 +739,6 @@ out:
return ret;
}
-static int
-nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
- bool no_wait_reserve, bool no_wait_gpu,
- struct ttm_mem_reg *new_mem)
-{
- u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
- struct ttm_placement placement;
- struct ttm_mem_reg tmp_mem;
- int ret;
-
- placement.fpfn = placement.lpfn = 0;
- placement.num_placement = placement.num_busy_placement = 1;
- placement.placement = placement.busy_placement = &placement_memtype;
-
- tmp_mem = *new_mem;
- tmp_mem.mm_node = NULL;
- ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, intr, no_wait_reserve, no_wait_gpu);
- if (ret)
- return ret;
-
- ret = ttm_tt_bind(bo->ttm, &tmp_mem);
- if (ret)
- goto out;
-
- ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem);
- if (ret)
- goto out;
-
- ret = ttm_bo_move_ttm(bo, new_mem);
-out:
- ttm_bo_mem_put(bo, &tmp_mem);
- return ret;
-}
-
-static int
-nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
- bool no_wait_reserve, bool no_wait_gpu,
- struct ttm_mem_reg *new_mem)
-{
- u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
- struct ttm_placement placement;
- struct ttm_mem_reg tmp_mem;
- int ret;
-
- placement.fpfn = placement.lpfn = 0;
- placement.num_placement = placement.num_busy_placement = 1;
- placement.placement = placement.busy_placement = &placement_memtype;
-
- tmp_mem = *new_mem;
- tmp_mem.mm_node = NULL;
- ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, intr, no_wait_reserve, no_wait_gpu);
- if (ret)
- return ret;
-
- ret = ttm_bo_move_ttm(bo, &tmp_mem);
- if (ret)
- goto out;
-
- ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, new_mem);
- if (ret)
- goto out;
-
-out:
- ttm_bo_mem_put(bo, &tmp_mem);
- return ret;
-}
-
static void
nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
{
@@ -865,59 +799,215 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
}
static int
-nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
- bool no_wait_reserve, bool no_wait_gpu,
- struct ttm_mem_reg *new_mem)
+nouveau_bo_move_vram_vram(struct ttm_buffer_object *bo,
+ bool evict,
+ struct ttm_mem_reg *new_mem)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
- struct nouveau_bo *nvbo = nouveau_bo(bo);
- struct ttm_mem_reg *old_mem = &bo->mem;
- struct nouveau_tile_reg *new_tile = NULL;
- int ret = 0;
+ int r;
- if (dev_priv->card_type < NV_50) {
- ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
- if (ret)
- return ret;
+ if (!dev_priv->channel) {
+ /* Software copy if the card isn't up and running yet. */
+ goto memcpy;
}
- /* Fake bo copy. */
- if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
- BUG_ON(bo->mem.mm_node != NULL);
- bo->mem = *new_mem;
- new_mem->mm_node = NULL;
- goto out;
+ r = nouveau_bo_move_m2mf(bo, evict, new_mem);
+ if (!r) {
+ return 0;
+ }
+
+memcpy:
+ /* fallback to memcpy */
+ return ttm_bo_move_memcpy(bo, new_mem);
+}
+
+static int
+nouveau_bo_move_ram_vram(struct ttm_buffer_object *bo,
+ bool evict, bool interruptible,
+ bool no_wait_reserve, bool no_wait_gpu,
+ struct ttm_mem_reg *new_mem)
+{
+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+ struct ttm_mem_reg *old_mem = &bo->mem;
+ struct ttm_mem_reg *dst_mem = new_mem;
+ struct ttm_mem_reg tmp_mem = { 0 };
+ int r;
+
+ nouveau_bo_move_ntfy(bo, new_mem);
+
+ /* new memory placement needs ttm */
+ if (bo->ttm == NULL) {
+ if (new_mem->mem_type == TTM_PL_VRAM) {
+ /* it's new bo bound to vram */
+ BUG_ON(bo->mem.mm_node != NULL);
+ bo->mem = *new_mem;
+ new_mem->mm_node = NULL;
+ return 0;
+ }
+
+ r = ttm_bo_add_tt(bo, false);
+ if (r) {
+ return r;
+ }
}
- /* Software copy if the card isn't up and running yet. */
if (!dev_priv->channel) {
- ret = ttm_bo_move_memcpy(bo, new_mem);
- goto out;
+ /* Software copy if the card isn't up and running yet. */
+ goto memcpy;
}
- /* Hardware assisted copy. */
- if (new_mem->mem_type == TTM_PL_SYSTEM)
- ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem);
- else if (old_mem->mem_type == TTM_PL_SYSTEM)
- ret = nouveau_bo_move_flips(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem);
- else
- ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem);
+ if (old_mem->mem_type == TTM_PL_SYSTEM || new_mem->mem_type == TTM_PL_SYSTEM) {
+ /* we need to use a temporary gtt memory to perform the blit */
+ struct ttm_placement placement;
+ u32 placements;
+
+ tmp_mem = *new_mem;
+ tmp_mem.mm_node = NULL;
+ placement.fpfn = 0;
+ placement.lpfn = 0;
+ placement.num_placement = 1;
+ placement.placement = &placements;
+ placement.num_busy_placement = 1;
+ placement.busy_placement = &placements;
+ placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
+ r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait_reserve, no_wait_gpu);
+ if (r) {
+ return r;
+ }
+ if (old_mem->mem_type == TTM_PL_SYSTEM) {
+ r = ttm_bo_move_ttm(bo, &tmp_mem);
+ if (r) {
+ goto out;
+ }
+ } else {
+ r = ttm_tt_bind(bo->ttm, &tmp_mem);
+ if (r) {
+ goto out;
+ }
+ dst_mem = &tmp_mem;
+ }
+ }
- if (!ret)
+ r = nouveau_bo_move_m2mf(bo, evict, new_mem);
+ if (r) {
+memcpy:
+ /* fallback to memcpy */
+ r = ttm_bo_move_memcpy(bo, dst_mem);
+ }
+ if (r) {
goto out;
+ }
- /* Fallback to software copy. */
- ret = ttm_bo_move_memcpy(bo, new_mem);
+ if (new_mem->mem_type == TTM_PL_SYSTEM) {
+ /* dst mem is temporary gtt mem, move to final system placement */
+ ttm_bo_move_ttm(bo, new_mem);
+ }
out:
+ if (r && old_mem->mem_type == TTM_PL_VRAM && bo->ttm) {
+ ttm_tt_destroy(bo->ttm);
+ bo->ttm = NULL;
+ }
+ ttm_bo_mem_put(bo, &tmp_mem);
+ return r;
+}
+
+static int
+nouveau_bo_move_sys_gtt(struct ttm_buffer_object *bo,
+ struct ttm_mem_reg *new_mem)
+{
+ int r;
+
+ /* new memory placement needs ttm */
+ if (bo->ttm == NULL) {
+ r = ttm_bo_add_tt(bo, 1);
+ if (r) {
+ return r;
+ }
+ }
+
+ r = ttm_tt_set_placement_caching(bo->ttm, new_mem->placement);
+ if (r) {
+ return r;
+ }
+
+ if (new_mem->mem_type == TTM_PL_TT) {
+ r = ttm_tt_bind(bo->ttm, new_mem);
+ if (r) {
+ return r;
+ }
+ }
+
+ bo->mem = *new_mem;
+ new_mem->mm_node = NULL;
+ return 0;
+}
+
+static int
+nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
+ bool no_wait_reserve, bool no_wait_gpu,
+ struct ttm_mem_reg *new_mem)
+{
+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+ struct ttm_mem_reg *old_mem = &bo->mem;
+ struct nouveau_bo *nvbo = nouveau_bo(bo);
+ struct nouveau_tile_reg *new_tile = NULL;
+ int r = -EINVAL;
+
+ /* this rely on the following */
+ ASSERT(TTM_PL_SYSTEM == 0);
+ ASSERT(TTM_PL_TT == 1);
+ ASSERT(TTM_PL_VRAM == 2);
+
+ /* bo is evicted before destruction */
+ if (new_mem == NULL && evict) {
+ nouveau_bo_move_ntfy(bo, NULL);
+ return 0;
+ }
+
if (dev_priv->card_type < NV_50) {
- if (ret)
+ r = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
+ if (r) {
+ return r;
+ }
+ }
+
+ nouveau_bo_move_ntfy(bo, new_mem);
+
+ switch ((old_mem->mem_type & 3) | ((new_mem->mem_type & 3) << 2)) {
+ case 0: /* SYSTEM -> SYSTEM */
+ case 1: /* TT -> SYSTEM */
+ case 4: /* SYSTEM -> TT */
+ case 5: /* TT -> TT */
+ r = nouveau_bo_move_sys_gtt(bo, new_mem);
+ break;
+ case 2: /* VRAM -> SYSTEM */
+ case 6: /* VRAM -> TT */
+ case 8: /* SYSTEM -> VRAM */
+ case 9: /* TT -> VRAM */
+ r = nouveau_bo_move_ram_vram(bo, evict, intr,
+ no_wait_reserve, no_wait_gpu,
+ new_mem);
+ break;
+ case 10: /* VRAM -> VRAM */
+ r = nouveau_bo_move_vram_vram(bo, evict, new_mem);
+ break;
+ default:
+ DRM_ERROR("invalid move src %d / dst %d\n",
+ old_mem->mem_type, new_mem->mem_type);
+ return -EINVAL;
+ }
+
+ if (dev_priv->card_type < NV_50) {
+ if (r) {
nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
- else
+ nouveau_bo_move_ntfy(bo, old_mem);
+ } else {
nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
+ }
}
- return ret;
+ return r;
}
static int
@@ -1142,10 +1232,8 @@ struct ttm_bo_driver nouveau_bo_driver = {
.ttm_tt_create = &nouveau_ttm_tt_create,
.ttm_tt_populate = &nouveau_ttm_tt_populate,
.ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate,
- .invalidate_caches = nouveau_bo_invalidate_caches,
.init_mem_type = nouveau_bo_init_mem_type,
.evict_flags = nouveau_bo_evict_flags,
- .move_notify = nouveau_bo_move_ntfy,
.move = nouveau_bo_move,
.verify_access = nouveau_bo_verify_access,
.sync_obj_signaled = __nouveau_fence_signalled,
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 65b4d2f..7a5a739 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -43,6 +43,18 @@
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+/* gcc should kill that code */
+#if 1
+#define ASSERT(expr) \
+ if (!(expr)) { \
+ printk("radeon: assertion failed! %s[%d]: %s\n", \
+ __func__, __LINE__, #expr); \
+ panic("radeon: %s", __func__); \
+ }
+#else
+#define ASSERT(expr) do {} while (0)
+#endif
+
static int radeon_ttm_debugfs_init(struct radeon_device *rdev);
static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev)
@@ -114,11 +126,6 @@ static void radeon_ttm_global_fini(struct radeon_device *rdev)
}
}
-static int radeon_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
-{
- return 0;
-}
-
static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
struct ttm_mem_type_manager *man)
{
@@ -215,10 +222,9 @@ static void radeon_move_null(struct ttm_buffer_object *bo,
new_mem->mm_node = NULL;
}
-static int radeon_move_blit(struct ttm_buffer_object *bo,
- bool evict, int no_wait_reserve, bool no_wait_gpu,
- struct ttm_mem_reg *new_mem,
- struct ttm_mem_reg *old_mem)
+static int radeon_move_blit(struct ttm_buffer_object *bo, bool evict,
+ struct ttm_mem_reg *new_mem,
+ struct ttm_mem_reg *old_mem)
{
struct radeon_device *rdev;
uint64_t old_start, new_start;
@@ -301,135 +307,198 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
return r;
}
-static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
- bool evict, bool interruptible,
- bool no_wait_reserve, bool no_wait_gpu,
- struct ttm_mem_reg *new_mem)
+static int radeon_bo_move_vram_vram(struct ttm_buffer_object *bo,
+ bool evict, struct ttm_mem_reg *new_mem)
{
- struct radeon_device *rdev;
struct ttm_mem_reg *old_mem = &bo->mem;
- struct ttm_mem_reg tmp_mem;
- u32 placements;
- struct ttm_placement placement;
+ struct radeon_device *rdev;
int r;
rdev = radeon_get_rdev(bo->bdev);
- tmp_mem = *new_mem;
- tmp_mem.mm_node = NULL;
- placement.fpfn = 0;
- placement.lpfn = 0;
- placement.num_placement = 1;
- placement.placement = &placements;
- placement.num_busy_placement = 1;
- placement.busy_placement = &placements;
- placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
- r = ttm_bo_mem_space(bo, &placement, &tmp_mem,
- interruptible, no_wait_reserve, no_wait_gpu);
- if (unlikely(r)) {
- return r;
- }
- r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement);
- if (unlikely(r)) {
- goto out_cleanup;
+ if (!rdev->ring[radeon_copy_ring_index(rdev)].ready ||
+ rdev->asic->copy.copy == NULL) {
+ /* use memcpy */
+ goto memcpy;
}
- r = ttm_tt_bind(bo->ttm, &tmp_mem);
- if (unlikely(r)) {
- goto out_cleanup;
+ r = radeon_move_blit(bo, evict, new_mem, old_mem);
+ if (!r) {
+ /* blit succesfull */
+ radeon_bo_move_notify(bo, new_mem);
+ return 0;
}
- r = radeon_move_blit(bo, true, no_wait_reserve, no_wait_gpu, &tmp_mem, old_mem);
- if (unlikely(r)) {
- goto out_cleanup;
+
+memcpy:
+ /* fallback to memcpy */
+ r = ttm_bo_move_memcpy(bo, new_mem);
+ if (!r) {
+ radeon_bo_move_notify(bo, new_mem);
}
- r = ttm_bo_move_ttm(bo, new_mem);
-out_cleanup:
- ttm_bo_mem_put(bo, &tmp_mem);
return r;
}
-static int radeon_move_ram_vram(struct ttm_buffer_object *bo,
- bool evict, bool interruptible,
- bool no_wait_reserve, bool no_wait_gpu,
- struct ttm_mem_reg *new_mem)
+static int radeon_bo_move_ram_vram(struct ttm_buffer_object *bo,
+ bool evict, bool interruptible,
+ bool no_wait_reserve, bool no_wait_gpu,
+ struct ttm_mem_reg *new_mem)
{
- struct radeon_device *rdev;
struct ttm_mem_reg *old_mem = &bo->mem;
- struct ttm_mem_reg tmp_mem;
- struct ttm_placement placement;
- u32 placements;
+ struct ttm_mem_reg *dst_mem = new_mem;
+ struct ttm_mem_reg tmp_mem = { 0 };
+ struct radeon_device *rdev;
int r;
rdev = radeon_get_rdev(bo->bdev);
- tmp_mem = *new_mem;
- tmp_mem.mm_node = NULL;
- placement.fpfn = 0;
- placement.lpfn = 0;
- placement.num_placement = 1;
- placement.placement = &placements;
- placement.num_busy_placement = 1;
- placement.busy_placement = &placements;
- placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
- r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait_reserve, no_wait_gpu);
- if (unlikely(r)) {
- return r;
+
+ /* new memory placement needs ttm */
+ if (bo->ttm == NULL) {
+ if (new_mem->mem_type == TTM_PL_VRAM) {
+ /* it's new bo bound to vram */
+ radeon_move_null(bo, new_mem);
+ return 0;
+ }
+
+ r = ttm_bo_add_tt(bo, false);
+ if (r) {
+ return r;
+ }
}
- r = ttm_bo_move_ttm(bo, &tmp_mem);
- if (unlikely(r)) {
- goto out_cleanup;
+
+ if (!rdev->ring[radeon_copy_ring_index(rdev)].ready ||
+ rdev->asic->copy.copy == NULL) {
+ /* use memcpy */
+ goto memcpy;
}
- r = radeon_move_blit(bo, true, no_wait_reserve, no_wait_gpu, new_mem, old_mem);
- if (unlikely(r)) {
- goto out_cleanup;
+
+ if (old_mem->mem_type == TTM_PL_SYSTEM || new_mem->mem_type == TTM_PL_SYSTEM) {
+ /* we need to use a temporary gtt memory to perform the blit */
+ struct ttm_placement placement;
+ u32 placements;
+
+ tmp_mem = *new_mem;
+ tmp_mem.mm_node = NULL;
+ placement.fpfn = 0;
+ placement.lpfn = 0;
+ placement.num_placement = 1;
+ placement.placement = &placements;
+ placement.num_busy_placement = 1;
+ placement.busy_placement = &placements;
+ placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
+ r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait_reserve, no_wait_gpu);
+ if (r) {
+ return r;
+ }
+ if (old_mem->mem_type == TTM_PL_SYSTEM) {
+ r = ttm_bo_move_ttm(bo, &tmp_mem);
+ if (r) {
+ goto out;
+ }
+ } else {
+ r = ttm_tt_bind(bo->ttm, &tmp_mem);
+ if (r) {
+ goto out;
+ }
+ dst_mem = &tmp_mem;
+ }
+ }
+
+ r = radeon_move_blit(bo, evict, dst_mem, old_mem);
+ if (r) {
+memcpy:
+ /* fallback to memcpy */
+ r = ttm_bo_move_memcpy(bo, dst_mem);
+ }
+ if (r) {
+ goto out;
+ }
+ radeon_bo_move_notify(bo, new_mem);
+
+ if (new_mem->mem_type == TTM_PL_SYSTEM) {
+ /* dst mem is temporary gtt mem, move to final system placement */
+ ttm_bo_move_ttm(bo, new_mem);
+ }
+
+out:
+ if (r && old_mem->mem_type == TTM_PL_VRAM && bo->ttm) {
+ ttm_tt_destroy(bo->ttm);
+ bo->ttm = NULL;
}
-out_cleanup:
ttm_bo_mem_put(bo, &tmp_mem);
return r;
}
+static int radeon_bo_move_sys_gtt(struct ttm_buffer_object *bo,
+ struct ttm_mem_reg *new_mem)
+{
+ int r;
+
+ /* new memory placement needs ttm */
+ if (bo->ttm == NULL) {
+ r = ttm_bo_add_tt(bo, 1);
+ if (r) {
+ return r;
+ }
+ }
+
+ r = ttm_tt_set_placement_caching(bo->ttm, new_mem->placement);
+ if (r) {
+ return r;
+ }
+
+ if (new_mem->mem_type == TTM_PL_TT) {
+ r = ttm_tt_bind(bo->ttm, new_mem);
+ if (r) {
+ return r;
+ }
+ }
+
+ radeon_move_null(bo, new_mem);
+ radeon_bo_move_notify(bo, new_mem);
+ return 0;
+}
+
static int radeon_bo_move(struct ttm_buffer_object *bo,
bool evict, bool interruptible,
bool no_wait_reserve, bool no_wait_gpu,
struct ttm_mem_reg *new_mem)
{
- struct radeon_device *rdev;
struct ttm_mem_reg *old_mem = &bo->mem;
- int r;
+ int r = -EINVAL;
- rdev = radeon_get_rdev(bo->bdev);
- if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
- radeon_move_null(bo, new_mem);
- return 0;
- }
- if ((old_mem->mem_type == TTM_PL_TT &&
- new_mem->mem_type == TTM_PL_SYSTEM) ||
- (old_mem->mem_type == TTM_PL_SYSTEM &&
- new_mem->mem_type == TTM_PL_TT)) {
- /* bind is enough */
- radeon_move_null(bo, new_mem);
- return 0;
- }
- if (!rdev->ring[radeon_copy_ring_index(rdev)].ready ||
- rdev->asic->copy.copy == NULL) {
- /* use memcpy */
- goto memcpy;
- }
+ /* this rely on the following */
+ ASSERT(TTM_PL_SYSTEM == 0);
+ ASSERT(TTM_PL_TT == 1);
+ ASSERT(TTM_PL_VRAM == 2);
- if (old_mem->mem_type == TTM_PL_VRAM &&
- new_mem->mem_type == TTM_PL_SYSTEM) {
- r = radeon_move_vram_ram(bo, evict, interruptible,
- no_wait_reserve, no_wait_gpu, new_mem);
- } else if (old_mem->mem_type == TTM_PL_SYSTEM &&
- new_mem->mem_type == TTM_PL_VRAM) {
- r = radeon_move_ram_vram(bo, evict, interruptible,
- no_wait_reserve, no_wait_gpu, new_mem);
- } else {
- r = radeon_move_blit(bo, evict, no_wait_reserve, no_wait_gpu, new_mem, old_mem);
+ /* bo is evicted before destruction */
+ if (new_mem == NULL && evict) {
+ radeon_bo_move_notify(bo, NULL);
+ return 0;
}
- if (r) {
-memcpy:
- r = ttm_bo_move_memcpy(bo, new_mem);
+ switch ((old_mem->mem_type & 3) | ((new_mem->mem_type & 3) << 2)) {
+ case 0: /* SYSTEM -> SYSTEM */
+ case 1: /* TT -> SYSTEM */
+ case 4: /* SYSTEM -> TT */
+ case 5: /* TT -> TT */
+ r = radeon_bo_move_sys_gtt(bo, new_mem);
+ break;
+ case 2: /* VRAM -> SYSTEM */
+ case 6: /* VRAM -> TT */
+ case 8: /* SYSTEM -> VRAM */
+ case 9: /* TT -> VRAM */
+ r = radeon_bo_move_ram_vram(bo, evict, interruptible,
+ no_wait_reserve, no_wait_gpu,
+ new_mem);
+ break;
+ case 10: /* VRAM -> VRAM */
+ r = radeon_bo_move_vram_vram(bo, evict, new_mem);
+ break;
+ default:
+ DRM_ERROR("invalid move src %d / dst %d\n",
+ old_mem->mem_type, new_mem->mem_type);
+ return -EINVAL;
}
return r;
}
@@ -687,7 +756,6 @@ static struct ttm_bo_driver radeon_bo_driver = {
.ttm_tt_create = &radeon_ttm_tt_create,
.ttm_tt_populate = &radeon_ttm_tt_populate,
.ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate,
- .invalidate_caches = &radeon_invalidate_caches,
.init_mem_type = &radeon_init_mem_type,
.evict_flags = &radeon_evict_flags,
.move = &radeon_bo_move,
@@ -697,7 +765,6 @@ static struct ttm_bo_driver radeon_bo_driver = {
.sync_obj_flush = &radeon_sync_obj_flush,
.sync_obj_unref = &radeon_sync_obj_unref,
.sync_obj_ref = &radeon_sync_obj_ref,
- .move_notify = &radeon_bo_move_notify,
.fault_reserve_notify = &radeon_bo_fault_reserve_notify,
.io_mem_reserve = &radeon_ttm_io_mem_reserve,
.io_mem_free = &radeon_ttm_io_mem_free,
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index f2aa2e2..1e58a54 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -320,7 +320,7 @@ EXPORT_SYMBOL(ttm_bo_unreserve);
/*
* Call bo->mutex locked.
*/
-static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
+int ttm_bo_add_tt(struct ttm_buffer_object *bo, bool zero_alloc)
{
struct ttm_bo_device *bdev = bo->bdev;
struct ttm_bo_global *glob = bo->glob;
@@ -351,6 +351,7 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
return ret;
}
+EXPORT_SYMBOL(ttm_bo_add_tt);
static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem,
@@ -361,99 +362,38 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
bool old_is_pci = ttm_mem_reg_is_pci(bdev, &bo->mem);
bool new_is_pci = ttm_mem_reg_is_pci(bdev, mem);
struct ttm_mem_type_manager *old_man = &bdev->man[bo->mem.mem_type];
- struct ttm_mem_type_manager *new_man = &bdev->man[mem->mem_type];
int ret = 0;
if (old_is_pci || new_is_pci ||
((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) {
ret = ttm_mem_io_lock(old_man, true);
- if (unlikely(ret != 0))
- goto out_err;
+ if (unlikely(ret != 0)) {
+ return ret;
+ }
ttm_bo_unmap_virtual_locked(bo);
ttm_mem_io_unlock(old_man);
}
- /*
- * Create and bind a ttm if required.
- */
-
- if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
- if (bo->ttm == NULL) {
- bool zero = !(old_man->flags & TTM_MEMTYPE_FLAG_FIXED);
- ret = ttm_bo_add_ttm(bo, zero);
- if (ret)
- goto out_err;
- }
-
- ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement);
- if (ret)
- goto out_err;
-
- if (mem->mem_type != TTM_PL_SYSTEM) {
- ret = ttm_tt_bind(bo->ttm, mem);
- if (ret)
- goto out_err;
- }
-
- if (bo->mem.mem_type == TTM_PL_SYSTEM) {
- if (bdev->driver->move_notify)
- bdev->driver->move_notify(bo, mem);
- bo->mem = *mem;
- mem->mm_node = NULL;
- goto moved;
- }
- }
-
- if (bdev->driver->move_notify)
- bdev->driver->move_notify(bo, mem);
-
- if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
- !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
- ret = ttm_bo_move_ttm(bo, mem);
- else if (bdev->driver->move)
- ret = bdev->driver->move(bo, evict, interruptible,
- no_wait_reserve, no_wait_gpu, mem);
- else
- ret = ttm_bo_move_memcpy(bo, mem);
+ ret = bdev->driver->move(bo, evict, interruptible,
+ no_wait_reserve, no_wait_gpu, mem);
if (ret) {
- if (bdev->driver->move_notify) {
- struct ttm_mem_reg tmp_mem = *mem;
- *mem = bo->mem;
- bo->mem = tmp_mem;
- bdev->driver->move_notify(bo, mem);
- bo->mem = *mem;
- }
-
- goto out_err;
+ return ret;
}
-moved:
if (bo->evicted) {
- ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
- if (ret)
- pr_err("Can not flush read caches\n");
bo->evicted = false;
}
if (bo->mem.mm_node) {
bo->offset = (bo->mem.start << PAGE_SHIFT) +
- bdev->man[bo->mem.mem_type].gpu_offset;
+ bdev->man[bo->mem.mem_type].gpu_offset;
bo->cur_placement = bo->mem.placement;
- } else
+ } else {
bo->offset = 0;
-
- return 0;
-
-out_err:
- new_man = &bdev->man[bo->mem.mem_type];
- if ((new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm) {
- ttm_tt_unbind(bo->ttm);
- ttm_tt_destroy(bo->ttm);
- bo->ttm = NULL;
}
- return ret;
+ return 0;
}
/**
@@ -466,8 +406,7 @@ out_err:
static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
{
- if (bo->bdev->driver->move_notify)
- bo->bdev->driver->move_notify(bo, NULL);
+ bo->bdev->driver->move(bo, true, true, false, false, NULL);
if (bo->ttm) {
ttm_tt_unbind(bo->ttm);
@@ -1142,7 +1081,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
* We might need to add a TTM.
*/
if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
- ret = ttm_bo_add_ttm(bo, true);
+ ret = ttm_bo_add_tt(bo, true);
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 8aafeef..000e3d6 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -181,6 +181,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
ttm->swap_storage = NULL;
ttm->func->destroy(ttm);
}
+EXPORT_SYMBOL(ttm_tt_destroy);
int ttm_tt_init(struct ttm_tt *ttm, struct ttm_bo_device *bdev,
unsigned long size, uint32_t page_flags,
@@ -259,6 +260,7 @@ void ttm_tt_unbind(struct ttm_tt *ttm)
ttm->state = tt_unbound;
}
}
+EXPORT_SYMBOL(ttm_tt_unbind);
int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
{
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
index 1e2c0fb..fa5e380 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -335,21 +335,82 @@ static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
VMW_FENCE_WAIT_TIMEOUT);
}
+static int vmw_bo_move(struct ttm_buffer_object *bo,
+ bool evict, bool interruptible,
+ bool no_wait_reserve, bool no_wait_gpu,
+ struct ttm_mem_reg *new_mem)
+{
+ struct ttm_mem_type_manager *old_man = &bo->bdev->man[bo->mem.mem_type];
+ struct ttm_mem_type_manager *new_man = &bo->bdev->man[new_mem->mem_type];
+ int ret;
+
+ /* bo is evicted before destruction */
+ if (new_mem == NULL && evict) {
+ return 0;
+ }
+
+ /*
+ * Create and bind a ttm if required.
+ */
+ if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
+ if (bo->ttm == NULL) {
+ bool zero = !(old_man->flags & TTM_MEMTYPE_FLAG_FIXED);
+ ret = ttm_bo_add_tt(bo, zero);
+ if (ret)
+ goto out_err;
+ }
+
+ ret = ttm_tt_set_placement_caching(bo->ttm, new_mem->placement);
+ if (ret) {
+ goto out_err;
+ }
+
+ if (new_mem->mem_type != TTM_PL_SYSTEM) {
+ ret = ttm_tt_bind(bo->ttm, new_mem);
+ if (ret)
+ goto out_err;
+ }
+
+ if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+ bo->mem = *new_mem;
+ new_mem->mm_node = NULL;
+ return 0;
+ }
+ }
+
+ if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
+ !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
+ ret = ttm_bo_move_ttm(bo, new_mem);
+ } else {
+ ret = ttm_bo_move_memcpy(bo, new_mem);
+ }
+ if (ret) {
+ goto out_err;
+ }
+ return 0;
+
+out_err:
+ new_man = &bo->bdev->man[bo->mem.mem_type];
+ if ((new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm) {
+ ttm_tt_destroy(bo->ttm);
+ bo->ttm = NULL;
+ }
+ return ret;
+}
+
struct ttm_bo_driver vmw_bo_driver = {
.ttm_tt_create = &vmw_ttm_tt_create,
.ttm_tt_populate = &ttm_pool_populate,
.ttm_tt_unpopulate = &ttm_pool_unpopulate,
- .invalidate_caches = vmw_invalidate_caches,
.init_mem_type = vmw_init_mem_type,
.evict_flags = vmw_evict_flags,
- .move = NULL,
+ .move = vmw_bo_move,
.verify_access = vmw_verify_access,
.sync_obj_signaled = vmw_sync_obj_signaled,
.sync_obj_wait = vmw_sync_obj_wait,
.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,
.fault_reserve_notify = &vmw_ttm_fault_reserve_notify,
.io_mem_reserve = &vmw_ttm_io_mem_reserve,
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 47f6f9d..a30be54 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -353,21 +353,9 @@ struct ttm_bo_driver {
*/
void (*ttm_tt_unpopulate)(struct ttm_tt *ttm);
- /**
- * struct ttm_bo_driver member invalidate_caches
- *
- * @bdev: the buffer object device.
- * @flags: new placement of the rebound buffer object.
- *
- * A previosly evicted buffer has been rebound in a
- * potentially new location. Tell the driver that it might
- * consider invalidating read (texture) caches on the next command
- * submission as a consequence.
- */
-
- int (*invalidate_caches) (struct ttm_bo_device *bdev, uint32_t flags);
int (*init_mem_type) (struct ttm_bo_device *bdev, uint32_t type,
struct ttm_mem_type_manager *man);
+
/**
* struct ttm_bo_driver member evict_flags:
*
@@ -377,9 +365,9 @@ struct ttm_bo_driver {
* These will be placed in proposed_flags so that when the move is
* finished, they'll end up in bo->mem.flags
*/
-
void(*evict_flags) (struct ttm_buffer_object *bo,
struct ttm_placement *placement);
+
/**
* struct ttm_bo_driver member move:
*
@@ -430,10 +418,6 @@ struct ttm_bo_driver {
void (*sync_obj_unref) (void **sync_obj);
void *(*sync_obj_ref) (void *sync_obj);
- /* hook to notify driver about a driver move so it
- * can do tiling things */
- void (*move_notify)(struct ttm_buffer_object *bo,
- struct ttm_mem_reg *new_mem);
/* notify the driver we are taking a fault on this BO
* and have reserved it */
int (*fault_reserve_notify)(struct ttm_buffer_object *bo);
@@ -628,7 +612,7 @@ extern void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma);
extern int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem);
/**
- * ttm_ttm_destroy:
+ * ttm_tt_destroy:
*
* @ttm: The struct ttm_tt.
*
@@ -688,6 +672,21 @@ extern int ttm_tt_swapout(struct ttm_tt *ttm,
*/
/**
+ * ttm_bo_add_tt
+ *
+ * @bo: Pointer to a struct ttm_buffer_object. the data of which
+ * @zero: Allocate page cleared to zero or not.
+ *
+ * Allocate tt the buffer object pointed to by @bo.
+ *
+ * Returns:
+ * -EINVAL: Invalid buffer object type.
+ * -ENOMEM: Could not allocate tt for the buffer object.
+ */
+extern int ttm_bo_add_tt(struct ttm_buffer_object *bo, bool zero_alloc);
+
+
+/**
* ttm_mem_reg_is_pci
*
* @bdev: Pointer to a struct ttm_bo_device.
--
1.7.7.6
More information about the dri-devel
mailing list