Commit 5ea7c81a authored by Kiran K's avatar Kiran K Committed by Marcel Holtmann

Bluetooth: btusb: Refactor of firmware download flow for Intel conrollers

Address the scalability to support new generation Intel controller with
respect to readability and enhancement to new firmware download sequence
Signed-off-by: default avatarKiran K <kiran.k@intel.com>
Reviewed-by: default avatarChethan T N <chethan.tumkur.narayan@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 3a0377d9
...@@ -511,7 +511,6 @@ struct btusb_data { ...@@ -511,7 +511,6 @@ struct btusb_data {
unsigned cmd_timeout_cnt; unsigned cmd_timeout_cnt;
}; };
static void btusb_intel_cmd_timeout(struct hci_dev *hdev) static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
{ {
struct btusb_data *data = hci_get_drvdata(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, ...@@ -2278,46 +2277,25 @@ static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
return true; 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; const struct firmware *fw;
u32 boot_param; u32 boot_param;
char fwname[64]; char fwname[64];
ktime_t calltime, delta, rettime;
unsigned long long duration;
int err; int err;
struct btusb_data *data = hci_get_drvdata(hdev);
BT_DBG("%s", hdev->name); if (!ver || !params)
return -EINVAL;
/* 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;
}
/* The hardware platform number has a fixed value of 0x37 and /* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value. * 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)", bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
ver.hw_platform); ver->hw_platform);
return -EINVAL; return -EINVAL;
} }
...@@ -2327,7 +2305,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -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 * This check has been put in place to ensure correct forward
* compatibility options when newer hardware variants come along. * compatibility options when newer hardware variants come along.
*/ */
switch (ver.hw_variant) { switch (ver->hw_variant) {
case 0x0b: /* SfP */ case 0x0b: /* SfP */
case 0x0c: /* WsP */ case 0x0c: /* WsP */
case 0x11: /* JfP */ case 0x11: /* JfP */
...@@ -2337,11 +2315,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2337,11 +2315,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
break; break;
default: default:
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
ver.hw_variant); ver->hw_variant);
return -EINVAL; return -EINVAL;
} }
btintel_version_info(hdev, &ver); btintel_version_info(hdev, ver);
/* The firmware variant determines if the device is in bootloader /* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware. The value 0x06 identifies * mode or is running operational firmware. The value 0x06 identifies
...@@ -2356,25 +2334,25 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -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 * It is not possible to use the Secure Boot Parameters in this
* case since that command is only available in bootloader mode. * 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); clear_bit(BTUSB_BOOTLOADER, &data->flags);
btintel_check_bdaddr(hdev); btintel_check_bdaddr(hdev);
goto finish; return 0;
} }
/* If the device is not in bootloader mode, then the only possible /* If the device is not in bootloader mode, then the only possible
* choice is to return an error and abort the device initialization. * 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)", bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
ver.fw_variant); ver->fw_variant);
return -ENODEV; return -ENODEV;
} }
/* Read the secure boot parameters to identify the operating /* Read the secure boot parameters to identify the operating
* details of the bootloader. * details of the bootloader.
*/ */
err = btintel_read_boot_params(hdev, &params); err = btintel_read_boot_params(hdev, params);
if (err) if (err)
return err; return err;
...@@ -2382,16 +2360,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2382,16 +2360,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* with a command complete event. If the boot parameters indicate * with a command complete event. If the boot parameters indicate
* that this bootloader does not send them, then abort the setup. * 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)", bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
params.limited_cce); params->limited_cce);
return -EINVAL; return -EINVAL;
} }
/* If the OTP has no valid Bluetooth device address, then there will /* If the OTP has no valid Bluetooth device address, then there will
* also be no valid address for the operational firmware. * 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"); bt_dev_info(hdev, "No device address configured");
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
} }
...@@ -2417,7 +2395,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2417,7 +2395,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi. * 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"); sizeof(fwname), "sfi");
if (!err) { if (!err) {
bt_dev_err(hdev, "Unsupported Intel firmware naming"); bt_dev_err(hdev, "Unsupported Intel firmware naming");
...@@ -2432,16 +2410,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2432,16 +2410,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
bt_dev_info(hdev, "Found device firmware: %s", fwname); 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) { if (fw->size < 644) {
bt_dev_err(hdev, "Invalid size of firmware file (%zu)", bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
fw->size); fw->size);
...@@ -2496,18 +2464,58 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2496,18 +2464,58 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
goto done; 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(); rettime = ktime_get();
delta = ktime_sub(rettime, calltime); delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10; duration = (unsigned long long) ktime_to_ns(delta) >> 10;
bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration); bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
done:
release_firmware(fw);
if (err < 0)
return err;
calltime = ktime_get(); calltime = ktime_get();
set_bit(BTUSB_BOOTING, &data->flags); set_bit(BTUSB_BOOTING, &data->flags);
...@@ -2551,13 +2559,20 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) ...@@ -2551,13 +2559,20 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
clear_bit(BTUSB_BOOTLOADER, &data->flags); clear_bit(BTUSB_BOOTLOADER, &data->flags);
/* Once the device is running in operational mode, it needs to apply err = btusb_setup_intel_new_get_fw_name(&ver, &params, ddcname,
* the device configuration (DDC) parameters. sizeof(ddcname), "ddc");
*
* The device can work without DDC parameters, so even if it fails if (!err) {
* to load the file, no need to fail the setup. bt_dev_err(hdev, "Unsupported Intel firmware naming");
*/ } else {
btintel_load_ddc_config(hdev, fwname); /* 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 /* Read the Intel supported features and if new exception formats
* supported, need to load the additional DDC config to enable. * supported, need to load the additional DDC config to enable.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment