Skip to content

Commit

Permalink
drm/nv50: implement global channel address space on new VM code
Browse files Browse the repository at this point in the history
As of this commit, it's guaranteed that if an object is in VRAM that its
GPU virtual address will be constant.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Dec 8, 2010
1 parent f869ef8 commit 4c13614
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 216 deletions.
41 changes: 25 additions & 16 deletions drivers/gpu/drm/nouveau/nouveau_bo.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
DRM_ERROR("bo %p still attached to GEM object\n", bo);

nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
nouveau_vm_put(&nvbo->vma);
kfree(nvbo);
}

Expand Down Expand Up @@ -113,6 +114,15 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
&align, &size);
align >>= PAGE_SHIFT;

if (!nvbo->no_vm && dev_priv->chan_vm) {
ret = nouveau_vm_get(dev_priv->chan_vm, size, 16,
NV_MEM_ACCESS_RW, &nvbo->vma);
if (ret) {
kfree(nvbo);
return ret;
}
}

nouveau_bo_placement_set(nvbo, flags, 0);

nvbo->channel = chan;
Expand All @@ -125,6 +135,11 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
}
nvbo->channel = NULL;

if (nvbo->vma.node) {
if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
nvbo->bo.offset = nvbo->vma.offset;
}

*pnvbo = nvbo;
return 0;
}
Expand Down Expand Up @@ -294,6 +309,11 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
if (ret)
return ret;

if (nvbo->vma.node) {
if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
nvbo->bo.offset = nvbo->vma.offset;
}

return 0;
}

Expand Down Expand Up @@ -400,10 +420,7 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->available_caching = TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_WC;
man->default_caching = TTM_PL_FLAG_WC;
if (dev_priv->card_type == NV_50)
man->gpu_offset = 0x40000000;
else
man->gpu_offset = 0;
man->gpu_offset = 0;
break;
case TTM_PL_TT:
man->func = &ttm_bo_manager_func;
Expand Down Expand Up @@ -507,12 +524,12 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
dst_offset = new_mem->start << PAGE_SHIFT;
if (!nvbo->no_vm) {
if (old_mem->mem_type == TTM_PL_VRAM)
src_offset += dev_priv->vm_vram_base;
src_offset = nvbo->vma.offset;
else
src_offset += dev_priv->vm_gart_base;

if (new_mem->mem_type == TTM_PL_VRAM)
dst_offset += dev_priv->vm_vram_base;
dst_offset = nvbo->vma.offset;
else
dst_offset += dev_priv->vm_gart_base;
}
Expand Down Expand Up @@ -756,7 +773,6 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
struct drm_device *dev = dev_priv->dev;
struct nouveau_bo *nvbo = nouveau_bo(bo);
uint64_t offset;
int ret;

if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
/* Nothing to do. */
Expand All @@ -766,15 +782,8 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,

offset = new_mem->start << PAGE_SHIFT;

if (dev_priv->card_type == NV_50) {
ret = nv50_mem_vm_bind_linear(dev,
offset + dev_priv->vm_vram_base,
new_mem->size,
nouveau_bo_tile_layout(nvbo),
offset);
if (ret)
return ret;

if (dev_priv->chan_vm) {
nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
} else if (dev_priv->card_type >= NV_10) {
*new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
nvbo->tile_mode,
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/nouveau_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)

if (dev_priv->card_type >= NV_50) {
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
dev_priv->vm_end, NV_MEM_ACCESS_RO,
(1ULL << 40), NV_MEM_ACCESS_RO,
NV_MEM_TARGET_VM, &pushbuf);
chan->pushbuf_base = pb->bo.offset;
} else
Expand Down
8 changes: 3 additions & 5 deletions drivers/gpu/drm/nouveau/nouveau_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,11 @@ nouveau_pci_resume(struct pci_dev *pdev)

list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT;

nv_crtc->cursor.set_offset(nv_crtc,
nv_crtc->cursor.nvbo->bo.offset -
dev_priv->vm_vram_base);

nv_crtc->cursor.set_offset(nv_crtc, offset);
nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
nv_crtc->cursor_saved_y);
nv_crtc->cursor_saved_y);
}

/* Force CLUT to get re-loaded during modeset */
Expand Down
17 changes: 2 additions & 15 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ struct nouveau_vram;
#define NOUVEAU_MAX_CHANNEL_NR 128
#define NOUVEAU_MAX_TILE_NR 15

