drm/nouveau/nvif: assign internal class identifiers to sw classes

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
index 193437c..7ac185c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
@@ -55,6 +55,10 @@
 #define NVIF_IOCTL_NEW_V0_CONTROL                                            -1
 #define NVIF_IOCTL_NEW_V0_PERFMON                                            -2
 #define NVIF_IOCTL_NEW_V0_PERFDOM                                            -3
+#define NVIF_IOCTL_NEW_V0_SW_NV04                                            -4
+#define NVIF_IOCTL_NEW_V0_SW_NV10                                            -5
+#define NVIF_IOCTL_NEW_V0_SW_NV50                                            -6
+#define NVIF_IOCTL_NEW_V0_SW_GF100                                           -7
 	__s32 oclass;
 	__u8  data[];		/* class data (class.h) */
 };
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h b/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h
index f880d66..16337f6 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h
@@ -45,7 +45,7 @@
 void nvkm_namedb_remove(struct nvkm_handle *);
 
 struct nvkm_handle *nvkm_namedb_get(struct nvkm_namedb *, u32);
-struct nvkm_handle *nvkm_namedb_get_class(struct nvkm_namedb *, u16);
+struct nvkm_handle *nvkm_namedb_get_class(struct nvkm_namedb *, s32);
 struct nvkm_handle *nvkm_namedb_get_vinst(struct nvkm_namedb *, u64);
 struct nvkm_handle *nvkm_namedb_get_cinst(struct nvkm_namedb *, u32);
 void nvkm_namedb_put(struct nvkm_handle *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 76c3632..1b3067ee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -74,23 +74,23 @@
 	return ret;
 }
 
-u16
+s32
 nouveau_abi16_swclass(struct nouveau_drm *drm)
 {
 	switch (drm->device.info.family) {
 	case NV_DEVICE_INFO_V0_TNT:
-		return 0x006e;
+		return NVIF_IOCTL_NEW_V0_SW_NV04;
 	case NV_DEVICE_INFO_V0_CELSIUS:
 	case NV_DEVICE_INFO_V0_KELVIN:
 	case NV_DEVICE_INFO_V0_RANKINE:
 	case NV_DEVICE_INFO_V0_CURIE:
-		return 0x016e;
+		return NVIF_IOCTL_NEW_V0_SW_NV10;
 	case NV_DEVICE_INFO_V0_TESLA:
-		return 0x506e;
+		return NVIF_IOCTL_NEW_V0_SW_NV50;
 	case NV_DEVICE_INFO_V0_FERMI:
 	case NV_DEVICE_INFO_V0_KEPLER:
 	case NV_DEVICE_INFO_V0_MAXWELL:
-		return 0x906e;
+		return NVIF_IOCTL_NEW_V0_SW_GF100;
 	}
 
 	return 0x0000;
@@ -368,9 +368,10 @@
 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
 	struct nouveau_abi16_chan *chan;
 	struct nouveau_abi16_ntfy *ntfy;
-	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nvif_client *client;
-	int ret;
+	u32 sclass[32];
+	s32 oclass = 0;
+	int ret, i;
 
 	if (unlikely(!abi16))
 		return -ENOMEM;
@@ -379,17 +380,62 @@
 		return nouveau_abi16_put(abi16, -EINVAL);
 	client = abi16->device.object.client;
 
-	/* compatibility with userspace that assumes 506e for all chipsets */
-	if (init->class == 0x506e) {
-		init->class = nouveau_abi16_swclass(drm);
-		if (init->class == 0x906e)
-			return nouveau_abi16_put(abi16, 0);
-	}
-
 	chan = nouveau_abi16_chan(abi16, init->channel);
 	if (!chan)
 		return nouveau_abi16_put(abi16, -ENOENT);
 
+	ret = nvif_object_sclass(&chan->chan->user, sclass, ARRAY_SIZE(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]) {
+			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];
+				break;
+			default:
+				break;
+			}
+		}
+	} else
+	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];
+				break;
+			}
+		}
+	} else
+	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];
+				break;
+			}
+		}
+	} else
+	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];
+				break;
+			}
+		}
+	} else {
+		oclass = init->class;
+	}
+
+	if (!oclass)
+		return nouveau_abi16_put(abi16, -EINVAL);
+
 	ntfy = kzalloc(sizeof(*ntfy), GFP_KERNEL);
 	if (!ntfy)
 		return nouveau_abi16_put(abi16, -ENOMEM);
@@ -397,7 +443,7 @@
 	list_add(&ntfy->head, &chan->notifiers);
 
 	client->route = NVDRM_OBJECT_ABI16;
-	ret = nvif_object_init(&chan->chan->user, init->handle, init->class,
+	ret = nvif_object_init(&chan->chan->user, init->handle, oclass,
 			       NULL, 0, &ntfy->object);
 	client->route = NVDRM_OBJECT_NVIF;
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h
index b8acfd7..6584557 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.h
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h
@@ -37,7 +37,7 @@
 struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *, struct drm_device *);
 int  nouveau_abi16_put(struct nouveau_abi16 *, int);
 void nouveau_abi16_fini(struct nouveau_abi16 *);
