drm/nouveau/client: add method to retrieve device list
authorBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 18:10:21 +0000 (04:10 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 19:13:08 +0000 (05:13 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/core/client.c
drivers/gpu/drm/nouveau/core/engine/device/base.c
drivers/gpu/drm/nouveau/core/include/core/device.h
drivers/gpu/drm/nouveau/nvif/class.h

index 42016cd..10598de 100644 (file)
@@ -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,
        },
 };
 
index a5e10d3..8d74a31 100644 (file)
@@ -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
  *****************************************************************************/
index a45ece1..aa62b63 100644 (file)
@@ -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)
 {
index 36ecc3e..3013656 100644 (file)
@@ -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
  ******************************************************************************/