[Nouveau] [PATCH] nouveau: Load firmware for BSP/VP engines on NV84-NV96, NVA0

Ilia Mirkin imirkin at alum.mit.edu
Wed Jun 26 23:29:49 PDT 2013


v2 -> v3:
  - Changed firmware naming convention to be more similar to falcon
  - Removed setting of 0x2090, it was out of place and seemingly
    unnecessary
  - Load firmware only once and then keep it around until dtor

Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---

Ben, as you requested, incremental diff against your other tree. I
manually touched up the patch off of the linux tree, but this does
seem to apply correctly.

Pretty sure I addressed all your comments, let me know if I missed
anything.

 nvkm/engine/xtensa.c         | 73 +++++++++++++---------
 nvkm/engine/bsp/nv84.c       |  2 -
 nvkm/engine/vp/nv84.c        |  2 -
 nvkm/include/engine/xtensa.h |  4 +-
 4 files changed, 43 insertions(+), 38 deletions(-)

diff --git a/nvkm/engine/xtensa.c b/nvkm/engine/xtensa.c
index 2dfab98..b8191e1 100644
--- a/nvkm/engine/xtensa.c
+++ b/nvkm/engine/xtensa.c
@@ -56,12 +56,11 @@ void
 _nouveau_xtensa_intr(struct nouveau_subdev *subdev)
 {
 	struct nouveau_xtensa *xtensa = (void *)subdev;
-	u32 intr, unk104, unk10c, chan;
+	u32 unk104 = nv_ro32(xtensa, 0xd04);
+	u32 intr = nv_ro32(xtensa, 0xc20);
+	u32 chan = nv_ro32(xtensa, 0xc28);
+	u32 unk10c = nv_ro32(xtensa, 0xd0c);
 
-	unk104 = nv_ro32(xtensa, 0xd04);
-	intr = nv_ro32(xtensa, 0xc20);
-	chan = nv_ro32(xtensa, 0xc28);
-	unk10c = nv_ro32(xtensa, 0xd0c);
 	if (intr & 0x10)
 		nv_warn(xtensa, "Watchdog interrupt, engine hung.\n");
 	nv_wo32(xtensa, 0xc20, intr);
@@ -101,6 +100,7 @@ _nouveau_xtensa_init(struct nouveau_object *object)
 	struct nouveau_device *device = nv_device(object);
 	struct nouveau_xtensa *xtensa = (void *)object;
 	const struct firmware *fw;
+	char name[32];
 	int i, ret;
 	u32 tmp;
 
@@ -108,37 +108,40 @@ _nouveau_xtensa_init(struct nouveau_object *object)
 	if (ret)
 		return ret;
 
-	ret = nouveau_gpuobj_new(object, NULL, 0x40000, 0x1000, 0,
-				 &xtensa->gpu_fw);
-	if (ret)
-		return ret;
-
-	ret = request_firmware(&fw, xtensa->firmware_fname, &device->pdev->dev);
-	if (ret) {
-		nv_warn(xtensa, "Firmware file %s unavailable.\n",
-			xtensa->firmware_fname);
-		return ret;
+	if (!xtensa->gpu_fw) {
+		ret = nouveau_gpuobj_new(object, NULL, 0x40000, 0x1000, 0,
+					 &xtensa->gpu_fw);
+		if (ret)
+			return ret;
+
+		snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",
+			 xtensa->addr >> 12);
+		ret = request_firmware(&fw, name, &device->pdev->dev);
+		if (ret) {
+			nv_warn(xtensa, "Firmware file %s unavailable.\n",
+				name);
+			nouveau_gpuobj_ref(NULL, &xtensa->gpu_fw);
+			return ret;
+		} else if (fw->size > 0x40000) {
+			nv_warn(xtensa, "Firmware file %s too large.\n", name);
+			release_firmware(fw);
+			nouveau_gpuobj_ref(NULL, &xtensa->gpu_fw);
+			return ret;
+		}
+
+		nv_debug(xtensa, "Loading firmware to address: 0x%llx\n",
+			 xtensa->gpu_fw->addr);
+
+		for (i = 0; i < fw->size / 4; i++)
+			nv_wo32(xtensa->gpu_fw, i * 4, *((u32 *)fw->data + i));
+
+		release_firmware(fw);
 	}
 
-	nv_debug(xtensa, "Loading firmware to address: 0x%llx\n",
-		 xtensa->gpu_fw->addr);
-
-	for (i = 0; i < fw->size / 4; i++)
-		nv_wo32(xtensa->gpu_fw, i * 4, *((u32 *)fw->data + i));
-
-	release_firmware(fw);
-
-	tmp = nv_ro32(xtensa, 0xc20); /* INTR */
-	if (tmp)
-		nv_warn(xtensa, "Unexpected read from XTENSA.INTR: 0x%x", tmp);
-
 	nv_wo32(xtensa, 0xd10, 0x1fffffff); /* ?? */
 	nv_wo32(xtensa, 0xd08, 0x0fffffff); /* ?? */
 
 	nv_wo32(xtensa, 0xd28, xtensa->unkd28); /* ?? */
-	nv_mask(xtensa, 0x2090,
-		0xf << (xtensa->fifo_nibble * 4),
-		0x8 << (xtensa->fifo_nibble * 4)); /* PFIFO.UNK90 */
 	nv_wo32(xtensa, 0xc20, 0x3f); /* INTR */
 	nv_wo32(xtensa, 0xd84, 0x3f); /* INTR_EN */
 
@@ -165,7 +168,15 @@ _nouveau_xtensa_fini(struct nouveau_object *object, bool suspend)
 	nv_wo32(xtensa, 0xd84, 0); /* INTR_EN */
 	nv_wo32(xtensa, 0xd94, 0); /* FIFO_CTRL */
 
+	return nouveau_engine_fini(&xtensa->base, suspend);
+}
+
+void
+_nouveau_xtensa_dtor(struct nouveau_object *object)
+{
+	struct nouveau_xtensa *xtensa = (void *)object;
+
 	nouveau_gpuobj_ref(NULL, &xtensa->gpu_fw);
 
-	return nouveau_engine_fini(&xtensa->base, suspend);
+	return nouveau_engine_destroy(&xtensa->base);
 }
