Commit c5c9127b authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/device: implement a generic method to query device-specific properties

We have a need to fetch data from GPU-specific sub-devices that is not
tied to any particular engine object.

This commit provides the framework to support such queries.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent f5650478
......@@ -39,9 +39,25 @@ struct nv_device_info_v0 {
char name[64];
};
struct nv_device_info_v1 {
__u8 version;
__u8 count;
__u8 pad02[6];
struct nv_device_info_v1_data {
__u64 mthd; /* NV_DEVICE_INFO_* (see below). */
__u64 data;
} data[];
};
struct nv_device_time_v0 {
__u8 version;
__u8 pad01[7];
__u64 time;
};
#define NV_DEVICE_INFO_UNIT (0xffffffffULL << 32)
#define NV_DEVICE_INFO(n) ((n) | (0x00000000ULL << 32))
/* This will be returned for unsupported queries. */
#define NV_DEVICE_INFO_INVALID ~0ULL
#endif
......@@ -18,6 +18,7 @@ struct nvkm_engine_func {
void *(*dtor)(struct nvkm_engine *);
void (*preinit)(struct nvkm_engine *);
int (*oneinit)(struct nvkm_engine *);
int (*info)(struct nvkm_engine *, u64 mthd, u64 *data);
int (*init)(struct nvkm_engine *);
int (*fini)(struct nvkm_engine *, bool suspend);
void (*intr)(struct nvkm_engine *);
......
......@@ -17,6 +17,7 @@ struct nvkm_subdev_func {
void *(*dtor)(struct nvkm_subdev *);
int (*preinit)(struct nvkm_subdev *);
int (*oneinit)(struct nvkm_subdev *);
int (*info)(struct nvkm_subdev *, u64 mthd, u64 *data);
int (*init)(struct nvkm_subdev *);
int (*fini)(struct nvkm_subdev *, bool suspend);
void (*intr)(struct nvkm_subdev *);
......@@ -29,6 +30,7 @@ void nvkm_subdev_del(struct nvkm_subdev **);
int nvkm_subdev_preinit(struct nvkm_subdev *);
int nvkm_subdev_init(struct nvkm_subdev *);
int nvkm_subdev_fini(struct nvkm_subdev *, bool suspend);
int nvkm_subdev_info(struct nvkm_subdev *, u64, u64 *);
void nvkm_subdev_intr(struct nvkm_subdev *);
/* subdev logging */
......
......@@ -82,6 +82,20 @@ nvkm_engine_intr(struct nvkm_subdev *subdev)
engine->func->intr(engine);
}
static int
nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
{
struct nvkm_engine *engine = nvkm_engine(subdev);
if (engine->func->info) {
if ((engine = nvkm_engine_ref(engine))) {
int ret = engine->func->info(engine, mthd, data);
nvkm_engine_unref(&engine);
return ret;
}
}
return -ENOSYS;
}
static int
nvkm_engine_fini(struct nvkm_subdev *subdev, bool suspend)
{
......@@ -150,6 +164,7 @@ nvkm_engine_func = {
.preinit = nvkm_engine_preinit,
.init = nvkm_engine_init,
.fini = nvkm_engine_fini,
.info = nvkm_engine_info,
.intr = nvkm_engine_intr,
};
......
......@@ -92,6 +92,14 @@ nvkm_subdev_intr(struct nvkm_subdev *subdev)
subdev->func->intr(subdev);
}
int
nvkm_subdev_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
{
if (subdev->func->info)
return subdev->func->info(subdev, mthd, data);
return -ENOSYS;
}
int
nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
{
......
......@@ -39,6 +39,40 @@ struct nvkm_udevice {
struct nvkm_device *device;
};
static int
nvkm_udevice_info_subdev(struct nvkm_device *device, u64 mthd, u64 *data)
{
struct nvkm_subdev *subdev;
enum nvkm_devidx subidx;
switch (mthd & NV_DEVICE_INFO_UNIT) {
default:
return -EINVAL;
}
subdev = nvkm_device_subdev(device, subidx);
if (subdev)
return nvkm_subdev_info(subdev, mthd, data);
return -ENODEV;
}
static void
nvkm_udevice_info_v1(struct nvkm_device *device,
struct nv_device_info_v1_data *args)
{
if (args->mthd & NV_DEVICE_INFO_UNIT) {
if (nvkm_udevice_info_subdev(device, args->mthd, &args->data))
args->mthd = NV_DEVICE_INFO_INVALID;
return;
}
switch (args->mthd) {
default:
args->mthd = NV_DEVICE_INFO_INVALID;
break;
}
}
static int
nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
{
......@@ -48,10 +82,21 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
struct nvkm_instmem *imem = device->imem;
union {
struct nv_device_info_v0 v0;
struct nv_device_info_v1 v1;
} *args = data;
int ret = -ENOSYS;
int ret = -ENOSYS, i;
nvif_ioctl(object, "device info size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v1, 1, 1, true))) {
nvif_ioctl(object, "device info vers %d count %d\n",
args->v1.version, args->v1.count);
if (args->v1.count * sizeof(args->v1.data[0]) == size) {
for (i = 0; i < args->v1.count; i++)
nvkm_udevice_info_v1(device, &args->v1.data[i]);
return 0;
}
return -EINVAL;
} else
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(object, "device info vers %d\n", args->v0.version);
} else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment