drm/nouveau/fault/gp100: expose MaxwellFaultBufferA

This nvclass exposes the replayable fault buffer, which will be used
by SVM to manage GPU page faults.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2018-05-08 20:39:48 +10:00
parent ab2ee9ffa3
commit 13e9572906
9 changed files with 142 additions and 8 deletions

View File

@ -54,6 +54,8 @@
#define VOLTA_USERMODE_A 0x0000c361
#define MAXWELL_FAULT_BUFFER_A /* clb069.h */ 0x0000b069
#define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b
#define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e
#define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e

View File

@ -0,0 +1,12 @@
#ifndef __NVIF_CLB069_H__
#define __NVIF_CLB069_H__
struct nvif_clb069_v0 {
__u8 version;
__u8 pad01[3];
__u32 entries;
__u32 get;
__u32 put;
};
#define NVB069_V0_NTFY_FAULT 0x00
#endif

View File

@ -13,6 +13,8 @@ struct nvkm_fault {
struct nvkm_event event;
struct nvkm_notify nrpfb;
struct nvkm_device_oclass user;
};
struct nvkm_fault_data {

View File

@ -365,16 +365,15 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index,
}
if (!sclass) {
switch (index) {
case 0: sclass = &nvkm_control_oclass; break;
case 1:
if (!device->mmu)
return -EINVAL;
if (index-- == 0)
sclass = &nvkm_control_oclass;
else if (device->mmu && index-- == 0)
sclass = &device->mmu->user;
break;
default:
else if (device->fault && index-- == 0)
sclass = &device->fault->user;
else
return -EINVAL;
}
oclass->base = sclass->base;
}

View File

@ -1,4 +1,5 @@
nvkm-y += nvkm/subdev/fault/base.o
nvkm-y += nvkm/subdev/fault/user.o
nvkm-y += nvkm/subdev/fault/gp100.o
nvkm-y += nvkm/subdev/fault/gv100.o
nvkm-y += nvkm/subdev/fault/tu102.o

View File

@ -176,5 +176,7 @@ nvkm_fault_new_(const struct nvkm_fault_func *func, struct nvkm_device *device,
return -ENOMEM;
nvkm_subdev_ctor(&nvkm_fault, device, index, &fault->subdev);
fault->func = func;
fault->user.ctor = nvkm_ufault_new;
fault->user.base = func->user.base;
return 0;
}

View File

@ -23,6 +23,8 @@
#include <subdev/mc.h>
#include <nvif/class.h>
static void
gp100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
{
@ -69,6 +71,7 @@ gp100_fault = {
.buffer.init = gp100_fault_buffer_init,
.buffer.fini = gp100_fault_buffer_fini,
.buffer.intr = gp100_fault_buffer_intr,
.user = { { 0, 0, MAXWELL_FAULT_BUFFER_A }, 0 },
};
int

View File

@ -34,7 +34,14 @@ struct nvkm_fault_func {
void (*fini)(struct nvkm_fault_buffer *);
void (*intr)(struct nvkm_fault_buffer *, bool enable);
} buffer;
struct {
struct nvkm_sclass base;
int rp;
} user;
};
int gv100_fault_oneinit(struct nvkm_fault *);
int nvkm_ufault_new(struct nvkm_device *, const struct nvkm_oclass *,
void *, u32, struct nvkm_object **);
#endif

View File

@ -0,0 +1,106 @@
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "priv.h"
#include <core/memory.h>
#include <subdev/mmu.h>
#include <nvif/clb069.h>
#include <nvif/unpack.h>
static int
nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
enum nvkm_object_map *type, u64 *addr, u64 *size)
{
struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
struct nvkm_device *device = buffer->fault->subdev.device;
*type = NVKM_OBJECT_MAP_IO;
*addr = device->func->resource_addr(device, 3) + buffer->addr;
*size = nvkm_memory_size(buffer->mem);
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
nvkm_ufault_fini(struct nvkm_object *object, bool suspend)
{
struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
buffer->fault->func->buffer.fini(buffer);
return 0;
}
static int
nvkm_ufault_init(struct nvkm_object *object)
{
struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
buffer->fault->func->buffer.init(buffer);
return 0;
}
static void *
nvkm_ufault_dtor(struct nvkm_object *object)
{
return NULL;
}
static const struct nvkm_object_func
nvkm_ufault = {
.dtor = nvkm_ufault_dtor,
.init = nvkm_ufault_init,
.fini = nvkm_ufault_fini,
.ntfy = nvkm_ufault_ntfy,
.map = nvkm_ufault_map,
};
int
nvkm_ufault_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
void *argv, u32 argc, struct nvkm_object **pobject)
{
union {
struct nvif_clb069_v0 v0;
} *args = argv;
struct nvkm_fault *fault = device->fault;
struct nvkm_fault_buffer *buffer = fault->buffer[fault->func->user.rp];
int ret = -ENOSYS;
if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
args->v0.entries = buffer->entries;
args->v0.get = buffer->get;
args->v0.put = buffer->put;
} else
return ret;
nvkm_object_ctor(&nvkm_ufault, oclass, &buffer->object);
*pobject = &buffer->object;
return 0;
}