| From e137040e0d0376b404fc5155eba44ea07126e3bd Mon Sep 17 00:00:00 2001 |
| From: Alexandre Courbot <acourbot@nvidia.com> |
| Date: Fri, 4 Nov 2016 18:36:17 +0900 |
| Subject: drm/nouveau/gr: fallback to legacy paths during firmware lookup |
| |
| From: Alexandre Courbot <acourbot@nvidia.com> |
| |
| commit e137040e0d0376b404fc5155eba44ea07126e3bd upstream. |
| |
| 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@nvidia.com> |
| Signed-off-by: Ben Skeggs <bskeggs@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 50 +++++++++++++++++++++++-- |
| 1 file changed, 46 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c |
| +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c |
| @@ -1756,6 +1756,50 @@ gf100_gr_ = { |
| }; |
| |
| int |
| +gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname, |
| + struct gf100_gr_fuc *fuc, int ret) |
| +{ |
| + struct nvkm_subdev *subdev = &gr->base.engine.subdev; |
| + struct nvkm_device *device = subdev->device; |
| + const struct firmware *fw; |
| + char f[32]; |
| + |
| + /* see if this firmware has a legacy path */ |
| + if (!strcmp(fwname, "fecs_inst")) |
| + fwname = "fuc409c"; |
| + else if (!strcmp(fwname, "fecs_data")) |
| + fwname = "fuc409d"; |
| + else if (!strcmp(fwname, "gpccs_inst")) |
| + fwname = "fuc41ac"; |
| + else if (!strcmp(fwname, "gpccs_data")) |
| + fwname = "fuc41ad"; |
| + else { |
| + /* nope, let's just return the error we got */ |
| + nvkm_error(subdev, "failed to load %s\n", fwname); |
| + return ret; |
| + } |
| + |
| + /* yes, try to load from the legacy path */ |
| + nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname); |
| + |
| + 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) |
| { |
| @@ -1765,10 +1809,8 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, co |
| int ret; |
| |
| ret = nvkm_firmware_get(device, fwname, &fw); |
| - if (ret) { |
| - nvkm_error(subdev, "failed to load %s\n", fwname); |
| - return ret; |
| - } |
| + if (ret) |
| + return gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret); |
| |
| fuc->size = fw->size; |
| fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); |