#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL)
#define NV50_VM_BLOCK (512*1024*1024ULL)
#define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)

struct nouveau_vram {
struct drm_device *dev;

Expand Down Expand Up @@ -106,6 +102,7 @@ struct nouveau_bo {

struct nouveau_channel *channel;

struct nouveau_vma vma;
bool mappable;
bool no_vm;

Expand Down Expand Up @@ -252,7 +249,6 @@ struct nouveau_channel {
struct nouveau_vm *vm;
struct nouveau_gpuobj *vm_pd;
struct nouveau_gpuobj *vm_gart_pt;
struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];

/* Objects */
struct nouveau_gpuobj *ramin; /* Private instmem */
Expand Down Expand Up @@ -712,13 +708,9 @@ struct drm_nouveau_private {
struct nouveau_vm *bar3_vm;

/* G8x/G9x virtual address space */
struct nouveau_vm *chan_vm;
uint64_t vm_gart_base;
uint64_t vm_gart_size;
uint64_t vm_vram_base;
uint64_t vm_vram_size;
uint64_t vm_end;
struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
int vm_vram_pt_nr;

struct nvbios vbios;

Expand Down Expand Up @@ -836,11 +828,6 @@ extern struct nouveau_tile_reg *nv10_mem_set_tiling(
extern void nv10_mem_put_tile_region(struct drm_device *dev,
struct nouveau_tile_reg *tile,
struct nouveau_fence *fence);
extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
uint32_t size, uint32_t flags,
uint64_t phys);
extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt,
uint32_t size);
extern const struct ttm_mem_type_manager_func nouveau_vram_manager;

/* nouveau_notifier.c */
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_fbcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
FBINFO_HWACCEL_IMAGEBLIT;
info->flags |= FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &nouveau_fbcon_sw_ops;
info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
dev_priv->vm_vram_base;
info->fix.smem_start = dev->mode_config.fb_base +
(nvbo->bo.mem.start << PAGE_SHIFT);
info->fix.smem_len = size;

info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
Expand Down
94 changes: 0 additions & 94 deletions drivers/gpu/drm/nouveau/nouveau_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,100 +144,6 @@ nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
return found;
}

/*
* NV50 VM helpers
*/
int
nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
uint32_t flags, uint64_t phys)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *pgt;
unsigned block;
int i;

virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
size = (size >> 16) << 1;

phys |= ((uint64_t)flags << 32);
phys |= 1;
if (dev_priv->vram_sys_base) {
phys += dev_priv->vram_sys_base;
phys |= 0x30;
}

while (size) {
unsigned offset_h = upper_32_bits(phys);
unsigned offset_l = lower_32_bits(phys);
unsigned pte, end;

for (i = 7; i >= 0; i--) {
block = 1 << (i + 1);
if (size >= block && !(virt & (block - 1)))
break;
}
offset_l |= (i << 7);

phys += block << 15;
size -= block;

while (block) {
pgt = dev_priv->vm_vram_pt[virt >> 14];
pte = virt & 0x3ffe;

end = pte + block;
if (end > 16384)
end = 16384;
block -= (end - pte);
virt += (end - pte);

while (pte < end) {
nv_wo32(pgt, (pte * 4) + 0, offset_l);
nv_wo32(pgt, (pte * 4) + 4, offset_h);
pte += 2;
}
}
}

dev_priv->engine.instmem.flush(dev);
dev_priv->engine.fifo.tlb_flush(dev);
dev_priv->engine.graph.tlb_flush(dev);
nv50_vm_flush_engine(dev, 6);
return 0;
}

void
nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *pgt;
unsigned pages, pte, end;

virt -= dev_priv->vm_vram_base;
pages = (size >> 16) << 1;

while (pages) {
pgt = dev_priv->vm_vram_pt[virt >> 29];
pte = (virt & 0x1ffe0000ULL) >> 15;

end = pte + pages;
if (end > 16384)
end = 16384;
pages -= (end - pte);
virt += (end - pte) << 15;

while (pte < end) {
nv_wo32(pgt, (pte * 4), 0);
pte++;
}
}

dev_priv->engine.instmem.flush(dev);
dev_priv->engine.fifo.tlb_flush(dev);
dev_priv->engine.graph.tlb_flush(dev);
nv50_vm_flush_engine(dev, 6);
}

/*
* Cleanup everything
*/
Expand Down
Loading

0 comments on commit 4c13614

Please sign in to comment.