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 { ...@@ -39,9 +39,25 @@ struct nv_device_info_v0 {
char name[64]; 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 { struct nv_device_time_v0 {
__u8 version; __u8 version;
__u8 pad01[7]; __u8 pad01[7];
__u64 time; __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 #endif
...@@ -18,6 +18,7 @@ struct nvkm_engine_func { ...@@ -18,6 +18,7 @@ struct nvkm_engine_func {
void *(*dtor)(struct nvkm_engine *); void *(*dtor)(struct nvkm_engine *);
void (*preinit)(struct nvkm_engine *); void (*preinit)(struct nvkm_engine *);
int (*oneinit)(struct nvkm_engine *); int (*oneinit)(struct nvkm_engine *);
int (*info)(struct nvkm_engine *, u64 mthd, u64 *data);
int (*init)(struct nvkm_engine *); int (*init)(struct nvkm_engine *);
int (*fini)(struct nvkm_engine *, bool suspend); int (*fini)(struct nvkm_engine *, bool suspend);
void (*intr)(struct nvkm_engine *); void (*intr)(struct nvkm_engine *);
......
...@@ -17,6 +17,7 @@ struct nvkm_subdev_func { ...@@ -17,6 +17,7 @@ struct nvkm_subdev_func {
void *(*dtor)(struct nvkm_subdev *); void *(*dtor)(struct nvkm_subdev *);
int (*preinit)(struct nvkm_subdev *); int (*preinit)(struct nvkm_subdev *);
int (*oneinit)(struct nvkm_subdev *); int (*oneinit)(struct nvkm_subdev *);
int (*info)(struct nvkm_subdev *, u64 mthd, u64 *data);
int (*init)(struct nvkm_subdev *); int (*init)(struct nvkm_subdev *);
int (*fini)(struct nvkm_subdev *, bool suspend); int (*fini)(struct nvkm_subdev *, bool suspend);
void (*intr)(struct nvkm_subdev *); void (*intr)(struct nvkm_subdev *);
...@@ -29,6 +30,7 @@ void nvkm_subdev_del(struct nvkm_subdev **); ...@@ -29,6 +30,7 @@ void nvkm_subdev_del(struct nvkm_subdev **);
int nvkm_subdev_preinit(struct nvkm_subdev *); int nvkm_subdev_preinit(struct nvkm_subdev *);
int nvkm_subdev_init(struct nvkm_subdev *); int nvkm_subdev_init(struct nvkm_subdev *);
int nvkm_subdev_fini(struct nvkm_subdev *, bool suspend); 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 *); void nvkm_subdev_intr(struct nvkm_subdev *);
/* subdev logging */ /* subdev logging */
......
...@@ -82,6 +82,20 @@ nvkm_engine_intr(struct nvkm_subdev *subdev) ...@@ -82,6 +82,20 @@ nvkm_engine_intr(struct nvkm_subdev *subdev)
engine->func->intr(engine); 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 static int
nvkm_engine_fini(struct nvkm_subdev *subdev, bool suspend) nvkm_engine_fini(struct nvkm_subdev *subdev, bool suspend)
{ {
...@@ -150,6 +164,7 @@ nvkm_engine_func = { ...@@ -150,6 +164,7 @@ nvkm_engine_func = {
.preinit = nvkm_engine_preinit, .preinit = nvkm_engine_preinit,
.init = nvkm_engine_init, .init = nvkm_engine_init,
.fini = nvkm_engine_fini, .fini = nvkm_engine_fini,
.info = nvkm_engine_info,
.intr = nvkm_engine_intr, .intr = nvkm_engine_intr,
}; };
......
...@@ -92,6 +92,14 @@ nvkm_subdev_intr(struct nvkm_subdev *subdev) ...@@ -92,6 +92,14 @@ nvkm_subdev_intr(struct nvkm_subdev *subdev)
subdev->func->intr(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 int
nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend) nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
{ {
......
...@@ -39,6 +39,40 @@ struct nvkm_udevice { ...@@ -39,6 +39,40 @@ struct nvkm_udevice {
struct nvkm_device *device; 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 static int
nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size) 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) ...@@ -48,10 +82,21 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
struct nvkm_instmem *imem = device->imem; struct nvkm_instmem *imem = device->imem;
union { union {
struct nv_device_info_v0 v0; struct nv_device_info_v0 v0;
struct nv_device_info_v1 v1;
} *args = data; } *args = data;
int ret = -ENOSYS; int ret = -ENOSYS, i;
nvif_ioctl(object, "device info size %d\n", size); 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))) { if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(object, "device info vers %d\n", args->v0.version); nvif_ioctl(object, "device info vers %d\n", args->v0.version);
} else } 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