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 {
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 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
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.
......
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