Bluetooth: btintel: Move operational checks after version check
[linux-2.6-block.git] / drivers / bluetooth / btusb.c
index 52683fd22e050f7e21e01d9a396e924c9f6d7894..a30f7ea9be3666b77b2eb7497a39b58006f7deea 100644 (file)
@@ -455,6 +455,8 @@ static const struct usb_device_id blacklist_table[] = {
                                                     BTUSB_WIDEBAND_SPEECH },
        { USB_DEVICE(0x0bda, 0xc123), .driver_info = BTUSB_REALTEK |
                                                     BTUSB_WIDEBAND_SPEECH },
+       { USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK |
+                                                    BTUSB_WIDEBAND_SPEECH },
 
        /* Silicon Wave based devices */
        { USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
@@ -2400,11 +2402,17 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
        return -EILSEQ;
 }
 
-static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
+static int btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
                                             struct intel_boot_params *params,
                                             char *fw_name, size_t len,
                                             const char *suffix)
 {
+       /* The hardware platform number has a fixed value of 0x37 and
+        * for now only accept this single value.
+        */
+       if (ver->hw_platform != 0x37)
+               return -EINVAL;
+
        switch (ver->hw_variant) {
        case 0x0b:      /* SfP */
        case 0x0c:      /* WsP */
@@ -2424,9 +2432,10 @@ static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
                        suffix);
                break;
        default:
-               return false;
+               return -EINVAL;
        }
-       return true;
+
+       return 0;
 }
 
 static void btusb_setup_intel_newgen_get_fw_name(const struct intel_version_tlv *ver_tlv,
@@ -2481,7 +2490,6 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
        if (ver->img_type == 0x03) {
                clear_bit(BTUSB_BOOTLOADER, &data->flags);
                btintel_check_bdaddr(hdev);
-               return 0;
        }
 
        /* Check for supported iBT hardware variants of this firmware
@@ -2538,7 +2546,8 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
        btusb_setup_intel_newgen_get_fw_name(ver, fwname, sizeof(fwname), "sfi");
        err = request_firmware(&fw, fwname, &hdev->dev);
        if (err < 0) {
-               bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err);
+               bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
+                          fwname, err);
                return err;
        }
 
@@ -2554,10 +2563,17 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
        set_bit(BTUSB_DOWNLOADING, &data->flags);
 
        /* Start firmware downloading and get boot parameter */
-       err = btintel_download_firmware_newgen(hdev, fw, boot_param,
+       err = btintel_download_firmware_newgen(hdev, ver, fw, boot_param,
                                               INTEL_HW_VARIANT(ver->cnvi_bt),
                                               ver->sbe_type);
        if (err < 0) {
+               if (err == -EALREADY) {
+                       /* Firmware has already been loaded */
+                       set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
+                       err = 0;
+                       goto done;
+               }
+
                /* When FW download fails, send Intel Reset to retry
                 * FW download.
                 */
@@ -2618,35 +2634,6 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
        if (!ver || !params)
                return -EINVAL;
 
-       /* The hardware platform number has a fixed value of 0x37 and
-        * for now only accept this single value.
-        */
-       if (ver->hw_platform != 0x37) {
-               bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
-                          ver->hw_platform);
-               return -EINVAL;
-       }
-
-       /* Check for supported iBT hardware variants of this firmware
-        * loading method.
-        *
-        * This check has been put in place to ensure correct forward
-        * compatibility options when newer hardware variants come along.
-        */
-       switch (ver->hw_variant) {
-       case 0x0b:      /* SfP */
-       case 0x0c:      /* WsP */
-       case 0x11:      /* JfP */
-       case 0x12:      /* ThP */
-       case 0x13:      /* HrP */
-       case 0x14:      /* CcP */
-               break;
-       default:
-               bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
-                          ver->hw_variant);
-               return -EINVAL;
-       }
-
        btintel_version_info(hdev, ver);
 
        /* The firmware variant determines if the device is in bootloader
@@ -2665,16 +2652,18 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
        if (ver->fw_variant == 0x23) {
                clear_bit(BTUSB_BOOTLOADER, &data->flags);
                btintel_check_bdaddr(hdev);
-               return 0;
-       }
 
-       /* If the device is not in bootloader mode, then the only possible
-        * choice is to return an error and abort the device initialization.
-        */
-       if (ver->fw_variant != 0x06) {
-               bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
-                          ver->fw_variant);
-               return -ENODEV;
+               /* SfP and WsP don't seem to update the firmware version on file
+                * so version checking is currently possible.
+                */
+               switch (ver->hw_variant) {
+               case 0x0b:      /* SfP */
+               case 0x0c:      /* WsP */
+                       return 0;
+               }
+
+               /* Proceed to download to check if the version matches */
+               goto download;
        }
 
        /* Read the secure boot parameters to identify the operating
@@ -2702,6 +2691,7 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
                set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
        }
 
+download:
        /* With this Intel bootloader only the hardware variant and device
         * revision information are used to select the right firmware for SfP
         * and WsP.
@@ -2725,14 +2715,15 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
         */
        err = btusb_setup_intel_new_get_fw_name(ver, params, fwname,
                                                sizeof(fwname), "sfi");
-       if (!err) {
+       if (err < 0) {
                bt_dev_err(hdev, "Unsupported Intel firmware naming");
                return -EINVAL;
        }
 
        err = request_firmware(&fw, fwname, &hdev->dev);
        if (err < 0) {
-               bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err);
+               bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
+                          fwname, err);
                return err;
        }
 
@@ -2748,8 +2739,15 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev,
        set_bit(BTUSB_DOWNLOADING, &data->flags);
 
        /* Start firmware downloading and get boot parameter */
-       err = btintel_download_firmware(hdev, fw, boot_param);
+       err = btintel_download_firmware(hdev, ver, fw, boot_param);
        if (err < 0) {
+               if (err == -EALREADY) {
+                       /* Firmware has already been loaded */
+                       set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
+                       err = 0;
+                       goto done;
+               }
+
                /* When FW download fails, send Intel Reset to retry
                 * FW download.
                 */
@@ -2890,7 +2888,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
        err = btusb_setup_intel_new_get_fw_name(&ver, &params, ddcname,
                                                sizeof(ddcname), "ddc");
 
-       if (!err) {
+       if (err < 0) {
                bt_dev_err(hdev, "Unsupported Intel firmware naming");
        } else {
                /* Once the device is running in operational mode, it needs to
@@ -3495,7 +3493,7 @@ static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwnam
        fw_ptr = fw->data;
        fw_bin_ptr = fw_ptr;
        globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
-       section_num = globaldesc->section_num;
+       section_num = le32_to_cpu(globaldesc->section_num);
 
        for (i = 0; i < section_num; i++) {
                first_block = 1;
@@ -3503,8 +3501,8 @@ static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwnam
                sectionmap = (struct btmtk_section_map *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
                              MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
 
-               section_offset = sectionmap->secoffset;
-               dl_size = sectionmap->bin_info_spec.dlsize;
+               section_offset = le32_to_cpu(sectionmap->secoffset);
+               dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
 
                if (dl_size > 0) {
                        retry = 20;
@@ -3740,7 +3738,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
        int err, status;
        u32 dev_id;
        char fw_bin_name[64];
-       u32 fw_version;
+       u32 fw_version = 0;
        u8 param;
 
        calltime = ktime_get();