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

drm/nouveau/fault: switch non-replayable faults to nvkm_event_ntfy



v2: fix flush_work() being called uninitialised during init

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent f43e47c0
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -2,7 +2,6 @@
#define __NVKM_FAULT_H__
#include <core/subdev.h>
#include <core/event.h>
#include <core/notify.h>

struct nvkm_fault {
	const struct nvkm_fault_func *func;
@@ -11,9 +10,11 @@ struct nvkm_fault {
	struct nvkm_fault_buffer *buffer[2];
	int buffer_nr;

#define NVKM_FAULT_BUFFER_EVENT_PENDING BIT(0)
	struct nvkm_event event;

	struct nvkm_notify nrpfb;
	struct nvkm_event_ntfy nrpfb;
	struct work_struct nrpfb_work;

	struct nvkm_device_oclass user;
};
+1 −1
Original line number Diff line number Diff line
@@ -145,7 +145,7 @@ nvkm_fault_dtor(struct nvkm_subdev *subdev)
	struct nvkm_fault *fault = nvkm_fault(subdev);
	int i;

	nvkm_notify_fini(&fault->nrpfb);
	nvkm_event_ntfy_del(&fault->nrpfb);
	nvkm_event_fini(&fault->event);

	for (i = 0; i < fault->buffer_nr; i++) {
+1 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
void
gp100_fault_intr(struct nvkm_fault *fault)
{
	nvkm_event_send(&fault->event, 1, 0, NULL, 0);
	nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0);
}

static const struct nvkm_fault_func
+26 −15
Original line number Diff line number Diff line
@@ -27,10 +27,12 @@

#include <nvif/class.h>

static void
gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer)
void
gv100_fault_buffer_process(struct work_struct *work)
{
	struct nvkm_device *device = buffer->fault->subdev.device;
	struct nvkm_fault *fault = container_of(work, typeof(*fault), nrpfb_work);
	struct nvkm_fault_buffer *buffer = fault->buffer[0];
	struct nvkm_device *device = fault->subdev.device;
	struct nvkm_memory *mem = buffer->mem;
	u32 get = nvkm_rd32(device, buffer->get);
	u32 put = nvkm_rd32(device, buffer->put);
@@ -115,11 +117,12 @@ gv100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
}

static int
gv100_fault_ntfy_nrpfb(struct nvkm_notify *notify)
gv100_fault_ntfy_nrpfb(struct nvkm_event_ntfy *ntfy, u32 bits)
{
	struct nvkm_fault *fault = container_of(notify, typeof(*fault), nrpfb);
	gv100_fault_buffer_process(fault->buffer[0]);
	return NVKM_NOTIFY_KEEP;
	struct nvkm_fault *fault = container_of(ntfy, typeof(*fault), nrpfb);

	schedule_work(&fault->nrpfb_work);
	return NVKM_EVENT_KEEP;
}

static void
@@ -163,14 +166,14 @@ gv100_fault_intr(struct nvkm_fault *fault)

	if (stat & 0x20000000) {
		if (fault->buffer[0]) {
			nvkm_event_send(&fault->event, 1, 0, NULL, 0);
			nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0);
			stat &= ~0x20000000;
		}
	}

	if (stat & 0x08000000) {
		if (fault->buffer[1]) {
			nvkm_event_send(&fault->event, 1, 1, NULL, 0);
			nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 1, NULL, 0);
			stat &= ~0x08000000;
		}
	}
@@ -183,9 +186,12 @@ gv100_fault_intr(struct nvkm_fault *fault)
static void
gv100_fault_fini(struct nvkm_fault *fault)
{
	nvkm_notify_put(&fault->nrpfb);
	nvkm_event_ntfy_block(&fault->nrpfb);
	flush_work(&fault->nrpfb_work);

	if (fault->buffer[0])
		fault->func->buffer.fini(fault->buffer[0]);

	nvkm_mask(fault->subdev.device, 0x100a34, 0x80000000, 0x80000000);
}

@@ -194,15 +200,15 @@ gv100_fault_init(struct nvkm_fault *fault)
{
	nvkm_mask(fault->subdev.device, 0x100a2c, 0x80000000, 0x80000000);
	fault->func->buffer.init(fault->buffer[0]);
	nvkm_notify_get(&fault->nrpfb);
	nvkm_event_ntfy_allow(&fault->nrpfb);
}

int
gv100_fault_oneinit(struct nvkm_fault *fault)
{
	return nvkm_notify_init(&fault->buffer[0]->object, &fault->event,
				gv100_fault_ntfy_nrpfb, true, NULL, 0, 0,
				&fault->nrpfb);
	nvkm_event_ntfy_add(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING, true,
			    gv100_fault_ntfy_nrpfb, &fault->nrpfb);
	return 0;
}

static const struct nvkm_fault_func
@@ -231,5 +237,10 @@ int
gv100_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
		struct nvkm_fault **pfault)
{
	return nvkm_fault_new_(&gv100_fault, device, type, inst, pfault);
	int ret = nvkm_fault_new_(&gv100_fault, device, type, inst, pfault);
	if (ret)
		return ret;

	INIT_WORK(&(*pfault)->nrpfb_work, gv100_fault_buffer_process);
	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ void gp100_fault_buffer_fini(struct nvkm_fault_buffer *);
void gp100_fault_buffer_init(struct nvkm_fault_buffer *);
u64 gp100_fault_buffer_pin(struct nvkm_fault_buffer *);
void gp100_fault_buffer_info(struct nvkm_fault_buffer *);
void gv100_fault_buffer_process(struct work_struct *);
void gp100_fault_intr(struct nvkm_fault *);

u64 gp10b_fault_buffer_pin(struct nvkm_fault_buffer *);
Loading