Received: by 2002:a25:824b:0:0:0:0:0 with SMTP id d11csp7881254ybn; Mon, 30 Sep 2019 22:58:29 -0700 (PDT) X-Google-Smtp-Source: APXvYqxPRgW42V8xHH7bP37GUZyKEzBaqT/bWDEi52qaw3r8AijJKfEkqM3XxBec+eFQU5o4YOTb X-Received: by 2002:a50:95a3:: with SMTP id w32mr23593636eda.211.1569909509058; Mon, 30 Sep 2019 22:58:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1569909509; cv=none; d=google.com; s=arc-20160816; b=WvSJUJ5yWRLJuLpm+K/A7V4aoXG5jXCZQz/WnclhW5yWacVnczfMtItyF2QAThxzs9 mqDdR1w5diKGT9VFyYDDeiWBxlPgorViDGqBUQ8Buk7Fcnn6uInHWscywBgq6DaP/Q0X 8fPWc8iEDdAU83EsA42J8q2qMDbFK1HA6bAulbWYksNDQACvesg9+ouIT4peMmSDEO0f D7kB4N4hyY1hYKjZ89uA8bsd7T3jWvJKXp1qGT9nYY32ebJN0IV9cp/g45vR6zFRIKSQ vvNn2zM1ihZn5nKR/N6ek4w7iflsN2j3cT4OuLejO6oamOuNAU6ug87avouBIS2g99Qc PdsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from; bh=MrdasJvQEL5n6+CTrbZHcNMEYijrG1mIRZ3hRfgoN8k=; b=pV3N9rIF4dxasuo/90HPjUQM6A34J09ttXReVbwdoel/sPSksnKoyn63MmxbnY6Djl 4LqlUr+nTj6MkCwV+fKj2xJi8VLIhZTMCV6Df7Twp+HHCZTyP3fcns1IndCQoPzi0N0k Fz61AuolOIUKDYOI5FmBhIOUEh4vzZ5JjP6t4uEYjM4nanoMPI+Adwo3JyzH+AE9IX2c S1jQ05qutzNQ2JV8LqYo1u23ltNy0KmLjigby9/5g4IjGdDRsznA+nqFy77Wu3nqAA0x T7fW/x+hVw6pccupeTZDFfSueN3FZ4SN9OGk2WNmQ27CYH7xJqp3X1p2UYZpriJgEYLn C+Vw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id br24si8517788ejb.101.2019.09.30.22.57.43; Mon, 30 Sep 2019 22:58:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731636AbfJAFy2 (ORCPT + 99 others); Tue, 1 Oct 2019 01:54:28 -0400 Received: from mga18.intel.com ([134.134.136.126]:53219 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725777AbfJAFy2 (ORCPT ); Tue, 1 Oct 2019 01:54:28 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Sep 2019 22:54:27 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,570,1559545200"; d="scan'208";a="194425186" Received: from unknown (HELO ubuntu-16-04.iind.intel.com) ([10.224.186.155]) by orsmga003.jf.intel.com with ESMTP; 30 Sep 2019 22:54:25 -0700 From: Amit K Bag To: linux-bluetooth@vger.kernel.org Cc: ravishankar.srivatsa@intel.com, chethan.tumkur.narayan@intel.com, Amit K Bag , Raghuram Hegde Subject: [PATCH v2] Bluetooth: btusb: Trigger Intel FW download error recovery Date: Tue, 1 Oct 2019 11:19:07 +0530 Message-Id: <1569908947-10516-1-git-send-email-amit.k.bag@intel.com> X-Mailer: git-send-email 2.7.4 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org 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 Signed-off-by: Chethan T N Signed-off-by: Amit K Bag --- drivers/bluetooth/btintel.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 6 ++++++ drivers/bluetooth/btusb.c | 20 ++++++++++++++++---- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index bb99c8653aab..0154764ebdf8 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -709,6 +709,45 @@ 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) +{ + /* Send Intel Reset command. This will result in + * re-enumeration of BT controller. + * + * Intel Reset parameter description: + * reset_param[0] => reset_type : 0x01 (Hard reset), + 0x00 (Soft reset) + * reset_param[1] => patch_enable : 0x01 (Enable), + * 0x00 (Do not enable) + * reset_param[2] => ddc_reload : 0x01 (Reload), + * 0x00 (Do not reload) + * reset_param[3] => boot_option: 0x00 (Current image), + 0x01 (Specified boot address) + * reset_param[4] to reset_param[7] => Boot address + * + */ + static const u8 reset_param[] = { 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), + reset_param, 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 "); 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, @@ -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; } -- 2.7.4