Skip to contentSkip to conversation

gr: fallback to legacy paths during firmware lookup

PATCH Superseded Alexandre Courbot 4 participants 6 messages Nov 2, 2016 – Nov 3, 2016 4 messages not in the archive

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 gr: fallback to legacy paths during firmware lookup

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")
---
 drm/nouveau/nvkm/engine/gr/gf100.c | 56 ++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 5 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +51 -5
index 157919c788e6..9e65adbab21c 100644
@@ -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
Signature · 6 lines
2.10.0

_______________________________________________
Nouveau mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/nouveau

A message that is not in the archive (sent off-list or not yet received): 20161102045417.5886-1-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

#2 lore raw
Quoted 67 lines · Alexandre Courbot

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")
---
 drm/nouveau/nvkm/engine/gr/gf100.c | 56 ++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 5 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +35 -1
index 157919c788e6..9e65adbab21c 100644
@@ -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;
+       }

drm/nouveau/nvkm/engine/gr/gf100.c gf100_gr_ = { · line 1812

Quoted 10 lines
drm/nouveau/nvkm/engine/gr/gf100.c +10 -0
+
+       /* 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";

As I mentioned on IRC, I find this strcmp thing a little jarring. It should be pretty easy to just pass the legacy fwname into gf100_gr_ctor_fw directly - there are only a handful of callers, and most would just pass NULL in as the legacy fwname - only the ones in gf100.c would pass the "old" names in.

Otherwise this looks great, thanks for taking care of it!

Quoted 20 lines
drm/nouveau/nvkm/engine/gr/gf100.c +6 -5
+
+       /* 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

Quoted 4 lines

_______________________________________________
Nouveau mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/nouveau

_______________________________________________
Nouveau mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/nouveau

A message that is not in the archive (sent off-list or not yet received): CAKb7UvhfHs=FJ+3FzkwMgmQfi+uMBvg0kSQ10FpTurRmfDX-cQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org

#4 lore raw
Quoted 76 lines · Ilia Mirkin
Quoted 75 lines · Alexandre Courbot

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")
---
 drm/nouveau/nvkm/engine/gr/gf100.c | 56 ++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 5 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +43 -1
index 157919c788e6..9e65adbab21c 100644
@@ -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";
Quoted 8 lines

drm/nouveau/nvkm/engine/gr/gf100.c gf100_gr_ = { · line 1812

Quoted 2 lines
drm/nouveau/nvkm/engine/gr/gf100.c +2 -0
+       else if (!strcmp(fwname, "gpccs_data"))
+               legacy_fwname = "fuc41ad";

As I mentioned on IRC, I find this strcmp thing a little jarring. It should be pretty easy to just pass the legacy fwname into gf100_gr_ctor_fw directly - there are only a handful of callers, and most would just pass NULL in as the legacy fwname - only the ones in gf100.c would pass the "old" names in.

Yeah, that was the original approach actually. I switched to this for the following reasons:

- We don't want to encourage using this legacy path, hence hiding it from callers
- There are only 4 possible legacy files - it's ugly but still manageable and contained in a single function

Of course, if the general consensus is that this is too ugly, it would be trivial to turn it the way you suggested, so I don't feel too strongly for one approach over the other.
_______________________________________________
Nouveau mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/nouveau

A message that is not in the archive (sent off-list or not yet received): a54062b0-afad-51e8-4d18-9fc84b8e48d8-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

#6 lore raw
Quoted 86 lines · Alexandre Courbot
Quoted 76 lines · Ilia Mirkin
Quoted 75 lines · Alexandre Courbot

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")
---
 drm/nouveau/nvkm/engine/gr/gf100.c | 56 ++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 5 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +43 -1
index 157919c788e6..9e65adbab21c 100644
@@ -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";
Quoted 8 lines

drm/nouveau/nvkm/engine/gr/gf100.c gf100_gr_ = { · line 1812

Quoted 2 lines
drm/nouveau/nvkm/engine/gr/gf100.c +2 -0
+       else if (!strcmp(fwname, "gpccs_data"))
+               legacy_fwname = "fuc41ad";

As I mentioned on IRC, I find this strcmp thing a little jarring. It should be pretty easy to just pass the legacy fwname into gf100_gr_ctor_fw directly - there are only a handful of callers, and most would just pass NULL in as the legacy fwname - only the ones in gf100.c would pass the "old" names in.

Quoted 7 lines

Yeah, that was the original approach actually. I switched to this for the following reasons:

- We don't want to encourage using this legacy path, hence hiding it from callers
- There are only 4 possible legacy files - it's ugly but still manageable and contained in a single function

I agree.

Quoted 4 lines

Of course, if the general consensus is that this is too ugly, it would be trivial to turn it the way you suggested, so I don't feel too strongly for one approach over the other.

As it is a legacy path, I'm more for hiding it away in ctor_legacy() as Emil suggests.

Ben.

_______________________________________________
Nouveau mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/nouveau

A message that is not in the archive (sent off-list or not yet received): cc55514d-56aa-6fdf-3f39-92884d4064b9-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

#8 lore raw
Quoted 96 lines · Ben Skeggs

* PGP Signed by an unknown key

Quoted 86 lines · Alexandre Courbot
Quoted 76 lines · Ilia Mirkin
Quoted 75 lines · Alexandre Courbot

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")
---
 drm/nouveau/nvkm/engine/gr/gf100.c | 56 ++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 5 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +43 -1
index 157919c788e6..9e65adbab21c 100644
@@ -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";
Quoted 8 lines

drm/nouveau/nvkm/engine/gr/gf100.c gf100_gr_ = { · line 1812

Quoted 2 lines
drm/nouveau/nvkm/engine/gr/gf100.c +2 -0
+       else if (!strcmp(fwname, "gpccs_data"))
+               legacy_fwname = "fuc41ad";

As I mentioned on IRC, I find this strcmp thing a little jarring. It should be pretty easy to just pass the legacy fwname into gf100_gr_ctor_fw directly - there are only a handful of callers, and most would just pass NULL in as the legacy fwname - only the ones in gf100.c would pass the "old" names in.

Quoted 7 lines

Yeah, that was the original approach actually. I switched to this for the following reasons:

- We don't want to encourage using this legacy path, hence hiding it from callers
- There are only 4 possible legacy files - it's ugly but still manageable and contained in a single function

Quoted 8 lines

I agree.

Quoted 4 lines

Of course, if the general consensus is that this is too ugly, it would be trivial to turn it the way you suggested, so I don't feel too strongly for one approach over the other.

As it is a legacy path, I'm more for hiding it away in ctor_legacy() as Emil suggests.

Makes sense - will respin later today.

Thanks!
Alex.
_______________________________________________
Nouveau mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/nouveau

#9 lore raw
In reply to a message not in the archive

Hi Alex,

drm/nouveau/nvkm/engine/gr/gf100.c gf100_gr_ = { · line 1813

Quoted 10 lines · Alexandre Courbot
drm/nouveau/nvkm/engine/gr/gf100.c +10 -0
+       /* 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";
+

Just an idea: If one's going for this route (and not Ilia's suggestion) it's worth moving this in the legacy function. As-is things look really weird ?

Thanks
Emil
_______________________________________________
Nouveau mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/nouveau