Skip to content

Commit

Permalink
drm/nv44/vm: fix and enable use of "real" pciegart
Browse files Browse the repository at this point in the history
Something seems to be missing in regards to flushing specific ranges of
the TLB.  For the moment, flushing the entire thing seems to make it
work alright.

Should give 39-bit DMA addressing on the relevant chipsets.

v2: allocate contig 16KiB for dummy pages, reported by mwk on irc

Signed-off-by: Ben Skeggs <[email protected]>
  • Loading branch information
Ben Skeggs committed Oct 3, 2012
1 parent 8a57d27 commit e5f186c
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 41 deletions.
16 changes: 8 additions & 8 deletions drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand All @@ -238,7 +238,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand All @@ -258,7 +258,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand All @@ -278,7 +278,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand All @@ -298,7 +298,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand All @@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand All @@ -338,7 +338,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand All @@ -358,7 +358,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
Expand Down
7 changes: 3 additions & 4 deletions drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,9 @@ nv04_vmmgr_dtor(struct nouveau_object *object)
nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]);
nouveau_vm_ref(NULL, &priv->vm, NULL);
}
if (priv->page) {
pci_unmap_page(nv_device(priv)->pdev, priv->null,
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
__free_page(priv->page);
if (priv->nullp) {
pci_free_consistent(nv_device(priv)->pdev, 16 * 1024,
priv->nullp, priv->null);
}
nouveau_vmmgr_destroy(&priv->base);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
struct nv04_vmmgr_priv {
struct nouveau_vmmgr base;
struct nouveau_vm *vm;
struct page *page;
dma_addr_t null;
void *nullp;
};

static inline struct nv04_vmmgr_priv *
Expand Down
45 changes: 17 additions & 28 deletions drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include <core/gpuobj.h>
#include <core/option.h>

#include <subdev/timer.h>
#include <subdev/vm.h>
Expand All @@ -36,16 +37,6 @@
* VM map/unmap callbacks
******************************************************************************/

static void
nv44_vm_flush_priv(struct nv04_vmmgr_priv *priv, u32 base, u32 size)
{
nv_wr32(priv, 0x100814, (size - 1) << 12);
nv_wr32(priv, 0x100808, base | 0x20);
if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001))
nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808));
nv_wr32(priv, 0x100808, 0x00000000);
}

static void
nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
dma_addr_t *list, u32 pte, u32 cnt)
Expand All @@ -57,6 +48,7 @@ nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
tmp[1] = nv_ro32(pgt, base + 0x4);
tmp[2] = nv_ro32(pgt, base + 0x8);
tmp[3] = nv_ro32(pgt, base + 0xc);

while (cnt--) {
u32 addr = list ? (*list++ >> 12) : (null >> 12);
switch (pte++ & 0x3) {
Expand Down Expand Up @@ -96,8 +88,6 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{
struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm;
u32 base = pte << 12;
u32 size = cnt;
u32 tmp[4];
int i;

Expand All @@ -122,15 +112,12 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,

if (cnt)
nv44_vm_fill(pgt, priv->null, list, pte, cnt);
nv44_vm_flush_priv(priv, base, size);
}

static void
nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
{
struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt);
u32 base = pte << 12;
u32 size = cnt;

if (pte & 3) {
u32 max = 4 - (pte & 3);
Expand All @@ -150,12 +137,17 @@ nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)

if (cnt)
nv44_vm_fill(pgt, priv->null, NULL, pte, cnt);
nv44_vm_flush_priv(priv, base, size);
}

static void
nv44_vm_flush(struct nouveau_vm *vm)
{
struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
nv_wr32(priv, 0x100814, priv->base.limit - NV44_GART_PAGE);
nv_wr32(priv, 0x100808, 0x00000020);
if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001))
nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808));
nv_wr32(priv, 0x100808, 0x00000000);
}

/*******************************************************************************
Expand All @@ -171,6 +163,11 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv04_vmmgr_priv *priv;
int ret;

if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
data, size, pobject);
}

ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART",
"pciegart", &priv);
*pobject = nv_object(priv);
Expand All @@ -187,20 +184,12 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->base.unmap = nv44_vm_unmap;
priv->base.flush = nv44_vm_flush;

priv->page = alloc_page(GFP_DMA32 | GFP_KERNEL);
if (priv->page) {
priv->null = pci_map_page(device->pdev, priv->page, 0,
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
if (pci_dma_mapping_error(device->pdev, priv->null)) {
__free_page(priv->page);
priv->page = NULL;
priv->null = 0;
}
priv->nullp = pci_alloc_consistent(device->pdev, 16 * 1024, &priv->null);
if (!priv->nullp) {
nv_error(priv, "unable to allocate dummy pages\n");
return -ENOMEM;
}

if (!priv->page)
nv_warn(priv, "unable to allocate dummy page\n");

ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096,
&priv->vm);
if (ret)
Expand Down

0 comments on commit e5f186c

Please sign in to comment.