diff options
-rw-r--r-- | nvif/class.h | 14 | ||||
-rw-r--r-- | nvkm/core/client.c | 42 | ||||
-rw-r--r-- | nvkm/engine/device/base.c | 14 | ||||
-rw-r--r-- | nvkm/include/core/device.h | 2 |
4 files changed, 72 insertions, 0 deletions
diff --git a/nvif/class.h b/nvif/class.h index 36ecc3e6a..3013656bd 100644 --- a/nvif/class.h +++ b/nvif/class.h @@ -10,6 +10,20 @@ /******************************************************************************* + * client + ******************************************************************************/ + +#define NV_CLIENT_DEVLIST 0x00 + +struct nv_client_devlist_v0 { + __u8 version; + __u8 count; + __u8 pad02[6]; + __u64 device[]; +}; + + +/******************************************************************************* * device ******************************************************************************/ diff --git a/nvkm/core/client.c b/nvkm/core/client.c index 42016cde5..10598dede 100644 --- a/nvkm/core/client.c +++ b/nvkm/core/client.c @@ -26,6 +26,7 @@ #include <core/client.h> #include <core/handle.h> #include <core/option.h> +#include <nvif/unpack.h> #include <nvif/class.h> #include <nvif/unpack.h> @@ -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/nvkm/engine/device/base.c b/nvkm/engine/device/base.c index a5e10d351..8d74a3163 100644 --- a/nvkm/engine/device/base.c +++ b/nvkm/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/nvkm/include/core/device.h b/nvkm/include/core/device.h index a45ece151..aa62b637c 100644 --- a/nvkm/include/core/device.h +++ b/nvkm/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) { |