Loading drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h +12 −12 Original line number Diff line number Diff line Loading @@ -7,30 +7,33 @@ struct nvkm_vma; struct nvkm_vm; #define NVOBJ_FLAG_ZERO_ALLOC 0x00000001 #define NVOBJ_FLAG_ZERO_FREE 0x00000002 #define NVOBJ_FLAG_HEAP 0x00000004 struct nvkm_gpuobj { struct nvkm_object object; struct nvkm_memory *memory; const struct nvkm_gpuobj_func *func; struct nvkm_gpuobj *parent; struct nvkm_memory *memory; struct nvkm_mm_node *node; struct nvkm_mm heap; u32 flags; u64 addr; u32 size; struct nvkm_mm heap; const struct nvkm_gpuobj_func *func; void __iomem *map; }; struct nvkm_gpuobj_func { void (*acquire)(struct nvkm_gpuobj *); void *(*acquire)(struct nvkm_gpuobj *); void (*release)(struct nvkm_gpuobj *); u32 (*rd32)(struct nvkm_gpuobj *, u32 offset); void (*wr32)(struct nvkm_gpuobj *, u32 offset, u32 data); }; int nvkm_gpuobj_new(struct nvkm_device *, u32 size, int align, bool zero, struct nvkm_gpuobj *parent, struct nvkm_gpuobj **); void nvkm_gpuobj_del(struct nvkm_gpuobj **); static inline struct nvkm_gpuobj * nv_gpuobj(void *obj) { Loading @@ -51,11 +54,8 @@ int nvkm_gpuobj_create_(struct nvkm_object *, struct nvkm_object *, u32 flags, int length, void **); void nvkm_gpuobj_destroy(struct nvkm_gpuobj *); int nvkm_gpuobj_new(struct nvkm_object *, struct nvkm_object *, u32 size, u32 align, u32 flags, struct nvkm_gpuobj **); int nvkm_gpuobj_dup(struct nvkm_object *, struct nvkm_memory *, struct nvkm_gpuobj **); int nvkm_gpuobj_map_vm(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **); int nvkm_gpuobj_map(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, struct nvkm_vma *); void nvkm_gpuobj_unmap(struct nvkm_vma *); Loading drivers/gpu/drm/nouveau/include/nvkm/engine/dmaobj.h +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ struct nvkm_dmaeng { struct nvkm_engine engine; /* creates a "physical" dma object from a struct nvkm_dmaobj */ int (*bind)(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, int (*bind)(struct nvkm_dmaobj *dmaobj, struct nvkm_gpuobj *parent, struct nvkm_gpuobj **); }; Loading drivers/gpu/drm/nouveau/nouveau_drm.c +3 −3 Original line number Diff line number Diff line Loading @@ -141,7 +141,7 @@ nouveau_accel_fini(struct nouveau_drm *drm) { nouveau_channel_del(&drm->channel); nvif_object_fini(&drm->ntfy); nvkm_gpuobj_ref(NULL, &drm->notify); nvkm_gpuobj_del(&drm->notify); nvif_object_fini(&drm->nvsw); nouveau_channel_del(&drm->cechan); nvif_object_fini(&drm->ttm.copy); Loading Loading @@ -264,8 +264,8 @@ nouveau_accel_init(struct nouveau_drm *drm) } if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { ret = nvkm_gpuobj_new(nvxx_object(&drm->device.object), NULL, 32, 0, 0, &drm->notify); ret = nvkm_gpuobj_new(nvxx_device(&drm->device), 32, 0, false, NULL, &drm->notify); if (ret) { NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); nouveau_accel_fini(drm); Loading drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c +186 −172 Original line number Diff line number Diff line Loading @@ -28,74 +28,209 @@ #include <subdev/bar.h> #include <subdev/mmu.h> /* fast-path, where backend is able to provide direct pointer to memory */ static u32 nvkm_gpuobj_rd32_fast(struct nvkm_gpuobj *gpuobj, u32 offset) { return ioread32_native(gpuobj->map + offset); } static void nvkm_gpuobj_release(struct nvkm_gpuobj *gpuobj) nvkm_gpuobj_wr32_fast(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) { if (gpuobj->node) { nvkm_done(gpuobj->parent); return; iowrite32_native(data, gpuobj->map + offset); } nvkm_done(gpuobj->memory); /* accessor functions for gpuobjs allocated directly from instmem */ static u32 nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) { return nvkm_ro32(gpuobj->memory, offset); } static void nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj) nvkm_gpuobj_heap_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) { nvkm_wo32(gpuobj->memory, offset, data); } static const struct nvkm_gpuobj_func nvkm_gpuobj_heap; static void nvkm_gpuobj_heap_release(struct nvkm_gpuobj *gpuobj) { if (gpuobj->node) { nvkm_kmap(gpuobj->parent); return; gpuobj->func = &nvkm_gpuobj_heap; nvkm_done(gpuobj->memory); } nvkm_kmap(gpuobj->memory); static const struct nvkm_gpuobj_func nvkm_gpuobj_heap_fast = { .release = nvkm_gpuobj_heap_release, .rd32 = nvkm_gpuobj_rd32_fast, .wr32 = nvkm_gpuobj_wr32_fast, }; static const struct nvkm_gpuobj_func nvkm_gpuobj_heap_slow = { .release = nvkm_gpuobj_heap_release, .rd32 = nvkm_gpuobj_heap_rd32, .wr32 = nvkm_gpuobj_heap_wr32, }; static void * nvkm_gpuobj_heap_acquire(struct nvkm_gpuobj *gpuobj) { gpuobj->map = nvkm_kmap(gpuobj->memory); if (likely(gpuobj->map)) gpuobj->func = &nvkm_gpuobj_heap_fast; else gpuobj->func = &nvkm_gpuobj_heap_slow; return gpuobj->map; } static const struct nvkm_gpuobj_func nvkm_gpuobj_heap = { .acquire = nvkm_gpuobj_heap_acquire, }; /* accessor functions for gpuobjs sub-allocated from a parent gpuobj */ static u32 nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) { if (gpuobj->node) return nvkm_ro32(gpuobj->parent, gpuobj->node->offset + offset); return nvkm_ro32(gpuobj->memory, offset); } static void nvkm_gpuobj_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) { if (gpuobj->node) { nvkm_wo32(gpuobj->parent, gpuobj->node->offset + offset, data); return; } nvkm_wo32(gpuobj->memory, offset, data); static const struct nvkm_gpuobj_func nvkm_gpuobj_func; static void nvkm_gpuobj_release(struct nvkm_gpuobj *gpuobj) { gpuobj->func = &nvkm_gpuobj_func; nvkm_done(gpuobj->parent); } void nvkm_gpuobj_destroy(struct nvkm_gpuobj *gpuobj) static const struct nvkm_gpuobj_func nvkm_gpuobj_fast = { .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32_fast, .wr32 = nvkm_gpuobj_wr32_fast, }; static const struct nvkm_gpuobj_func nvkm_gpuobj_slow = { .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32, .wr32 = nvkm_gpuobj_wr32, }; static void * nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj) { int i; gpuobj->map = nvkm_kmap(gpuobj->parent); if (likely(gpuobj->map)) { gpuobj->map = (u8 *)gpuobj->map + gpuobj->node->offset; gpuobj->func = &nvkm_gpuobj_fast; } else { gpuobj->func = &nvkm_gpuobj_slow; } return gpuobj->map; } static const struct nvkm_gpuobj_func nvkm_gpuobj_func = { .acquire = nvkm_gpuobj_acquire, }; if (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE) { static int nvkm_gpuobj_ctor(struct nvkm_device *device, u32 size, int align, bool zero, struct nvkm_gpuobj *parent, struct nvkm_gpuobj *gpuobj) { u32 offset; int ret; if (parent) { if (align >= 0) { ret = nvkm_mm_head(&parent->heap, 0, 1, size, size, max(align, 1), &gpuobj->node); } else { ret = nvkm_mm_tail(&parent->heap, 0, 1, size, size, -align, &gpuobj->node); } if (ret) return ret; gpuobj->parent = parent; gpuobj->func = &nvkm_gpuobj_func; gpuobj->addr = parent->addr + gpuobj->node->offset; gpuobj->size = gpuobj->node->length; if (zero) { nvkm_kmap(gpuobj); for (i = 0; i < gpuobj->size; i += 4) nvkm_wo32(gpuobj, i, 0x00000000); for (offset = 0; offset < gpuobj->size; offset += 4) nvkm_wo32(gpuobj, offset, 0x00000000); nvkm_done(gpuobj); } } else { ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, abs(align), zero, &gpuobj->memory); if (ret) return ret; gpuobj->func = &nvkm_gpuobj_heap; gpuobj->addr = nvkm_memory_addr(gpuobj->memory); gpuobj->size = nvkm_memory_size(gpuobj->memory); } return nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); } void nvkm_gpuobj_del(struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj *gpuobj = *pgpuobj; if (gpuobj) { if (gpuobj->parent) nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node); nvkm_mm_fini(&gpuobj->heap); nvkm_memory_del(&gpuobj->memory); kfree(*pgpuobj); *pgpuobj = NULL; } } int nvkm_gpuobj_new(struct nvkm_device *device, u32 size, int align, bool zero, struct nvkm_gpuobj *parent, struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj *gpuobj; int ret; if (!(gpuobj = *pgpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL))) return -ENOMEM; ret = nvkm_gpuobj_ctor(device, size, align, zero, parent, gpuobj); if (ret) nvkm_gpuobj_del(pgpuobj); return ret; } void nvkm_gpuobj_destroy(struct nvkm_gpuobj *gpuobj) { if (gpuobj->node) nvkm_mm_free(&nv_gpuobj(gpuobj->parent)->heap, &gpuobj->node); nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node); if (gpuobj->heap.block_size) gpuobj->heap.block_size = 1; nvkm_mm_fini(&gpuobj->heap); nvkm_memory_del(&gpuobj->memory); nvkm_object_destroy(&gpuobj->object); } static const struct nvkm_gpuobj_func nvkm_gpuobj_func = { .acquire = nvkm_gpuobj_acquire, .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32, .wr32 = nvkm_gpuobj_wr32, }; int nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, u32 pclass, Loading @@ -103,12 +238,10 @@ nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, int length, void **pobject) { struct nvkm_device *device = nv_device(parent); struct nvkm_memory *memory = NULL; struct nvkm_gpuobj *pargpu = NULL; struct nvkm_gpuobj *gpuobj; struct nvkm_mm *heap = NULL; int ret, i; u64 addr; const bool zero = (flags & NVOBJ_FLAG_ZERO_ALLOC); int ret; *pobject = NULL; Loading @@ -122,83 +255,18 @@ nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, if (WARN_ON(objgpu == NULL)) return -EINVAL; pargpu = nv_gpuobj(objgpu); addr = pargpu->addr; heap = &pargpu->heap; } else { ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, align, false, &memory); if (ret) return ret; addr = nvkm_memory_addr(memory); size = nvkm_memory_size(memory); } ret = nvkm_object_create_(parent, engine, oclass, pclass | NV_GPUOBJ_CLASS, length, pobject); gpuobj = *pobject; if (ret) { nvkm_memory_del(&memory); return ret; } gpuobj->func = &nvkm_gpuobj_func; gpuobj->memory = memory; gpuobj->parent = pargpu; gpuobj->flags = flags; gpuobj->addr = addr; gpuobj->size = size; if (heap) { ret = nvkm_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 = nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); if (ret) return ret; } if (flags & NVOBJ_FLAG_ZERO_ALLOC) { nvkm_kmap(gpuobj); for (i = 0; i < gpuobj->size; i += 4) nvkm_wo32(gpuobj, i, 0x00000000); nvkm_done(gpuobj); } return ret; } struct nvkm_gpuobj_class { struct nvkm_object *pargpu; u64 size; u32 align; u32 flags; }; static int _nvkm_gpuobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { struct nvkm_gpuobj_class *args = data; struct nvkm_gpuobj *object; int ret; ret = nvkm_gpuobj_create(parent, engine, oclass, 0, args->pargpu, args->size, args->align, args->flags, &object); *pobject = nv_object(object); if (ret) ret = nvkm_gpuobj_ctor(device, size, align, zero, pargpu, gpuobj); if (!(flags & NVOBJ_FLAG_HEAP)) gpuobj->heap.block_size = 0; return ret; return 0; } void Loading Loading @@ -233,38 +301,8 @@ _nvkm_gpuobj_wr32(struct nvkm_object *object, u64 addr, u32 data) nvkm_wo32(gpuobj, addr, data); } static struct nvkm_oclass _nvkm_gpuobj_oclass = { .handle = 0x00000000, .ofuncs = &(struct nvkm_ofuncs) { .ctor = _nvkm_gpuobj_ctor, .dtor = _nvkm_gpuobj_dtor, .init = _nvkm_gpuobj_init, .fini = _nvkm_gpuobj_fini, .rd32 = _nvkm_gpuobj_rd32, .wr32 = _nvkm_gpuobj_wr32, }, }; int nvkm_gpuobj_new(struct nvkm_object *parent, struct nvkm_object *pargpu, u32 size, u32 align, u32 flags, struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj_class args = { .pargpu = pargpu, .size = size, .align = align, .flags = flags, }; return nvkm_object_old(parent, &parent->engine->subdev.object, &_nvkm_gpuobj_oclass, &args, sizeof(args), (struct nvkm_object **)pgpuobj); } int nvkm_gpuobj_map_vm(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm, nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm, u32 access, struct nvkm_vma *vma) { struct nvkm_memory *memory = gpuobj->memory; Loading @@ -288,37 +326,13 @@ nvkm_gpuobj_unmap(struct nvkm_vma *vma) * anywhere else. */ static void nvkm_gpudup_dtor(struct nvkm_object *object) { struct nvkm_gpuobj *gpuobj = (void *)object; nvkm_object_destroy(&gpuobj->object); } static struct nvkm_oclass nvkm_gpudup_oclass = { .handle = NV_GPUOBJ_CLASS, .ofuncs = &(struct nvkm_ofuncs) { .dtor = nvkm_gpudup_dtor, .init = _nvkm_object_init, .fini = _nvkm_object_fini, }, }; int nvkm_gpuobj_dup(struct nvkm_object *parent, struct nvkm_memory *base, struct nvkm_gpuobj **pgpuobj) nvkm_gpuobj_wrap(struct nvkm_memory *memory, struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj *gpuobj; int ret; ret = nvkm_object_create(parent, &parent->engine->subdev.object, &nvkm_gpudup_oclass, 0, &gpuobj); *pgpuobj = gpuobj; if (ret) return ret; if (!(*pgpuobj = kzalloc(sizeof(**pgpuobj), GFP_KERNEL))) return -ENOMEM; gpuobj->addr = nvkm_memory_addr(base); gpuobj->size = nvkm_memory_size(base); (*pgpuobj)->addr = nvkm_memory_addr(memory); (*pgpuobj)->size = nvkm_memory_size(memory); return 0; } drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/base.c +47 −5 Original line number Diff line number Diff line Loading @@ -24,32 +24,74 @@ #include "priv.h" #include <core/client.h> #include <core/gpuobj.h> #include <subdev/fb.h> #include <subdev/instmem.h> #include <nvif/class.h> #include <nvif/unpack.h> struct hack { struct nvkm_gpuobj object; struct nvkm_gpuobj *parent; }; static void dtor(struct nvkm_object *object) { struct hack *hack = (void *)object; nvkm_gpuobj_del(&hack->parent); nvkm_object_destroy(&hack->object.object); } static struct nvkm_oclass hack = { .handle = NV_GPUOBJ_CLASS, .ofuncs = &(struct nvkm_ofuncs) { .dtor = dtor, .init = _nvkm_object_init, .fini = _nvkm_object_fini, }, }; static int nvkm_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, nvkm_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_gpuobj *pargpu, struct nvkm_gpuobj **pgpuobj) { const struct nvkm_dmaeng_impl *impl = (void *) nv_oclass(nv_object(dmaobj)->engine); int ret = 0; if (nv_object(dmaobj) == parent) { /* ctor bind */ if (&dmaobj->base == &pargpu->object) { /* ctor bind */ struct nvkm_object *parent = (void *)pargpu; struct hack *object; if (nv_mclass(parent->parent) == NV_DEVICE) { /* delayed, or no, binding */ return 0; } ret = impl->bind(dmaobj, parent, pgpuobj); if (ret == 0) pargpu = (void *)nv_pclass((void *)pargpu, NV_GPUOBJ_CLASS); ret = nvkm_object_create(parent, NULL, &hack, NV_GPUOBJ_CLASS, &object); if (ret == 0) { nvkm_object_ref(NULL, &parent); *pgpuobj = &object->object; ret = impl->bind(dmaobj, pargpu, &object->parent); if (ret) return ret; object->object.node = object->parent->node; object->object.addr = object->parent->addr; object->object.size = object->parent->size; return 0; } return ret; } return impl->bind(dmaobj, parent, pgpuobj); return impl->bind(dmaobj, pargpu, pgpuobj); } int Loading Loading
drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h +12 −12 Original line number Diff line number Diff line Loading @@ -7,30 +7,33 @@ struct nvkm_vma; struct nvkm_vm; #define NVOBJ_FLAG_ZERO_ALLOC 0x00000001 #define NVOBJ_FLAG_ZERO_FREE 0x00000002 #define NVOBJ_FLAG_HEAP 0x00000004 struct nvkm_gpuobj { struct nvkm_object object; struct nvkm_memory *memory; const struct nvkm_gpuobj_func *func; struct nvkm_gpuobj *parent; struct nvkm_memory *memory; struct nvkm_mm_node *node; struct nvkm_mm heap; u32 flags; u64 addr; u32 size; struct nvkm_mm heap; const struct nvkm_gpuobj_func *func; void __iomem *map; }; struct nvkm_gpuobj_func { void (*acquire)(struct nvkm_gpuobj *); void *(*acquire)(struct nvkm_gpuobj *); void (*release)(struct nvkm_gpuobj *); u32 (*rd32)(struct nvkm_gpuobj *, u32 offset); void (*wr32)(struct nvkm_gpuobj *, u32 offset, u32 data); }; int nvkm_gpuobj_new(struct nvkm_device *, u32 size, int align, bool zero, struct nvkm_gpuobj *parent, struct nvkm_gpuobj **); void nvkm_gpuobj_del(struct nvkm_gpuobj **); static inline struct nvkm_gpuobj * nv_gpuobj(void *obj) { Loading @@ -51,11 +54,8 @@ int nvkm_gpuobj_create_(struct nvkm_object *, struct nvkm_object *, u32 flags, int length, void **); void nvkm_gpuobj_destroy(struct nvkm_gpuobj *); int nvkm_gpuobj_new(struct nvkm_object *, struct nvkm_object *, u32 size, u32 align, u32 flags, struct nvkm_gpuobj **); int nvkm_gpuobj_dup(struct nvkm_object *, struct nvkm_memory *, struct nvkm_gpuobj **); int nvkm_gpuobj_map_vm(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **); int nvkm_gpuobj_map(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, struct nvkm_vma *); void nvkm_gpuobj_unmap(struct nvkm_vma *); Loading
drivers/gpu/drm/nouveau/include/nvkm/engine/dmaobj.h +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ struct nvkm_dmaeng { struct nvkm_engine engine; /* creates a "physical" dma object from a struct nvkm_dmaobj */ int (*bind)(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, int (*bind)(struct nvkm_dmaobj *dmaobj, struct nvkm_gpuobj *parent, struct nvkm_gpuobj **); }; Loading
drivers/gpu/drm/nouveau/nouveau_drm.c +3 −3 Original line number Diff line number Diff line Loading @@ -141,7 +141,7 @@ nouveau_accel_fini(struct nouveau_drm *drm) { nouveau_channel_del(&drm->channel); nvif_object_fini(&drm->ntfy); nvkm_gpuobj_ref(NULL, &drm->notify); nvkm_gpuobj_del(&drm->notify); nvif_object_fini(&drm->nvsw); nouveau_channel_del(&drm->cechan); nvif_object_fini(&drm->ttm.copy); Loading Loading @@ -264,8 +264,8 @@ nouveau_accel_init(struct nouveau_drm *drm) } if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { ret = nvkm_gpuobj_new(nvxx_object(&drm->device.object), NULL, 32, 0, 0, &drm->notify); ret = nvkm_gpuobj_new(nvxx_device(&drm->device), 32, 0, false, NULL, &drm->notify); if (ret) { NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); nouveau_accel_fini(drm); Loading
drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c +186 −172 Original line number Diff line number Diff line Loading @@ -28,74 +28,209 @@ #include <subdev/bar.h> #include <subdev/mmu.h> /* fast-path, where backend is able to provide direct pointer to memory */ static u32 nvkm_gpuobj_rd32_fast(struct nvkm_gpuobj *gpuobj, u32 offset) { return ioread32_native(gpuobj->map + offset); } static void nvkm_gpuobj_release(struct nvkm_gpuobj *gpuobj) nvkm_gpuobj_wr32_fast(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) { if (gpuobj->node) { nvkm_done(gpuobj->parent); return; iowrite32_native(data, gpuobj->map + offset); } nvkm_done(gpuobj->memory); /* accessor functions for gpuobjs allocated directly from instmem */ static u32 nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) { return nvkm_ro32(gpuobj->memory, offset); } static void nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj) nvkm_gpuobj_heap_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) { nvkm_wo32(gpuobj->memory, offset, data); } static const struct nvkm_gpuobj_func nvkm_gpuobj_heap; static void nvkm_gpuobj_heap_release(struct nvkm_gpuobj *gpuobj) { if (gpuobj->node) { nvkm_kmap(gpuobj->parent); return; gpuobj->func = &nvkm_gpuobj_heap; nvkm_done(gpuobj->memory); } nvkm_kmap(gpuobj->memory); static const struct nvkm_gpuobj_func nvkm_gpuobj_heap_fast = { .release = nvkm_gpuobj_heap_release, .rd32 = nvkm_gpuobj_rd32_fast, .wr32 = nvkm_gpuobj_wr32_fast, }; static const struct nvkm_gpuobj_func nvkm_gpuobj_heap_slow = { .release = nvkm_gpuobj_heap_release, .rd32 = nvkm_gpuobj_heap_rd32, .wr32 = nvkm_gpuobj_heap_wr32, }; static void * nvkm_gpuobj_heap_acquire(struct nvkm_gpuobj *gpuobj) { gpuobj->map = nvkm_kmap(gpuobj->memory); if (likely(gpuobj->map)) gpuobj->func = &nvkm_gpuobj_heap_fast; else gpuobj->func = &nvkm_gpuobj_heap_slow; return gpuobj->map; } static const struct nvkm_gpuobj_func nvkm_gpuobj_heap = { .acquire = nvkm_gpuobj_heap_acquire, }; /* accessor functions for gpuobjs sub-allocated from a parent gpuobj */ static u32 nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) { if (gpuobj->node) return nvkm_ro32(gpuobj->parent, gpuobj->node->offset + offset); return nvkm_ro32(gpuobj->memory, offset); } static void nvkm_gpuobj_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) { if (gpuobj->node) { nvkm_wo32(gpuobj->parent, gpuobj->node->offset + offset, data); return; } nvkm_wo32(gpuobj->memory, offset, data); static const struct nvkm_gpuobj_func nvkm_gpuobj_func; static void nvkm_gpuobj_release(struct nvkm_gpuobj *gpuobj) { gpuobj->func = &nvkm_gpuobj_func; nvkm_done(gpuobj->parent); } void nvkm_gpuobj_destroy(struct nvkm_gpuobj *gpuobj) static const struct nvkm_gpuobj_func nvkm_gpuobj_fast = { .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32_fast, .wr32 = nvkm_gpuobj_wr32_fast, }; static const struct nvkm_gpuobj_func nvkm_gpuobj_slow = { .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32, .wr32 = nvkm_gpuobj_wr32, }; static void * nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj) { int i; gpuobj->map = nvkm_kmap(gpuobj->parent); if (likely(gpuobj->map)) { gpuobj->map = (u8 *)gpuobj->map + gpuobj->node->offset; gpuobj->func = &nvkm_gpuobj_fast; } else { gpuobj->func = &nvkm_gpuobj_slow; } return gpuobj->map; } static const struct nvkm_gpuobj_func nvkm_gpuobj_func = { .acquire = nvkm_gpuobj_acquire, }; if (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE) { static int nvkm_gpuobj_ctor(struct nvkm_device *device, u32 size, int align, bool zero, struct nvkm_gpuobj *parent, struct nvkm_gpuobj *gpuobj) { u32 offset; int ret; if (parent) { if (align >= 0) { ret = nvkm_mm_head(&parent->heap, 0, 1, size, size, max(align, 1), &gpuobj->node); } else { ret = nvkm_mm_tail(&parent->heap, 0, 1, size, size, -align, &gpuobj->node); } if (ret) return ret; gpuobj->parent = parent; gpuobj->func = &nvkm_gpuobj_func; gpuobj->addr = parent->addr + gpuobj->node->offset; gpuobj->size = gpuobj->node->length; if (zero) { nvkm_kmap(gpuobj); for (i = 0; i < gpuobj->size; i += 4) nvkm_wo32(gpuobj, i, 0x00000000); for (offset = 0; offset < gpuobj->size; offset += 4) nvkm_wo32(gpuobj, offset, 0x00000000); nvkm_done(gpuobj); } } else { ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, abs(align), zero, &gpuobj->memory); if (ret) return ret; gpuobj->func = &nvkm_gpuobj_heap; gpuobj->addr = nvkm_memory_addr(gpuobj->memory); gpuobj->size = nvkm_memory_size(gpuobj->memory); } return nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); } void nvkm_gpuobj_del(struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj *gpuobj = *pgpuobj; if (gpuobj) { if (gpuobj->parent) nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node); nvkm_mm_fini(&gpuobj->heap); nvkm_memory_del(&gpuobj->memory); kfree(*pgpuobj); *pgpuobj = NULL; } } int nvkm_gpuobj_new(struct nvkm_device *device, u32 size, int align, bool zero, struct nvkm_gpuobj *parent, struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj *gpuobj; int ret; if (!(gpuobj = *pgpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL))) return -ENOMEM; ret = nvkm_gpuobj_ctor(device, size, align, zero, parent, gpuobj); if (ret) nvkm_gpuobj_del(pgpuobj); return ret; } void nvkm_gpuobj_destroy(struct nvkm_gpuobj *gpuobj) { if (gpuobj->node) nvkm_mm_free(&nv_gpuobj(gpuobj->parent)->heap, &gpuobj->node); nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node); if (gpuobj->heap.block_size) gpuobj->heap.block_size = 1; nvkm_mm_fini(&gpuobj->heap); nvkm_memory_del(&gpuobj->memory); nvkm_object_destroy(&gpuobj->object); } static const struct nvkm_gpuobj_func nvkm_gpuobj_func = { .acquire = nvkm_gpuobj_acquire, .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32, .wr32 = nvkm_gpuobj_wr32, }; int nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, u32 pclass, Loading @@ -103,12 +238,10 @@ nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, int length, void **pobject) { struct nvkm_device *device = nv_device(parent); struct nvkm_memory *memory = NULL; struct nvkm_gpuobj *pargpu = NULL; struct nvkm_gpuobj *gpuobj; struct nvkm_mm *heap = NULL; int ret, i; u64 addr; const bool zero = (flags & NVOBJ_FLAG_ZERO_ALLOC); int ret; *pobject = NULL; Loading @@ -122,83 +255,18 @@ nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine, if (WARN_ON(objgpu == NULL)) return -EINVAL; pargpu = nv_gpuobj(objgpu); addr = pargpu->addr; heap = &pargpu->heap; } else { ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, align, false, &memory); if (ret) return ret; addr = nvkm_memory_addr(memory); size = nvkm_memory_size(memory); } ret = nvkm_object_create_(parent, engine, oclass, pclass | NV_GPUOBJ_CLASS, length, pobject); gpuobj = *pobject; if (ret) { nvkm_memory_del(&memory); return ret; } gpuobj->func = &nvkm_gpuobj_func; gpuobj->memory = memory; gpuobj->parent = pargpu; gpuobj->flags = flags; gpuobj->addr = addr; gpuobj->size = size; if (heap) { ret = nvkm_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 = nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); if (ret) return ret; } if (flags & NVOBJ_FLAG_ZERO_ALLOC) { nvkm_kmap(gpuobj); for (i = 0; i < gpuobj->size; i += 4) nvkm_wo32(gpuobj, i, 0x00000000); nvkm_done(gpuobj); } return ret; } struct nvkm_gpuobj_class { struct nvkm_object *pargpu; u64 size; u32 align; u32 flags; }; static int _nvkm_gpuobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { struct nvkm_gpuobj_class *args = data; struct nvkm_gpuobj *object; int ret; ret = nvkm_gpuobj_create(parent, engine, oclass, 0, args->pargpu, args->size, args->align, args->flags, &object); *pobject = nv_object(object); if (ret) ret = nvkm_gpuobj_ctor(device, size, align, zero, pargpu, gpuobj); if (!(flags & NVOBJ_FLAG_HEAP)) gpuobj->heap.block_size = 0; return ret; return 0; } void Loading Loading @@ -233,38 +301,8 @@ _nvkm_gpuobj_wr32(struct nvkm_object *object, u64 addr, u32 data) nvkm_wo32(gpuobj, addr, data); } static struct nvkm_oclass _nvkm_gpuobj_oclass = { .handle = 0x00000000, .ofuncs = &(struct nvkm_ofuncs) { .ctor = _nvkm_gpuobj_ctor, .dtor = _nvkm_gpuobj_dtor, .init = _nvkm_gpuobj_init, .fini = _nvkm_gpuobj_fini, .rd32 = _nvkm_gpuobj_rd32, .wr32 = _nvkm_gpuobj_wr32, }, }; int nvkm_gpuobj_new(struct nvkm_object *parent, struct nvkm_object *pargpu, u32 size, u32 align, u32 flags, struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj_class args = { .pargpu = pargpu, .size = size, .align = align, .flags = flags, }; return nvkm_object_old(parent, &parent->engine->subdev.object, &_nvkm_gpuobj_oclass, &args, sizeof(args), (struct nvkm_object **)pgpuobj); } int nvkm_gpuobj_map_vm(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm, nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm, u32 access, struct nvkm_vma *vma) { struct nvkm_memory *memory = gpuobj->memory; Loading @@ -288,37 +326,13 @@ nvkm_gpuobj_unmap(struct nvkm_vma *vma) * anywhere else. */ static void nvkm_gpudup_dtor(struct nvkm_object *object) { struct nvkm_gpuobj *gpuobj = (void *)object; nvkm_object_destroy(&gpuobj->object); } static struct nvkm_oclass nvkm_gpudup_oclass = { .handle = NV_GPUOBJ_CLASS, .ofuncs = &(struct nvkm_ofuncs) { .dtor = nvkm_gpudup_dtor, .init = _nvkm_object_init, .fini = _nvkm_object_fini, }, }; int nvkm_gpuobj_dup(struct nvkm_object *parent, struct nvkm_memory *base, struct nvkm_gpuobj **pgpuobj) nvkm_gpuobj_wrap(struct nvkm_memory *memory, struct nvkm_gpuobj **pgpuobj) { struct nvkm_gpuobj *gpuobj; int ret; ret = nvkm_object_create(parent, &parent->engine->subdev.object, &nvkm_gpudup_oclass, 0, &gpuobj); *pgpuobj = gpuobj; if (ret) return ret; if (!(*pgpuobj = kzalloc(sizeof(**pgpuobj), GFP_KERNEL))) return -ENOMEM; gpuobj->addr = nvkm_memory_addr(base); gpuobj->size = nvkm_memory_size(base); (*pgpuobj)->addr = nvkm_memory_addr(memory); (*pgpuobj)->size = nvkm_memory_size(memory); return 0; }
drivers/gpu/drm/nouveau/nvkm/engine/dmaobj/base.c +47 −5 Original line number Diff line number Diff line Loading @@ -24,32 +24,74 @@ #include "priv.h" #include <core/client.h> #include <core/gpuobj.h> #include <subdev/fb.h> #include <subdev/instmem.h> #include <nvif/class.h> #include <nvif/unpack.h> struct hack { struct nvkm_gpuobj object; struct nvkm_gpuobj *parent; }; static void dtor(struct nvkm_object *object) { struct hack *hack = (void *)object; nvkm_gpuobj_del(&hack->parent); nvkm_object_destroy(&hack->object.object); } static struct nvkm_oclass hack = { .handle = NV_GPUOBJ_CLASS, .ofuncs = &(struct nvkm_ofuncs) { .dtor = dtor, .init = _nvkm_object_init, .fini = _nvkm_object_fini, }, }; static int nvkm_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_object *parent, nvkm_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_gpuobj *pargpu, struct nvkm_gpuobj **pgpuobj) { const struct nvkm_dmaeng_impl *impl = (void *) nv_oclass(nv_object(dmaobj)->engine); int ret = 0; if (nv_object(dmaobj) == parent) { /* ctor bind */ if (&dmaobj->base == &pargpu->object) { /* ctor bind */ struct nvkm_object *parent = (void *)pargpu; struct hack *object; if (nv_mclass(parent->parent) == NV_DEVICE) { /* delayed, or no, binding */ return 0; } ret = impl->bind(dmaobj, parent, pgpuobj); if (ret == 0) pargpu = (void *)nv_pclass((void *)pargpu, NV_GPUOBJ_CLASS); ret = nvkm_object_create(parent, NULL, &hack, NV_GPUOBJ_CLASS, &object); if (ret == 0) { nvkm_object_ref(NULL, &parent); *pgpuobj = &object->object; ret = impl->bind(dmaobj, pargpu, &object->parent); if (ret) return ret; object->object.node = object->parent->node; object->object.addr = object->parent->addr; object->object.size = object->parent->size; return 0; } return ret; } return impl->bind(dmaobj, parent, pgpuobj); return impl->bind(dmaobj, pargpu, pgpuobj); } int Loading