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)
{
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,
- struct nvkm_vma *);
+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 *);
static inline void
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 **);
};
{
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);
}
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);
#include <subdev/bar.h>
#include <subdev/mmu.h>
-static void
-nvkm_gpuobj_release(struct nvkm_gpuobj *gpuobj)
+/* fast-path, where backend is able to provide direct pointer to memory */
+static u32
+nvkm_gpuobj_rd32_fast(struct nvkm_gpuobj *gpuobj, u32 offset)
{
- if (gpuobj->node) {
- nvkm_done(gpuobj->parent);
- return;
- }
- nvkm_done(gpuobj->memory);
+ return ioread32_native(gpuobj->map + offset);
}
static void
-nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj)
+nvkm_gpuobj_wr32_fast(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data)
{
- if (gpuobj->node) {
- nvkm_kmap(gpuobj->parent);
- return;
- }
- nvkm_kmap(gpuobj->memory);
+ iowrite32_native(data, gpuobj->map + offset);
}
+/* accessor functions for gpuobjs allocated directly from instmem */
static u32
-nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset)
+nvkm_gpuobj_heap_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)
+nvkm_gpuobj_heap_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);
}
-void
-nvkm_gpuobj_destroy(struct nvkm_gpuobj *gpuobj)
+static const struct nvkm_gpuobj_func nvkm_gpuobj_heap;
+static void
+nvkm_gpuobj_heap_release(struct nvkm_gpuobj *gpuobj)
{
- int i;
+ gpuobj->func = &nvkm_gpuobj_heap;
+ nvkm_done(gpuobj->memory);
+}
- if (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE) {
- nvkm_kmap(gpuobj);
- for (i = 0; i < gpuobj->size; i += 4)
- nvkm_wo32(gpuobj, i, 0x00000000);
- nvkm_done(gpuobj);
- }
+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,
+};
- if (gpuobj->node)
- nvkm_mm_free(&nv_gpuobj(gpuobj->parent)->heap, &gpuobj->node);
+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,
+};
- if (gpuobj->heap.block_size)
- nvkm_mm_fini(&gpuobj->heap);
+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;
+}
- nvkm_memory_del(&gpuobj->memory);
- nvkm_object_destroy(&gpuobj->object);
+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)
+{
+ return nvkm_ro32(gpuobj->parent, gpuobj->node->offset + offset);
+}
+
+static void
+nvkm_gpuobj_wr32(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data)
+{
+ nvkm_wo32(gpuobj->parent, gpuobj->node->offset + 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);
}
static const struct nvkm_gpuobj_func
-nvkm_gpuobj_func = {
- .acquire = nvkm_gpuobj_acquire,
+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)
+{
+ 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,
+};
+
+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 (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(&gpuobj->parent->heap, &gpuobj->node);
+
+ gpuobj->heap.block_size = 1;
+ nvkm_mm_fini(&gpuobj->heap);
+
+ nvkm_memory_del(&gpuobj->memory);
+ nvkm_object_destroy(&gpuobj->object);
+}
+
int
nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, u32 pclass,
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;
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)
return ret;
- return 0;
+ ret = nvkm_gpuobj_ctor(device, size, align, zero, pargpu, gpuobj);
+ if (!(flags & NVOBJ_FLAG_HEAP))
+ gpuobj->heap.block_size = 0;
+ return ret;
}
void
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,
- u32 access, struct nvkm_vma *vma)
+nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm,
+ u32 access, struct nvkm_vma *vma)
{
struct nvkm_memory *memory = gpuobj->memory;
int ret = nvkm_vm_get(vm, gpuobj->size, 12, access, 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;
}
#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
};
static int
-gf100_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_object *parent,
+gf100_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_gpuobj *parent,
struct nvkm_gpuobj **pgpuobj)
{
struct gf100_dmaobj *dmaobj = container_of(obj, typeof(*dmaobj), base);
+ struct nvkm_device *device = dmaobj->base.base.engine->subdev.device;
int ret;
- if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
- switch (nv_mclass(parent->parent)) {
- case GT214_DISP_CORE_CHANNEL_DMA:
- case GT214_DISP_BASE_CHANNEL_DMA:
- case GT214_DISP_OVERLAY_CHANNEL_DMA:
- break;
- default:
- return -EINVAL;
- }
- } else
- return 0;
-
- ret = nvkm_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+ ret = nvkm_gpuobj_new(device, 24, 32, false, parent, pgpuobj);
if (ret == 0) {
nvkm_kmap(*pgpuobj);
nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0 | nv_mclass(dmaobj));
break;
}
- return dmaeng->bind(&dmaobj->base, nv_object(dmaobj), (void *)pobject);
+ return dmaeng->bind(&dmaobj->base, (void *)dmaobj, (void *)pobject);
}
static struct nvkm_ofuncs
};
static int
-gf110_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_object *parent,
+gf110_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_gpuobj *parent,
struct nvkm_gpuobj **pgpuobj)
{
struct gf110_dmaobj *dmaobj = container_of(obj, typeof(*dmaobj), base);
+ struct nvkm_device *device = dmaobj->base.base.engine->subdev.device;
int ret;
- if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
- switch (nv_mclass(parent->parent)) {
- case GF110_DISP_CORE_CHANNEL_DMA:
- case GK104_DISP_CORE_CHANNEL_DMA:
- case GK110_DISP_CORE_CHANNEL_DMA:
- case GM107_DISP_CORE_CHANNEL_DMA:
- case GM204_DISP_CORE_CHANNEL_DMA:
- case GF110_DISP_BASE_CHANNEL_DMA:
- case GK104_DISP_BASE_CHANNEL_DMA:
- case GK110_DISP_BASE_CHANNEL_DMA:
- case GF110_DISP_OVERLAY_CONTROL_DMA:
- case GK104_DISP_OVERLAY_CONTROL_DMA:
- break;
- default:
- return -EINVAL;
- }
- } else
- return 0;
-
- ret = nvkm_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+ ret = nvkm_gpuobj_new(device, 24, 32, false, parent, pgpuobj);
if (ret == 0) {
nvkm_kmap(*pgpuobj);
nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0);
return -EINVAL;
}
- return dmaeng->bind(&dmaobj->base, nv_object(dmaobj), (void *)pobject);
+ return dmaeng->bind(&dmaobj->base, (void *)dmaobj, (void *)pobject);
}
static struct nvkm_ofuncs
};
static int
-nv04_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_object *parent,
+nv04_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_gpuobj *parent,
struct nvkm_gpuobj **pgpuobj)
{
struct nv04_dmaobj *dmaobj = container_of(obj, typeof(*dmaobj), base);
- struct nvkm_gpuobj *gpuobj;
+ struct nvkm_device *device = dmaobj->base.base.engine->subdev.device;
u64 offset = dmaobj->base.start & 0xfffff000;
u64 adjust = dmaobj->base.start & 0x00000fff;
u32 length = dmaobj->base.limit - dmaobj->base.start;
int ret;
- if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
- switch (nv_mclass(parent->parent)) {
- case NV03_CHANNEL_DMA:
- case NV10_CHANNEL_DMA:
- case NV17_CHANNEL_DMA:
- case NV40_CHANNEL_DMA:
- break;
- default:
- return -EINVAL;
- }
- }
-
if (dmaobj->clone) {
struct nv04_mmu *mmu = nv04_mmu(dmaobj);
struct nvkm_memory *pgt = mmu->vm->pgt[0].mem[0];
if (!dmaobj->base.start)
- return nvkm_gpuobj_dup(parent, pgt, pgpuobj);
+ return nvkm_gpuobj_wrap(pgt, pgpuobj);
nvkm_kmap(pgt);
offset = nvkm_ro32(pgt, 8 + (offset >> 10));
offset &= 0xfffff000;
nvkm_done(pgt);
}
- ret = nvkm_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
- *pgpuobj = gpuobj;
+ ret = nvkm_gpuobj_new(device, 16, 16, false, parent, pgpuobj);
if (ret == 0) {
nvkm_kmap(*pgpuobj);
nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0 | (adjust << 20));
return -EINVAL;
}
- return dmaeng->bind(&dmaobj->base, nv_object(dmaobj), (void *)pobject);
+ return dmaeng->bind(&dmaobj->base, (void *)dmaobj, (void *)pobject);
}
static struct nvkm_ofuncs
};
static int
-nv50_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_object *parent,
+nv50_dmaobj_bind(struct nvkm_dmaobj *obj, struct nvkm_gpuobj *parent,
struct nvkm_gpuobj **pgpuobj)
{
struct nv50_dmaobj *dmaobj = container_of(obj, typeof(*dmaobj), base);
+ struct nvkm_device *device = dmaobj->base.base.engine->subdev.device;
int ret;
- if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
- switch (nv_mclass(parent->parent)) {
- case NV40_CHANNEL_DMA:
- case NV50_CHANNEL_GPFIFO:
- case G82_CHANNEL_GPFIFO:
- case NV50_DISP_CORE_CHANNEL_DMA:
- case G82_DISP_CORE_CHANNEL_DMA:
- case GT206_DISP_CORE_CHANNEL_DMA:
- case GT200_DISP_CORE_CHANNEL_DMA:
- case GT214_DISP_CORE_CHANNEL_DMA:
- case NV50_DISP_BASE_CHANNEL_DMA:
- case G82_DISP_BASE_CHANNEL_DMA:
- case GT200_DISP_BASE_CHANNEL_DMA:
- case GT214_DISP_BASE_CHANNEL_DMA:
- case NV50_DISP_OVERLAY_CHANNEL_DMA:
- case G82_DISP_OVERLAY_CHANNEL_DMA:
- case GT200_DISP_OVERLAY_CHANNEL_DMA:
- case GT214_DISP_OVERLAY_CHANNEL_DMA:
- break;
- default:
- return -EINVAL;
- }
- }
-
- ret = nvkm_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+ ret = nvkm_gpuobj_new(device, 24, 32, false, parent, pgpuobj);
if (ret == 0) {
nvkm_kmap(*pgpuobj);
nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0 | nv_mclass(dmaobj));
return -EINVAL;
}
- return dmaeng->bind(&dmaobj->base, nv_object(dmaobj), (void *)pobject);
+ return dmaeng->bind(&dmaobj->base, (void *)dmaobj, (void *)pobject);
}
static struct nvkm_ofuncs
struct nvkm_dmaeng_impl {
struct nvkm_oclass base;
struct nvkm_oclass *sclass;
- int (*bind)(struct nvkm_dmaobj *, struct nvkm_object *,
+ int (*bind)(struct nvkm_dmaobj *, struct nvkm_gpuobj *,
struct nvkm_gpuobj **);
};
#endif
struct nvkm_handle *handle;
struct nvkm_dmaobj *dmaobj;
struct nvkm_fifo *fifo = (void *)engine;
+ struct nvkm_fifo_base *base = (void *)parent;
struct nvkm_fifo_chan *chan;
struct nvkm_dmaeng *dmaeng;
struct nvkm_subdev *subdev = &fifo->engine.subdev;
return -EINVAL;
}
- ret = dmaeng->bind(dmaobj, parent, &chan->pushgpu);
+ ret = dmaeng->bind(dmaobj, &base->gpuobj, &chan->pushgpu);
if (ret)
return ret;
}
fifo->channel[chan->chid] = NULL;
spin_unlock_irqrestore(&fifo->lock, flags);
- nvkm_gpuobj_ref(NULL, &chan->pushgpu);
+ nvkm_gpuobj_del(&chan->pushgpu);
nvkm_namedb_destroy(&chan->namedb);
}
else
context = 0x00000004; /* just non-zero */
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW : context |= 0x00000000; break;
- case NVDEV_ENGINE_GR : context |= 0x00100000; break;
- case NVDEV_ENGINE_MPEG :
- case NVDEV_ENGINE_MSPPP : context |= 0x00200000; break;
- case NVDEV_ENGINE_ME :
- case NVDEV_ENGINE_CE0 : context |= 0x00300000; break;
- case NVDEV_ENGINE_VP :
- case NVDEV_ENGINE_MSPDEC: context |= 0x00400000; break;
- case NVDEV_ENGINE_CIPHER:
- case NVDEV_ENGINE_SEC :
- case NVDEV_ENGINE_VIC : context |= 0x00500000; break;
- case NVDEV_ENGINE_BSP :
- case NVDEV_ENGINE_MSVLD : context |= 0x00600000; break;
- default:
- return -EINVAL;
+ if (object->engine) {
+ switch (nv_engidx(object->engine)) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : context |= 0x00000000; break;
+ case NVDEV_ENGINE_GR : context |= 0x00100000; break;
+ case NVDEV_ENGINE_MPEG :
+ case NVDEV_ENGINE_MSPPP : context |= 0x00200000; break;
+ case NVDEV_ENGINE_ME :
+ case NVDEV_ENGINE_CE0 : context |= 0x00300000; break;
+ case NVDEV_ENGINE_VP :
+ case NVDEV_ENGINE_MSPDEC: context |= 0x00400000; break;
+ case NVDEV_ENGINE_CIPHER:
+ case NVDEV_ENGINE_SEC :
+ case NVDEV_ENGINE_VIC : context |= 0x00500000; break;
+ case NVDEV_ENGINE_BSP :
+ case NVDEV_ENGINE_MSVLD : context |= 0x00600000; break;
+ default:
+ return -EINVAL;
+ }
}
return nvkm_ramht_insert(chan->ramht, 0, handle, context);
struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject)
{
+ struct nvkm_device *device = nv_engine(engine)->subdev.device;
struct nv50_fifo_base *base;
int ret;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x0200, 0,
- NVOBJ_FLAG_ZERO_ALLOC, &base->eng);
+ ret = nvkm_gpuobj_new(device, 0x0200, 0, true, &base->base.gpuobj,
+ &base->eng);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x4000, 0,
- 0, &base->pgd);
+ ret = nvkm_gpuobj_new(device, 0x4000, 0, false, &base->base.gpuobj,
+ &base->pgd);
if (ret)
return ret;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x1000,
- 0x400, NVOBJ_FLAG_ZERO_ALLOC, &base->cache);
+ ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, &base->base.gpuobj,
+ &base->cache);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x0100,
- 0x100, NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc);
+ ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, &base->base.gpuobj,
+ &base->ramfc);
if (ret)
return ret;
}
if (!ectx->vma.node) {
- ret = nvkm_gpuobj_map_vm(nv_gpuobj(ectx), base->vm,
- NV_MEM_ACCESS_RW, &ectx->vma);
+ ret = nvkm_gpuobj_map(nv_gpuobj(ectx), base->vm,
+ NV_MEM_ACCESS_RW, &ectx->vma);
if (ret)
return ret;
struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject)
{
+ struct nvkm_device *device = nv_engine(engine)->subdev.device;
struct gf100_fifo_base *base;
int ret;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), NULL, 0x10000, 0x1000, 0,
- &base->pgd);
+ ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &base->pgd);
if (ret)
return ret;
{
struct gf100_fifo_base *base = (void *)object;
nvkm_vm_ref(NULL, &base->vm, base->pgd);
- nvkm_gpuobj_ref(NULL, &base->pgd);
+ nvkm_gpuobj_del(&base->pgd);
nvkm_fifo_context_destroy(&base->base);
}
}
if (!ectx->vma.node) {
- ret = nvkm_gpuobj_map_vm(nv_gpuobj(ectx), base->vm,
- NV_MEM_ACCESS_RW, &ectx->vma);
+ ret = nvkm_gpuobj_map(nv_gpuobj(ectx), base->vm,
+ NV_MEM_ACCESS_RW, &ectx->vma);
if (ret)
return ret;
struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject)
{
+ struct nvkm_device *device = nv_engine(engine)->subdev.device;
struct gk104_fifo_base *base;
int ret;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), NULL, 0x10000, 0x1000, 0,
- &base->pgd);
+ ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &base->pgd);
if (ret)
return ret;
{
struct gk104_fifo_base *base = (void *)object;
nvkm_vm_ref(NULL, &base->vm, base->pgd);
- nvkm_gpuobj_ref(NULL, &base->pgd);
+ nvkm_gpuobj_del(&base->pgd);
nvkm_fifo_context_destroy(&base->base);
}
else
context = 0x00000004; /* just non-zero */
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW:
- context |= 0x00000000;
- break;
- case NVDEV_ENGINE_GR:
- context |= 0x00010000;
- break;
- case NVDEV_ENGINE_MPEG:
- context |= 0x00020000;
- break;
- default:
- return -EINVAL;
+ if (object->engine) {
+ switch (nv_engidx(object->engine)) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW:
+ context |= 0x00000000;
+ break;
+ case NVDEV_ENGINE_GR:
+ context |= 0x00010000;
+ break;
+ case NVDEV_ENGINE_MPEG:
+ context |= 0x00020000;
+ break;
+ default:
+ return -EINVAL;
+ }
}
context |= 0x80000000; /* valid */
else
context = 0x00000004; /* just non-zero */
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW:
- context |= 0x00000000;
- break;
- case NVDEV_ENGINE_GR:
- context |= 0x00100000;
- break;
- case NVDEV_ENGINE_MPEG:
- context |= 0x00200000;
- break;
- default:
- return -EINVAL;
+ if (object->engine) {
+ switch (nv_engidx(object->engine)) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW:
+ context |= 0x00000000;
+ break;
+ case NVDEV_ENGINE_GR:
+ context |= 0x00100000;
+ break;
+ case NVDEV_ENGINE_MPEG:
+ context |= 0x00200000;
+ break;
+ default:
+ return -EINVAL;
+ }
}
context |= chid << 23;
else
context = 0x00000004; /* just non-zero */
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW : context |= 0x00000000; break;
- case NVDEV_ENGINE_GR : context |= 0x00100000; break;
- case NVDEV_ENGINE_MPEG : context |= 0x00200000; break;
- default:
- return -EINVAL;
+ if (object->engine) {
+ switch (nv_engidx(object->engine)) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : context |= 0x00000000; break;
+ case NVDEV_ENGINE_GR : context |= 0x00100000; break;
+ case NVDEV_ENGINE_MPEG : context |= 0x00200000; break;
+ default:
+ return -EINVAL;
+ }
}
return nvkm_ramht_insert(chan->ramht, 0, handle, context);
struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject)
{
+ struct nvkm_device *device = nv_engine(engine)->subdev.device;
struct nv50_fifo_base *base;
int ret;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x0200,
- 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc);
+ ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, &base->base.gpuobj,
+ &base->ramfc);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x1200, 0,
- NVOBJ_FLAG_ZERO_ALLOC, &base->eng);
+ ret = nvkm_gpuobj_new(device, 0x1200, 0, true, &base->base.gpuobj,
+ &base->eng);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(base), nv_object(base), 0x4000, 0, 0,
+ ret = nvkm_gpuobj_new(device, 0x4000, 0, false, &base->base.gpuobj,
&base->pgd);
if (ret)
return ret;
{
struct nv50_fifo_base *base = (void *)object;
nvkm_vm_ref(NULL, &base->vm, base->pgd);
- nvkm_gpuobj_ref(NULL, &base->pgd);
- nvkm_gpuobj_ref(NULL, &base->eng);
- nvkm_gpuobj_ref(NULL, &base->ramfc);
- nvkm_gpuobj_ref(NULL, &base->cache);
+ nvkm_gpuobj_del(&base->pgd);
+ nvkm_gpuobj_del(&base->eng);
+ nvkm_gpuobj_del(&base->ramfc);
+ nvkm_gpuobj_del(&base->cache);
nvkm_fifo_context_destroy(&base->base);
}
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(bar), NULL, 0x8000, 0, 0,
- &bar_vm->pgd);
+ ret = nvkm_gpuobj_new(device, 0x8000, 0, false, NULL, &bar_vm->pgd);
if (ret)
return ret;
struct gf100_bar *bar = (void *)object;
nvkm_vm_ref(NULL, &bar->bar[1].vm, bar->bar[1].pgd);
- nvkm_gpuobj_ref(NULL, &bar->bar[1].pgd);
+ nvkm_gpuobj_del(&bar->bar[1].pgd);
nvkm_memory_del(&bar->bar[1].mem);
if (bar->bar[0].vm) {
nvkm_memory_del(&bar->bar[0].vm->pgt[0].mem[0]);
nvkm_vm_ref(NULL, &bar->bar[0].vm, bar->bar[0].pgd);
}
- nvkm_gpuobj_ref(NULL, &bar->bar[0].pgd);
+ nvkm_gpuobj_del(&bar->bar[0].pgd);
nvkm_memory_del(&bar->bar[0].mem);
nvkm_bar_destroy(&bar->base);
static struct lock_class_key bar1_lock;
static struct lock_class_key bar3_lock;
struct nvkm_device *device = nv_device(parent);
- struct nvkm_object *heap;
struct nvkm_vm *vm;
struct nv50_bar *bar;
u64 start, limit;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(bar), NULL, 0x20000, 0,
- NVOBJ_FLAG_HEAP, &bar->mem);
- heap = nv_object(bar->mem);
+ ret = nvkm_gpuobj_new(device, 0x20000, 0, false, NULL, &bar->mem);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(bar), heap,
- (device->chipset == 0x50) ? 0x1400 : 0x0200,
- 0, 0, &bar->pad);
+ ret = nvkm_gpuobj_new(device, (device->chipset == 0x50) ?
+ 0x1400 : 0x200, 0, false, bar->mem,
+ &bar->pad);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(bar), heap, 0x4000, 0, 0, &bar->pgd);
+ ret = nvkm_gpuobj_new(device, 0x4000, 0, false, bar->mem, &bar->pgd);
if (ret)
return ret;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(bar), heap, 24, 16, 0, &bar->bar3);
+ ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar3);
if (ret)
return ret;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(bar), heap, 24, 16, 0, &bar->bar1);
+ ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar1);
if (ret)
return ret;
nv50_bar_dtor(struct nvkm_object *object)
{
struct nv50_bar *bar = (void *)object;
- nvkm_gpuobj_ref(NULL, &bar->bar1);
+ nvkm_gpuobj_del(&bar->bar1);
nvkm_vm_ref(NULL, &bar->bar1_vm, bar->pgd);
- nvkm_gpuobj_ref(NULL, &bar->bar3);
+ nvkm_gpuobj_del(&bar->bar3);
if (bar->bar3_vm) {
nvkm_memory_del(&bar->bar3_vm->pgt[0].mem[0]);
nvkm_vm_ref(NULL, &bar->bar3_vm, bar->pgd);
}
- nvkm_gpuobj_ref(NULL, &bar->pgd);
- nvkm_gpuobj_ref(NULL, &bar->pad);
- nvkm_gpuobj_ref(NULL, &bar->mem);
+ nvkm_gpuobj_del(&bar->pgd);
+ nvkm_gpuobj_del(&bar->pad);
+ nvkm_gpuobj_del(&bar->mem);
nvkm_bar_destroy(&bar->base);
}
if (!vpgd)
return -ENOMEM;
- nvkm_gpuobj_ref(pgd, &vpgd->obj);
+ vpgd->obj = pgd;
mutex_lock(&vm->mutex);
for (i = vm->fpde; i <= vm->lpde; i++)
nvkm_vm_unlink(struct nvkm_vm *vm, struct nvkm_gpuobj *mpgd)
{
struct nvkm_vm_pgd *vpgd, *tmp;
- struct nvkm_gpuobj *pgd = NULL;
if (!mpgd)
return;
mutex_lock(&vm->mutex);
list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
if (vpgd->obj == mpgd) {
- pgd = vpgd->obj;
list_del(&vpgd->head);
kfree(vpgd);
break;
}
}
mutex_unlock(&vm->mutex);
-
- nvkm_gpuobj_ref(NULL, &pgd);
}
static void