drm/nouveau/fault: switch non-replayable faults to nvkm_event_ntfy
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:46:37 +0000 (20:46 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 9 Nov 2022 00:44:27 +0000 (10:44 +1000)
v2: fix flush_work() being called uninitialised during init

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c

index 9c78f072d62b48b19b2c95167626350445f33e0b..e781c5e4dcaebbd73d4ad40288d1adfc5247e0d1 100644 (file)
@@ -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;
 };
index cc6fa1bb503434b80cd7fb80e73253aa822447b9..7dd722c9b66019b86b9c5dc8708ef09f2b91b349 100644 (file)
@@ -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++) {
index 6af7959e02ea64df99415fc111998522c1aa54e6..a96a1d633cb315dce231603e404f2dade09ebcd0 100644 (file)
@@ -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
index cd9d2ade5ac7a5c5174ecfc0ce5995055ada4917..21756d65663b7139aa454bc76925481b57996b67 100644 (file)
 
 #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;
 }
index 36681c347fb597a631a1909200d63e148f38ea70..30cc0d088897257afea1f4a84d64d9d4e4383ae1 100644 (file)
@@ -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 *);
index 91eb6729c84d67977b61b15f59af10658fdaf568..2d3660d21b9a90f972918527e181779b5ea528da 100644 (file)
@@ -126,7 +126,7 @@ tu102_fault_intr(struct nvkm_fault *fault)
                nvkm_wr32(device, 0xb81010, 0x10);
 
                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 &= ~0x00000200;
                }
        }
@@ -137,7 +137,7 @@ tu102_fault_intr(struct nvkm_fault *fault)
                nvkm_wr32(device, 0xb81008, 0x1);
 
                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 &= ~0x00000100;
                }
        }
@@ -150,7 +150,9 @@ tu102_fault_intr(struct nvkm_fault *fault)
 static void
 tu102_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]);
        /*XXX: disable priv faults */
@@ -161,7 +163,7 @@ tu102_fault_init(struct nvkm_fault *fault)
 {
        /*XXX: enable priv faults */
        fault->func->buffer.init(fault->buffer[0]);
-       nvkm_notify_get(&fault->nrpfb);
+       nvkm_event_ntfy_allow(&fault->nrpfb);
 }
 
 static const struct nvkm_fault_func
@@ -184,5 +186,10 @@ int
 tu102_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
                struct nvkm_fault **pfault)
 {
-       return nvkm_fault_new_(&tu102_fault, device, type, inst, pfault);
+       int ret = nvkm_fault_new_(&tu102_fault, device, type, inst, pfault);
+       if (ret)
+               return ret;
+
+       INIT_WORK(&(*pfault)->nrpfb_work, gv100_fault_buffer_process);
+       return 0;
 }