Bluetooth: btusb: Helper function to download firmware to Intel adapters
Define a helper function to download firmware for new generation Intel controllers Signed-off-by: Kiran K <kiran.k@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
9a93b8b8ee
commit
3f43a37838
@ -2400,6 +2400,167 @@ static void btusb_setup_intel_newgen_get_fw_name(const struct intel_version_tlv
|
||||
suffix);
|
||||
}
|
||||
|
||||
static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
|
||||
struct intel_version_tlv *ver,
|
||||
u32 *boot_param)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
char fwname[64];
|
||||
int err;
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
|
||||
if (!ver || !boot_param)
|
||||
return -EINVAL;
|
||||
|
||||
/* The hardware platform number has a fixed value of 0x37 and
|
||||
* for now only accept this single value.
|
||||
*/
|
||||
if (INTEL_HW_PLATFORM(ver->cnvi_bt) != 0x37) {
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware platform (0x%2x)",
|
||||
INTEL_HW_PLATFORM(ver->cnvi_bt));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The firmware variant determines if the device is in bootloader
|
||||
* mode or is running operational firmware. The value 0x03 identifies
|
||||
* the bootloader and the value 0x23 identifies the operational
|
||||
* firmware.
|
||||
*
|
||||
* When the operational firmware is already present, then only
|
||||
* the check for valid Bluetooth device address is needed. This
|
||||
* determines if the device will be added as configured or
|
||||
* unconfigured controller.
|
||||
*
|
||||
* It is not possible to use the Secure Boot Parameters in this
|
||||
* case since that command is only available in bootloader mode.
|
||||
*/
|
||||
if (ver->img_type == 0x03) {
|
||||
clear_bit(BTUSB_BOOTLOADER, &data->flags);
|
||||
btintel_check_bdaddr(hdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for supported iBT hardware variants of this firmware
|
||||
* loading method.
|
||||
*
|
||||
* This check has been put in place to ensure correct forward
|
||||
* compatibility options when newer hardware variants come along.
|
||||
*/
|
||||
switch (INTEL_HW_VARIANT(ver->cnvi_bt)) {
|
||||
case 0x17: /* TyP */
|
||||
case 0x18: /* Slr */
|
||||
case 0x19: /* Slr-F */
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
|
||||
INTEL_HW_VARIANT(ver->cnvi_bt));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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->img_type != 0x01) {
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware variant (0x%x)",
|
||||
ver->img_type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* It is required that every single firmware fragment is acknowledged
|
||||
* with a command complete event. If the boot parameters indicate
|
||||
* that this bootloader does not send them, then abort the setup.
|
||||
*/
|
||||
if (ver->limited_cce != 0x00) {
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware loading method (0x%x)",
|
||||
ver->limited_cce);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */
|
||||
if (ver->sbe_type > 0x01) {
|
||||
bt_dev_err(hdev, "Unsupported Intel secure boot engine type (0x%x)",
|
||||
ver->sbe_type);
|
||||
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(&ver->otp_bd_addr, BDADDR_ANY)) {
|
||||
bt_dev_info(hdev, "No device address configured");
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
}
|
||||
|
||||
btusb_setup_intel_newgen_get_fw_name(ver, fwname, sizeof(fwname), "sfi");
|
||||
err = request_firmware(&fw, fwname, &hdev->dev);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "Found device firmware: %s", fwname);
|
||||
|
||||
if (fw->size < 644) {
|
||||
bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
|
||||
fw->size);
|
||||
err = -EBADF;
|
||||
goto done;
|
||||
}
|
||||
|
||||
set_bit(BTUSB_DOWNLOADING, &data->flags);
|
||||
|
||||
/* Start firmware downloading and get boot parameter */
|
||||
err = btintel_download_firmware_newgen(hdev, fw, boot_param,
|
||||
INTEL_HW_VARIANT(ver->cnvi_bt),
|
||||
ver->sbe_type);
|
||||
if (err < 0) {
|
||||
/* When FW download fails, send Intel Reset to retry
|
||||
* FW download.
|
||||
*/
|
||||
btintel_reset_to_bootloader(hdev);
|
||||
goto done;
|
||||
}
|
||||
set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
|
||||
|
||||
bt_dev_info(hdev, "Waiting for firmware download to complete");
|
||||
|
||||
/* Before switching the device into operational mode and with that
|
||||
* booting the loaded firmware, wait for the bootloader notification
|
||||
* that all fragments have been successfully received.
|
||||
*
|
||||
* When the event processing receives the notification, then the
|
||||
* BTUSB_DOWNLOADING flag will be cleared.
|
||||
*
|
||||
* The firmware loading should not take longer than 5 seconds
|
||||
* and thus just timeout if that happens and fail the setup
|
||||
* of this device.
|
||||
*/
|
||||
err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING,
|
||||
TASK_INTERRUPTIBLE,
|
||||
msecs_to_jiffies(5000));
|
||||
if (err == -EINTR) {
|
||||
bt_dev_err(hdev, "Firmware loading interrupted");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Firmware loading timeout");
|
||||
err = -ETIMEDOUT;
|
||||
btintel_reset_to_bootloader(hdev);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) {
|
||||
bt_dev_err(hdev, "Firmware loading failed");
|
||||
err = -ENOEXEC;
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btusb_intel_download_firmware(struct hci_dev *hdev,
|
||||
struct intel_version *ver,
|
||||
struct intel_boot_params *params,
|
||||
@ -2768,6 +2929,10 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev)
|
||||
|
||||
btintel_version_info_tlv(hdev, &version);
|
||||
|
||||
err = btusb_intel_download_firmware_newgen(hdev, &version, &boot_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* check if controller is already having an operational firmware */
|
||||
if (version.img_type == 0x03)
|
||||
goto finish;
|
||||
|
Loading…
Reference in New Issue
Block a user