summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvif/object.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-08-20 07:54:16 +0300
committerBen Skeggs <bskeggs@redhat.com>2015-08-28 05:40:32 +0300
commit41a634064db489713945e228e216336080ba57f8 (patch)
tree5ca615eea8bc281f826d4e7a109063068156ac0e /drivers/gpu/drm/nouveau/nvif/object.c
parentf58ddf9581655d3fea51465f06f292d365af9c87 (diff)
downloadlinux-41a634064db489713945e228e216336080ba57f8.tar.xz
drm/nouveau/nvif: return min/max versions for supported object classes
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvif/object.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvif/object.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c
index 0c09e6433fbb..c3fb6a20f567 100644
--- a/drivers/gpu/drm/nouveau/nvif/object.c
+++ b/drivers/gpu/drm/nouveau/nvif/object.c
@@ -48,26 +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, s32 *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;
+ }
- 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;
}