drm/nouveau/core: support versioned firmware loading
authorBen Skeggs <bskeggs@redhat.com>
Wed, 22 May 2019 06:15:54 +0000 (16:15 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 7 Jun 2019 05:13:58 +0000 (15:13 +1000)
We have a need for this now with updated SEC2 LS FW images that have an
incompatible interface from the previous version.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
drivers/gpu/drm/nouveau/nvkm/core/firmware.c

index d0fe98b..54da9c6 100644 (file)
@@ -3,7 +3,10 @@
 #define __NVKM_FIRMWARE_H__
 #include <core/subdev.h>
 
+int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname,
+                             int min_version, int max_version,
+                             const struct firmware **);
 int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname,
-                     const struct firmware **fw);
-void nvkm_firmware_put(const struct firmware *fw);
+                     const struct firmware **);
+void nvkm_firmware_put(const struct firmware *);
 #endif
index 8772813..092acde 100644 (file)
@@ -32,8 +32,9 @@
  * Firmware files released by NVIDIA will always follow this format.
  */
 int
-nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname,
-                 const struct firmware **fw)
+nvkm_firmware_get_version(const struct nvkm_subdev *subdev, const char *fwname,
+                         int min_version, int max_version,
+                         const struct firmware **fw)
 {
        struct nvkm_device *device = subdev->device;
        char f[64];
@@ -49,8 +50,29 @@ nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname,
                cname[i] = tolower(cname[i]);
        }
 
-       snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
-       return request_firmware(fw, f, device->dev);
+       for (i = max_version; i >= min_version; i--) {
+               if (i != 0)
+                       snprintf(f, sizeof(f), "nvidia/%s/%s-%d.bin", cname, fwname, i);
+               else
+                       snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
+
+               if (!firmware_request_nowarn(fw, f, device->dev)) {
+                       nvkm_debug(subdev, "firmware \"%s\" loaded\n", f);
+                       return i;
+               }
+
+               nvkm_debug(subdev, "firmware \"%s\" unavailable\n", f);
+       }
+
+       nvkm_error(subdev, "failed to load firmware \"%s\"", fwname);
+       return -ENOENT;
+}
+
+int
+nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname,
+                 const struct firmware **fw)
+{
+       return nvkm_firmware_get_version(subdev, fwname, 0, 0, fw);
 }
 
 /**