]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
Bluetooth: btusb: Refactor of firmware download flow for Intel conrollers
authorKiran K <kiran.k@intel.com>
Wed, 24 Jun 2020 18:34:32 +0000 (00:04 +0530)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 25 Jun 2020 08:43:38 +0000 (10:43 +0200)
Address the scalability to support new generation Intel controller with
respect to readability and enhancement to new firmware download sequence

Signed-off-by: Kiran K <kiran.k@intel.com>
Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/btusb.c

index 1ac6fd7c4534420156434a94caf31e7074cd9dbc..f8a71fdabb3d1b50d4a3e487c278fb0f22f99be0 100644 (file)
@@ -511,7 +511,6 @@ struct btusb_data {
        unsigned cmd_timeout_cnt;
 };
 
-
 static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
 {
        struct btusb_data *data = hci_get_drvdata(hdev);
@@ -2278,46 +2277,25 @@ static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
        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;
        }
 
@@ -2327,7 +2305,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
         * 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 */
@@ -2337,11 +2315,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
                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
@@ -2356,25 +2334,25 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
         * 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, &params);
+       err = btintel_read_boot_params(hdev, params);
        if (err)
                return err;
 
@@ -2382,16 +2360,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
         * 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(&params.otp_bdaddr, BDADDR_ANY)) {
+       if (!bacmp(&params->otp_bdaddr, BDADDR_ANY)) {
                bt_dev_info(hdev, "No device address configured");
                set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
        }
@@ -2417,7 +2395,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
         * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
         *
         */
-       err = btusb_setup_intel_new_get_fw_name(&ver, &params, 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");
@@ -2432,16 +2410,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
 
        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, &params, 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);
@@ -2496,18 +2464,58 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
                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, &params);
+       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);
@@ -2551,13 +2559,20 @@ done:
 
        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, &params, 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.