unsigned cmd_timeout_cnt;
 };
 
-
 static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
 {
        struct btusb_data *data = hci_get_drvdata(hdev);
        return true;
 }
 
-static int btusb_setup_intel_new(struct hci_dev *hdev)
+static int btusb_intel_download_firmware(struct hci_dev *hdev,
+                                        struct intel_version *ver,
+                                        struct intel_boot_params *params)
 {
-       struct btusb_data *data = hci_get_drvdata(hdev);
-       struct intel_version ver;
-       struct intel_boot_params params;
-       struct intel_debug_features features;
        const struct firmware *fw;
        u32 boot_param;
        char fwname[64];
-       ktime_t calltime, delta, rettime;
-       unsigned long long duration;
        int err;
+       struct btusb_data *data = hci_get_drvdata(hdev);
 
-       BT_DBG("%s", hdev->name);
-
-       /* Set the default boot parameter to 0x0 and it is updated to
-        * SKU specific boot parameter after reading Intel_Write_Boot_Params
-        * command while downloading the firmware.
-        */
-       boot_param = 0x00000000;
-
-       calltime = ktime_get();
-
-       /* Read the Intel version information to determine if the device
-        * is in bootloader mode or if it already has operational firmware
-        * loaded.
-        */
-       err = btintel_read_version(hdev, &ver);
-       if (err) {
-               bt_dev_err(hdev, "Intel Read version failed (%d)", err);
-               btintel_reset_to_bootloader(hdev);
-               return err;
-       }
+       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) {
+       if (ver->hw_platform != 0x37) {
                bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
-                          ver.hw_platform);
+                          ver->hw_platform);
                return -EINVAL;
        }
 
         * This check has been put in place to ensure correct forward
         * compatibility options when newer hardware variants come along.
         */
-       switch (ver.hw_variant) {
+       switch (ver->hw_variant) {
        case 0x0b:      /* SfP */
        case 0x0c:      /* WsP */
        case 0x11:      /* JfP */
                break;
        default:
                bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
-                          ver.hw_variant);
+                          ver->hw_variant);
                return -EINVAL;
        }
 
-       btintel_version_info(hdev, &ver);
+       btintel_version_info(hdev, ver);
 
        /* The firmware variant determines if the device is in bootloader
         * mode or is running operational firmware. The value 0x06 identifies
         * It is not possible to use the Secure Boot Parameters in this
         * case since that command is only available in bootloader mode.
         */
-       if (ver.fw_variant == 0x23) {
+       if (ver->fw_variant == 0x23) {
                clear_bit(BTUSB_BOOTLOADER, &data->flags);
                btintel_check_bdaddr(hdev);
-               goto finish;
+               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) {
+       if (ver->fw_variant != 0x06) {
                bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
-                          ver.fw_variant);
+                          ver->fw_variant);
                return -ENODEV;
        }
 
        /* Read the secure boot parameters to identify the operating
         * details of the bootloader.
         */
-       err = btintel_read_boot_params(hdev, ¶ms);
+       err = btintel_read_boot_params(hdev, params);
        if (err)
                return err;
 
         * with a command complete event. If the boot parameters indicate
         * that this bootloader does not send them, then abort the setup.
         */
-       if (params.limited_cce != 0x00) {
+       if (params->limited_cce != 0x00) {
                bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
-                          params.limited_cce);
+                          params->limited_cce);
                return -EINVAL;
        }
 
        /* If the OTP has no valid Bluetooth device address, then there will
         * also be no valid address for the operational firmware.
         */
-       if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) {
+       if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
                bt_dev_info(hdev, "No device address configured");
                set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
        }
         * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
         *
         */
-       err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, fwname,
+       err = btusb_setup_intel_new_get_fw_name(ver, params, fwname,
                                                sizeof(fwname), "sfi");
        if (!err) {
                bt_dev_err(hdev, "Unsupported Intel firmware naming");
 
        bt_dev_info(hdev, "Found device firmware: %s", fwname);
 
-       /* Save the DDC file name for later use to apply once the firmware
-        * downloading is done.
-        */
-       err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, fwname,
-                                               sizeof(fwname), "ddc");
-       if (!err) {
-               bt_dev_err(hdev, "Unsupported Intel firmware naming");
-               return -EINVAL;
-       }
-
        if (fw->size < 644) {
                bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
                           fw->size);
                goto done;
        }
 
+done:
+       release_firmware(fw);
+       return err;
+}
+
+static int btusb_setup_intel_new(struct hci_dev *hdev)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct intel_version ver;
+       struct intel_boot_params params;
+       u32 boot_param;
+       char ddcname[64];
+       ktime_t calltime, delta, rettime;
+       unsigned long long duration;
+       int err;
+       struct intel_debug_features features;
+
+       BT_DBG("%s", hdev->name);
+
+       /* Set the default boot parameter to 0x0 and it is updated to
+        * SKU specific boot parameter after reading Intel_Write_Boot_Params
+        * command while downloading the firmware.
+        */
+       boot_param = 0x00000000;
+
+       calltime = ktime_get();
+
+       /* Read the Intel version information to determine if the device
+        * is in bootloader mode or if it already has operational firmware
+        * loaded.
+        */
+       err = btintel_read_version(hdev, &ver);
+       if (err) {
+               bt_dev_err(hdev, "Intel Read version failed (%d)", err);
+               btintel_reset_to_bootloader(hdev);
+               return err;
+       }
+
+       err = btusb_intel_download_firmware(hdev, &ver, ¶ms);
+       if (err)
+               return err;
+
+       /* controller is already having an operational firmware */
+       if (ver.fw_variant == 0x23)
+               goto finish;
+
        rettime = ktime_get();
        delta = ktime_sub(rettime, calltime);
        duration = (unsigned long long) ktime_to_ns(delta) >> 10;
 
        bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
 
-done:
-       release_firmware(fw);
-
-       if (err < 0)
-               return err;
-
        calltime = ktime_get();
 
        set_bit(BTUSB_BOOTING, &data->flags);
 
        clear_bit(BTUSB_BOOTLOADER, &data->flags);
 
-       /* Once the device is running in operational mode, it needs to apply
-        * the device configuration (DDC) parameters.
-        *
-        * The device can work without DDC parameters, so even if it fails
-        * to load the file, no need to fail the setup.
-        */
-       btintel_load_ddc_config(hdev, fwname);
+       err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, ddcname,
+                                               sizeof(ddcname), "ddc");
+
+       if (!err) {
+               bt_dev_err(hdev, "Unsupported Intel firmware naming");
+       } else {
+               /* Once the device is running in operational mode, it needs to
+                * apply the device configuration (DDC) parameters.
+                *
+                * The device can work without DDC parameters, so even if it
+                * fails to load the file, no need to fail the setup.
+                */
+               btintel_load_ddc_config(hdev, ddcname);
+       }
 
        /* Read the Intel supported features and if new exception formats
         * supported, need to load the additional DDC config to enable.