diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index 42016cde5781..10598dede9e9 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -139,6 +140,46 @@ nvkm_client_notify_new(struct nouveau_client *client, return 0; } +static int +nouveau_client_devlist(struct nouveau_object *object, void *data, u32 size) +{ + union { + struct nv_client_devlist_v0 v0; + } *args = data; + int ret; + + nv_ioctl(object, "client devlist size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, true)) { + nv_ioctl(object, "client devlist vers %d count %d\n", + args->v0.version, args->v0.count); + if (size == sizeof(args->v0.device[0]) * args->v0.count) { + ret = nouveau_device_list(args->v0.device, + args->v0.count); + if (ret >= 0) { + args->v0.count = ret; + ret = 0; + } + } else { + ret = -EINVAL; + } + } + + return ret; +} + +static int +nouveau_client_mthd(struct nouveau_object *object, u32 mthd, + void *data, u32 size) +{ + switch (mthd) { + case NV_CLIENT_DEVLIST: + return nouveau_client_devlist(object, data, size); + default: + break; + } + return -EINVAL; +} + static void nouveau_client_dtor(struct nouveau_object *object) { @@ -155,6 +196,7 @@ static struct nouveau_oclass nouveau_client_oclass = { .ofuncs = &(struct nouveau_ofuncs) { .dtor = nouveau_client_dtor, + .mthd = nouveau_client_mthd, }, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index a5e10d351365..8d74a31635bf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c @@ -54,6 +54,20 @@ nouveau_device_find(u64 name) return match; } +int +nouveau_device_list(u64 *name, int size) +{ + struct nouveau_device *device; + int nr = 0; + mutex_lock(&nv_devices_mutex); + list_for_each_entry(device, &nv_devices, head) { + if (nr++ < size) + name[nr - 1] = device->handle; + } + mutex_unlock(&nv_devices_mutex); + return nr; +} + /****************************************************************************** * nouveau_devobj (0x0080): class implementation *****************************************************************************/ diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index a45ece151948..aa62b637c389 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -101,6 +101,8 @@ struct nouveau_device { } acpi; }; +int nouveau_device_list(u64 *name, int size); + static inline struct nouveau_device * nv_device(void *obj) { diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h index 36ecc3e6a241..3013656bdfa6 100644 --- a/drivers/gpu/drm/nouveau/nvif/class.h +++ b/drivers/gpu/drm/nouveau/nvif/class.h @@ -9,6 +9,20 @@ #define NV_DEVICE 0x00000080 +/******************************************************************************* + * client + ******************************************************************************/ + +#define NV_CLIENT_DEVLIST 0x00 + +struct nv_client_devlist_v0 { + __u8 version; + __u8 count; + __u8 pad02[6]; + __u64 device[]; +}; + + /******************************************************************************* * device ******************************************************************************/