-u16  nouveau_abi16_swclass(struct nouveau_drm *);
+s32  nouveau_abi16_swclass(struct nouveau_drm *);
 
 #define NOUVEAU_GEM_DOMAIN_VRAM      (1 << 1)
 #define NOUVEAU_GEM_DOMAIN_GART      (1 << 2)
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 9dd2f4f..65a144f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -24,6 +24,7 @@
 
 #include <nvif/os.h>
 #include <nvif/class.h>
+#include <nvif/ioctl.h>
 
 /*XXX*/
 #include <core/client.h>
@@ -363,7 +364,8 @@
 
 	/* allocate software object class (used for fences on <= nv05) */
 	if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
-		ret = nvif_object_init(&chan->user, 0x006e, 0x006e,
+		ret = nvif_object_init(&chan->user, 0x006e,
+				       NVIF_IOCTL_NEW_V0_SW_NV04,
 				       NULL, 0, &chan->nvsw);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/namedb.c b/drivers/gpu/drm/nouveau/nvkm/core/namedb.c
index 6400767..ca625c5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/namedb.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/namedb.c
@@ -39,7 +39,7 @@
 }
 
 static struct nvkm_handle *
-nvkm_namedb_lookup_class(struct nvkm_namedb *namedb, u16 oclass)
+nvkm_namedb_lookup_class(struct nvkm_namedb *namedb, s32 oclass)
 {
 	struct nvkm_handle *handle;
 
@@ -122,7 +122,7 @@
 }
 
 struct nvkm_handle *
-nvkm_namedb_get_class(struct nvkm_namedb *namedb, u16 oclass)
+nvkm_namedb_get_class(struct nvkm_namedb *namedb, s32 oclass)
 {
 	struct nvkm_handle *handle;
 	read_lock(&namedb->lock);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index cfaa8ae..cdb25b5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -33,6 +33,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/ioctl.h>
 #include <nvif/unpack.h>
 
 struct gf100_fifo {
@@ -494,7 +495,7 @@
 	if (unlikely(!chan))
 		goto out;
 
-	bind = nvkm_namedb_get_class(nv_namedb(chan), 0x906e);
+	bind = nvkm_namedb_get_class(nv_namedb(chan), NVIF_IOCTL_NEW_V0_SW_GF100);
 	if (likely(bind)) {
 		if (!mthd || !nv_call(bind->object, mthd, data))
 			ret = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index 9c42351..49d7ea0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -33,6 +33,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/ioctl.h>
 #include <nvif/unpack.h>
 
 #define _(a,b) { (a), ((1ULL << (a)) | (b)) }
@@ -533,7 +534,7 @@
 	if (unlikely(!chan))
 		goto out;
 
-	bind = nvkm_namedb_get_class(nv_namedb(chan), 0x906e);
+	bind = nvkm_namedb_get_class(nv_namedb(chan), NVIF_IOCTL_NEW_V0_SW_GF100);
 	if (likely(bind)) {
 		if (!mthd || !nv_call(bind->object, mthd, data))
 			ret = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
index eade9e3..061ea72 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
@@ -25,6 +25,8 @@
 
 #include <subdev/bar.h>
 
+#include <nvif/ioctl.h>
+
 /*******************************************************************************
  * software object classes
  ******************************************************************************/
@@ -87,7 +89,7 @@
 
 static struct nvkm_oclass
 gf100_sw_sclass[] = {
-	{ 0x906e, &nvkm_object_ofuncs, gf100_sw_omthds },
+	{ NVIF_IOCTL_NEW_V0_SW_GF100, &nvkm_object_ofuncs, gf100_sw_omthds },
 	{}
 };
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c
index 3bdab84..74c8c9d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c
@@ -24,6 +24,8 @@
 #include <engine/sw.h>
 #include <engine/fifo.h>
 
+#include <nvif/ioctl.h>
+
 /*******************************************************************************
  * software object classes
  ******************************************************************************/
@@ -55,7 +57,7 @@
 
 static struct nvkm_oclass
 nv04_sw_sclass[] = {
-	{ 0x006e, &nvkm_object_ofuncs, nv04_sw_omthds },
+	{ NVIF_IOCTL_NEW_V0_SW_NV04, &nvkm_object_ofuncs, nv04_sw_omthds },
 	{}
 };
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c
index 1288142..26ccd69 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c
@@ -23,6 +23,8 @@
  */
 #include <engine/sw.h>
 
+#include <nvif/ioctl.h>
+
 /*******************************************************************************
  * software object classes
  ******************************************************************************/
@@ -44,7 +46,7 @@
 
 static struct nvkm_oclass
 nv10_sw_sclass[] = {
-	{ 0x016e, &nvkm_object_ofuncs, nv10_sw_omthds },
+	{ NVIF_IOCTL_NEW_V0_SW_NV10, &nvkm_object_ofuncs, nv10_sw_omthds },
 	{}
 };
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
index ab3175a..ca4b8a0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
@@ -29,6 +29,7 @@
 #include <subdev/bar.h>
 
 #include <nvif/event.h>
+#include <nvif/ioctl.h>
 
 /*******************************************************************************
  * software object classes
@@ -108,7 +109,7 @@
 
 static struct nvkm_oclass
 nv50_sw_sclass[] = {
-	{ 0x506e, &nvkm_object_ofuncs, nv50_sw_omthds },
+	{ NVIF_IOCTL_NEW_V0_SW_NV50, &nvkm_object_ofuncs, nv50_sw_omthds },
 	{}
 };