Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 997a8900 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/core/memory: add reference counting



We need to be able to prevent memory from being freed while it's still
mapped in a GPU's address-space.

Will be used by upcoming MMU changes.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 2c9c4910
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ enum nvkm_memory_target {
struct nvkm_memory {
	const struct nvkm_memory_func *func;
	const struct nvkm_memory_ptrs *ptrs;
	struct kref kref;
	struct nvkm_tags *tags;
};

@@ -44,7 +45,8 @@ struct nvkm_memory_ptrs {
void nvkm_memory_ctor(const struct nvkm_memory_func *, struct nvkm_memory *);
int nvkm_memory_new(struct nvkm_device *, enum nvkm_memory_target,
		    u64 size, u32 align, bool zero, struct nvkm_memory **);
void nvkm_memory_del(struct nvkm_memory **);
struct nvkm_memory *nvkm_memory_ref(struct nvkm_memory *);
void nvkm_memory_unref(struct nvkm_memory **);
int nvkm_memory_tags_get(struct nvkm_memory *, struct nvkm_device *, u32 tags,
			 void (*clear)(struct nvkm_device *, u32, u32),
			 struct nvkm_tags **);
+1 −1
Original line number Diff line number Diff line
@@ -219,7 +219,7 @@ nvkm_gpuobj_del(struct nvkm_gpuobj **pgpuobj)
		if (gpuobj->parent)
			nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node);
		nvkm_mm_fini(&gpuobj->heap);
		nvkm_memory_del(&gpuobj->memory);
		nvkm_memory_unref(&gpuobj->memory);
		kfree(*pgpuobj);
		*pgpuobj = NULL;
	}
+23 −5
Original line number Diff line number Diff line
@@ -100,20 +100,38 @@ nvkm_memory_ctor(const struct nvkm_memory_func *func,
		 struct nvkm_memory *memory)
{
	memory->func = func;
	kref_init(&memory->kref);
}

static void
nvkm_memory_del(struct kref *kref)
{
	struct nvkm_memory *memory = container_of(kref, typeof(*memory), kref);
	if (!WARN_ON(!memory->func)) {
		if (memory->func->dtor)
			memory = memory->func->dtor(memory);
		kfree(memory);
	}
}

void
nvkm_memory_del(struct nvkm_memory **pmemory)
nvkm_memory_unref(struct nvkm_memory **pmemory)
{
	struct nvkm_memory *memory = *pmemory;
	if (memory && !WARN_ON(!memory->func)) {
		if (memory->func->dtor)
			*pmemory = memory->func->dtor(memory);
		kfree(*pmemory);
	if (memory) {
		kref_put(&memory->kref, nvkm_memory_del);
		*pmemory = NULL;
	}
}

struct nvkm_memory *
nvkm_memory_ref(struct nvkm_memory *memory)
{
	if (memory)
		kref_get(&memory->kref);
	return memory;
}

int
nvkm_memory_new(struct nvkm_device *device, enum nvkm_memory_target target,
		u64 size, u32 align, bool zero,
+1 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
	const u32 base = falcon->addr;

	if (!suspend) {
		nvkm_memory_del(&falcon->core);
		nvkm_memory_unref(&falcon->core);
		if (falcon->external) {
			vfree(falcon->data.data);
			vfree(falcon->code.data);
+3 −3
Original line number Diff line number Diff line
@@ -642,9 +642,9 @@ gf100_fifo_dtor(struct nvkm_fifo *base)
{
	struct gf100_fifo *fifo = gf100_fifo(base);
	nvkm_vm_put(&fifo->user.bar);
	nvkm_memory_del(&fifo->user.mem);
	nvkm_memory_del(&fifo->runlist.mem[0]);
	nvkm_memory_del(&fifo->runlist.mem[1]);
	nvkm_memory_unref(&fifo->user.mem);
	nvkm_memory_unref(&fifo->runlist.mem[0]);
	nvkm_memory_unref(&fifo->runlist.mem[1]);
	return fifo;
}

Loading