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:
parent
55520832d6
commit
b418ff8863
@ -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
|
||||||
|
@ -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,10 +1004,10 @@ 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;
|
||||||
|
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user