diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2018-05-08 20:39:46 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2018-05-18 15:01:21 +1000 |
commit | c5c9127b25b2946369877d16b3c208cf54d4bf54 (patch) | |
tree | 076d07e3f9defef3378c00feddd478923c168fc4 /drivers/gpu/drm/nouveau/nvkm | |
parent | f5650478ab07c0921127a6a0735253b64073e978 (diff) |
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>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/engine.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/subdev.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/user.c | 47 |
3 files changed, 69 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c index 657231c3c098..d0322ce85172 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c @@ -83,6 +83,20 @@ nvkm_engine_intr(struct nvkm_subdev *subdev) } 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) { struct nvkm_engine *engine = nvkm_engine(subdev); @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c index c707306ac286..b96f9e2f237a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c @@ -93,6 +93,14 @@ nvkm_subdev_intr(struct nvkm_subdev *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) { struct nvkm_device *device = subdev->device; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c index 17adcb4e8854..3526516765f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -40,6 +40,40 @@ struct nvkm_udevice { }; 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) { struct nvkm_object *object = &udev->object; @@ -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 |