These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / ath / ath9k / hif_usb.c
index 10c02f5..165dd20 100644 (file)
 #include <asm/unaligned.h>
 #include "htc.h"
 
-/* identify firmware images */
-#define FIRMWARE_AR7010_1_1     "htc_7010.fw"
-#define FIRMWARE_AR9271         "htc_9271.fw"
-
-MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
-MODULE_FIRMWARE(FIRMWARE_AR9271);
+MODULE_FIRMWARE(HTC_7010_MODULE_FW);
+MODULE_FIRMWARE(HTC_9271_MODULE_FW);
 
 static struct usb_device_id ath9k_hif_usb_ids[] = {
        { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
@@ -1080,12 +1076,88 @@ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev)
                device_unlock(parent);
 }
 
+static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context);
+
+/* taken from iwlwifi */
+static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev,
+                                     bool first)
+{
+       char index[8], *chip;
+       int ret;
+
+       if (first) {
+               if (htc_use_dev_fw) {
+                       hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX + 1;
+                       sprintf(index, "%s", "dev");
+               } else {
+                       hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX;
+                       sprintf(index, "%d", hif_dev->fw_minor_index);
+               }
+       } else {
+               hif_dev->fw_minor_index--;
+               sprintf(index, "%d", hif_dev->fw_minor_index);
+       }
+
+       /* test for FW 1.3 */
+       if (MAJOR_VERSION_REQ == 1 && hif_dev->fw_minor_index == 3) {
+               const char *filename;
+
+               if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info))
+                       filename = FIRMWARE_AR7010_1_1;
+               else
+                       filename = FIRMWARE_AR9271;
+
+               /* expected fw locations:
+                * - htc_9271.fw   (stable version 1.3, depricated)
+                */
+               snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name),
+                        "%s", filename);
+
+       } else if (hif_dev->fw_minor_index < FIRMWARE_MINOR_IDX_MIN) {
+               dev_err(&hif_dev->udev->dev, "no suitable firmware found!\n");
+
+               return -ENOENT;
+       } else {
+               if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info))
+                       chip = "7010";
+               else
+                       chip = "9271";
+
+               /* expected fw locations:
+                * - ath9k_htc/htc_9271-1.dev.0.fw (development version)
+                * - ath9k_htc/htc_9271-1.4.0.fw   (stable version)
+                */
+               snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name),
+                        "%s/htc_%s-%d.%s.0.fw", HTC_FW_PATH,
+                        chip, MAJOR_VERSION_REQ, index);
+       }
+
+       ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
+                                     &hif_dev->udev->dev, GFP_KERNEL,
+                                     hif_dev, ath9k_hif_usb_firmware_cb);
+       if (ret) {
+               dev_err(&hif_dev->udev->dev,
+                       "ath9k_htc: Async request for firmware %s failed\n",
+                       hif_dev->fw_name);
+               return ret;
+       }
+
+       dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
+                hif_dev->fw_name);
+
+       return ret;
+}
+
 static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
 {
        struct hif_device_usb *hif_dev = context;
        int ret;
 
        if (!fw) {
+               ret = ath9k_hif_request_firmware(hif_dev, false);
+               if (!ret)
+                       return;
+
                dev_err(&hif_dev->udev->dev,
                        "ath9k_htc: Failed to get firmware %s\n",
                        hif_dev->fw_name);
@@ -1215,27 +1287,11 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
 
        init_completion(&hif_dev->fw_done);
 
-       /* Find out which firmware to load */
-
-       if (IS_AR7010_DEVICE(id->driver_info))
-               hif_dev->fw_name = FIRMWARE_AR7010_1_1;
-       else
-               hif_dev->fw_name = FIRMWARE_AR9271;
-
-       ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
-                                     &hif_dev->udev->dev, GFP_KERNEL,
-                                     hif_dev, ath9k_hif_usb_firmware_cb);
-       if (ret) {
-               dev_err(&hif_dev->udev->dev,
-                       "ath9k_htc: Async request for firmware %s failed\n",
-                       hif_dev->fw_name);
+       ret = ath9k_hif_request_firmware(hif_dev, true);
+       if (ret)
                goto err_fw_req;
-       }
 
-       dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
-                hif_dev->fw_name);
-
-       return 0;
+       return ret;
 
 err_fw_req:
        usb_set_intfdata(interface, NULL);