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

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
This commit is contained in:
Ben Skeggs 2022-06-01 20:46:37 +10:00
parent 55520832d6
commit b418ff8863
4 changed files with 53 additions and 48 deletions

View File

@ -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

View File

@ -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 @@ out:
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;

View File

@ -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,
}; };

View File

@ -22,11 +22,27 @@
#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
nvkm_ufault_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
{
struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
union nvif_clb069_event_args *args = argv;
if (!uevent)
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_map(struct nvkm_object *object, void *argv, u32 argc, nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
enum nvkm_object_map *type, u64 *addr, u64 *size) enum nvkm_object_map *type, u64 *addr, u64 *size)
@ -39,18 +55,6 @@ nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
return 0; return 0;
} }
static int
nvkm_ufault_ntfy(struct nvkm_object *object, u32 type,
struct nvkm_event **pevent)
{
struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
if (type == NVB069_V0_NTFY_FAULT) {
*pevent = &buffer->fault->event;
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