Merge tag 'mvebu-defconfig-3.17-2' of git://git.infradead.org/linux-mvebu into next...
[cascardo/linux.git] / drivers / net / wireless / rt2x00 / rt2800usb.c
index a49c3d7..e11dab2 100644 (file)
@@ -229,6 +229,27 @@ static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
 /*
  * Firmware functions
  */
+static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev)
+{
+       __le32 reg;
+       u32 fw_mode;
+
+       /* cannot use rt2x00usb_register_read here as it uses different
+        * mode (MULTI_READ vs. DEVICE_MODE) and does not pass the
+        * magic value USB_MODE_AUTORUN (0x11) to the device, thus the
+        * returned value would be invalid.
+        */
+       rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE,
+                                USB_VENDOR_REQUEST_IN, 0, USB_MODE_AUTORUN,
+                                &reg, sizeof(reg), REGISTER_TIMEOUT_FIRMWARE);
+       fw_mode = le32_to_cpu(reg);
+
+       if ((fw_mode & 0x00000003) == 2)
+               return 1;
+
+       return 0;
+}
+
 static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
 {
        return FIRMWARE_RT2870;
@@ -257,8 +278,13 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
        /*
         * Write firmware to device.
         */
-       rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-                                     data + offset, length);
+       if (rt2800usb_autorun_detect(rt2x00dev)) {
+               rt2x00_info(rt2x00dev,
+                           "Firmware loading not required - NIC in AutoRun mode\n");
+       } else {
+               rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+                                             data + offset, length);
+       }
 
        rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
        rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
@@ -735,11 +761,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
 /*
  * Device probe functions.
  */
+static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)
+{
+       if (rt2800usb_autorun_detect(rt2x00dev))
+               return 1;
+       return rt2800_efuse_detect(rt2x00dev);
+}
+
 static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
 
-       if (rt2800_efuse_detect(rt2x00dev))
+       if (rt2800usb_efuse_detect(rt2x00dev))
                retval = rt2800_read_eeprom_efuse(rt2x00dev);
        else
                retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,