summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2009-02-22 10:55:29 +1000
committerBen Skeggs <bskeggs@redhat.com>2009-02-22 11:38:41 +1000
commitafac6a4ddc96fc3135c9b18fcc2514393984d536 (patch)
tree7b6ee3e00733675fbff95e1d8072284f9531f249
parentcdba1bf2e4c92f38c8378770594e33aa65a8e897 (diff)
nouveau: hide instmem map, force use of {prepare,finish}_access
-rw-r--r--linux-core/nouveau_sgdma.c10
-rw-r--r--shared-core/nouveau_drv.h13
-rw-r--r--shared-core/nouveau_fifo.c2
-rw-r--r--shared-core/nouveau_irq.c8
-rw-r--r--shared-core/nouveau_mem.c2
-rw-r--r--shared-core/nouveau_object.c63
-rw-r--r--shared-core/nouveau_state.c16
-rw-r--r--shared-core/nv04_fifo.c9
-rw-r--r--shared-core/nv04_instmem.c19
-rw-r--r--shared-core/nv10_fifo.c9
-rw-r--r--shared-core/nv20_graph.c4
-rw-r--r--shared-core/nv40_fifo.c9
-rw-r--r--shared-core/nv40_graph.c2
-rw-r--r--shared-core/nv50_fifo.c10
-rw-r--r--shared-core/nv50_graph.c8
-rw-r--r--shared-core/nv50_instmem.c26
16 files changed, 188 insertions, 22 deletions
diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c
index 16543a90..c7c646f8 100644
--- a/linux-core/nouveau_sgdma.c
+++ b/linux-core/nouveau_sgdma.c
@@ -105,11 +105,13 @@ nouveau_sgdma_bind(struct drm_ttm_backend *be, struct drm_bo_mem_reg *mem)
if (dev_priv->card_type < NV_50)
nvbe->pte_start += 2; /* skip ctxdma header */
+ dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
for (i = nvbe->pte_start; i < nvbe->pte_start + nvbe->pages; i++) {
uint64_t pteval = nvbe->pagelist[i - nvbe->pte_start];
if (pteval & NV_CTXDMA_PAGE_MASK) {
DRM_ERROR("Bad pteval 0x%llx\n", pteval);
+ dev_priv->engine.instmem.finish_access(nvbe->dev);
return -EINVAL;
}
@@ -129,6 +131,7 @@ nouveau_sgdma_bind(struct drm_ttm_backend *be, struct drm_bo_mem_reg *mem)
INSTANCE_WR(gpuobj, (i<<1)+1, tile);
}
}
+ dev_priv->engine.instmem.finish_access(nvbe->dev);
nvbe->is_bound = 1;
return 0;
@@ -146,6 +149,7 @@ nouveau_sgdma_unbind(struct drm_ttm_backend *be)
struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
unsigned int pte;
+ dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
pte = nvbe->pte_start;
while (pte < (nvbe->pte_start + nvbe->pages)) {
uint64_t pteval = dev_priv->gart_info.sg_dummy_bus;
@@ -159,6 +163,7 @@ nouveau_sgdma_unbind(struct drm_ttm_backend *be)
pte++;
}
+ dev_priv->engine.instmem.finish_access(nvbe->dev);
nvbe->is_bound = 0;
}
@@ -242,6 +247,7 @@ nouveau_sgdma_init(struct drm_device *dev)
pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ dev_priv->engine.instmem.prepare_access(dev, true);
if (dev_priv->card_type < NV_50) {
/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
* confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE
@@ -263,6 +269,7 @@ nouveau_sgdma_init(struct drm_device *dev)
INSTANCE_WR(gpuobj, (i+4)/4, 0);
}
}
+ dev_priv->engine.instmem.finish_access(dev);
dev_priv->gart_info.type = NOUVEAU_GART_SGDMA;
dev_priv->gart_info.aper_base = 0;
@@ -343,11 +350,14 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
int pte;
pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
if (dev_priv->card_type < NV_50) {
+ instmem->prepare_access(dev, false);
*page = INSTANCE_RD(gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
+ instmem->finish_access(dev);
return 0;
}
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index ac22c5c6..cd618e6c 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -202,6 +202,8 @@ struct nouveau_instmem_engine {
void (*clear)(struct drm_device *, struct nouveau_gpuobj *);
int (*bind)(struct drm_device *, struct nouveau_gpuobj *);
int (*unbind)(struct drm_device *, struct nouveau_gpuobj *);
+ void (*prepare_access)(struct drm_device *, bool write);
+ void (*finish_access)(struct drm_device *);
};
struct nouveau_mc_engine {
@@ -273,7 +275,8 @@ struct drm_nouveau_private {
drm_local_map_t *mmio;
drm_local_map_t *fb;
- drm_local_map_t *ramin; /* NV40 onwards */
+ drm_local_map_t *ramin_map;
+ drm_local_map_t *ramin;
int fifo_alloc_count;
struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];
@@ -633,6 +636,8 @@ extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
+extern void nv04_instmem_prepare_access(struct drm_device *, bool write);
+extern void nv04_instmem_finish_access(struct drm_device *);
/* nv50_instmem.c */
extern int nv50_instmem_init(struct drm_device *);
@@ -642,6 +647,8 @@ extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
+extern void nv50_instmem_prepare_access(struct drm_device *, bool write);
+extern void nv50_instmem_finish_access(struct drm_device *);
/* nv04_mc.c */
extern int nv04_mc_init(struct drm_device *);
@@ -720,8 +727,8 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
#define nv_wait(reg,mask,val) nouveau_wait_until(dev, 1000000000ULL, (reg), \
(mask), (val))
/* PRAMIN access */
-#define nv_ri32(reg) nv_in32(dev_priv->ramin, (reg))
-#define nv_wi32(reg,val) nv_out32(dev_priv->ramin, (reg), (val))
+#define nv_ri32(reg) nv_in32(dev_priv->ramin_map, (reg))
+#define nv_wi32(reg,val) nv_out32(dev_priv->ramin_map, (reg), (val))
/* object access */
#define INSTANCE_RD(o,i) nv_ri32((o)->im_pramin->start + ((i)<<2))
#define INSTANCE_WR(o,i,v) nv_wi32((o)->im_pramin->start + ((i)<<2), (v))
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 7efd9416..9cfc1711 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -438,10 +438,12 @@ nouveau_channel_idle(struct nouveau_channel *chan)
return 1;
}
+ engine->instmem.prepare_access(dev, false);
if (INSTANCE_RD(ramfc, 0) != INSTANCE_RD(ramfc, 1))
idle = 0;
else
idle = 1;
+ engine->instmem.finish_access(dev);
} else {
idle = (nv_rd32(NV04_PFIFO_CACHE1_DMA_GET) ==
nv_rd32(NV04_PFIFO_CACHE1_DMA_PUT));
diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c
index 427ef474..3c0d192c 100644
--- a/shared-core/nouveau_irq.c
+++ b/shared-core/nouveau_irq.c
@@ -201,7 +201,7 @@ static int
nouveau_graph_chid_from_grctx(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- uint32_t inst;
+ uint32_t inst, tmp;
int i;
if (dev_priv->card_type < NV_40)
@@ -222,7 +222,11 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev)
if (inst == chan->ramin_grctx->instance)
break;
} else {
- if (inst == INSTANCE_RD(chan->ramin_grctx->gpuobj, 0))
+ dev_priv->engine.instmem.prepare_access(dev, false);
+ tmp = INSTANCE_RD(chan->ramin_grctx->gpuobj, 0);
+ dev_priv->engine.instmem.finish_access(dev);
+
+ if (inst == tmp)
break;
}
}
diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c
index 3b4a707e..d70fa5ff 100644
--- a/shared-core/nouveau_mem.c
+++ b/shared-core/nouveau_mem.c
@@ -305,6 +305,7 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
size &= ~(psz - 1);
+ dev_priv->engine.instmem.prepare_access(dev, true);
if (flags & 0x80000000) {
while (size) {
struct nouveau_gpuobj *pt = pgt[virt / (512*1024*1024)];
@@ -329,6 +330,7 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
virt += psz;
}
}
+ dev_priv->engine.instmem.finish_access(dev);
return 0;
}
diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c
index 14b24cb4..bcd82052 100644
--- a/shared-core/nouveau_object.c
+++ b/shared-core/nouveau_object.c
@@ -102,6 +102,7 @@ static int
nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
{
struct drm_nouveau_private *dev_priv=dev->dev_private;
+ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
struct nouveau_gpuobj *gpuobj = ref->gpuobj;
@@ -126,6 +127,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
(gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
}
+ instmem->prepare_access(dev, true);
co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle);
do {
if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
@@ -135,6 +137,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
INSTANCE_WR(ramht, (co + 4)/4, ctx);
list_add_tail(&ref->list, &chan->ramht_refs);
+ instmem->finish_access(dev);
return 0;
}
DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n",
@@ -149,6 +152,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
break;
}
} while (co != ho);
+ instmem->finish_access(dev);
DRM_ERROR("RAMHT space exhausted. ch=%d\n", ref->channel);
return -ENOMEM;
@@ -158,6 +162,7 @@ static void
nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
uint32_t co, ho;
@@ -167,6 +172,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
return;
}
+ instmem->prepare_access(dev, true);
co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle);
do {
if (nouveau_ramht_entry_valid(dev, ramht, co) &&
@@ -178,6 +184,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
INSTANCE_WR(ramht, (co + 4)/4, 0x00000000);
list_del(&ref->list);
+ instmem->finish_access(dev);
return;
}
@@ -185,6 +192,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
if (co >= dev_priv->ramht_size)
co = 0;
} while (co != ho);
+ instmem->finish_access(dev);
DRM_ERROR("RAMHT entry not found. ch=%d, handle=0x%08x\n",
ref->channel, ref->handle);
@@ -263,8 +271,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
int i;
+ engine->instmem.prepare_access(dev, true);
for (i = 0; i < gpuobj->im_pramin->size; i += 4)
INSTANCE_WR(gpuobj, i/4, 0);
+ engine->instmem.finish_access(dev);
}
*gpuobj_ret = gpuobj;
@@ -582,8 +592,10 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
}
if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
+ dev_priv->engine.instmem.prepare_access(dev, true);
for (i = 0; i < gpuobj->im_pramin->size; i += 4)
INSTANCE_WR(gpuobj, i/4, 0);
+ dev_priv->engine.instmem.finish_access(dev);
}
if (pref) {
@@ -646,6 +658,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
int ret;
uint32_t is_scatter_gather = 0;
@@ -682,6 +695,8 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
return ret;
}
+ instmem->prepare_access(dev, true);
+
if (dev_priv->card_type < NV_50) {
uint32_t frame, adjust, pte_flags = 0;
adjust = offset & 0x00000fff;
@@ -745,6 +760,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
#else
if (dma_mapping_error(dev->sg->busaddr[idx])) {
#endif
+ instmem->finish_access(dev);
return -ENOMEM;
}
}
@@ -773,6 +789,8 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
INSTANCE_WR(*gpuobj, 2, offset);
INSTANCE_WR(*gpuobj, 5, flags5);
}
+
+ instmem->finish_access(dev);
(*gpuobj)->engine = NVOBJ_ENGINE_SW;
(*gpuobj)->class = class;
@@ -886,30 +904,32 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
return ret;
}
+ dev_priv->engine.instmem.prepare_access(dev, true);
if (dev_priv->card_type >= NV_50) {
INSTANCE_WR(*gpuobj, 0, class);
INSTANCE_WR(*gpuobj, 5, 0x00010000);
} else {
- switch (class) {
- case NV_CLASS_NULL:
- INSTANCE_WR(*gpuobj, 0, 0x00001030);
- INSTANCE_WR(*gpuobj, 1, 0xFFFFFFFF);
- break;
- default:
- if (dev_priv->card_type >= NV_40) {
- INSTANCE_WR(*gpuobj, 0, class);
+ switch (class) {
+ case NV_CLASS_NULL:
+ INSTANCE_WR(*gpuobj, 0, 0x00001030);
+ INSTANCE_WR(*gpuobj, 1, 0xFFFFFFFF);
+ break;
+ default:
+ if (dev_priv->card_type >= NV_40) {
+ INSTANCE_WR(*gpuobj, 0, class);
#ifdef __BIG_ENDIAN
- INSTANCE_WR(*gpuobj, 2, 0x01000000);
+ INSTANCE_WR(*gpuobj, 2, 0x01000000);
#endif
- } else {
+ } else {
#ifdef __BIG_ENDIAN
- INSTANCE_WR(*gpuobj, 0, class | 0x00080000);
+ INSTANCE_WR(*gpuobj, 0, class | 0x00080000);
#else
- INSTANCE_WR(*gpuobj, 0, class);
+ INSTANCE_WR(*gpuobj, 0, class);
#endif
+ }
}
}
- }
+ dev_priv->engine.instmem.finish_access(dev);
(*gpuobj)->engine = NVOBJ_ENGINE_GR;
(*gpuobj)->class = class;
@@ -972,6 +992,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
struct nouveau_gpuobj *vram = NULL, *tt = NULL;
int ret, i;
@@ -998,6 +1019,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
if (dev_priv->card_type >= NV_50) {
uint32_t vm_offset, pde;
+ instmem->prepare_access(dev, true);
+
vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
vm_offset += chan->ramin->gpuobj->im_pramin->start;
if ((ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
@@ -1012,8 +1035,10 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
dev_priv->gart_info.sg_ctxdma,
&chan->vm_gart_pt);
- if (ret)
+ if (ret) {
+ instmem->finish_access(dev);
return ret;
+ }
INSTANCE_WR(chan->vm_pd, pde++,
chan->vm_gart_pt->instance | 0x03);
INSTANCE_WR(chan->vm_pd, pde++, 0x00000000);
@@ -1022,16 +1047,20 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
drm_calloc(dev_priv->vm_vram_pt_nr,
sizeof(struct nouveau_gpuobj_ref *),
DRM_MEM_DRIVER);
- if (!chan->vm_vram_pt)
+ if (!chan->vm_vram_pt) {
+ instmem->finish_access(dev);
return -ENOMEM;
+ }
pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 2;
for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
dev_priv->vm_vram_pt[i],
&chan->vm_vram_pt[i]);
- if (ret)
+ if (ret) {
+ instmem->finish_access(dev);
return ret;
+ }
INSTANCE_WR(chan->vm_pd, pde++,
chan->vm_vram_pt[i]->instance | 0x61);
@@ -1039,6 +1068,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
}
}
+ instmem->finish_access(dev);
+
/* RAMHT */
if (dev_priv->card_type < NV_50) {
ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht,
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index d91adb86..11ecc30d 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -47,6 +47,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.clear = nv04_instmem_clear;
engine->instmem.bind = nv04_instmem_bind;
engine->instmem.unbind = nv04_instmem_unbind;
+ engine->instmem.prepare_access = nv04_instmem_prepare_access;
+ engine->instmem.finish_access = nv04_instmem_finish_access;
engine->mc.init = nv04_mc_init;
engine->mc.takedown = nv04_mc_takedown;
engine->timer.init = nv04_timer_init;
@@ -76,6 +78,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.clear = nv04_instmem_clear;
engine->instmem.bind = nv04_instmem_bind;
engine->instmem.unbind = nv04_instmem_unbind;
+ engine->instmem.prepare_access = nv04_instmem_prepare_access;
+ engine->instmem.finish_access = nv04_instmem_finish_access;
engine->mc.init = nv04_mc_init;
engine->mc.takedown = nv04_mc_takedown;
engine->timer.init = nv04_timer_init;
@@ -105,6 +109,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.clear = nv04_instmem_clear;
engine->instmem.bind = nv04_instmem_bind;
engine->instmem.unbind = nv04_instmem_unbind;
+ engine->instmem.prepare_access = nv04_instmem_prepare_access;
+ engine->instmem.finish_access = nv04_instmem_finish_access;
engine->mc.init = nv04_mc_init;
engine->mc.takedown = nv04_mc_takedown;
engine->timer.init = nv04_timer_init;
@@ -134,6 +140,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.clear = nv04_instmem_clear;
engine->instmem.bind = nv04_instmem_bind;
engine->instmem.unbind = nv04_instmem_unbind;
+ engine->instmem.prepare_access = nv04_instmem_prepare_access;
+ engine->instmem.finish_access = nv04_instmem_finish_access;
engine->mc.init = nv04_mc_init;
engine->mc.takedown = nv04_mc_takedown;
engine->timer.init = nv04_timer_init;
@@ -164,6 +172,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.clear = nv04_instmem_clear;
engine->instmem.bind = nv04_instmem_bind;
engine->instmem.unbind = nv04_instmem_unbind;
+ engine->instmem.prepare_access = nv04_instmem_prepare_access;
+ engine->instmem.finish_access = nv04_instmem_finish_access;
engine->mc.init = nv40_mc_init;
engine->mc.takedown = nv40_mc_takedown;
engine->timer.init = nv04_timer_init;
@@ -196,6 +206,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.clear = nv50_instmem_clear;
engine->instmem.bind = nv50_instmem_bind;
engine->instmem.unbind = nv50_instmem_unbind;
+ engine->instmem.prepare_access = nv50_instmem_prepare_access;
+ engine->instmem.finish_access = nv50_instmem_finish_access;
engine->mc.init = nv50_mc_init;
engine->mc.takedown = nv50_mc_takedown;
engine->timer.init = nv04_timer_init;
@@ -526,7 +538,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
}
/* map larger RAMIN aperture on NV40 cards */
- dev_priv->ramin = NULL;
+ dev_priv->ramin_map = dev_priv->ramin = NULL;
if (dev_priv->card_type >= NV_40) {
int ramin_resource = 2;
if (drm_get_resource_len(dev, ramin_resource) == 0)
@@ -812,8 +824,10 @@ static int nouveau_suspend(struct drm_device *dev)
engine->graph.save_context(dev_priv->fifos[engine->fifo.channel_id(dev)]);
nouveau_wait_for_idle(dev);
+ engine->instmem.prepare_access(dev, false);
for (i = 0; i < susres->ramin_size / 4; i++)
susres->ramin_copy[i] = nv_ri32(i << 2);
+ engine->instmem.finish_access(dev);
/* reenable the fifo caches */
nv_wr32(NV04_PFIFO_CACHE1_DMA_PUSH,
diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c
index 3463e073..18605d00 100644
--- a/shared-core/nv04_fifo.c
+++ b/shared-core/nv04_fifo.c
@@ -59,6 +59,7 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
return ret;
/* Setup initial state */
+ dev_priv->engine.instmem.prepare_access(dev, true);
RAMFC_WR(DMA_PUT, chan->pushbuf_base);
RAMFC_WR(DMA_GET, chan->pushbuf_base);
RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4);
@@ -69,6 +70,7 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
NV_PFIFO_CACHE1_BIG_ENDIAN |
#endif
0));
+ dev_priv->engine.instmem.finish_access(dev);
/* enable the fifo dma operation */
nv_wr32(NV04_PFIFO_MODE,nv_rd32(NV04_PFIFO_MODE) | (1<<chan->id));
@@ -93,6 +95,8 @@ nv04_fifo_load_context(struct nouveau_channel *chan)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t tmp;
+ dev_priv->engine.instmem.prepare_access(dev, false);
+
nv_wr32(NV03_PFIFO_CACHE1_PUSH1,
NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
@@ -108,6 +112,8 @@ nv04_fifo_load_context(struct nouveau_channel *chan)
nv_wr32(NV04_PFIFO_CACHE1_ENGINE, RAMFC_RD(ENGINE));
nv_wr32(NV04_PFIFO_CACHE1_PULL1, RAMFC_RD(PULL1_ENGINE));
+ dev_priv->engine.instmem.finish_access(dev);
+
/* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
tmp = nv_rd32(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
nv_wr32(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
@@ -122,6 +128,8 @@ nv04_fifo_save_context(struct nouveau_channel *chan)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t tmp;
+ dev_priv->engine.instmem.prepare_access(dev, true);
+
RAMFC_WR(DMA_PUT, nv_rd32(NV04_PFIFO_CACHE1_DMA_PUT));
RAMFC_WR(DMA_GET, nv_rd32(NV04_PFIFO_CACHE1_DMA_GET));
@@ -134,5 +142,6 @@ nv04_fifo_save_context(struct nouveau_channel *chan)
RAMFC_WR(ENGINE, nv_rd32(NV04_PFIFO_CACHE1_ENGINE));
RAMFC_WR(PULL1_ENGINE, nv_rd32(NV04_PFIFO_CACHE1_PULL1));
+ dev_priv->engine.instmem.finish_access(dev);
return 0;
}
diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c
index 62685299..7d902d86 100644
--- a/shared-core/nv04_instmem.c
+++ b/shared-core/nv04_instmem.c
@@ -167,3 +167,22 @@ nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
gpuobj->im_bound = 0;
return 0;
}
+
+void
+nv04_instmem_prepare_access(struct drm_device *dev, bool write)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ BUG_ON(dev_priv->ramin_map != NULL);
+ dev_priv->ramin_map = dev_priv->ramin;
+}
+
+void
+nv04_instmem_finish_access(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ BUG_ON(dev_priv->ramin_map == NULL);
+ dev_priv->ramin_map = NULL;
+}
+
diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c
index b2245585..4d594571 100644
--- a/shared-core/nv10_fifo.c
+++ b/shared-core/nv10_fifo.c
@@ -62,6 +62,7 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
/* Fill entries that are seen filled in dumps of nvidia driver just
* after channel's is put into DMA mode
*/
+ dev_priv->engine.instmem.prepare_access(dev, true);
RAMFC_WR(DMA_PUT , chan->pushbuf_base);
RAMFC_WR(DMA_GET , chan->pushbuf_base);
RAMFC_WR(DMA_INSTANCE , chan->pushbuf->instance >> 4);
@@ -72,6 +73,7 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
NV_PFIFO_CACHE1_BIG_ENDIAN |
#endif
0);
+ dev_priv->engine.instmem.finish_access(dev);
/* enable the fifo dma operation */
nv_wr32(NV04_PFIFO_MODE,nv_rd32(NV04_PFIFO_MODE)|(1<<chan->id));
@@ -99,6 +101,8 @@ nv10_fifo_load_context(struct nouveau_channel *chan)
nv_wr32(NV03_PFIFO_CACHE1_PUSH1,
NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
+ dev_priv->engine.instmem.prepare_access(dev, false);
+
nv_wr32(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET));
nv_wr32(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT));
nv_wr32(NV10_PFIFO_CACHE1_REF_CNT , RAMFC_RD(REF_CNT));
@@ -125,6 +129,8 @@ nv10_fifo_load_context(struct nouveau_channel *chan)
RAMFC_RD(DMA_SUBROUTINE));
}
+ dev_priv->engine.instmem.finish_access(dev);
+
/* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
tmp = nv_rd32(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
nv_wr32(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
@@ -139,6 +145,8 @@ nv10_fifo_save_context(struct nouveau_channel *chan)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t tmp;
+ dev_priv->engine.instmem.prepare_access(dev, true);
+
RAMFC_WR(DMA_PUT , nv_rd32(NV04_PFIFO_CACHE1_DMA_PUT));
RAMFC_WR(DMA_GET , nv_rd32(NV04_PFIFO_CACHE1_DMA_GET));
RAMFC_WR(REF_CNT , nv_rd32(NV10_PFIFO_CACHE1_REF_CNT));
@@ -165,5 +173,6 @@ nv10_fifo_save_context(struct nouveau_channel *chan)
nv_rd32(NV04_PFIFO_CACHE1_DMA_GET));
}
+ dev_priv->engine.instmem.finish_access(dev);
return 0;
}
diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c
index 122bfb58..b8e138e9 100644
--- a/shared-core/nv20_graph.c
+++ b/shared-core/nv20_graph.c
@@ -606,6 +606,7 @@ int nv20_graph_create_context(struct nouveau_channel *chan)
return ret;
/* Initialise default context values */
+ dev_priv->engine.instmem.prepare_access(dev, true);
ctx_init(dev, chan->ramin_grctx->gpuobj);
/* nv20: INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, chan->id<<24); */
@@ -615,6 +616,7 @@ int nv20_graph_create_context(struct nouveau_channel *chan)
INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id,
chan->ramin_grctx->instance >> 4);
+ dev_priv->engine.instmem.finish_access(dev);
return 0;
}
@@ -626,7 +628,9 @@ void nv20_graph_destroy_context(struct nouveau_channel *chan)
if (chan->ramin_grctx)
nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
+ dev_priv->engine.instmem.prepare_access(dev, true);
INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0);
+ dev_priv->engine.instmem.finish_access(dev);
}
int nv20_graph_load_context(struct nouveau_channel *chan)
diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c
index 983b346d..b156dc86 100644
--- a/shared-core/nv40_fifo.c
+++ b/shared-core/nv40_fifo.c
@@ -53,6 +53,7 @@ nv40_fifo_create_context(struct nouveau_channel *chan)
/* Fill entries that are seen filled in dumps of nvidia driver just
* after channel's is put into DMA mode
*/
+ dev_priv->engine.instmem.prepare_access(dev, true);
RAMFC_WR(DMA_PUT , chan->pushbuf_base);
RAMFC_WR(DMA_GET , chan->pushbuf_base);
RAMFC_WR(DMA_INSTANCE , chan->pushbuf->instance >> 4);
@@ -66,6 +67,7 @@ nv40_fifo_create_context(struct nouveau_channel *chan)
RAMFC_WR(DMA_SUBROUTINE, 0);
RAMFC_WR(GRCTX_INSTANCE, chan->ramin_grctx->instance >> 4);
RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF);
+ dev_priv->engine.instmem.finish_access(dev);
/* enable the fifo dma operation */
nv_wr32(NV04_PFIFO_MODE,nv_rd32(NV04_PFIFO_MODE)|(1<<chan->id));
@@ -91,6 +93,8 @@ nv40_fifo_load_context(struct nouveau_channel *chan)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t tmp, tmp2;
+ dev_priv->engine.instmem.prepare_access(dev, false);
+
nv_wr32(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET));
nv_wr32(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT));
nv_wr32(NV10_PFIFO_CACHE1_REF_CNT , RAMFC_RD(REF_CNT));
@@ -134,6 +138,8 @@ nv40_fifo_load_context(struct nouveau_channel *chan)
tmp |= RAMFC_RD(DMA_TIMESLICE) & 0x1FFFF;
nv_wr32(NV04_PFIFO_DMA_TIMESLICE, tmp);
+ dev_priv->engine.instmem.finish_access(dev);
+
/* Set channel active, and in DMA mode */
nv_wr32(NV03_PFIFO_CACHE1_PUSH1,
NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
@@ -152,6 +158,8 @@ nv40_fifo_save_context(struct nouveau_channel *chan)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t tmp;
+ dev_priv->engine.instmem.prepare_access(dev, true);
+
RAMFC_WR(DMA_PUT , nv_rd32(NV04_PFIFO_CACHE1_DMA_PUT));
RAMFC_WR(DMA_GET , nv_rd32(NV04_PFIFO_CACHE1_DMA_GET));
RAMFC_WR(REF_CNT , nv_rd32(NV10_PFIFO_CACHE1_REF_CNT));
@@ -192,6 +200,7 @@ nv40_fifo_save_context(struct nouveau_channel *chan)
RAMFC_WR(UNK_48 , tmp);
#endif
+ dev_priv->engine.instmem.finish_access(dev);
return 0;
}
diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c
index b0340c5a..31147ef0 100644
--- a/shared-core/nv40_graph.c
+++ b/shared-core/nv40_graph.c
@@ -1514,7 +1514,9 @@ nv40_graph_create_context(struct nouveau_channel *chan)
return ret;
/* Initialise default context values */
+ dev_priv->engine.instmem.prepare_access(dev, true);
ctx_init(dev, chan->ramin_grctx->gpuobj);
+ dev_priv->engine.instmem.finish_access(dev);
return 0;
}
diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c
index b8150b61..f7763969 100644
--- a/shared-core/nv50_fifo.c
+++ b/shared-core/nv50_fifo.c
@@ -49,11 +49,14 @@ nv50_fifo_init_thingo(struct drm_device *dev)
priv->cur_thingo = !priv->cur_thingo;
/* We never schedule channel 0 or 127 */
+ dev_priv->engine.instmem.prepare_access(dev, true);
for (i = 1, nr = 0; i < 127; i++) {
if (dev_priv->fifos[i]) {
INSTANCE_WR(cur->gpuobj, nr++, i);
}
}
+ dev_priv->engine.instmem.finish_access(dev);
+
nv_wr32(0x32f4, cur->instance >> 12);
nv_wr32(0x32ec, nr);
nv_wr32(0x2500, 0x101);
@@ -253,6 +256,8 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
ramfc = chan->ramfc->gpuobj;
}
+ dev_priv->engine.instmem.prepare_access(dev, true);
+
INSTANCE_WR(ramfc, 0x08/4, chan->pushbuf_base);
INSTANCE_WR(ramfc, 0x10/4, chan->pushbuf_base);
INSTANCE_WR(ramfc, 0x48/4, chan->pushbuf->instance >> 4);
@@ -275,6 +280,8 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12);
}
+ dev_priv->engine.instmem.finish_access(dev);
+
ret = nv50_fifo_channel_enable(dev, chan->id, 0);
if (ret) {
DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret);
@@ -315,6 +322,7 @@ nv50_fifo_load_context(struct nouveau_channel *chan)
DRM_DEBUG("ch%d\n", chan->id);
/*XXX: incomplete, only touches the regs that NV does */
+ dev_priv->engine.instmem.prepare_access(dev, false);
nv_wr32(0x3244, INSTANCE_RD(ramfc, 0x08/4));
nv_wr32(0x3240, INSTANCE_RD(ramfc, 0x10/4));
@@ -330,6 +338,8 @@ nv50_fifo_load_context(struct nouveau_channel *chan)
nv_wr32(0x3410, INSTANCE_RD(ramfc, 0x98/4));
}
+ dev_priv->engine.instmem.finish_access(dev);
+
nv_wr32(NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
return 0;
}
diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c
index a4c7e1b1..b892830e 100644
--- a/shared-core/nv50_graph.c
+++ b/shared-core/nv50_graph.c
@@ -182,6 +182,7 @@ nv50_graph_create_context(struct nouveau_channel *chan)
ctx = chan->ramin_grctx->gpuobj;
hdr = IS_G80 ? 0x200 : 0x20;
+ dev_priv->engine.instmem.prepare_access(dev, true);
INSTANCE_WR(ramin, (hdr + 0x00)/4, 0x00190002);
INSTANCE_WR(ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
grctx_size - 1);
@@ -189,6 +190,7 @@ nv50_graph_create_context(struct nouveau_channel *chan)
INSTANCE_WR(ramin, (hdr + 0x0c)/4, 0);
INSTANCE_WR(ramin, (hdr + 0x10)/4, 0);
INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000);
+ dev_priv->engine.instmem.finish_access(dev);
switch (dev_priv->chipset) {
case 0x50:
@@ -222,6 +224,8 @@ nv50_graph_create_context(struct nouveau_channel *chan)
break;
}
+ dev_priv->engine.instmem.prepare_access(dev, true);
+
pos = 0;
while (*ctxvals) {
int cnt = *ctxvals++;
@@ -237,6 +241,8 @@ nv50_graph_create_context(struct nouveau_channel *chan)
else
INSTANCE_WR(ctx, 0x0011c/4, 0x00000002);
+ dev_priv->engine.instmem.finish_access(dev);
+
return 0;
}
@@ -252,8 +258,10 @@ nv50_graph_destroy_context(struct nouveau_channel *chan)
int i, hdr;
hdr = IS_G80 ? 0x200 : 0x20;
+ dev_priv->engine.instmem.prepare_access(dev, true);
for (i=hdr; i<hdr+24; i+=4)
INSTANCE_WR(chan->ramin->gpuobj, i/4, 0);
+ dev_priv->engine.instmem.finish_access(dev);
nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
}
diff --git a/shared-core/nv50_instmem.c b/shared-core/nv50_instmem.c
index 393d5570..661c9346 100644
--- a/shared-core/nv50_instmem.c
+++ b/shared-core/nv50_instmem.c
@@ -176,12 +176,14 @@ nv50_instmem_init(struct drm_device *dev)
/* Assume that praying isn't enough, check that we can re-read the
* entire fake channel back from the PRAMIN BAR */
+ dev_priv->engine.instmem.prepare_access(dev, false);
for (i = 0; i < c_size; i+=4) {
if (nv_rd32(NV_RAMIN + i) != nv_ri32(i)) {
DRM_ERROR("Error reading back PRAMIN at 0x%08x\n", i);
return -EINVAL;
}
}
+ dev_priv->engine.instmem.finish_access(dev);
/* Global PRAMIN heap */
if (nouveau_mem_init_heap(&dev_priv->ramin_heap,
@@ -289,6 +291,7 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
DRM_DEBUG("first vram page: 0x%llx\n",
gpuobj->im_backing->start);
+ dev_priv->engine.instmem.prepare_access(dev, true);
while (pte < pte_end) {
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1);
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000);
@@ -296,6 +299,7 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
pte += 8;
vram += NV50_INSTMEM_PAGE_SIZE;
}
+ dev_priv->engine.instmem.finish_access(dev);
nv_wr32(0x070000, 0x00000001);
while(nv_rd32(0x070000) & 1);
@@ -320,12 +324,34 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
pte = (gpuobj->im_pramin->start >> 12) << 3;
pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte;
+
+ dev_priv->engine.instmem.prepare_access(dev, true);
while (pte < pte_end) {
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009);
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000);
pte += 8;
}
+ dev_priv->engine.instmem.finish_access(dev);
gpuobj->im_bound = 0;
return 0;
}
+
+void
+nv50_instmem_prepare_access(struct drm_device *dev, bool write)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ BUG_ON(dev_priv->ramin_map != NULL);
+ dev_priv->ramin_map = dev_priv->ramin;
+}
+
+void
+nv50_instmem_finish_access(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ BUG_ON(dev_priv->ramin_map == NULL);
+ dev_priv->ramin_map = NULL;
+}
+