]> git.karo-electronics.de Git - linux-beck.git/commitdiff
drm/nouveau/gr: fallback to legacy paths during firmware lookup
authorAlexandre Courbot <acourbot@nvidia.com>
Fri, 4 Nov 2016 09:36:17 +0000 (18:36 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 7 Nov 2016 04:05:04 +0000 (14:05 +1000)
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>
Cc: stable@vger.kernel.org
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c

index eccdee04107d39113240f8381eac86b0c983c97a..60a1b5c8214be5671e3f0baf3f55a7981bbc1184 100644 (file)
@@ -1755,6 +1755,50 @@ gf100_gr_ = {
        .object_get = gf100_gr_object_get,
 };
 
+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, const char *fwname,
        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);