[Nouveau] [PATCH] gr: fallback to legacy paths during firmware lookup

Alexandre Courbot acourbot at nvidia.com
Wed Nov 2 04:54:17 UTC 2016


Look for firmware files using the legacy ("nouveau/nvxx_fucxxxx") path
if they cannot be found in the new, "official" path. User setups were
broken by the switch, which is bad.

There are only 4 firmware files we may want to look up that way, so
hardcode them into the lookup function. All new firmware files should
use the standard "nvidia/<chip>/gr/" path.

Fixes: 8539b37acef7 ("drm/nouveau/gr: use NVIDIA-provided external firmwares")
Signed-off-by: Alexandre Courbot <acourbot at nvidia.com>
---
 drm/nouveau/nvkm/engine/gr/gf100.c | 56 ++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 5 deletions(-)

diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c
index 157919c788e6..9e65adbab21c 100644
--- a/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1756,24 +1756,70 @@ gf100_gr_ = {
 };
 
 int
+gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname,
+			struct gf100_gr_fuc *fuc)
+{
+	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+	struct nvkm_device *device = subdev->device;
+	const struct firmware *fw;
+	char f[32];
+	int ret;
+
+	snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
+	ret = request_firmware(&fw, f, device->dev);
+	if (ret) {
+		snprintf(f, sizeof(f), "nouveau/%s", fwname);
+		ret = request_firmware(&fw, f, device->dev);
+		if (ret) {
+			nvkm_error(subdev, "failed to load %s\n", fwname);
+			return ret;
+		}
+	}
+
+	fuc->size = fw->size;
+	fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
+	release_firmware(fw);
+	return (fuc->data != NULL) ? 0 : -ENOMEM;
+}
+
+int
 gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
 		 struct gf100_gr_fuc *fuc)
 {
 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
+	const char *legacy_fwname = NULL;
 	const struct firmware *fw;
 	int ret;
 
 	ret = nvkm_firmware_get(device, fwname, &fw);
-	if (ret) {
+	/* firmware found, success! */
+	if (!ret) {
+		fuc->size = fw->size;
+		fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
+		nvkm_firmware_put(fw);
+		return (fuc->data != NULL) ? 0 : -ENOMEM;
+	}
+
+	/* see if this firmware has a legacy path */
+	if (!strcmp(fwname, "fecs_inst"))
+		legacy_fwname = "fuc409c";
+	else if (!strcmp(fwname, "fecs_data"))
+		legacy_fwname = "fuc409d";
+	else if (!strcmp(fwname, "gpccs_inst"))
+		legacy_fwname = "fuc41ac";
+	else if (!strcmp(fwname, "gpccs_data"))
+		legacy_fwname = "fuc41ad";
+
+	/* nope, let's just return the error we got */
+	if (!legacy_fwname) {
 		nvkm_error(subdev, "failed to load %s\n", fwname);
 		return ret;
 	}
 
-	fuc->size = fw->size;
-	fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
-	nvkm_firmware_put(fw);
-	return (fuc->data != NULL) ? 0 : -ENOMEM;
+	/* yes, try to load from the legacy path */
+	nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname);
+	return gf100_gr_ctor_fw_legacy(gr, legacy_fwname, fuc);
 }
 
 int
-- 
2.10.0



More information about the Nouveau mailing list