Re: [PATCH v3] Bluetooth: btusb: Trigger Intel FW download error recovery

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Amit,

> Sometimes during FW data download stage, in case of an error is
> encountered the controller device could not be recovered. To recover
> from such failures send Intel hard Reset to re-trigger FW download in
> following error scenarios:
> 
> 1. Intel Read version command error
> 2. Firmware download timeout
> 3. Failure in Intel Soft Reset for switching to operational FW
> 4. Boot timeout for switching to operaional FW
> 
> Signed-off-by: Raghuram Hegde <raghuram.hegde@xxxxxxxxx>
> Signed-off-by: Chethan T N <chethan.tumkur.narayan@xxxxxxxxx>
> Signed-off-by: Amit K Bag <amit.k.bag@xxxxxxxxx>
> ---
> drivers/bluetooth/btintel.c | 49 +++++++++++++++++++++++++++++++++++++++++++++
> drivers/bluetooth/btintel.h |  6 ++++++
> drivers/bluetooth/btusb.c   | 20 ++++++++++++++----
> 3 files changed, 71 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
> index bb99c8653aab..a93aec22d3a6 100644
> --- a/drivers/bluetooth/btintel.c
> +++ b/drivers/bluetooth/btintel.c
> @@ -709,6 +709,55 @@ int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
> }
> EXPORT_SYMBOL_GPL(btintel_download_firmware);
> 
> +void btintel_reset_to_bootloader(struct hci_dev *hdev)
> +{
> +	const struct intel_reset params;
> +	struct sk_buff *skb;
> +	u32 boot_param;
> +
> +
> +	boot_param = 0x00000000;
> +
> +	/* Send Intel Reset command. This will result in
> +	 * re-enumeration of BT controller.
> +	 *
> +	 * Intel Reset parameter description:
> +	 * reset_type :   0x00 (Soft reset),
> +	 *		  0x01 (Hard reset)
> +	 * patch_enable : 0x00 (Do not enable),
> +	 *		  0x01 (Enable)
> +	 * ddc_reload :   0x00 (Do not reload),
> +	 *		  0x01 (Reload)
> +	 * boot_option:   0x00 (Current image),
> +	 *                0x01 (Specified boot address)
> +	 * boot_param:    Boot address
> +	 *
> +	 */
> +	params.reset_type = 0x01;
> +	params.patch_enable = 0x01;
> +	params.ddc_reload = 0x01;
> +	params.boot_option = 0x00;
> +	params.boot_param = cpu_to_le32(boot_param);

params.boot_param = cpu_to_le32(0x00000000);

> +
> +	skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params),
> +			     &params, HCI_INIT_TIMEOUT);
> +	if (IS_ERR(skb)) {
> +		bt_dev_err(hdev, "FW download error recovery failed (%ld)",
> +			   PTR_ERR(skb));
> +		return;
> +	}
> +	bt_dev_info(hdev, "Intel reset sent to retry FW download");
> +	kfree_skb(skb);
> +
> +	/* Current Intel BT controllers(ThP/JfP) hold the USB reset
> +	 * lines for 2ms when it receives Intel Reset in bootloader mode.
> +	 * Whereas, the upcoming Intel BT controllers will hold USB reset
> +	 * for 150ms. To keep the delay generic, 150ms is chosen here.
> +	 */
> +	msleep(150);
> +}
> +EXPORT_SYMBOL_GPL(btintel_reset_to_bootloader);
> +
> MODULE_AUTHOR("Marcel Holtmann <marcel@xxxxxxxxxxxx>");
> MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
> MODULE_VERSION(VERSION);
> diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
> index 3d846190f2bf..d2311156f778 100644
> --- a/drivers/bluetooth/btintel.h
> +++ b/drivers/bluetooth/btintel.h
> @@ -87,6 +87,7 @@ int btintel_read_boot_params(struct hci_dev *hdev,
> 			     struct intel_boot_params *params);
> int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
> 			      u32 *boot_param);
> +void btintel_reset_to_bootloader(struct hci_dev *hdev);
> #else
> 
> static inline int btintel_check_bdaddr(struct hci_dev *hdev)
> @@ -181,4 +182,9 @@ static inline int btintel_download_firmware(struct hci_dev *dev,
> {
> 	return -EOPNOTSUPP;
> }
> +
> +static inline void btintel_reset_to_bootloader(struct hci_dev *hdev)
> +{
> +	return -EOPNOTSUPP;
> +}
> #endif
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 5d7bc3410104..47178af7f7fe 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -1846,8 +1846,11 @@ static int btusb_setup_intel(struct hci_dev *hdev)
> 	 * firmware variant, revision and build number.
> 	 */
> 	err = btintel_read_version(hdev, &ver);
> -	if (err)
> +	if (err) {
> +		bt_dev_err(hdev, "Intel Read version failed (%d)", err);
> +		btintel_reset_to_bootloader(hdev);
> 		return err;
> +	}
> 
> 	bt_dev_info(hdev, "read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x",
> 		    ver.hw_platform, ver.hw_variant, ver.hw_revision,

I am bit confused on why you modify the read_version in the legacy Intel setup and not in the new one. Can we focus with this patch on setup_intel_new and you add support for legacy setup in a second patch if that is needed as well.

> @@ -2326,9 +2329,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
> 
> 	/* Start firmware downloading and get boot parameter */
> 	err = btintel_download_firmware(hdev, fw, &boot_param);
> -	if (err < 0)
> +	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");
> @@ -2355,6 +2362,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
> 	if (err) {
> 		bt_dev_err(hdev, "Firmware loading timeout");
> 		err = -ETIMEDOUT;
> +		btintel_reset_to_bootloader(hdev);
> 		goto done;
> 	}
> 
> @@ -2381,8 +2389,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
> 	set_bit(BTUSB_BOOTING, &data->flags);
> 
> 	err = btintel_send_intel_reset(hdev, boot_param);
> -	if (err)
> +	if (err) {
> +		bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err);
> +		btintel_reset_to_bootloader(hdev);
> 		return err;
> +	}
> 
> 	/* The bootloader will not indicate when the device is ready. This
> 	 * is done by the operational firmware sending bootup notification.
> @@ -2404,6 +2415,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
> 
> 	if (err) {
> 		bt_dev_err(hdev, "Device boot timeout");
> +		btintel_reset_to_bootloader(hdev);
> 		return -ETIMEDOUT;
> 	}

Regards

Marcel




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux