mirror of https://gitee.com/openkylin/linux.git
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: Kiran K <kiran.k@intel.com> Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
3a0377d993
commit
5ea7c81a4f
|
@ -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, ¶ms);
|
||||
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(¶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);
|
||||
}
|
||||
|
@ -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, ¶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");
|
||||
|
@ -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, ¶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);
|
||||
|
@ -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, ¶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);
|
||||
|
@ -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, ¶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.
|
||||
|
|
Loading…
Reference in New Issue