diff --git a/nvkm/engine/bsp/nv84.c b/nvkm/engine/bsp/nv84.c
index ee4cff1..90d8c13 100644
--- a/nvkm/engine/bsp/nv84.c
+++ b/nvkm/engine/bsp/nv84.c
@@ -75,9 +75,7 @@ nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	nv_engine(priv)->cclass = &nv84_bsp_cclass;
 	nv_engine(priv)->sclass = nv84_bsp_sclass;
 	priv->fifo_val = 0x1111;
-	priv->fifo_nibble = 7;
 	priv->unkd28 = 0x90044;
-	priv->firmware_fname = "nouveau/nv84_bsp";
 	return 0;
 }
 
diff --git a/nvkm/engine/vp/nv84.c b/nvkm/engine/vp/nv84.c
index 0450a2d..9ec0ace 100644
--- a/nvkm/engine/vp/nv84.c
+++ b/nvkm/engine/vp/nv84.c
@@ -75,9 +75,7 @@ nv84_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	nv_engine(priv)->cclass = &nv84_vp_cclass;
 	nv_engine(priv)->sclass = nv84_vp_sclass;
 	priv->fifo_val = 0x111;
-	priv->fifo_nibble = 3;
 	priv->unkd28 = 0x9c544;
-	priv->firmware_fname = "nouveau/nv84_vp";
 	return 0;
 }
 
diff --git a/nvkm/include/engine/xtensa.h b/nvkm/include/engine/xtensa.h
index bc7eaf8..a13eaf8 100644
--- a/nvkm/include/engine/xtensa.h
+++ b/nvkm/include/engine/xtensa.h
@@ -10,9 +10,7 @@ struct nouveau_xtensa {
 
 	u32 addr;
 	struct nouveau_gpuobj *gpu_fw;
-	const char *firmware_fname;
 	u32 fifo_val;
-	u8 fifo_nibble;
 	u32 unkd28;
 };
 
@@ -31,7 +29,7 @@ int nouveau_xtensa_create_(struct nouveau_object *,
 			   struct nouveau_oclass *, u32, bool,
 			   const char *, const char *,
 			   int, void **);
-#define _nouveau_xtensa_dtor _nouveau_engine_dtor
+void _nouveau_xtensa_dtor(struct nouveau_object *);
 int _nouveau_xtensa_init(struct nouveau_object *);
 int _nouveau_xtensa_fini(struct nouveau_object *, bool);
 u32  _nouveau_xtensa_rd32(struct nouveau_object *, u64);
-- 
1.8.1.5



More information about the Nouveau mailing list