nouveau: hide instmem map, force use of {prepare,finish}_access

This commit is contained in:
Ben Skeggs 2009-02-22 10:55:29 +10:00
parent cdba1bf2e4
commit afac6a4ddc
16 changed files with 188 additions and 22 deletions

View file

@ -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;
}

View file

@ -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))

View file

@ -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));

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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,

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}