From afac6a4ddc96fc3135c9b18fcc2514393984d536 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 22 Feb 2009 10:55:29 +1000 Subject: nouveau: hide instmem map, force use of {prepare,finish}_access --- linux-core/nouveau_sgdma.c | 10 +++++++ shared-core/nouveau_drv.h | 13 ++++++--- shared-core/nouveau_fifo.c | 2 ++ shared-core/nouveau_irq.c | 8 ++++-- shared-core/nouveau_mem.c | 2 ++ shared-core/nouveau_object.c | 63 +++++++++++++++++++++++++++++++++----------- shared-core/nouveau_state.c | 16 ++++++++++- shared-core/nv04_fifo.c | 9 +++++++ shared-core/nv04_instmem.c | 19 +++++++++++++ shared-core/nv10_fifo.c | 9 +++++++ shared-core/nv20_graph.c | 4 +++ shared-core/nv40_fifo.c | 9 +++++++ shared-core/nv40_graph.c | 2 ++ shared-core/nv50_fifo.c | 10 +++++++ shared-core/nv50_graph.c | 8 ++++++ shared-core/nv50_instmem.c | 26 ++++++++++++++++++ 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<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<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<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; iramin->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; +} + -- cgit v1.2.3