summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nouveau_svm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_svm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_svm.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
index 31a5b81ee9fc..a74ba8d84ba7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -24,7 +24,7 @@
#include "nouveau_chan.h"
#include "nouveau_dmem.h"
-#include <nvif/notify.h>
+#include <nvif/event.h>
#include <nvif/object.h>
#include <nvif/vmm.h>
@@ -51,7 +51,8 @@ struct nouveau_svm {
u32 putaddr;
u32 get;
u32 put;
- struct nvif_notify notify;
+ struct nvif_event notify;
+ struct work_struct work;
struct nouveau_svm_fault {
u64 inst;
@@ -711,13 +712,11 @@ out:
return ret;
}
-static int
-nouveau_svm_fault(struct nvif_notify *notify)
+static void
+nouveau_svm_fault(struct work_struct *work)
{
- struct nouveau_svm_fault_buffer *buffer =
- container_of(notify, typeof(*buffer), notify);
- struct nouveau_svm *svm =
- container_of(buffer, typeof(*svm), buffer[buffer->id]);
+ struct nouveau_svm_fault_buffer *buffer = container_of(work, typeof(*buffer), work);
+ struct nouveau_svm *svm = container_of(buffer, typeof(*svm), buffer[buffer->id]);
struct nvif_object *device = &svm->drm->client.device.object;
struct nouveau_svmm *svmm;
struct {
@@ -737,7 +736,7 @@ nouveau_svm_fault(struct nvif_notify *notify)
buffer->put = nvif_rd32(device, buffer->putaddr);
buffer->get = nvif_rd32(device, buffer->getaddr);
if (buffer->get == buffer->put)
- return NVIF_NOTIFY_KEEP;
+ return;
}
buffer->fault_nr = 0;
@@ -881,7 +880,15 @@ nouveau_svm_fault(struct nvif_notify *notify)
/* Issue fault replay to the GPU. */
if (replay)
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 *
@@ -936,7 +943,9 @@ static void
nouveau_svm_fault_buffer_fini(struct nouveau_svm *svm, int 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
@@ -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 nvif_object *device = &svm->drm->client.device.object;
+
buffer->get = nvif_rd32(device, buffer->getaddr);
buffer->put = nvif_rd32(device, buffer->putaddr);
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
@@ -956,15 +967,18 @@ nouveau_svm_fault_buffer_dtor(struct nouveau_svm *svm, int id)
struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
int i;
+ if (!nvif_object_constructed(&buffer->object))
+ return;
+
+ nouveau_svm_fault_buffer_fini(svm, id);
+
if (buffer->fault) {
for (i = 0; buffer->fault[i] && i < buffer->entries; i++)
kfree(buffer->fault[i]);
kvfree(buffer->fault);
}
- nouveau_svm_fault_buffer_fini(svm, id);
-
- nvif_notify_dtor(&buffer->notify);
+ nvif_event_dtor(&buffer->notify);
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->getaddr = args.get;
buffer->putaddr = args.put;
+ INIT_WORK(&buffer->work, nouveau_svm_fault);
- ret = nvif_notify_ctor(&buffer->object, "svmFault", nouveau_svm_fault,
- true, NVB069_V0_NTFY_FAULT, NULL, 0, 0,
- &buffer->notify);
+ ret = nvif_event_ctor(&buffer->object, "svmFault", id, nouveau_svm_event, true, NULL, 0,
+ &buffer->notify);
if (ret)
return ret;