summaryrefslogtreecommitdiff
path: root/drivers
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
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')
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/ioctl.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/object.h9
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/parent.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c21
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c11
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvif/object.c53
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/parent.c19
8 files changed, 92 insertions, 42 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
index 7ac185c6e71f..b0ac0215ebf9 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
@@ -40,7 +40,11 @@ struct nvif_ioctl_sclass_v0 {
__u8 version;
__u8 count;
__u8 pad02[6];
- __s32 oclass[];
+ struct nvif_ioctl_sclass_oclass_v0 {
+ __s32 oclass;
+ __s16 minver;
+ __s16 maxver;
+ } oclass[];
};
struct nvif_ioctl_new_v0 {
diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h
index 66d3425e4764..8d815967767f 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/object.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/object.h
@@ -3,6 +3,12 @@
#include <nvif/os.h>
+struct nvif_sclass {
+ s32 oclass;
+ int minver;
+ int maxver;
+};
+
struct nvif_object {
struct nvif_client *client;
u32 handle;
@@ -18,7 +24,8 @@ int nvif_object_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
struct nvif_object *);
void nvif_object_fini(struct nvif_object *);
int nvif_object_ioctl(struct nvif_object *, void *, u32, void **);
-int nvif_object_sclass(struct nvif_object *, s32 *, int);
+int nvif_object_sclass_get(struct nvif_object *, struct nvif_sclass **);
+void nvif_object_sclass_put(struct nvif_sclass **);
u32 nvif_object_rd(struct nvif_object *, int, u64);
void nvif_object_wr(struct nvif_object *, int, u64, u32);
int nvif_object_mthd(struct nvif_object *, u32, void *, u32);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h b/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h
index bc4dc1f2403f..45d2066ff97a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/parent.h
@@ -47,5 +47,5 @@ void _nvkm_parent_dtor(struct nvkm_object *);
int nvkm_parent_sclass(struct nvkm_object *, s32 handle,
struct nvkm_object **pengine,
struct nvkm_oclass **poclass);
-int nvkm_parent_lclass(struct nvkm_object *, s32 *, int);
+int nvkm_parent_lclass(struct nvkm_object *, void *, int);
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 1b3067ee0442..98c74985e27d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -369,7 +369,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
struct nvif_client *client;
- u32 sclass[32];
+ struct nvif_sclass *sclass;
s32 oclass = 0;
int ret, i;
@@ -384,19 +384,19 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if (!chan)
return nouveau_abi16_put(abi16, -ENOENT);
- ret = nvif_object_sclass(&chan->chan->user, sclass, ARRAY_SIZE(sclass));
+ ret = nvif_object_sclass_get(&chan->chan->user, &sclass);
if (ret < 0)
return nouveau_abi16_put(abi16, ret);
if ((init->class & 0x00ff) == 0x006e) {
/* nvsw: compatibility with older 0x*6e class identifier */
for (i = 0; !oclass && i < ret; i++) {
- switch (sclass[i]) {
+ switch (sclass[i].oclass) {
case NVIF_IOCTL_NEW_V0_SW_NV04:
case NVIF_IOCTL_NEW_V0_SW_NV10:
case NVIF_IOCTL_NEW_V0_SW_NV50:
case NVIF_IOCTL_NEW_V0_SW_GF100:
- oclass = sclass[i];
+ oclass = sclass[i].oclass;
break;
default:
break;
@@ -406,8 +406,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if ((init->class & 0x00ff) == 0x00b1) {
/* msvld: compatibility with incorrect version exposure */
for (i = 0; i < ret; i++) {
- if ((sclass[i] & 0x00ff) == 0x00b1) {
- oclass = sclass[i];
+ if ((sclass[i].oclass & 0x00ff) == 0x00b1) {
+ oclass = sclass[i].oclass;
break;
}
}
@@ -415,8 +415,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if ((init->class & 0x00ff) == 0x00b2) { /* mspdec */
/* mspdec: compatibility with incorrect version exposure */
for (i = 0; i < ret; i++) {
- if ((sclass[i] & 0x00ff) == 0x00b2) {
- oclass = sclass[i];
+ if ((sclass[i].oclass & 0x00ff) == 0x00b2) {
+ oclass = sclass[i].oclass;
break;
}
}
@@ -424,8 +424,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if ((init->class & 0x00ff) == 0x00b3) { /* msppp */
/* msppp: compatibility with incorrect version exposure */
for (i = 0; i < ret; i++) {
- if ((sclass[i] & 0x00ff) == 0x00b3) {
- oclass = sclass[i];
+ if ((sclass[i].oclass & 0x00ff) == 0x00b3) {
+ oclass = sclass[i].oclass;
break;
}
}
@@ -433,6 +433,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
oclass = init->class;
}
+ nvif_object_sclass_put(&sclass);
if (!oclass)
return nouveau_abi16_put(abi16, -EINVAL);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 65ceb6fa4209..37dbd5e1c08f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -152,9 +152,9 @@ static void
nouveau_accel_init(struct nouveau_drm *drm)
{
struct nvif_device *device = &drm->device;
+ struct nvif_sclass *sclass;
u32 arg0, arg1;
- s32 sclass[16];
- int ret, i;
+ int ret, i, n;
if (nouveau_noaccel)
return;
@@ -163,12 +163,12 @@ nouveau_accel_init(struct nouveau_drm *drm)
/*XXX: this is crap, but the fence/channel stuff is a little
* backwards in some places. this will be fixed.
*/
- ret = nvif_object_sclass(&device->object, sclass, ARRAY_SIZE(sclass));
+ ret = n = nvif_object_sclass_get(&device->object, &sclass);
if (ret < 0)
return;
- for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) {
- switch (sclass[i]) {
+ for (ret = -ENOSYS, i = 0; i < n; i++) {
+ switch (sclass[i].oclass) {
case NV03_CHANNEL_DMA:
ret = nv04_fence_create(drm);
break;
@@ -195,6 +195,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
}
}
+ nvif_object_sclass_put(&sclass);
if (ret) {
NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret);
nouveau_accel_fini(drm);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 65e70f085325..817ce09acb19 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -69,29 +69,30 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp,
struct nv50_chan *chan)
{
const u32 handle = (oclass[0] << 16) | head;
- s32 sclass[8];
- int ret, i;
+ struct nvif_sclass *sclass;
+ int ret, i, n;
chan->device = device;
- ret = nvif_object_sclass(disp, sclass, ARRAY_SIZE(sclass));
- WARN_ON(ret > ARRAY_SIZE(sclass));
+ ret = n = nvif_object_sclass_get(disp, &sclass);
if (ret < 0)
return ret;
while (oclass[0]) {
- for (i = 0; i < ARRAY_SIZE(sclass); i++) {
- if (sclass[i] == oclass[0]) {
+ for (i = 0; i < n; i++) {
+ if (sclass[i].oclass == oclass[0]) {
ret = nvif_object_init(disp, handle, oclass[0],
data, size, &chan->user);
if (ret == 0)
nvif_object_map(&chan->user);
+ nvif_object_sclass_put(&sclass);
return ret;
}
}
oclass++;
}
+ nvif_object_sclass_put(&sclass);
return -ENOSYS;
}
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;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/parent.c b/drivers/gpu/drm/nouveau/nvkm/core/parent.c
index 43abd208b486..aecf5b8901b2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/parent.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/parent.c
@@ -25,6 +25,8 @@
#include <core/client.h>
#include <core/engine.h>
+#include <nvif/ioctl.h>
+
int
nvkm_parent_sclass(struct nvkm_object *parent, s32 handle,
struct nvkm_object **pengine,
@@ -66,8 +68,9 @@ nvkm_parent_sclass(struct nvkm_object *parent, s32 handle,
}
int
-nvkm_parent_lclass(struct nvkm_object *parent, s32 *lclass, int size)
+nvkm_parent_lclass(struct nvkm_object *parent, void *data, int size)
{
+ struct nvif_ioctl_sclass_oclass_v0 *lclass = data;
struct nvkm_oclass *sclass, *oclass;
struct nvkm_engine *engine;
int nr = -1, i;
@@ -75,8 +78,11 @@ nvkm_parent_lclass(struct nvkm_object *parent, s32 *lclass, int size)
sclass = nv_parent(parent)->sclass;
while ((oclass = sclass++) && oclass->ofuncs) {
- if (++nr < size)
- lclass[nr] = oclass->handle;
+ if (++nr < size) {
+ lclass[nr].oclass = oclass->handle;
+ lclass[nr].minver = -2;
+ lclass[nr].maxver = -2;
+ }
}
mask = nv_parent(parent)->engine;
@@ -84,8 +90,11 @@ nvkm_parent_lclass(struct nvkm_object *parent, s32 *lclass, int size)
engine = nvkm_engine(parent, i);
if (engine && (oclass = engine->sclass)) {
while (oclass->ofuncs) {
- if (++nr < size)
- lclass[nr] = oclass->handle;
+ if (++nr < size) {
+ lclass[nr].oclass = oclass->handle;
+ lclass[nr].minver = -2;
+ lclass[nr].maxver = -2;
+ }
oclass++;
}
}