mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-07 05:04:04 +08:00
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: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
f5650478ab
commit
c5c9127b25
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user