drm/nouveau/xtensa: convert to new-style nvkm_engine
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / nouveau / nvif / object.c
index b914e34a43c3b72414cdb9143a82a35fb00fd112..c3fb6a20f567d1454bfb49ffd19b151470eb6b90 100644 (file)
@@ -48,27 +48,53 @@ nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
                                     data, size, hack);
 }
 
+void
+nvif_object_sclass_put(struct nvif_sclass **psclass)
+{
+       kfree(*psclass);
+       *psclass = NULL;
+}
+
 int
-nvif_object_sclass(struct nvif_object *object, u32 *oclass, int count)
+nvif_object_sclass_get(struct nvif_object *object, struct nvif_sclass **psclass)
 {
        struct {
                struct nvif_ioctl_v0 ioctl;
                struct nvif_ioctl_sclass_v0 sclass;
-       } *args;
-       u32 size = count * sizeof(args->sclass.oclass[0]);
-       int ret;
+       } *args = NULL;
+       int ret, cnt = 0, i;
+       u32 size;
 
-       if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
-               return -ENOMEM;
-       args->ioctl.version = 0;
-       args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
-       args->sclass.version = 0;
-       args->sclass.count = count;
+       while (1) {
+               size = sizeof(*args) + cnt * sizeof(args->sclass.oclass[0]);
+               if (!(args = kmalloc(size, GFP_KERNEL)))
+                       return -ENOMEM;
+               args->ioctl.version = 0;
+               args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
+               args->sclass.version = 0;
+               args->sclass.count = cnt;
+
+               ret = nvif_object_ioctl(object, args, size, NULL);
+               if (ret == 0 && args->sclass.count <= cnt)
+                       break;
+               cnt = args->sclass.count;
+               kfree(args);
+               if (ret != 0)
+                       return ret;
+       }
+
+       *psclass = kzalloc(sizeof(**psclass) * args->sclass.count, GFP_KERNEL);
+       if (*psclass) {
+               for (i = 0; i < args->sclass.count; i++) {
+                       (*psclass)[i].oclass = args->sclass.oclass[i].oclass;
+                       (*psclass)[i].minver = args->sclass.oclass[i].minver;
+                       (*psclass)[i].maxver = args->sclass.oclass[i].maxver;
+               }
+               ret = args->sclass.count;
+       } else {
+               ret = -ENOMEM;
+       }
 
-       memcpy(args->sclass.oclass, oclass, size);
-       ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
-       ret = ret ? ret : args->sclass.count;
-       memcpy(oclass, args->sclass.oclass, size);
        kfree(args);
        return ret;
 }
@@ -203,7 +229,7 @@ nvif_object_fini(struct nvif_object *object)
 }
 
 int
-nvif_object_init(struct nvif_object *parent, u32 handle, u32 oclass,
+nvif_object_init(struct nvif_object *parent, u32 handle, s32 oclass,
                 void *data, u32 size, struct nvif_object *object)
 {
        struct {