提交 d2f96666 编写于 作者: B Ben Skeggs

drm/nouveau: create temp vmas for both src and dst of bo moves

Greatly simplifies a number of things, particularly once per-client GPU
address spaces are involved.

May add this back later once I know what things'll look like.
Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 f91bac5b
...@@ -496,19 +496,12 @@ static int ...@@ -496,19 +496,12 @@ static int
nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
{ {
struct nouveau_mem *old_node = old_mem->mm_node; struct nouveau_mem *node = old_mem->mm_node;
struct nouveau_mem *new_node = new_mem->mm_node; u64 src_offset = node->vma[0].offset;
struct nouveau_bo *nvbo = nouveau_bo(bo); u64 dst_offset = node->vma[1].offset;
u32 page_count = new_mem->num_pages; u32 page_count = new_mem->num_pages;
u64 src_offset, dst_offset;
int ret; int ret;
src_offset = old_node->tmp_vma.offset;
if (new_node->tmp_vma.node)
dst_offset = new_node->tmp_vma.offset;
else
dst_offset = nvbo->vma.offset;
page_count = new_mem->num_pages; page_count = new_mem->num_pages;
while (page_count) { while (page_count) {
int line_count = (page_count > 2047) ? 2047 : page_count; int line_count = (page_count > 2047) ? 2047 : page_count;
...@@ -542,19 +535,13 @@ static int ...@@ -542,19 +535,13 @@ static int
nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
{ {
struct nouveau_mem *old_node = old_mem->mm_node; struct nouveau_mem *node = old_mem->mm_node;
struct nouveau_mem *new_node = new_mem->mm_node;
struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_bo *nvbo = nouveau_bo(bo);
u64 length = (new_mem->num_pages << PAGE_SHIFT); u64 length = (new_mem->num_pages << PAGE_SHIFT);
u64 src_offset, dst_offset; u64 src_offset = node->vma[0].offset;
u64 dst_offset = node->vma[1].offset;
int ret; int ret;
src_offset = old_node->tmp_vma.offset;
if (new_node->tmp_vma.node)
dst_offset = new_node->tmp_vma.offset;
else
dst_offset = nvbo->vma.offset;
while (length) { while (length) {
u32 amount, stride, height; u32 amount, stride, height;
...@@ -689,6 +676,27 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, ...@@ -689,6 +676,27 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
return 0; return 0;
} }
static int
nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
struct ttm_mem_reg *mem, struct nouveau_vma *vma)
{
struct nouveau_mem *node = mem->mm_node;
int ret;
ret = nouveau_vm_get(chan->vm, mem->num_pages << PAGE_SHIFT,
node->page_shift, NV_MEM_ACCESS_RO, vma);
if (ret)
return ret;
if (mem->mem_type == TTM_PL_VRAM)
nouveau_vm_map(vma, node);
else
nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT,
node, node->pages);
return 0;
}
static int static int
nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
bool no_wait_reserve, bool no_wait_gpu, bool no_wait_reserve, bool no_wait_gpu,
...@@ -706,31 +714,20 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, ...@@ -706,31 +714,20 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
} }
/* create temporary vma for old memory, this will get cleaned /* create temporary vmas for the transfer and attach them to the
* up after ttm destroys the ttm_mem_reg * old nouveau_mem node, these will get cleaned up after ttm has
* destroyed the ttm_mem_reg
*/ */
if (dev_priv->card_type >= NV_50) { if (dev_priv->card_type >= NV_50) {
struct nouveau_mem *node = old_mem->mm_node; struct nouveau_mem *node = old_mem->mm_node;
if (!node->tmp_vma.node) {
u32 page_shift = nvbo->vma.node->type;
if (old_mem->mem_type == TTM_PL_TT)
page_shift = nvbo->vma.vm->spg_shift;
ret = nouveau_vm_get(chan->vm,
old_mem->num_pages << PAGE_SHIFT,
page_shift, NV_MEM_ACCESS_RO,
&node->tmp_vma);
if (ret)
goto out;
}
if (old_mem->mem_type == TTM_PL_VRAM) ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]);
nouveau_vm_map(&node->tmp_vma, node); if (ret)
else { goto out;
nouveau_vm_map_sg(&node->tmp_vma, 0,
old_mem->num_pages << PAGE_SHIFT, ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]);
node, node->pages); if (ret)
} goto out;
} }
if (dev_priv->card_type < NV_50) if (dev_priv->card_type < NV_50)
...@@ -757,7 +754,6 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, ...@@ -757,7 +754,6 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
bool no_wait_reserve, bool no_wait_gpu, bool no_wait_reserve, bool no_wait_gpu,
struct ttm_mem_reg *new_mem) struct ttm_mem_reg *new_mem)
{ {
struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
struct ttm_placement placement; struct ttm_placement placement;
struct ttm_mem_reg tmp_mem; struct ttm_mem_reg tmp_mem;
...@@ -777,23 +773,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, ...@@ -777,23 +773,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
if (ret) if (ret)
goto out; goto out;
if (dev_priv->card_type >= NV_50) {
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_mem *node = tmp_mem.mm_node;
struct nouveau_vma *vma = &nvbo->vma;
if (vma->node->type != vma->vm->spg_shift)
vma = &node->tmp_vma;
nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT,
node, node->pages);
}
ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem); ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem);
if (dev_priv->card_type >= NV_50) {
struct nouveau_bo *nvbo = nouveau_bo(bo);
nouveau_vm_unmap(&nvbo->vma);
}
if (ret) if (ret)
goto out; goto out;
...@@ -846,21 +826,15 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) ...@@ -846,21 +826,15 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
if (!vma->vm) if (!vma->vm)
return; return;
switch (new_mem->mem_type) { if (new_mem->mem_type == TTM_PL_VRAM) {
case TTM_PL_VRAM: nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
nouveau_vm_map(vma, node); } else
break; if (new_mem->mem_type == TTM_PL_TT &&
case TTM_PL_TT: nvbo->page_shift == nvbo->vma.vm->spg_shift) {
if (vma->node->type != vma->vm->spg_shift) { nouveau_vm_map_sg(&nvbo->vma, 0, new_mem->
nouveau_vm_unmap(vma); num_pages << PAGE_SHIFT, node, node->pages);
vma = &node->tmp_vma; } else {
}
nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT,
node, node->pages);
break;
default:
nouveau_vm_unmap(&nvbo->vma); nouveau_vm_unmap(&nvbo->vma);
break;
} }
} }
......
...@@ -77,7 +77,7 @@ struct nouveau_mem { ...@@ -77,7 +77,7 @@ struct nouveau_mem {
struct drm_device *dev; struct drm_device *dev;
struct nouveau_vma bar_vma; struct nouveau_vma bar_vma;
struct nouveau_vma tmp_vma; struct nouveau_vma vma[2];
u8 page_shift; u8 page_shift;
struct drm_mm_node *tag; struct drm_mm_node *tag;
......
...@@ -762,20 +762,29 @@ nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) ...@@ -762,20 +762,29 @@ nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
return 0; return 0;
} }
static inline void
nouveau_mem_node_cleanup(struct nouveau_mem *node)
{
if (node->vma[0].node) {
nouveau_vm_unmap(&node->vma[0]);
nouveau_vm_put(&node->vma[0]);
}
if (node->vma[1].node) {
nouveau_vm_unmap(&node->vma[1]);
nouveau_vm_put(&node->vma[1]);
}
}
static void static void
nouveau_vram_manager_del(struct ttm_mem_type_manager *man, nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem) struct ttm_mem_reg *mem)
{ {
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
struct nouveau_mem *node = mem->mm_node;
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
if (node->tmp_vma.node) { nouveau_mem_node_cleanup(mem->mm_node);
nouveau_vm_unmap(&node->tmp_vma);
nouveau_vm_put(&node->tmp_vma);
}
vram->put(dev, (struct nouveau_mem **)&mem->mm_node); vram->put(dev, (struct nouveau_mem **)&mem->mm_node);
} }
...@@ -860,15 +869,9 @@ static void ...@@ -860,15 +869,9 @@ static void
nouveau_gart_manager_del(struct ttm_mem_type_manager *man, nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem) struct ttm_mem_reg *mem)
{ {
struct nouveau_mem *node = mem->mm_node; nouveau_mem_node_cleanup(mem->mm_node);
if (node->tmp_vma.node) {
nouveau_vm_unmap(&node->tmp_vma);
nouveau_vm_put(&node->tmp_vma);
}
mem->mm_node = NULL; mem->mm_node = NULL;
kfree(node); kfree(mem->mm_node);
} }
static int static int
...@@ -878,11 +881,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, ...@@ -878,11 +881,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem) struct ttm_mem_reg *mem)
{ {
struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_vma *vma = &nvbo->vma;
struct nouveau_vm *vm = vma->vm;
struct nouveau_mem *node; struct nouveau_mem *node;
int ret;
if (unlikely((mem->num_pages << PAGE_SHIFT) >= if (unlikely((mem->num_pages << PAGE_SHIFT) >=
dev_priv->gart_info.aper_size)) dev_priv->gart_info.aper_size))
...@@ -891,24 +890,8 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, ...@@ -891,24 +890,8 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
node = kzalloc(sizeof(*node), GFP_KERNEL); node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node) if (!node)
return -ENOMEM; return -ENOMEM;
node->page_shift = 12;
/* This node must be for evicting large-paged VRAM
* to system memory. Due to a nv50 limitation of
* not being able to mix large/small pages within
* the same PDE, we need to create a temporary
* small-paged VMA for the eviction.
*/
if (vma->node->type != vm->spg_shift) {
ret = nouveau_vm_get(vm, (u64)vma->node->length << 12,
vm->spg_shift, NV_MEM_ACCESS_RW,
&node->tmp_vma);
if (ret) {
kfree(node);
return ret;
}
}
node->page_shift = nvbo->vma.node->type;
mem->mm_node = node; mem->mm_node = node;
mem->start = 0; mem->start = 0;
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册