Commit b418ff88 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fault: expose replayable fault buffer event class



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 55520832
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -8,5 +8,8 @@ struct nvif_clb069_v0 {
	__u32 put;
	__u32 put;
};
};


#define NVB069_V0_NTFY_FAULT                                                0x00
union nvif_clb069_event_args {
	struct nvif_clb069_event_vn {
	} vn;
};
#endif
#endif
+32 −18
Original line number Original line Diff line number Diff line
@@ -24,7 +24,7 @@
#include "nouveau_chan.h"
#include "nouveau_chan.h"
#include "nouveau_dmem.h"
#include "nouveau_dmem.h"


#include <nvif/notify.h>
#include <nvif/event.h>
#include <nvif/object.h>
#include <nvif/object.h>
#include <nvif/vmm.h>
#include <nvif/vmm.h>


@@ -51,7 +51,8 @@ struct nouveau_svm {
		u32 putaddr;
		u32 putaddr;
		u32 get;
		u32 get;
		u32 put;
		u32 put;
		struct nvif_notify notify;
		struct nvif_event notify;
		struct work_struct work;


		struct nouveau_svm_fault {
		struct nouveau_svm_fault {
			u64 inst;
			u64 inst;
@@ -711,13 +712,11 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
	return ret;
	return ret;
}
}


static int
static void
nouveau_svm_fault(struct nvif_notify *notify)
nouveau_svm_fault(struct work_struct *work)
{
{
	struct nouveau_svm_fault_buffer *buffer =
	struct nouveau_svm_fault_buffer *buffer = container_of(work, typeof(*buffer), work);
		container_of(notify, typeof(*buffer), notify);
	struct nouveau_svm *svm = container_of(buffer, typeof(*svm), buffer[buffer->id]);
	struct nouveau_svm *svm =
		container_of(buffer, typeof(*svm), buffer[buffer->id]);
	struct nvif_object *device = &svm->drm->client.device.object;
	struct nvif_object *device = &svm->drm->client.device.object;
	struct nouveau_svmm *svmm;
	struct nouveau_svmm *svmm;
	struct {
	struct {
@@ -737,7 +736,7 @@ nouveau_svm_fault(struct nvif_notify *notify)
		buffer->put = nvif_rd32(device, buffer->putaddr);
		buffer->put = nvif_rd32(device, buffer->putaddr);
		buffer->get = nvif_rd32(device, buffer->getaddr);
		buffer->get = nvif_rd32(device, buffer->getaddr);
		if (buffer->get == buffer->put)
		if (buffer->get == buffer->put)
			return NVIF_NOTIFY_KEEP;
			return;
	}
	}
	buffer->fault_nr = 0;
	buffer->fault_nr = 0;


@@ -881,7 +880,15 @@ nouveau_svm_fault(struct nvif_notify *notify)
	/* Issue fault replay to the GPU. */
	/* Issue fault replay to the GPU. */
	if (replay)
	if (replay)
		nouveau_svm_fault_replay(svm);
		nouveau_svm_fault_replay(svm);
	return NVIF_NOTIFY_KEEP;
}

static int
nouveau_svm_event(struct nvif_event *event, void *argv, u32 argc)
{
	struct nouveau_svm_fault_buffer *buffer = container_of(event, typeof(*buffer), notify);

	schedule_work(&buffer->work);
	return NVIF_EVENT_KEEP;
}
}


static struct nouveau_pfnmap_args *
static struct nouveau_pfnmap_args *
@@ -936,7 +943,9 @@ static void
nouveau_svm_fault_buffer_fini(struct nouveau_svm *svm, int id)
nouveau_svm_fault_buffer_fini(struct nouveau_svm *svm, int id)
{
{
	struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
	struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
	nvif_notify_put(&buffer->notify);

	nvif_event_block(&buffer->notify);
	flush_work(&buffer->work);
}
}


static int
static int
@@ -944,10 +953,12 @@ nouveau_svm_fault_buffer_init(struct nouveau_svm *svm, int id)
{
{
	struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
	struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
	struct nvif_object *device = &svm->drm->client.device.object;
	struct nvif_object *device = &svm->drm->client.device.object;

	buffer->get = nvif_rd32(device, buffer->getaddr);
	buffer->get = nvif_rd32(device, buffer->getaddr);
	buffer->put = nvif_rd32(device, buffer->putaddr);
	buffer->put = nvif_rd32(device, buffer->putaddr);
	SVM_DBG(svm, "get %08x put %08x (init)", buffer->get, buffer->put);
	SVM_DBG(svm, "get %08x put %08x (init)", buffer->get, buffer->put);
	return nvif_notify_get(&buffer->notify);

	return nvif_event_allow(&buffer->notify);
}
}


static void
static void
@@ -956,15 +967,18 @@ nouveau_svm_fault_buffer_dtor(struct nouveau_svm *svm, int id)
	struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
	struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
	int i;
	int i;


	if (!nvif_object_constructed(&buffer->object))
		return;

	nouveau_svm_fault_buffer_fini(svm, id);

	if (buffer->fault) {
	if (buffer->fault) {
		for (i = 0; buffer->fault[i] && i < buffer->entries; i++)
		for (i = 0; buffer->fault[i] && i < buffer->entries; i++)
			kfree(buffer->fault[i]);
			kfree(buffer->fault[i]);
		kvfree(buffer->fault);
		kvfree(buffer->fault);
	}
	}


	nouveau_svm_fault_buffer_fini(svm, id);
	nvif_event_dtor(&buffer->notify);

	nvif_notify_dtor(&buffer->notify);
	nvif_object_dtor(&buffer->object);
	nvif_object_dtor(&buffer->object);
}
}


