From patchwork Thu Jul 2 12:03:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 11638681 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C4D5513B4 for ; Thu, 2 Jul 2020 12:02:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9D245207CD for ; Thu, 2 Jul 2020 12:02:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728778AbgGBMCL (ORCPT ); Thu, 2 Jul 2020 08:02:11 -0400 Received: from mga14.intel.com ([192.55.52.115]:27652 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728668AbgGBMCK (ORCPT ); Thu, 2 Jul 2020 08:02:10 -0400 IronPort-SDR: jwmiNYVKGNJOSxLvoKwrqLmSn9Q0dRkRRDeJY7gznFtUwT3gCxsB8L6BYcTeR25/IkwbD8PYn4 5MxSm5ZQn8nQ== X-IronPort-AV: E=McAfee;i="6000,8403,9669"; a="145947815" X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="145947815" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jul 2020 05:02:09 -0700 IronPort-SDR: vY+9SStY/8TEzuxV6rTvQX2LczjwzClowCcBA0sN4oFzvMMBhEvtgmnZKMxm3LuplaMLtvYA4x ODP9XmnLkpfw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="304224706" Received: from unknown (HELO intel-Lenovo-Legion-Y540-15IRH-PG0.iind.intel.com) ([10.224.186.95]) by fmsmga004.fm.intel.com with ESMTP; 02 Jul 2020 05:02:06 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: ravishankar.srivatsa@intel.com, chethan.tumkur.narayan@intel.com, kiraank@gmail.com, Kiran K , Amit K Bag , Raghuram Hegde Subject: [PATCH 1/5] Bluetooth: btintel: Make controller version read generic Date: Thu, 2 Jul 2020 17:33:11 +0530 Message-Id: <20200702120315.26768-2-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200702120315.26768-1-kiran.k@intel.com> References: <20200702120315.26768-1-kiran.k@intel.com> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Make controller read vesion function more generic to support different type of controllers. Signed-off-by: Kiran K Signed-off-by: Amit K Bag Signed-off-by: Raghuram Hegde Reviewed-by: Chethan T N Reviewed-by: Sathish Narasimman Reviewed-by: Srivatsa Ravishankar --- drivers/bluetooth/btintel.c | 36 ++++++++++++++---- drivers/bluetooth/btintel.h | 15 ++++++-- drivers/bluetooth/btusb.c | 71 +++++++++++++++++++++++------------ drivers/bluetooth/hci_ag6xx.c | 12 +++++- drivers/bluetooth/hci_intel.c | 12 +++++- 5 files changed, 106 insertions(+), 40 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 5fa5be3c5598..dea96c585ecb 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -204,9 +204,15 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code) } EXPORT_SYMBOL_GPL(btintel_hw_error); -void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) +void btintel_version_info(struct hci_dev *hdev, const struct btintel_version *version) { const char *variant; + const struct intel_version *ver; + + if (version->is_tlv_supported) + return; + + ver = &version->intel_version; switch (ver->fw_variant) { case 0x06: @@ -335,27 +341,41 @@ int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) } EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg); -int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver) +int btintel_read_version(struct hci_dev *hdev, struct btintel_version *version) { struct sk_buff *skb; + u8 *data, param, status, check_tlv; + + if (!version) + return -EINVAL; - skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT); + param = 0xFF; + + skb = __hci_cmd_sync(hdev, 0xfc05, 1, ¶m, HCI_CMD_TIMEOUT); if (IS_ERR(skb)) { bt_dev_err(hdev, "Reading Intel version information failed (%ld)", PTR_ERR(skb)); return PTR_ERR(skb); } - if (skb->len != sizeof(*ver)) { - bt_dev_err(hdev, "Intel version event size mismatch"); + data = skb->data; + status = *data; + if (status) { + bt_dev_err(hdev, "Intel Read Version command failed (%02x)", + status); kfree_skb(skb); - return -EILSEQ; + return -bt_to_errno(status); } - memcpy(ver, skb->data, sizeof(*ver)); + check_tlv = *(data + 1); + if (skb->len == sizeof(version->intel_version) && check_tlv == 0x37) { + memcpy(&version->intel_version, skb->data, sizeof(version->intel_version)); + version->is_tlv_supported = false; + } else { + version->is_tlv_supported = true; + } kfree_skb(skb); - return 0; } EXPORT_SYMBOL_GPL(btintel_read_version); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 08e20606fb58..0865d2d4aca7 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -66,6 +66,13 @@ struct intel_debug_features { __u8 page1[16]; } __packed; +struct btintel_version { + bool is_tlv_supported; + union { + struct intel_version intel_version; /* legacy version */ + }; +} __packed; + #if IS_ENABLED(CONFIG_BT_INTEL) int btintel_check_bdaddr(struct hci_dev *hdev); @@ -76,13 +83,13 @@ int btintel_set_diag(struct hci_dev *hdev, bool enable); int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable); void btintel_hw_error(struct hci_dev *hdev, u8 code); -void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver); +void btintel_version_info(struct hci_dev *hdev, const struct btintel_version *version); int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, const void *param); int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name); int btintel_set_event_mask(struct hci_dev *hdev, bool debug); int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug); -int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver); +int btintel_read_version(struct hci_dev *hdev, struct btintel_version *version); struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, u16 opcode_write); @@ -133,7 +140,7 @@ static inline void btintel_hw_error(struct hci_dev *hdev, u8 code) } static inline void btintel_version_info(struct hci_dev *hdev, - struct intel_version *ver) + struct btintel_version *version) { } @@ -160,7 +167,7 @@ static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) } static inline int btintel_read_version(struct hci_dev *hdev, - struct intel_version *ver) + struct btintel_version *version) { return -EOPNOTSUPP; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index faa863dd5d0a..d06c946f7810 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1938,6 +1938,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) const u8 *fw_ptr; int disable_patch, err; struct intel_version ver; + struct btintel_version version; BT_DBG("%s", hdev->name); @@ -1963,10 +1964,16 @@ static int btusb_setup_intel(struct hci_dev *hdev) * The returned information are hardware variant and revision plus * firmware variant, revision and build number. */ - err = btintel_read_version(hdev, &ver); + err = btintel_read_version(hdev, &version); if (err) return err; + if (version.is_tlv_supported) { + bt_dev_err(hdev, "FW download in tlv format not supported"); + return -EOPNOTSUPP; + } + ver = version.intel_version; + 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, ver.fw_variant, ver.fw_revision, ver.fw_build_num, @@ -2049,11 +2056,11 @@ static int btusb_setup_intel(struct hci_dev *hdev) /* Need build number for downloaded fw patches in * every power-on boot */ - err = btintel_read_version(hdev, &ver); - if (err) - return err; - bt_dev_info(hdev, "Intel BT fw patch 0x%02x completed & activated", - ver.fw_patch_num); + err = btintel_read_version(hdev, &version); + if (err) + return err; + bt_dev_info(hdev, "Intel BT fw patch 0x%02x completed & activated", + version.intel_version.fw_patch_num); goto complete; @@ -2251,11 +2258,18 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) return -EILSEQ; } -static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver, - struct intel_boot_params *params, - char *fw_name, size_t len, - const char *suffix) +static bool btusb_setup_intel_new_get_fw_name(const struct btintel_version *version, + struct intel_boot_params *params, + char *fw_name, size_t len, + const char *suffix) { + const struct intel_version *ver; + + if (version->is_tlv_supported) + return false; + + ver = &version->intel_version; + switch (ver->hw_variant) { case 0x0b: /* SfP */ case 0x0c: /* WsP */ @@ -2281,18 +2295,21 @@ static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver, } static int btusb_intel_download_firmware(struct hci_dev *hdev, - struct intel_version *ver, + struct btintel_version *version, struct intel_boot_params *params) { const struct firmware *fw; u32 boot_param; char fwname[64]; int err; + const struct intel_version *ver; struct btusb_data *data = hci_get_drvdata(hdev); - if (!ver || !params) + if (!version || !params) return -EINVAL; + ver = &version->intel_version; + /* The hardware platform number has a fixed value of 0x37 and * for now only accept this single value. */ @@ -2322,8 +2339,6 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev, return -EINVAL; } - 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 * the bootloader and the value 0x23 identifies the operational @@ -2398,7 +2413,7 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev, * ibt---.sfi. * */ - err = btusb_setup_intel_new_get_fw_name(ver, params, fwname, + err = btusb_setup_intel_new_get_fw_name(version, params, fwname, sizeof(fwname), "sfi"); if (!err) { bt_dev_err(hdev, "Unsupported Intel firmware naming"); @@ -2483,6 +2498,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) unsigned long long duration; int err; struct intel_debug_features features; + struct btintel_version version; BT_DBG("%s", hdev->name); @@ -2494,21 +2510,28 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) 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. + /* Read controller version information and support of tlv format */ - err = btintel_read_version(hdev, &ver); + err = btintel_read_version(hdev, &version); if (err) { - bt_dev_err(hdev, "Intel Read version failed (%d)", err); + bt_dev_err(hdev, "Intel Read version new failed (%d)", err); btintel_reset_to_bootloader(hdev); return err; } - err = btusb_intel_download_firmware(hdev, &ver, ¶ms); + if (version.is_tlv_supported) { + bt_dev_err(hdev, "Firmware download in tlv format is not supported"); + return -EOPNOTSUPP; + } + + btintel_version_info(hdev, &version); + + err = btusb_intel_download_firmware(hdev, &version, ¶ms); if (err) return err; + ver = version.intel_version; + /* controller is already having an operational firmware */ if (ver.fw_variant == 0x23) goto finish; @@ -2562,7 +2585,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) clear_bit(BTUSB_BOOTLOADER, &data->flags); - err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, ddcname, + err = btusb_setup_intel_new_get_fw_name(&version, ¶ms, ddcname, sizeof(ddcname), "ddc"); if (!err) { @@ -2586,11 +2609,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) btintel_set_debug_features(hdev, &features); /* Read the Intel version information after loading the FW */ - err = btintel_read_version(hdev, &ver); + err = btintel_read_version(hdev, &version); if (err) return err; - btintel_version_info(hdev, &ver); + btintel_version_info(hdev, &version); finish: /* All Intel controllers that support the Microsoft vendor diff --git a/drivers/bluetooth/hci_ag6xx.c b/drivers/bluetooth/hci_ag6xx.c index 1f55df93e4ce..6f6a1e061972 100644 --- a/drivers/bluetooth/hci_ag6xx.c +++ b/drivers/bluetooth/hci_ag6xx.c @@ -153,6 +153,7 @@ static int ag6xx_setup(struct hci_uart *hu) struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; struct intel_version ver; + struct btintel_version version; const struct firmware *fw; const u8 *fw_ptr; char fwname[64]; @@ -166,11 +167,18 @@ static int ag6xx_setup(struct hci_uart *hu) if (err) return err; - err = btintel_read_version(hdev, &ver); + err = btintel_read_version(hdev, &version); if (err) return err; - btintel_version_info(hdev, &ver); + if (version.is_tlv_supported) { + bt_dev_err(hdev, "Firmware download in tlv format over ag6xx is not supported"); + return -EOPNOTSUPP; + } + + btintel_version_info(hdev, &version); + + ver = version.intel_version; /* The hardware platform number has a fixed value of 0x37 and * for now only accept this single value. diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index f1299da6eed8..f30cbc66d48f 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -532,6 +532,7 @@ static int intel_setup(struct hci_uart *hu) struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; struct intel_version ver; + struct btintel_version version; struct intel_boot_params params; struct list_head *p; const struct firmware *fw; @@ -584,10 +585,17 @@ static int intel_setup(struct hci_uart *hu) * is in bootloader mode or if it already has operational firmware * loaded. */ - err = btintel_read_version(hdev, &ver); + err = btintel_read_version(hdev, &version); if (err) return err; + if (version.is_tlv_supported) { + /* firmware download in tlv format is not supported on UART transport */ + bt_dev_err(hdev, "Firmware download in tlv format is not supported"); + return -EOPNOTSUPP; + } + ver = version.intel_version; + /* The hardware platform number has a fixed value of 0x37 and * for now only accept this single value. */ @@ -614,7 +622,7 @@ static int intel_setup(struct hci_uart *hu) return -EINVAL; } - btintel_version_info(hdev, &ver); + btintel_version_info(hdev, &version); /* The firmware variant determines if the device is in bootloader * mode or is running operational firmware. The value 0x06 identifies From patchwork Thu Jul 2 12:03:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 11638683 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E5F76912 for ; Thu, 2 Jul 2020 12:02:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CAB2920737 for ; Thu, 2 Jul 2020 12:02:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728807AbgGBMCM (ORCPT ); Thu, 2 Jul 2020 08:02:12 -0400 Received: from mga14.intel.com ([192.55.52.115]:27652 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728668AbgGBMCL (ORCPT ); Thu, 2 Jul 2020 08:02:11 -0400 IronPort-SDR: XGl3C8HuIy2Jk/PMhqYYGOf9VnzyYKu0pnj5uYUSTOeQs9Pg/vZGBmQiZNVAMm3QOKMuMVISQJ 2gcmdH3KhKlA== X-IronPort-AV: E=McAfee;i="6000,8403,9669"; a="145947827" X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="145947827" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jul 2020 05:02:11 -0700 IronPort-SDR: W2BRSz48UqmPOn4XB85Y3nspYydEHmB0wdj0zs+Sd36QKGQzKovQd6ASbqbvoeQBGSTcyeaih2 0703lwsYyUlQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="304224715" Received: from unknown (HELO intel-Lenovo-Legion-Y540-15IRH-PG0.iind.intel.com) ([10.224.186.95]) by fmsmga004.fm.intel.com with ESMTP; 02 Jul 2020 05:02:09 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: ravishankar.srivatsa@intel.com, chethan.tumkur.narayan@intel.com, kiraank@gmail.com, Kiran K , Amit K Bag , Raghuram Hegde Subject: [PATCH 2/5] Bluetooth: btintel: Refactor firmware header download sequence Date: Thu, 2 Jul 2020 17:33:12 +0530 Message-Id: <20200702120315.26768-3-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200702120315.26768-1-kiran.k@intel.com> References: <20200702120315.26768-1-kiran.k@intel.com> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Move firmware header download code to a separate function to enhance readability and reusability Signed-off-by: Kiran K Signed-off-by: Amit K Bag Signed-off-by: Raghuram Hegde Reviewed-by: Chethan T N Reviewed-by: Sathish Narasimman Reviewed-by: Srivatsa Ravishankar --- drivers/bluetooth/btintel.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index dea96c585ecb..1c820c187421 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -646,12 +646,10 @@ int btintel_read_boot_params(struct hci_dev *hdev, } EXPORT_SYMBOL_GPL(btintel_read_boot_params); -int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw, - u32 *boot_param) +static int btintel_sfi_rsa_header_secure_send(struct hci_dev *hdev, + const struct firmware *fw) { int err; - const u8 *fw_ptr; - u32 frag_len; /* Start the firmware download transaction with the Init fragment * represented by the 128 bytes of CSS header. @@ -679,6 +677,21 @@ int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw, bt_dev_err(hdev, "Failed to send firmware signature (%d)", err); goto done; } +done: + return err; +} + +int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw, + u32 *boot_param) +{ + int err; + const u8 *fw_ptr; + u32 frag_len; + + err = btintel_sfi_rsa_header_secure_send(hdev, fw); + if (err) + goto done; + fw_ptr = fw->data + 644; frag_len = 0; From patchwork Thu Jul 2 12:03:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 11638685 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 78FA6912 for ; Thu, 2 Jul 2020 12:02:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 64D6020737 for ; Thu, 2 Jul 2020 12:02:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728827AbgGBMCQ (ORCPT ); Thu, 2 Jul 2020 08:02:16 -0400 Received: from mga14.intel.com ([192.55.52.115]:27652 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728808AbgGBMCO (ORCPT ); Thu, 2 Jul 2020 08:02:14 -0400 IronPort-SDR: kH1COQjSUSRVcskqBe+NboQo63WDpALiWX9kgWIx8eS3H6E4o6Jcdk5ZKtMmQya7ZL5XYlMlum hYN/4ceB724g== X-IronPort-AV: E=McAfee;i="6000,8403,9669"; a="145947831" X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="145947831" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jul 2020 05:02:14 -0700 IronPort-SDR: IuS5FJv9Xs18+7XPuq9aVg7WvtRi142tL8Y90l7j+mJsp443jK4jtTbhgBOLDpg3bWNcSKh2ue drvdkOQ9WbXA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="304224729" Received: from unknown (HELO intel-Lenovo-Legion-Y540-15IRH-PG0.iind.intel.com) ([10.224.186.95]) by fmsmga004.fm.intel.com with ESMTP; 02 Jul 2020 05:02:11 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: ravishankar.srivatsa@intel.com, chethan.tumkur.narayan@intel.com, kiraank@gmail.com, Kiran K , Amit K Bag , Raghuram Hegde Subject: [PATCH 3/5] Bluetooth: btintel: Refactor firmware payload download code Date: Thu, 2 Jul 2020 17:33:13 +0530 Message-Id: <20200702120315.26768-4-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200702120315.26768-1-kiran.k@intel.com> References: <20200702120315.26768-1-kiran.k@intel.com> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Move firmware payload download code to a separate function to enhance readability and reusability Signed-off-by: Kiran K Signed-off-by: Amit K Bag Signed-off-by: Raghuram Hegde Reviewed-by: Chethan T N Reviewed-by: Sathish Narasimman Reviewed-by: Srivatsa Ravishankar --- drivers/bluetooth/btintel.c | 29 ++++++++++++++++++++--------- drivers/bluetooth/btintel.h | 10 +++++----- drivers/bluetooth/btusb.c | 2 +- drivers/bluetooth/hci_intel.c | 2 +- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 1c820c187421..d0c6576212d7 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -19,6 +19,7 @@ #define VERSION "0.1" #define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}}) +#define RSA_HEADER_LEN 644 int btintel_check_bdaddr(struct hci_dev *hdev) { @@ -681,20 +682,17 @@ static int btintel_sfi_rsa_header_secure_send(struct hci_dev *hdev, return err; } -int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw, - u32 *boot_param) +static int btintel_download_firmware_payload(struct hci_dev *hdev, + const struct firmware *fw, + u32 *boot_param, size_t offset) { int err; const u8 *fw_ptr; u32 frag_len; - err = btintel_sfi_rsa_header_secure_send(hdev, fw); - if (err) - goto done; - - - fw_ptr = fw->data + 644; + fw_ptr = fw->data + offset; frag_len = 0; + err = -EINVAL; while (fw_ptr - fw->data < fw->size) { struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); @@ -740,7 +738,20 @@ int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw, done: return err; } -EXPORT_SYMBOL_GPL(btintel_download_firmware); + +int btintel_download_firmware_legacy(struct hci_dev *hdev, + const struct firmware *fw, + u32 *boot_param) +{ + int err; + + err = btintel_sfi_rsa_header_secure_send(hdev, fw); + if (err) + return err; + + return btintel_download_firmware_payload(hdev, fw, boot_param, RSA_HEADER_LEN); +} +EXPORT_SYMBOL_GPL(btintel_download_firmware_legacy); void btintel_reset_to_bootloader(struct hci_dev *hdev) { diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 0865d2d4aca7..e476105d495b 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -96,8 +96,8 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); 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); +int btintel_download_firmware_legacy(struct hci_dev *dev, const struct firmware *fw, + u32 *boot_param); void btintel_reset_to_bootloader(struct hci_dev *hdev); int btintel_read_debug_features(struct hci_dev *hdev, struct intel_debug_features *features); @@ -191,9 +191,9 @@ static inline int btintel_read_boot_params(struct hci_dev *hdev, return -EOPNOTSUPP; } -static inline int btintel_download_firmware(struct hci_dev *dev, - const struct firmware *fw, - u32 *boot_param) +static inline int btintel_download_firmware_legacy(struct hci_dev *dev, + const struct firmware *fw, + u32 *boot_param) { return -EOPNOTSUPP; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d06c946f7810..364da6d44ee3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2438,7 +2438,7 @@ static int btusb_intel_download_firmware(struct hci_dev *hdev, set_bit(BTUSB_DOWNLOADING, &data->flags); /* Start firmware downloading and get boot parameter */ - err = btintel_download_firmware(hdev, fw, &boot_param); + err = btintel_download_firmware_legacy(hdev, fw, &boot_param); if (err < 0) { /* When FW download fails, send Intel Reset to retry * FW download. diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index f30cbc66d48f..14045a464309 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -755,7 +755,7 @@ static int intel_setup(struct hci_uart *hu) set_bit(STATE_DOWNLOADING, &intel->flags); /* Start firmware downloading and get boot parameter */ - err = btintel_download_firmware(hdev, fw, &boot_param); + err = btintel_download_firmware_legacy(hdev, fw, &boot_param); if (err < 0) goto done; From patchwork Thu Jul 2 12:03:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 11638687 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E7B0B13B4 for ; Thu, 2 Jul 2020 12:02:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DA12C20884 for ; Thu, 2 Jul 2020 12:02:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728830AbgGBMCR (ORCPT ); Thu, 2 Jul 2020 08:02:17 -0400 Received: from mga14.intel.com ([192.55.52.115]:27652 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728808AbgGBMCR (ORCPT ); Thu, 2 Jul 2020 08:02:17 -0400 IronPort-SDR: akBWXgdARYuOAJ8SjTYgHaEqOU1KSaYXcjHuxSvgTuS+ADRAoTPu3KIsy2IuXpInGuxqIbfHNz Sesjq3pysSNA== X-IronPort-AV: E=McAfee;i="6000,8403,9669"; a="145947836" X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="145947836" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jul 2020 05:02:16 -0700 IronPort-SDR: ZxOrpL5QWXxsFcqZEh1k6Gk+Qj+vOlj91ITW1vOExGaHLppWW0ziAMHMCs7js8+tjB4JgkVVFE U6XaCQomDDSA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="304224741" Received: from unknown (HELO intel-Lenovo-Legion-Y540-15IRH-PG0.iind.intel.com) ([10.224.186.95]) by fmsmga004.fm.intel.com with ESMTP; 02 Jul 2020 05:02:14 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: ravishankar.srivatsa@intel.com, chethan.tumkur.narayan@intel.com, kiraank@gmail.com, Kiran K , Amit K Bag , Raghuram Hegde Subject: [PATCH 4/5] Bluetooth: btintel: Define tlv structure for new generation Controllers Date: Thu, 2 Jul 2020 17:33:14 +0530 Message-Id: <20200702120315.26768-5-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200702120315.26768-1-kiran.k@intel.com> References: <20200702120315.26768-1-kiran.k@intel.com> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Define structure used for reading controller information and to downloading firmware in tlv format used for new generation Intel controllers Signed-off-by: Kiran K Signed-off-by: Amit K Bag Signed-off-by: Raghuram Hegde Reviewed-by: Chethan T N Reviewed-by: Sathish Narasimman Reviewed-by: Srivatsa Ravishankar --- drivers/bluetooth/btintel.h | 85 +++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index e476105d495b..e37f84155c50 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -6,6 +6,90 @@ * Copyright (C) 2015 Intel Corporation */ +/* List of tlv type */ +enum { + INTEL_TLV_CNVI_TOP = 0x10, + INTEL_TLV_CNVR_TOP, + INTEL_TLV_CNVI_BT, + INTEL_TLV_CNVR_BT, + INTEL_TLV_CNVI_OTP, + INTEL_TLV_CNVR_OTP, + INTEL_TLV_DEV_REV_ID, + INTEL_TLV_USB_VENDOR_ID, + INTEL_TLV_USB_PRODUCT_ID, + INTEL_TLV_PCIE_VENDOR_ID, + INTEL_TLV_PCIE_DEVICE_ID, + INTEL_TLV_PCIE_SUBSYSTEM_ID, + INTEL_TLV_IMAGE_TYPE, + INTEL_TLV_TIME_STAMP, + INTEL_TLV_BUILD_TYPE, + INTEL_TLV_BUILD_NUM, + INTEL_TLV_FW_BUILD_PRODUCT, + INTEL_TLV_FW_BUILD_HW, + INTEL_TLV_FW_STEP, + INTEL_TLV_BT_SPEC, + INTEL_TLV_MFG_NAME, + INTEL_TLV_HCI_REV, + INTEL_TLV_LMP_SUBVER, + INTEL_TLV_OTP_PATCH_VER, + INTEL_TLV_SECURE_BOOT, + INTEL_TLV_KEY_FROM_HDR, + INTEL_TLV_OTP_LOCK, + INTEL_TLV_API_LOCK, + INTEL_TLV_DEBUG_LOCK, + INTEL_TLV_MIN_FW, + INTEL_TLV_LIMITED_CCE, + INTEL_TLV_SBE_TYPE, + INTEL_TLV_OTP_BDADDR, + INTEL_TLV_UNLOCKED_STATE +}; + +struct intel_tlv { + u8 type; + u8 len; + u8 val[0]; +} __packed; + +struct intel_version_tlv { + u8 status; + u32 cnvi_top; + u32 cnvr_top; + u32 cnvi_bt; + u32 cnvr_bt; + u16 cnvi_otp; + u16 cnvr_otp; + u16 dev_rev_id; + u16 usb_vid; + u16 usb_pid; + u16 pcie_vendor_id; + u16 pcie_dev_id; + u16 pcie_subsys_id; + u8 img_type; + u16 timestamp; + u8 build_type; + u32 build_num; + u8 fw_build_prod; + u8 fw_build_hw; + u8 fw_build_step; + u8 bt_spec_ver; + u16 mfg_name; + u16 hci_rev; + u16 lmp_sub_ver; + u8 otp_patch_ver; + u8 secure_boot; + u8 key_from_hdr; + u8 otp_lock; + u8 api_lock; + u8 debug_lock; + u8 min_fw_build_nn; + u8 min_fw_build_cw; + u8 min_fw_build_yy; + u8 limited_cce; + u8 sbe_type; + bdaddr_t otp_bd_addr; + u8 unlocked_state; +} __packed; + struct intel_version { u8 status; u8 hw_platform; @@ -70,6 +154,7 @@ struct btintel_version { bool is_tlv_supported; union { struct intel_version intel_version; /* legacy version */ + struct intel_version_tlv intel_version_tlv; }; } __packed; From patchwork Thu Jul 2 12:03:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 11638689 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3FF66912 for ; Thu, 2 Jul 2020 12:02:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 272C320737 for ; Thu, 2 Jul 2020 12:02:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728837AbgGBMCT (ORCPT ); Thu, 2 Jul 2020 08:02:19 -0400 Received: from mga14.intel.com ([192.55.52.115]:27652 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728808AbgGBMCT (ORCPT ); Thu, 2 Jul 2020 08:02:19 -0400 IronPort-SDR: 8Ooc2OLX4tBlKGKm4u+yx3NfekMt5g6icSV6bYE6YGIP6eQfJLT2jPi9T4OEEgFY2uXnmncjF3 YF8zwlWUVdWA== X-IronPort-AV: E=McAfee;i="6000,8403,9669"; a="145947837" X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="145947837" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jul 2020 05:02:19 -0700 IronPort-SDR: q9tRtfvsuvhut+7YyuJVwOgcdkq40T4IUtjTHt8Zv7LuBGPXT61XrQ/nPbCWmYCORPN6nnLAb1 oub/PhJuv1vg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,304,1589266800"; d="scan'208";a="304224756" Received: from unknown (HELO intel-Lenovo-Legion-Y540-15IRH-PG0.iind.intel.com) ([10.224.186.95]) by fmsmga004.fm.intel.com with ESMTP; 02 Jul 2020 05:02:17 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: ravishankar.srivatsa@intel.com, chethan.tumkur.narayan@intel.com, kiraank@gmail.com, Kiran K , Amit K Bag , Raghuram Hegde Subject: [PATCH 5/5] Bluetooth: btintel: Parse controller information present in TLV format Date: Thu, 2 Jul 2020 17:33:15 +0530 Message-Id: <20200702120315.26768-6-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200702120315.26768-1-kiran.k@intel.com> References: <20200702120315.26768-1-kiran.k@intel.com> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org New generation Intel controllers returns controller information in TLV format. Adding capability to parse and log it for debug purpose Signed-off-by: Kiran K Signed-off-by: Amit K Bag Signed-off-by: Raghuram Hegde Reviewed-by: Chethan T N Reviewed-by: Sathish Narasimman Reviewed-by: Srivatsa Ravishankar --- drivers/bluetooth/btintel.c | 161 ++++++++++++++++++++++++++++++++---- drivers/bluetooth/btusb.c | 4 +- 2 files changed, 148 insertions(+), 17 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index d0c6576212d7..f0b087d97a83 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -209,27 +209,59 @@ void btintel_version_info(struct hci_dev *hdev, const struct btintel_version *ve { const char *variant; const struct intel_version *ver; + const struct intel_version_tlv *ver_tlv; - if (version->is_tlv_supported) - return; + if (!version->is_tlv_supported) { + ver = &version->intel_version; + + switch (ver->fw_variant) { + case 0x06: + variant = "Bootloader"; + break; + case 0x23: + variant = "Firmware"; + break; + default: + goto done; + } - ver = &version->intel_version; + bt_dev_info(hdev, "%s revision %u.%u build %u week %u %u", + variant, ver->fw_revision >> 4, + ver->fw_revision & 0x0f, ver->fw_build_num, + ver->fw_build_ww, 2000 + ver->fw_build_yy); + goto done; + } + + ver_tlv = &version->intel_version_tlv; - switch (ver->fw_variant) { - case 0x06: + switch (ver_tlv->img_type) { + case 0x01: variant = "Bootloader"; - break; - case 0x23: + bt_dev_info(hdev, "Device revision is %u", ver_tlv->dev_rev_id); + bt_dev_info(hdev, "Secure boot is %s", + ver_tlv->secure_boot ? "enabled" : "disabled"); + bt_dev_info(hdev, "OTP lock is %s", + ver_tlv->otp_lock ? "enabled" : "disabled"); + bt_dev_info(hdev, "API lock is %s", + ver_tlv->api_lock ? "enabled" : "disabled"); + bt_dev_info(hdev, "Debug lock is %s", + ver_tlv->debug_lock ? "enabled" : "disabled"); + bt_dev_info(hdev, "Minimum firmware build %u week %u %u", + ver_tlv->min_fw_build_nn, ver_tlv->min_fw_build_cw, + 2000 + ver_tlv->min_fw_build_yy); + break; + case 0x03: variant = "Firmware"; - break; + break; default: - return; + goto done; } - bt_dev_info(hdev, "%s revision %u.%u build %u week %u %u", - variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f, - ver->fw_build_num, ver->fw_build_ww, - 2000 + ver->fw_build_yy); + bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant, + 2000 + (ver_tlv->timestamp >> 8), ver_tlv->timestamp & 0xff, + ver_tlv->build_type, ver_tlv->build_num); +done: + return; } EXPORT_SYMBOL_GPL(btintel_version_info); @@ -346,6 +378,8 @@ int btintel_read_version(struct hci_dev *hdev, struct btintel_version *version) { struct sk_buff *skb; u8 *data, param, status, check_tlv; + struct intel_version_tlv *ver_tlv; + struct intel_tlv *tlv; if (!version) return -EINVAL; @@ -373,9 +407,106 @@ int btintel_read_version(struct hci_dev *hdev, struct btintel_version *version) if (skb->len == sizeof(version->intel_version) && check_tlv == 0x37) { memcpy(&version->intel_version, skb->data, sizeof(version->intel_version)); version->is_tlv_supported = false; - } else { - version->is_tlv_supported = true; + goto done; } + + bt_dev_info(hdev, "Supports tlv firmware download sequence"); + version->is_tlv_supported = true; + ver_tlv = &version->intel_version_tlv; + + /* Consume Command Complete Status field */ + skb_pull(skb, 1); + + /* Event parameters contatin multiple TLVs. Read each of them + * and only keep the required data. Also, it use existing legacy + * version field like hw_platform, hw_variant, and fw_variant + * to keep the existing setup flow + */ + while (skb->len) { + tlv = (struct intel_tlv *)skb->data; + switch (tlv->type) { + case INTEL_TLV_CNVI_TOP: + ver_tlv->cnvi_top = (tlv->val[3] << 24) | + (tlv->val[2] << 16) | + (tlv->val[1] << 8) | + (tlv->val[0]); + break; + case INTEL_TLV_CNVR_TOP: + ver_tlv->cnvr_top = (tlv->val[3] << 24) | + (tlv->val[2] << 16) | + (tlv->val[1] << 8) | + (tlv->val[0]); + break; + case INTEL_TLV_CNVI_BT: + ver_tlv->cnvi_bt = (tlv->val[3] << 24) | + (tlv->val[2] << 16) | + (tlv->val[1] << 8) | + (tlv->val[0]); + break; + case INTEL_TLV_CNVR_BT: + ver_tlv->cnvr_bt = (tlv->val[3] << 24) | + (tlv->val[2] << 16) | + (tlv->val[1] << 8) | + (tlv->val[0]); + break; + case INTEL_TLV_USB_VENDOR_ID: + ver_tlv->usb_vid = (tlv->val[1] << 8) | (tlv->val[0]); + break; + case INTEL_TLV_USB_PRODUCT_ID: + ver_tlv->usb_pid = (tlv->val[1] << 8) | (tlv->val[0]); + break; + case INTEL_TLV_IMAGE_TYPE: + ver_tlv->img_type = tlv->val[0]; + break; + case INTEL_TLV_TIME_STAMP: + ver_tlv->timestamp = (tlv->val[1] << 8) | (tlv->val[0]); + break; + case INTEL_TLV_BUILD_TYPE: + ver_tlv->build_type = tlv->val[0]; + break; + case INTEL_TLV_BUILD_NUM: + ver_tlv->build_num = (tlv->val[3] << 24) | + (tlv->val[2] << 16) | + (tlv->val[1] << 8) | + (tlv->val[0]); + break; + case INTEL_TLV_SECURE_BOOT: + ver_tlv->secure_boot = tlv->val[0]; + break; + case INTEL_TLV_KEY_FROM_HDR: + ver_tlv->key_from_hdr = tlv->val[0]; + break; + case INTEL_TLV_OTP_LOCK: + ver_tlv->otp_lock = tlv->val[0]; + break; + case INTEL_TLV_API_LOCK: + ver_tlv->api_lock = tlv->val[0]; + break; + case INTEL_TLV_DEBUG_LOCK: + ver_tlv->debug_lock = tlv->val[0]; + break; + case INTEL_TLV_MIN_FW: + ver_tlv->min_fw_build_nn = tlv->val[0]; + ver_tlv->min_fw_build_cw = tlv->val[1]; + ver_tlv->min_fw_build_yy = tlv->val[2]; + break; + case INTEL_TLV_LIMITED_CCE: + ver_tlv->limited_cce = tlv->val[0]; + break; + case INTEL_TLV_SBE_TYPE: + ver_tlv->sbe_type = tlv->val[0]; + break; + case INTEL_TLV_OTP_BDADDR: + memcpy(&ver_tlv->otp_bd_addr, tlv->val, tlv->len); + break; + default: + /* Ignore rest of information */ + break; + } + /* consume the current tlv and move to next*/ + skb_pull(skb, tlv->len + sizeof(*tlv)); + } +done: kfree_skb(skb); return 0; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 364da6d44ee3..f30b43e15a26 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2519,13 +2519,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) return err; } + btintel_version_info(hdev, &version); + if (version.is_tlv_supported) { bt_dev_err(hdev, "Firmware download in tlv format is not supported"); return -EOPNOTSUPP; } - btintel_version_info(hdev, &version); - err = btusb_intel_download_firmware(hdev, &version, ¶ms); if (err) return err;