summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-09-27 08:55:53 +1000
committerBen Skeggs <bskeggs@redhat.com>2012-10-03 13:13:17 +1000
commite5f186c4f9812eccbc291da6dfe8b15da546f961 (patch)
tree84e667ebbe00bd91e10cff16defaad95b38d85a9
parent8a57d279d6e1bf19d2d2e54f51d4f40c46c7d1a8 (diff)
downloadlwn-e5f186c4f9812eccbc291da6dfe8b15da546f961.tar.gz
lwn-e5f186c4f9812eccbc291da6dfe8b15da546f961.zip
drm/nv44/vm: fix and enable use of "real" pciegart
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 <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv40.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c45
4 files changed, 29 insertions, 41 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
index 320ccc4ae05c..18de4c5b202f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
index ad6ad5de51b8..6adbbc9cc361 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
@@ -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);
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
index e21369cd09c0..ec42d4bc86a6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
@@ -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 *
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
index 8c9cece25e63..0ac18d05a146 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
@@ -23,6 +23,7 @@
*/
#include <core/gpuobj.h>
+#include <core/option.h>
#include <subdev/timer.h>
#include <subdev/vm.h>
@@ -37,16 +38,6 @@
******************************************************************************/
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)
{
@@ -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) {
@@ -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;
@@ -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);
@@ -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);
}
/*******************************************************************************
@@ -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);
@@ -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)