void _nouveau_gpuobj_wr32(struct nouveau_object *object, u64 addr, u32 data) { struct nouveau_gpuobj *gpuobj = nv_gpuobj(object); struct nouveau_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent); if (gpuobj->node) addr += gpuobj->node->offset; pfuncs->wr32(gpuobj->parent, addr, data); }
u32 _nouveau_gpuobj_rd32(struct nouveau_object *object, u64 addr) { struct nouveau_gpuobj *gpuobj = nv_gpuobj(object); struct nouveau_ofuncs *pfuncs = nv_ofuncs(gpuobj->parent); if (gpuobj->node) addr += gpuobj->node->offset; return pfuncs->rd32(gpuobj->parent, addr); }
static int nvd0_disp_dmac_object_attach(struct nouveau_object *parent, struct nouveau_object *object, u32 name) { struct nv50_disp_base *base = (void *)parent->parent; struct nv50_disp_chan *chan = (void *)parent; u32 addr = nv_gpuobj(object)->node->offset; u32 data = (chan->chid << 27) | (addr << 9) | 0x00000001; return nouveau_ramht_insert(base->ramht, chan->chid, name, data); }
void nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj) { int i; if (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE) { for (i = 0; i < gpuobj->size; i += 4) nv_wo32(gpuobj, i, 0x00000000); } if (gpuobj->node) { nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap, &gpuobj->node); } if (gpuobj->heap.block_size) nouveau_mm_fini(&gpuobj->heap); nouveau_object_destroy(&gpuobj->base); }
static int nv50_graph_context_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nv50_graph_priv *priv = (void *)engine; struct nv50_graph_chan *chan; int ret; ret = nouveau_graph_context_create(parent, engine, oclass, NULL, priv->size, 0, NVOBJ_FLAG_ZERO_ALLOC, &chan); *pobject = nv_object(chan); if (ret) return ret; nv50_grctx_fill(nv_device(priv), nv_gpuobj(chan)); return 0; }
static int nv50_software_mthd_dma_vblsem(struct nouveau_object *object, u32 mthd, void *args, u32 size) { struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); struct nouveau_fifo_chan *fifo = (void *)nv_object(chan)->parent; struct nouveau_handle *handle; int ret = -EINVAL; handle = nouveau_namedb_get(nv_namedb(fifo), *(u32 *)args); if (!handle) return -ENOENT; if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { struct nouveau_gpuobj *gpuobj = nv_gpuobj(handle->object); chan->vblank.ctxdma = gpuobj->node->offset >> 4; ret = 0; } nouveau_namedb_put(handle); return ret; }
int nouveau_ramht_insert(struct nouveau_ramht *ramht, int chid, u32 handle, u32 context) { struct nouveau_bar *bar = nouveau_bar(ramht); u32 co, ho; co = ho = nouveau_ramht_hash(ramht, chid, handle); do { if (!nv_ro32(ramht, co + 4)) { nv_wo32(ramht, co + 0, handle); nv_wo32(ramht, co + 4, context); if (bar) bar->flush(bar); return co; } co += 8; if (co >= nv_gpuobj(ramht)->size) co = 0; } while (co != ho); return -ENOMEM; }
int nouveau_gpuobj_create_(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, u32 pclass, struct nouveau_object *pargpu, u32 size, u32 align, u32 flags, int length, void **pobject) { struct nouveau_instmem *imem = nouveau_instmem(parent); struct nouveau_bar *bar = nouveau_bar(parent); struct nouveau_gpuobj *gpuobj; struct nouveau_mm *heap = NULL; int ret, i; u64 addr; *pobject = NULL; if (pargpu) { while ((pargpu = nv_pclass(pargpu, NV_GPUOBJ_CLASS))) { if (nv_gpuobj(pargpu)->heap.block_size) break; pargpu = pargpu->parent; } if (unlikely(pargpu == NULL)) { nv_error(parent, "no gpuobj heap\n"); return -EINVAL; } addr = nv_gpuobj(pargpu)->addr; heap = &nv_gpuobj(pargpu)->heap; atomic_inc(&parent->refcount); } else { ret = imem->alloc(imem, parent, size, align, &parent); pargpu = parent; if (ret) return ret; addr = nv_memobj(pargpu)->addr; size = nv_memobj(pargpu)->size; if (bar && bar->alloc) { struct nouveau_instobj *iobj = (void *)parent; struct nouveau_mem **mem = (void *)(iobj + 1); struct nouveau_mem *node = *mem; if (!bar->alloc(bar, parent, node, &pargpu)) { nouveau_object_ref(NULL, &parent); parent = pargpu; } } } ret = nouveau_object_create_(parent, engine, oclass, pclass | NV_GPUOBJ_CLASS, length, pobject); nouveau_object_ref(NULL, &parent); gpuobj = *pobject; if (ret) return ret; gpuobj->parent = pargpu; gpuobj->flags = flags; gpuobj->addr = addr; gpuobj->size = size; if (heap) { ret = nouveau_mm_head(heap, 0, 1, size, size, max(align, (u32)1), &gpuobj->node); if (ret) return ret; gpuobj->addr += gpuobj->node->offset; } if (gpuobj->flags & NVOBJ_FLAG_HEAP) { ret = nouveau_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); if (ret) return ret; } if (flags & NVOBJ_FLAG_ZERO_ALLOC) { for (i = 0; i < gpuobj->size; i += 4) nv_wo32(gpuobj, i, 0x00000000); } return ret; }
int _nouveau_gpuobj_fini(struct nouveau_object *object, bool suspend) { return nouveau_gpuobj_fini(nv_gpuobj(object), suspend); }
int _nouveau_gpuobj_init(struct nouveau_object *object) { return nouveau_gpuobj_init(nv_gpuobj(object)); }
void _nouveau_gpuobj_dtor(struct nouveau_object *object) { nouveau_gpuobj_destroy(nv_gpuobj(object)); }
int nvc0_graph_context_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *args, u32 size, struct nouveau_object **pobject) { struct nouveau_vm *vm = nouveau_client(parent)->vm; struct nvc0_graph_priv *priv = (void *)engine; struct nvc0_graph_data *data = priv->mmio_data; struct nvc0_graph_mmio *mmio = priv->mmio_list; struct nvc0_graph_chan *chan; int ret, i; /* allocate memory for context, and fill with default values */ ret = nouveau_graph_context_create(parent, engine, oclass, NULL, priv->size, 0x100, NVOBJ_FLAG_ZERO_ALLOC, &chan); *pobject = nv_object(chan); if (ret) return ret; /* allocate memory for a "mmio list" buffer that's used by the HUB * fuc to modify some per-context register settings on first load * of the context. */ ret = nouveau_gpuobj_new(nv_object(chan), NULL, 0x1000, 0x100, 0, &chan->mmio); if (ret) return ret; ret = nouveau_gpuobj_map_vm(nv_gpuobj(chan->mmio), vm, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, &chan->mmio_vma); if (ret) return ret; /* allocate buffers referenced by mmio list */ for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) { ret = nouveau_gpuobj_new(nv_object(chan), NULL, data->size, data->align, 0, &chan->data[i].mem); if (ret) return ret; ret = nouveau_gpuobj_map_vm(chan->data[i].mem, vm, data->access, &chan->data[i].vma); if (ret) return ret; data++; } /* finally, fill in the mmio list and point the context at it */ for (i = 0; mmio->addr && i < ARRAY_SIZE(priv->mmio_list); i++) { u32 addr = mmio->addr; u32 data = mmio->data; if (mmio->shift) { u64 info = chan->data[mmio->buffer].vma.offset; data |= info >> mmio->shift; } nv_wo32(chan->mmio, chan->mmio_nr++ * 4, addr); nv_wo32(chan->mmio, chan->mmio_nr++ * 4, data); mmio++; }