int nouveau_gpuobj_map(struct nouveau_gpuobj *gpuobj, u32 access, struct nouveau_vma *vma) { struct nouveau_bar *bar = nouveau_bar(gpuobj); int ret = -EINVAL; if (bar && bar->umap) { struct nouveau_instobj *iobj = (void *) nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); struct nouveau_mem **mem = (void *)(iobj + 1); ret = bar->umap(bar, *mem, access, vma); } return ret; }
int nouveau_gpuobj_map_vm(struct nouveau_gpuobj *gpuobj, struct nouveau_vm *vm, u32 access, struct nouveau_vma *vma) { struct nouveau_instobj *iobj = (void *) nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); struct nouveau_mem **mem = (void *)(iobj + 1); int ret; ret = nouveau_vm_get(vm, gpuobj->size, 12, access, vma); if (ret) return ret; nouveau_vm_map(vma, *mem); return 0; }
static int nvkm_ioctl_path(struct nouveau_handle *parent, u32 type, u32 nr, u32 *path, void *data, u32 size, u8 owner, u8 *route, u64 *token) { struct nouveau_handle *handle = parent; struct nouveau_namedb *namedb; struct nouveau_object *object; int ret; while ((object = parent->object), nr--) { nv_ioctl(object, "path 0x%08x\n", path[nr]); if (!nv_iclass(object, NV_PARENT_CLASS)) { nv_debug(object, "cannot have children (path)\n"); return -EINVAL; } if (!(namedb = (void *)nv_pclass(object, NV_NAMEDB_CLASS)) || !(handle = nouveau_namedb_get(namedb, path[nr]))) { nv_debug(object, "handle 0x%08x not found\n", path[nr]); return -ENOENT; } nouveau_namedb_put(handle); parent = handle; } if (owner != NVIF_IOCTL_V0_OWNER_ANY && owner != handle->route) { nv_ioctl(object, "object route != owner\n"); return -EACCES; } *route = handle->route; *token = handle->token; if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) { if (nvkm_ioctl_v0[type].version == 0) { ret = nvkm_ioctl_v0[type].func(handle, data, size); } } return ret; }
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; }