@@ -990,9 +1004,9 @@ nouveau_svm_fault_buffer_ctor(struct nouveau_svm *svm, s32 oclass, int id)
	buffer->entries = args.entries;
	buffer->entries = args.entries;
	buffer->getaddr = args.get;
	buffer->getaddr = args.get;
	buffer->putaddr = args.put;
	buffer->putaddr = args.put;
	INIT_WORK(&buffer->work, nouveau_svm_fault);


	ret = nvif_notify_ctor(&buffer->object, "svmFault", nouveau_svm_fault,
	ret = nvif_event_ctor(&buffer->object, "svmFault", id, nouveau_svm_event, true, NULL, 0,
			       true, NVB069_V0_NTFY_FAULT, NULL, 0, 0,
			      &buffer->notify);
			      &buffer->notify);
	if (ret)
	if (ret)
		return ret;
		return ret;
+0 −16
Original line number Original line Diff line number Diff line
@@ -22,7 +22,6 @@
#include "priv.h"
#include "priv.h"


#include <core/memory.h>
#include <core/memory.h>
#include <core/notify.h>


static void
static void
nvkm_fault_ntfy_fini(struct nvkm_event *event, int type, int index)
nvkm_fault_ntfy_fini(struct nvkm_event *event, int type, int index)
@@ -38,23 +37,8 @@ nvkm_fault_ntfy_init(struct nvkm_event *event, int type, int index)
	fault->func->buffer.intr(fault->buffer[index], true);
	fault->func->buffer.intr(fault->buffer[index], true);
}
}


static int
nvkm_fault_ntfy_ctor(struct nvkm_object *object, void *argv, u32 argc,
		     struct nvkm_notify *notify)
{
	struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
	if (argc == 0) {
		notify->size  = 0;
		notify->types = 1;
		notify->index = buffer->id;
		return 0;
	}
	return -ENOSYS;
}

static const struct nvkm_event_func
static const struct nvkm_event_func
nvkm_fault_ntfy = {
nvkm_fault_ntfy = {
	.ctor = nvkm_fault_ntfy_ctor,
	.init = nvkm_fault_ntfy_init,
	.init = nvkm_fault_ntfy_init,
	.fini = nvkm_fault_ntfy_fini,
	.fini = nvkm_fault_ntfy_fini,
};
};
+17 −13
Original line number Original line Diff line number Diff line
@@ -22,34 +22,38 @@
#include "priv.h"
#include "priv.h"


#include <core/memory.h>
#include <core/memory.h>
#include <core/event.h>
#include <subdev/mmu.h>
#include <subdev/mmu.h>


#include <nvif/clb069.h>
#include <nvif/clb069.h>
#include <nvif/unpack.h>
#include <nvif/unpack.h>


static int
static int
nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
nvkm_ufault_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
		enum nvkm_object_map *type, u64 *addr, u64 *size)
{
{
	struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
	struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
	struct nvkm_device *device = buffer->fault->subdev.device;
	union nvif_clb069_event_args *args = argv;
	*type = NVKM_OBJECT_MAP_IO;

	*addr = device->func->resource_addr(device, 3) + buffer->addr;
	if (!uevent)
	*size = nvkm_memory_size(buffer->mem);
		return 0;
		return 0;
	if (argc != sizeof(args->vn))
		return -ENOSYS;

	return nvkm_uevent_add(uevent, &buffer->fault->event, buffer->id,
			       NVKM_FAULT_BUFFER_EVENT_PENDING, NULL);
}
}


static int
static int
nvkm_ufault_ntfy(struct nvkm_object *object, u32 type,
nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
		 struct nvkm_event **pevent)
		enum nvkm_object_map *type, u64 *addr, u64 *size)
{
{
	struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
	struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
	if (type == NVB069_V0_NTFY_FAULT) {
	struct nvkm_device *device = buffer->fault->subdev.device;
		*pevent = &buffer->fault->event;
	*type = NVKM_OBJECT_MAP_IO;
	*addr = device->func->resource_addr(device, 3) + buffer->addr;
	*size = nvkm_memory_size(buffer->mem);
	return 0;
	return 0;
}
}
	return -EINVAL;
}


static int
static int
nvkm_ufault_fini(struct nvkm_object *object, bool suspend)
nvkm_ufault_fini(struct nvkm_object *object, bool suspend)
@@ -78,8 +82,8 @@ nvkm_ufault = {
	.dtor = nvkm_ufault_dtor,
	.dtor = nvkm_ufault_dtor,
	.init = nvkm_ufault_init,
	.init = nvkm_ufault_init,
	.fini = nvkm_ufault_fini,
	.fini = nvkm_ufault_fini,
	.ntfy = nvkm_ufault_ntfy,
	.map = nvkm_ufault_map,
	.map = nvkm_ufault_map,
	.uevent = nvkm_ufault_uevent,
};
};


int
int