|  | // SPDX-License-Identifier: GPL-2.0-or-later | 
|  | /* | 
|  | * | 
|  | *  Bluetooth support for Intel devices | 
|  | * | 
|  | *  Copyright (C) 2015  Intel Corporation | 
|  | */ | 
|  |  | 
|  | #include <linux/module.h> | 
|  | #include <linux/firmware.h> | 
|  | #include <linux/regmap.h> | 
|  | #include <asm/unaligned.h> | 
|  |  | 
|  | #include <net/bluetooth/bluetooth.h> | 
|  | #include <net/bluetooth/hci_core.h> | 
|  |  | 
|  | #include "btintel.h" | 
|  |  | 
|  | #define VERSION "0.1" | 
|  |  | 
|  | #define BDADDR_INTEL		(&(bdaddr_t){{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}}) | 
|  | #define RSA_HEADER_LEN		644 | 
|  | #define CSS_HEADER_OFFSET	8 | 
|  | #define ECDSA_OFFSET		644 | 
|  | #define ECDSA_HEADER_LEN	320 | 
|  |  | 
|  | #define CMD_WRITE_BOOT_PARAMS	0xfc0e | 
|  | struct cmd_write_boot_params { | 
|  | u32 boot_addr; | 
|  | u8  fw_build_num; | 
|  | u8  fw_build_ww; | 
|  | u8  fw_build_yy; | 
|  | } __packed; | 
|  |  | 
|  | int btintel_check_bdaddr(struct hci_dev *hdev) | 
|  | { | 
|  | struct hci_rp_read_bd_addr *bda; | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, | 
|  | HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | int err = PTR_ERR(skb); | 
|  | bt_dev_err(hdev, "Reading Intel device address failed (%d)", | 
|  | err); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | if (skb->len != sizeof(*bda)) { | 
|  | bt_dev_err(hdev, "Intel device address length mismatch"); | 
|  | kfree_skb(skb); | 
|  | return -EIO; | 
|  | } | 
|  |  | 
|  | bda = (struct hci_rp_read_bd_addr *)skb->data; | 
|  |  | 
|  | /* For some Intel based controllers, the default Bluetooth device | 
|  | * address 00:03:19:9E:8B:00 can be found. These controllers are | 
|  | * fully operational, but have the danger of duplicate addresses | 
|  | * and that in turn can cause problems with Bluetooth operation. | 
|  | */ | 
|  | if (!bacmp(&bda->bdaddr, BDADDR_INTEL)) { | 
|  | bt_dev_err(hdev, "Found Intel default device address (%pMR)", | 
|  | &bda->bdaddr); | 
|  | set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); | 
|  | } | 
|  |  | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_check_bdaddr); | 
|  |  | 
|  | int btintel_enter_mfg(struct hci_dev *hdev) | 
|  | { | 
|  | static const u8 param[] = { 0x01, 0x00 }; | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Entering manufacturer mode failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_enter_mfg); | 
|  |  | 
|  | int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched) | 
|  | { | 
|  | u8 param[] = { 0x00, 0x00 }; | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | /* The 2nd command parameter specifies the manufacturing exit method: | 
|  | * 0x00: Just disable the manufacturing mode (0x00). | 
|  | * 0x01: Disable manufacturing mode and reset with patches deactivated. | 
|  | * 0x02: Disable manufacturing mode and reset with patches activated. | 
|  | */ | 
|  | if (reset) | 
|  | param[1] |= patched ? 0x02 : 0x01; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Exiting manufacturer mode failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_exit_mfg); | 
|  |  | 
|  | int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | int err; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | err = PTR_ERR(skb); | 
|  | bt_dev_err(hdev, "Changing Intel device address failed (%d)", | 
|  | err); | 
|  | return err; | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_set_bdaddr); | 
|  |  | 
|  | static int btintel_set_event_mask(struct hci_dev *hdev, bool debug) | 
|  | { | 
|  | u8 mask[8] = { 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | 
|  | struct sk_buff *skb; | 
|  | int err; | 
|  |  | 
|  | if (debug) | 
|  | mask[1] |= 0x62; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | err = PTR_ERR(skb); | 
|  | bt_dev_err(hdev, "Setting Intel event mask failed (%d)", err); | 
|  | return err; | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int btintel_set_diag(struct hci_dev *hdev, bool enable) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | u8 param[3]; | 
|  | int err; | 
|  |  | 
|  | if (enable) { | 
|  | param[0] = 0x03; | 
|  | param[1] = 0x03; | 
|  | param[2] = 0x03; | 
|  | } else { | 
|  | param[0] = 0x00; | 
|  | param[1] = 0x00; | 
|  | param[2] = 0x00; | 
|  | } | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc43, 3, param, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | err = PTR_ERR(skb); | 
|  | if (err == -ENODATA) | 
|  | goto done; | 
|  | bt_dev_err(hdev, "Changing Intel diagnostic mode failed (%d)", | 
|  | err); | 
|  | return err; | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | done: | 
|  | btintel_set_event_mask(hdev, enable); | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_set_diag); | 
|  |  | 
|  | static int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) | 
|  | { | 
|  | int err, ret; | 
|  |  | 
|  | err = btintel_enter_mfg(hdev); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | ret = btintel_set_diag(hdev, enable); | 
|  |  | 
|  | err = btintel_exit_mfg(hdev, false, false); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static int btintel_set_diag_combined(struct hci_dev *hdev, bool enable) | 
|  | { | 
|  | int ret; | 
|  |  | 
|  | /* Legacy ROM device needs to be in the manufacturer mode to apply | 
|  | * diagnostic setting | 
|  | * | 
|  | * This flag is set after reading the Intel version. | 
|  | */ | 
|  | if (btintel_test_flag(hdev, INTEL_ROM_LEGACY)) | 
|  | ret = btintel_set_diag_mfg(hdev, enable); | 
|  | else | 
|  | ret = btintel_set_diag(hdev, enable); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static void btintel_hw_error(struct hci_dev *hdev, u8 code) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | u8 type = 0x00; | 
|  |  | 
|  | bt_dev_err(hdev, "Hardware error 0x%2.2x", code); | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Reset after hardware error failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return; | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (skb->len != 13) { | 
|  | bt_dev_err(hdev, "Exception info size mismatch"); | 
|  | kfree_skb(skb); | 
|  | return; | 
|  | } | 
|  |  | 
|  | bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1)); | 
|  |  | 
|  | kfree_skb(skb); | 
|  | } | 
|  |  | 
|  | int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) | 
|  | { | 
|  | const char *variant; | 
|  |  | 
|  | /* The hardware platform number has a fixed value of 0x37 and | 
|  | * for now only accept this single value. | 
|  | */ | 
|  | if (ver->hw_platform != 0x37) { | 
|  | bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)", | 
|  | ver->hw_platform); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /* 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 (ver->hw_variant) { | 
|  | case 0x07:	/* WP - Legacy ROM */ | 
|  | case 0x08:	/* StP - Legacy ROM */ | 
|  | case 0x0b:      /* SfP */ | 
|  | case 0x0c:      /* WsP */ | 
|  | case 0x11:      /* JfP */ | 
|  | case 0x12:      /* ThP */ | 
|  | case 0x13:      /* HrP */ | 
|  | case 0x14:      /* CcP */ | 
|  | break; | 
|  | default: | 
|  | bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", | 
|  | ver->hw_variant); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | switch (ver->fw_variant) { | 
|  | case 0x01: | 
|  | variant = "Legacy ROM 2.5"; | 
|  | break; | 
|  | case 0x06: | 
|  | variant = "Bootloader"; | 
|  | break; | 
|  | case 0x22: | 
|  | variant = "Legacy ROM 2.x"; | 
|  | break; | 
|  | case 0x23: | 
|  | variant = "Firmware"; | 
|  | break; | 
|  | default: | 
|  | bt_dev_err(hdev, "Unsupported firmware variant(%02x)", ver->fw_variant); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | 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); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_version_info); | 
|  |  | 
|  | static int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, | 
|  | const void *param) | 
|  | { | 
|  | while (plen > 0) { | 
|  | struct sk_buff *skb; | 
|  | u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen; | 
|  |  | 
|  | cmd_param[0] = fragment_type; | 
|  | memcpy(cmd_param + 1, param, fragment_len); | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1, | 
|  | cmd_param, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) | 
|  | return PTR_ERR(skb); | 
|  |  | 
|  | kfree_skb(skb); | 
|  |  | 
|  | plen -= fragment_len; | 
|  | param += fragment_len; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name) | 
|  | { | 
|  | const struct firmware *fw; | 
|  | struct sk_buff *skb; | 
|  | const u8 *fw_ptr; | 
|  | int err; | 
|  |  | 
|  | err = request_firmware_direct(&fw, ddc_name, &hdev->dev); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, "Failed to load Intel DDC file %s (%d)", | 
|  | ddc_name, err); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | bt_dev_info(hdev, "Found Intel DDC parameters: %s", ddc_name); | 
|  |  | 
|  | fw_ptr = fw->data; | 
|  |  | 
|  | /* DDC file contains one or more DDC structure which has | 
|  | * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2). | 
|  | */ | 
|  | while (fw->size > fw_ptr - fw->data) { | 
|  | u8 cmd_plen = fw_ptr[0] + sizeof(u8); | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr, | 
|  | HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Failed to send Intel_Write_DDC (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | release_firmware(fw); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  |  | 
|  | fw_ptr += cmd_plen; | 
|  | kfree_skb(skb); | 
|  | } | 
|  |  | 
|  | release_firmware(fw); | 
|  |  | 
|  | bt_dev_info(hdev, "Applying Intel DDC parameters completed"); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_load_ddc_config); | 
|  |  | 
|  | int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) | 
|  | { | 
|  | int err, ret; | 
|  |  | 
|  | err = btintel_enter_mfg(hdev); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | ret = btintel_set_event_mask(hdev, debug); | 
|  |  | 
|  | err = btintel_exit_mfg(hdev, false, false); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | return ret; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg); | 
|  |  | 
|  | int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, 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"); | 
|  | kfree_skb(skb); | 
|  | return -EILSEQ; | 
|  | } | 
|  |  | 
|  | memcpy(ver, skb->data, sizeof(*ver)); | 
|  |  | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_read_version); | 
|  |  | 
|  | static int btintel_version_info_tlv(struct hci_dev *hdev, | 
|  | struct intel_version_tlv *version) | 
|  | { | 
|  | const char *variant; | 
|  |  | 
|  | /* The hardware platform number has a fixed value of 0x37 and | 
|  | * for now only accept this single value. | 
|  | */ | 
|  | if (INTEL_HW_PLATFORM(version->cnvi_bt) != 0x37) { | 
|  | bt_dev_err(hdev, "Unsupported Intel hardware platform (0x%2x)", | 
|  | INTEL_HW_PLATFORM(version->cnvi_bt)); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /* 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(version->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(version->cnvi_bt)); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | switch (version->img_type) { | 
|  | case 0x01: | 
|  | variant = "Bootloader"; | 
|  | /* 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 (version->limited_cce != 0x00) { | 
|  | bt_dev_err(hdev, "Unsupported Intel firmware loading method (0x%x)", | 
|  | version->limited_cce); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */ | 
|  | if (version->sbe_type > 0x01) { | 
|  | bt_dev_err(hdev, "Unsupported Intel secure boot engine type (0x%x)", | 
|  | version->sbe_type); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | bt_dev_info(hdev, "Device revision is %u", version->dev_rev_id); | 
|  | bt_dev_info(hdev, "Secure boot is %s", | 
|  | version->secure_boot ? "enabled" : "disabled"); | 
|  | bt_dev_info(hdev, "OTP lock is %s", | 
|  | version->otp_lock ? "enabled" : "disabled"); | 
|  | bt_dev_info(hdev, "API lock is %s", | 
|  | version->api_lock ? "enabled" : "disabled"); | 
|  | bt_dev_info(hdev, "Debug lock is %s", | 
|  | version->debug_lock ? "enabled" : "disabled"); | 
|  | bt_dev_info(hdev, "Minimum firmware build %u week %u %u", | 
|  | version->min_fw_build_nn, version->min_fw_build_cw, | 
|  | 2000 + version->min_fw_build_yy); | 
|  | break; | 
|  | case 0x03: | 
|  | variant = "Firmware"; | 
|  | break; | 
|  | default: | 
|  | bt_dev_err(hdev, "Unsupported image type(%02x)", version->img_type); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant, | 
|  | 2000 + (version->timestamp >> 8), version->timestamp & 0xff, | 
|  | version->build_type, version->build_num); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_parse_version_tlv(struct hci_dev *hdev, | 
|  | struct intel_version_tlv *version, | 
|  | struct sk_buff *skb) | 
|  | { | 
|  | /* 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) { | 
|  | struct intel_tlv *tlv; | 
|  |  | 
|  | /* Make sure skb has a minimum length of the header */ | 
|  | if (skb->len < sizeof(*tlv)) | 
|  | return -EINVAL; | 
|  |  | 
|  | tlv = (struct intel_tlv *)skb->data; | 
|  |  | 
|  | /* Make sure skb has a enough data */ | 
|  | if (skb->len < tlv->len + sizeof(*tlv)) | 
|  | return -EINVAL; | 
|  |  | 
|  | switch (tlv->type) { | 
|  | case INTEL_TLV_CNVI_TOP: | 
|  | version->cnvi_top = get_unaligned_le32(tlv->val); | 
|  | break; | 
|  | case INTEL_TLV_CNVR_TOP: | 
|  | version->cnvr_top = get_unaligned_le32(tlv->val); | 
|  | break; | 
|  | case INTEL_TLV_CNVI_BT: | 
|  | version->cnvi_bt = get_unaligned_le32(tlv->val); | 
|  | break; | 
|  | case INTEL_TLV_CNVR_BT: | 
|  | version->cnvr_bt = get_unaligned_le32(tlv->val); | 
|  | break; | 
|  | case INTEL_TLV_DEV_REV_ID: | 
|  | version->dev_rev_id = get_unaligned_le16(tlv->val); | 
|  | break; | 
|  | case INTEL_TLV_IMAGE_TYPE: | 
|  | version->img_type = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_TIME_STAMP: | 
|  | /* If image type is Operational firmware (0x03), then | 
|  | * running FW Calendar Week and Year information can | 
|  | * be extracted from Timestamp information | 
|  | */ | 
|  | version->min_fw_build_cw = tlv->val[0]; | 
|  | version->min_fw_build_yy = tlv->val[1]; | 
|  | version->timestamp = get_unaligned_le16(tlv->val); | 
|  | break; | 
|  | case INTEL_TLV_BUILD_TYPE: | 
|  | version->build_type = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_BUILD_NUM: | 
|  | /* If image type is Operational firmware (0x03), then | 
|  | * running FW build number can be extracted from the | 
|  | * Build information | 
|  | */ | 
|  | version->min_fw_build_nn = tlv->val[0]; | 
|  | version->build_num = get_unaligned_le32(tlv->val); | 
|  | break; | 
|  | case INTEL_TLV_SECURE_BOOT: | 
|  | version->secure_boot = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_OTP_LOCK: | 
|  | version->otp_lock = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_API_LOCK: | 
|  | version->api_lock = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_DEBUG_LOCK: | 
|  | version->debug_lock = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_MIN_FW: | 
|  | version->min_fw_build_nn = tlv->val[0]; | 
|  | version->min_fw_build_cw = tlv->val[1]; | 
|  | version->min_fw_build_yy = tlv->val[2]; | 
|  | break; | 
|  | case INTEL_TLV_LIMITED_CCE: | 
|  | version->limited_cce = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_SBE_TYPE: | 
|  | version->sbe_type = tlv->val[0]; | 
|  | break; | 
|  | case INTEL_TLV_OTP_BDADDR: | 
|  | memcpy(&version->otp_bd_addr, tlv->val, | 
|  | sizeof(bdaddr_t)); | 
|  | break; | 
|  | default: | 
|  | /* Ignore rest of information */ | 
|  | break; | 
|  | } | 
|  | /* consume the current tlv and move to next*/ | 
|  | skb_pull(skb, tlv->len + sizeof(*tlv)); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_read_version_tlv(struct hci_dev *hdev, | 
|  | struct intel_version_tlv *version) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | const u8 param[1] = { 0xFF }; | 
|  |  | 
|  | if (!version) | 
|  | return -EINVAL; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, 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->data[0]) { | 
|  | bt_dev_err(hdev, "Intel Read Version command failed (%02x)", | 
|  | skb->data[0]); | 
|  | kfree_skb(skb); | 
|  | return -EIO; | 
|  | } | 
|  |  | 
|  | btintel_parse_version_tlv(hdev, version, skb); | 
|  |  | 
|  | kfree_skb(skb); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* ------- REGMAP IBT SUPPORT ------- */ | 
|  |  | 
|  | #define IBT_REG_MODE_8BIT  0x00 | 
|  | #define IBT_REG_MODE_16BIT 0x01 | 
|  | #define IBT_REG_MODE_32BIT 0x02 | 
|  |  | 
|  | struct regmap_ibt_context { | 
|  | struct hci_dev *hdev; | 
|  | __u16 op_write; | 
|  | __u16 op_read; | 
|  | }; | 
|  |  | 
|  | struct ibt_cp_reg_access { | 
|  | __le32  addr; | 
|  | __u8    mode; | 
|  | __u8    len; | 
|  | __u8    data[]; | 
|  | } __packed; | 
|  |  | 
|  | struct ibt_rp_reg_access { | 
|  | __u8    status; | 
|  | __le32  addr; | 
|  | __u8    data[]; | 
|  | } __packed; | 
|  |  | 
|  | static int regmap_ibt_read(void *context, const void *addr, size_t reg_size, | 
|  | void *val, size_t val_size) | 
|  | { | 
|  | struct regmap_ibt_context *ctx = context; | 
|  | struct ibt_cp_reg_access cp; | 
|  | struct ibt_rp_reg_access *rp; | 
|  | struct sk_buff *skb; | 
|  | int err = 0; | 
|  |  | 
|  | if (reg_size != sizeof(__le32)) | 
|  | return -EINVAL; | 
|  |  | 
|  | switch (val_size) { | 
|  | case 1: | 
|  | cp.mode = IBT_REG_MODE_8BIT; | 
|  | break; | 
|  | case 2: | 
|  | cp.mode = IBT_REG_MODE_16BIT; | 
|  | break; | 
|  | case 4: | 
|  | cp.mode = IBT_REG_MODE_32BIT; | 
|  | break; | 
|  | default: | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /* regmap provides a little-endian formatted addr */ | 
|  | cp.addr = *(__le32 *)addr; | 
|  | cp.len = val_size; | 
|  |  | 
|  | bt_dev_dbg(ctx->hdev, "Register (0x%x) read", le32_to_cpu(cp.addr)); | 
|  |  | 
|  | skb = hci_cmd_sync(ctx->hdev, ctx->op_read, sizeof(cp), &cp, | 
|  | HCI_CMD_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | err = PTR_ERR(skb); | 
|  | bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error (%d)", | 
|  | le32_to_cpu(cp.addr), err); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | if (skb->len != sizeof(*rp) + val_size) { | 
|  | bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad len", | 
|  | le32_to_cpu(cp.addr)); | 
|  | err = -EINVAL; | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | rp = (struct ibt_rp_reg_access *)skb->data; | 
|  |  | 
|  | if (rp->addr != cp.addr) { | 
|  | bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad addr", | 
|  | le32_to_cpu(rp->addr)); | 
|  | err = -EINVAL; | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | memcpy(val, rp->data, val_size); | 
|  |  | 
|  | done: | 
|  | kfree_skb(skb); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static int regmap_ibt_gather_write(void *context, | 
|  | const void *addr, size_t reg_size, | 
|  | const void *val, size_t val_size) | 
|  | { | 
|  | struct regmap_ibt_context *ctx = context; | 
|  | struct ibt_cp_reg_access *cp; | 
|  | struct sk_buff *skb; | 
|  | int plen = sizeof(*cp) + val_size; | 
|  | u8 mode; | 
|  | int err = 0; | 
|  |  | 
|  | if (reg_size != sizeof(__le32)) | 
|  | return -EINVAL; | 
|  |  | 
|  | switch (val_size) { | 
|  | case 1: | 
|  | mode = IBT_REG_MODE_8BIT; | 
|  | break; | 
|  | case 2: | 
|  | mode = IBT_REG_MODE_16BIT; | 
|  | break; | 
|  | case 4: | 
|  | mode = IBT_REG_MODE_32BIT; | 
|  | break; | 
|  | default: | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | cp = kmalloc(plen, GFP_KERNEL); | 
|  | if (!cp) | 
|  | return -ENOMEM; | 
|  |  | 
|  | /* regmap provides a little-endian formatted addr/value */ | 
|  | cp->addr = *(__le32 *)addr; | 
|  | cp->mode = mode; | 
|  | cp->len = val_size; | 
|  | memcpy(&cp->data, val, val_size); | 
|  |  | 
|  | bt_dev_dbg(ctx->hdev, "Register (0x%x) write", le32_to_cpu(cp->addr)); | 
|  |  | 
|  | skb = hci_cmd_sync(ctx->hdev, ctx->op_write, plen, cp, HCI_CMD_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | err = PTR_ERR(skb); | 
|  | bt_dev_err(ctx->hdev, "regmap: Register (0x%x) write error (%d)", | 
|  | le32_to_cpu(cp->addr), err); | 
|  | goto done; | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | done: | 
|  | kfree(cp); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static int regmap_ibt_write(void *context, const void *data, size_t count) | 
|  | { | 
|  | /* data contains register+value, since we only support 32bit addr, | 
|  | * minimum data size is 4 bytes. | 
|  | */ | 
|  | if (WARN_ONCE(count < 4, "Invalid register access")) | 
|  | return -EINVAL; | 
|  |  | 
|  | return regmap_ibt_gather_write(context, data, 4, data + 4, count - 4); | 
|  | } | 
|  |  | 
|  | static void regmap_ibt_free_context(void *context) | 
|  | { | 
|  | kfree(context); | 
|  | } | 
|  |  | 
|  | static struct regmap_bus regmap_ibt = { | 
|  | .read = regmap_ibt_read, | 
|  | .write = regmap_ibt_write, | 
|  | .gather_write = regmap_ibt_gather_write, | 
|  | .free_context = regmap_ibt_free_context, | 
|  | .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, | 
|  | .val_format_endian_default = REGMAP_ENDIAN_LITTLE, | 
|  | }; | 
|  |  | 
|  | /* Config is the same for all register regions */ | 
|  | static const struct regmap_config regmap_ibt_cfg = { | 
|  | .name      = "btintel_regmap", | 
|  | .reg_bits  = 32, | 
|  | .val_bits  = 32, | 
|  | }; | 
|  |  | 
|  | struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, | 
|  | u16 opcode_write) | 
|  | { | 
|  | struct regmap_ibt_context *ctx; | 
|  |  | 
|  | bt_dev_info(hdev, "regmap: Init R%x-W%x region", opcode_read, | 
|  | opcode_write); | 
|  |  | 
|  | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 
|  | if (!ctx) | 
|  | return ERR_PTR(-ENOMEM); | 
|  |  | 
|  | ctx->op_read = opcode_read; | 
|  | ctx->op_write = opcode_write; | 
|  | ctx->hdev = hdev; | 
|  |  | 
|  | return regmap_init(&hdev->dev, ®map_ibt, ctx, ®map_ibt_cfg); | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_regmap_init); | 
|  |  | 
|  | int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param) | 
|  | { | 
|  | struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 }; | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | params.boot_param = cpu_to_le32(boot_param); | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), ¶ms, | 
|  | HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Failed to send Intel Reset command"); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  |  | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_send_intel_reset); | 
|  |  | 
|  | int btintel_read_boot_params(struct hci_dev *hdev, | 
|  | struct intel_boot_params *params) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  |  | 
|  | if (skb->len != sizeof(*params)) { | 
|  | bt_dev_err(hdev, "Intel boot parameters size mismatch"); | 
|  | kfree_skb(skb); | 
|  | return -EILSEQ; | 
|  | } | 
|  |  | 
|  | memcpy(params, skb->data, sizeof(*params)); | 
|  |  | 
|  | kfree_skb(skb); | 
|  |  | 
|  | if (params->status) { | 
|  | bt_dev_err(hdev, "Intel boot parameters command failed (%02x)", | 
|  | params->status); | 
|  | return -bt_to_errno(params->status); | 
|  | } | 
|  |  | 
|  | bt_dev_info(hdev, "Device revision is %u", | 
|  | le16_to_cpu(params->dev_revid)); | 
|  |  | 
|  | bt_dev_info(hdev, "Secure boot is %s", | 
|  | params->secure_boot ? "enabled" : "disabled"); | 
|  |  | 
|  | bt_dev_info(hdev, "OTP lock is %s", | 
|  | params->otp_lock ? "enabled" : "disabled"); | 
|  |  | 
|  | bt_dev_info(hdev, "API lock is %s", | 
|  | params->api_lock ? "enabled" : "disabled"); | 
|  |  | 
|  | bt_dev_info(hdev, "Debug lock is %s", | 
|  | params->debug_lock ? "enabled" : "disabled"); | 
|  |  | 
|  | bt_dev_info(hdev, "Minimum firmware build %u week %u %u", | 
|  | params->min_fw_build_nn, params->min_fw_build_cw, | 
|  | 2000 + params->min_fw_build_yy); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_read_boot_params); | 
|  |  | 
|  | static int btintel_sfi_rsa_header_secure_send(struct hci_dev *hdev, | 
|  | const struct firmware *fw) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | /* Start the firmware download transaction with the Init fragment | 
|  | * represented by the 128 bytes of CSS header. | 
|  | */ | 
|  | err = btintel_secure_send(hdev, 0x00, 128, fw->data); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, "Failed to send firmware header (%d)", err); | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | /* Send the 256 bytes of public key information from the firmware | 
|  | * as the PKey fragment. | 
|  | */ | 
|  | err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err); | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | /* Send the 256 bytes of signature information from the firmware | 
|  | * as the Sign fragment. | 
|  | */ | 
|  | err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, "Failed to send firmware signature (%d)", err); | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | done: | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static int btintel_sfi_ecdsa_header_secure_send(struct hci_dev *hdev, | 
|  | const struct firmware *fw) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | /* Start the firmware download transaction with the Init fragment | 
|  | * represented by the 128 bytes of CSS header. | 
|  | */ | 
|  | err = btintel_secure_send(hdev, 0x00, 128, fw->data + 644); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, "Failed to send firmware header (%d)", err); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | /* Send the 96 bytes of public key information from the firmware | 
|  | * as the PKey fragment. | 
|  | */ | 
|  | err = btintel_secure_send(hdev, 0x03, 96, fw->data + 644 + 128); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | /* Send the 96 bytes of signature information from the firmware | 
|  | * as the Sign fragment | 
|  | */ | 
|  | err = btintel_secure_send(hdev, 0x02, 96, fw->data + 644 + 224); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, "Failed to send firmware signature (%d)", | 
|  | err); | 
|  | return err; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_download_firmware_payload(struct hci_dev *hdev, | 
|  | const struct firmware *fw, | 
|  | size_t offset) | 
|  | { | 
|  | int err; | 
|  | const u8 *fw_ptr; | 
|  | u32 frag_len; | 
|  |  | 
|  | 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); | 
|  |  | 
|  | frag_len += sizeof(*cmd) + cmd->plen; | 
|  |  | 
|  | /* The parameter length of the secure send command requires | 
|  | * a 4 byte alignment. It happens so that the firmware file | 
|  | * contains proper Intel_NOP commands to align the fragments | 
|  | * as needed. | 
|  | * | 
|  | * Send set of commands with 4 byte alignment from the | 
|  | * firmware data buffer as a single Data fragement. | 
|  | */ | 
|  | if (!(frag_len % 4)) { | 
|  | err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr); | 
|  | if (err < 0) { | 
|  | bt_dev_err(hdev, | 
|  | "Failed to send firmware data (%d)", | 
|  | err); | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | fw_ptr += frag_len; | 
|  | frag_len = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | done: | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static bool btintel_firmware_version(struct hci_dev *hdev, | 
|  | u8 num, u8 ww, u8 yy, | 
|  | const struct firmware *fw, | 
|  | u32 *boot_addr) | 
|  | { | 
|  | const u8 *fw_ptr; | 
|  |  | 
|  | fw_ptr = fw->data; | 
|  |  | 
|  | while (fw_ptr - fw->data < fw->size) { | 
|  | struct hci_command_hdr *cmd = (void *)(fw_ptr); | 
|  |  | 
|  | /* Each SKU has a different reset parameter to use in the | 
|  | * HCI_Intel_Reset command and it is embedded in the firmware | 
|  | * data. So, instead of using static value per SKU, check | 
|  | * the firmware data and save it for later use. | 
|  | */ | 
|  | if (le16_to_cpu(cmd->opcode) == CMD_WRITE_BOOT_PARAMS) { | 
|  | struct cmd_write_boot_params *params; | 
|  |  | 
|  | params = (void *)(fw_ptr + sizeof(*cmd)); | 
|  |  | 
|  | bt_dev_info(hdev, "Boot Address: 0x%x", | 
|  | le32_to_cpu(params->boot_addr)); | 
|  |  | 
|  | bt_dev_info(hdev, "Firmware Version: %u-%u.%u", | 
|  | params->fw_build_num, params->fw_build_ww, | 
|  | params->fw_build_yy); | 
|  |  | 
|  | return (num == params->fw_build_num && | 
|  | ww == params->fw_build_ww && | 
|  | yy == params->fw_build_yy); | 
|  | } | 
|  |  | 
|  | fw_ptr += sizeof(*cmd) + cmd->plen; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | int btintel_download_firmware(struct hci_dev *hdev, | 
|  | struct intel_version *ver, | 
|  | const struct firmware *fw, | 
|  | u32 *boot_param) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | /* SfP and WsP don't seem to update the firmware version on file | 
|  | * so version checking is currently not possible. | 
|  | */ | 
|  | switch (ver->hw_variant) { | 
|  | case 0x0b:	/* SfP */ | 
|  | case 0x0c:	/* WsP */ | 
|  | /* Skip version checking */ | 
|  | break; | 
|  | default: | 
|  | /* Skip reading firmware file version in bootloader mode */ | 
|  | if (ver->fw_variant == 0x06) | 
|  | break; | 
|  |  | 
|  | /* Skip download if firmware has the same version */ | 
|  | if (btintel_firmware_version(hdev, ver->fw_build_num, | 
|  | ver->fw_build_ww, ver->fw_build_yy, | 
|  | fw, boot_param)) { | 
|  | bt_dev_info(hdev, "Firmware already loaded"); | 
|  | /* Return -EALREADY to indicate that the firmware has | 
|  | * already been loaded. | 
|  | */ | 
|  | return -EALREADY; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* 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 | 
|  | * firmware. | 
|  | * | 
|  | * If the firmware version has changed that means it needs to be reset | 
|  | * to bootloader when operational so the new firmware can be loaded. | 
|  | */ | 
|  | if (ver->fw_variant == 0x23) | 
|  | return -EINVAL; | 
|  |  | 
|  | err = btintel_sfi_rsa_header_secure_send(hdev, fw); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | return btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_download_firmware); | 
|  |  | 
|  | static int btintel_download_fw_tlv(struct hci_dev *hdev, | 
|  | struct intel_version_tlv *ver, | 
|  | const struct firmware *fw, u32 *boot_param, | 
|  | u8 hw_variant, u8 sbe_type) | 
|  | { | 
|  | int err; | 
|  | u32 css_header_ver; | 
|  |  | 
|  | /* Skip reading firmware file version in bootloader mode */ | 
|  | if (ver->img_type != 0x01) { | 
|  | /* Skip download if firmware has the same version */ | 
|  | if (btintel_firmware_version(hdev, ver->min_fw_build_nn, | 
|  | ver->min_fw_build_cw, | 
|  | ver->min_fw_build_yy, | 
|  | fw, boot_param)) { | 
|  | bt_dev_info(hdev, "Firmware already loaded"); | 
|  | /* Return -EALREADY to indicate that firmware has | 
|  | * already been loaded. | 
|  | */ | 
|  | return -EALREADY; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* The firmware variant determines if the device is in bootloader | 
|  | * mode or is running operational firmware. The value 0x01 identifies | 
|  | * the bootloader and the value 0x03 identifies the operational | 
|  | * firmware. | 
|  | * | 
|  | * If the firmware version has changed that means it needs to be reset | 
|  | * to bootloader when operational so the new firmware can be loaded. | 
|  | */ | 
|  | if (ver->img_type == 0x03) | 
|  | return -EINVAL; | 
|  |  | 
|  | /* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support | 
|  | * only RSA secure boot engine. Hence, the corresponding sfi file will | 
|  | * have RSA header of 644 bytes followed by Command Buffer. | 
|  | * | 
|  | * iBT hardware variants 0x17, 0x18 onwards support both RSA and ECDSA | 
|  | * secure boot engine. As a result, the corresponding sfi file will | 
|  | * have RSA header of 644, ECDSA header of 320 bytes followed by | 
|  | * Command Buffer. | 
|  | * | 
|  | * CSS Header byte positions 0x08 to 0x0B represent the CSS Header | 
|  | * version: RSA(0x00010000) , ECDSA (0x00020000) | 
|  | */ | 
|  | css_header_ver = get_unaligned_le32(fw->data + CSS_HEADER_OFFSET); | 
|  | if (css_header_ver != 0x00010000) { | 
|  | bt_dev_err(hdev, "Invalid CSS Header version"); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | if (hw_variant <= 0x14) { | 
|  | if (sbe_type != 0x00) { | 
|  | bt_dev_err(hdev, "Invalid SBE type for hardware variant (%d)", | 
|  | hw_variant); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | err = btintel_sfi_rsa_header_secure_send(hdev, fw); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | err = btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); | 
|  | if (err) | 
|  | return err; | 
|  | } else if (hw_variant >= 0x17) { | 
|  | /* Check if CSS header for ECDSA follows the RSA header */ | 
|  | if (fw->data[ECDSA_OFFSET] != 0x06) | 
|  | return -EINVAL; | 
|  |  | 
|  | /* Check if the CSS Header version is ECDSA(0x00020000) */ | 
|  | css_header_ver = get_unaligned_le32(fw->data + ECDSA_OFFSET + CSS_HEADER_OFFSET); | 
|  | if (css_header_ver != 0x00020000) { | 
|  | bt_dev_err(hdev, "Invalid CSS Header version"); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | if (sbe_type == 0x00) { | 
|  | err = btintel_sfi_rsa_header_secure_send(hdev, fw); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | err = btintel_download_firmware_payload(hdev, fw, | 
|  | RSA_HEADER_LEN + ECDSA_HEADER_LEN); | 
|  | if (err) | 
|  | return err; | 
|  | } else if (sbe_type == 0x01) { | 
|  | err = btintel_sfi_ecdsa_header_secure_send(hdev, fw); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | err = btintel_download_firmware_payload(hdev, fw, | 
|  | RSA_HEADER_LEN + ECDSA_HEADER_LEN); | 
|  | if (err) | 
|  | return err; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void btintel_reset_to_bootloader(struct hci_dev *hdev) | 
|  | { | 
|  | struct intel_reset params; | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | /* 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(0x00000000); | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), | 
|  | ¶ms, 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); | 
|  | } | 
|  |  | 
|  | static int btintel_read_debug_features(struct hci_dev *hdev, | 
|  | struct intel_debug_features *features) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | u8 page_no = 1; | 
|  |  | 
|  | /* Intel controller supports two pages, each page is of 128-bit | 
|  | * feature bit mask. And each bit defines specific feature support | 
|  | */ | 
|  | skb = __hci_cmd_sync(hdev, 0xfca6, sizeof(page_no), &page_no, | 
|  | HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Reading supported features failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  |  | 
|  | if (skb->len != (sizeof(features->page1) + 3)) { | 
|  | bt_dev_err(hdev, "Supported features event size mismatch"); | 
|  | kfree_skb(skb); | 
|  | return -EILSEQ; | 
|  | } | 
|  |  | 
|  | memcpy(features->page1, skb->data + 3, sizeof(features->page1)); | 
|  |  | 
|  | /* Read the supported features page2 if required in future. | 
|  | */ | 
|  | kfree_skb(skb); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_set_debug_features(struct hci_dev *hdev, | 
|  | const struct intel_debug_features *features) | 
|  | { | 
|  | u8 mask[11] = { 0x0a, 0x92, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, | 
|  | 0x00, 0x00, 0x00 }; | 
|  | struct sk_buff *skb; | 
|  |  | 
|  | if (!features) | 
|  | return -EINVAL; | 
|  |  | 
|  | if (!(features->page1[0] & 0x3f)) { | 
|  | bt_dev_info(hdev, "Telemetry exception format not supported"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | skb = __hci_cmd_sync(hdev, 0xfc8b, 11, mask, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Setting Intel telemetry ddc write event mask failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  |  | 
|  | kfree_skb(skb); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev, | 
|  | struct intel_version *ver) | 
|  | { | 
|  | const struct firmware *fw; | 
|  | char fwname[64]; | 
|  | int ret; | 
|  |  | 
|  | snprintf(fwname, sizeof(fwname), | 
|  | "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq", | 
|  | ver->hw_platform, ver->hw_variant, ver->hw_revision, | 
|  | ver->fw_variant,  ver->fw_revision, ver->fw_build_num, | 
|  | ver->fw_build_ww, ver->fw_build_yy); | 
|  |  | 
|  | ret = request_firmware(&fw, fwname, &hdev->dev); | 
|  | if (ret < 0) { | 
|  | if (ret == -EINVAL) { | 
|  | bt_dev_err(hdev, "Intel firmware file request failed (%d)", | 
|  | ret); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | bt_dev_err(hdev, "failed to open Intel firmware file: %s (%d)", | 
|  | fwname, ret); | 
|  |  | 
|  | /* If the correct firmware patch file is not found, use the | 
|  | * default firmware patch file instead | 
|  | */ | 
|  | snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq", | 
|  | ver->hw_platform, ver->hw_variant); | 
|  | if (request_firmware(&fw, fwname, &hdev->dev) < 0) { | 
|  | bt_dev_err(hdev, "failed to open default fw file: %s", | 
|  | fwname); | 
|  | return NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | bt_dev_info(hdev, "Intel Bluetooth firmware file: %s", fwname); | 
|  |  | 
|  | return fw; | 
|  | } | 
|  |  | 
|  | static int btintel_legacy_rom_patching(struct hci_dev *hdev, | 
|  | const struct firmware *fw, | 
|  | const u8 **fw_ptr, int *disable_patch) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | struct hci_command_hdr *cmd; | 
|  | const u8 *cmd_param; | 
|  | struct hci_event_hdr *evt = NULL; | 
|  | const u8 *evt_param = NULL; | 
|  | int remain = fw->size - (*fw_ptr - fw->data); | 
|  |  | 
|  | /* The first byte indicates the types of the patch command or event. | 
|  | * 0x01 means HCI command and 0x02 is HCI event. If the first bytes | 
|  | * in the current firmware buffer doesn't start with 0x01 or | 
|  | * the size of remain buffer is smaller than HCI command header, | 
|  | * the firmware file is corrupted and it should stop the patching | 
|  | * process. | 
|  | */ | 
|  | if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) { | 
|  | bt_dev_err(hdev, "Intel fw corrupted: invalid cmd read"); | 
|  | return -EINVAL; | 
|  | } | 
|  | (*fw_ptr)++; | 
|  | remain--; | 
|  |  | 
|  | cmd = (struct hci_command_hdr *)(*fw_ptr); | 
|  | *fw_ptr += sizeof(*cmd); | 
|  | remain -= sizeof(*cmd); | 
|  |  | 
|  | /* Ensure that the remain firmware data is long enough than the length | 
|  | * of command parameter. If not, the firmware file is corrupted. | 
|  | */ | 
|  | if (remain < cmd->plen) { | 
|  | bt_dev_err(hdev, "Intel fw corrupted: invalid cmd len"); | 
|  | return -EFAULT; | 
|  | } | 
|  |  | 
|  | /* If there is a command that loads a patch in the firmware | 
|  | * file, then enable the patch upon success, otherwise just | 
|  | * disable the manufacturer mode, for example patch activation | 
|  | * is not required when the default firmware patch file is used | 
|  | * because there are no patch data to load. | 
|  | */ | 
|  | if (*disable_patch && le16_to_cpu(cmd->opcode) == 0xfc8e) | 
|  | *disable_patch = 0; | 
|  |  | 
|  | cmd_param = *fw_ptr; | 
|  | *fw_ptr += cmd->plen; | 
|  | remain -= cmd->plen; | 
|  |  | 
|  | /* This reads the expected events when the above command is sent to the | 
|  | * device. Some vendor commands expects more than one events, for | 
|  | * example command status event followed by vendor specific event. | 
|  | * For this case, it only keeps the last expected event. so the command | 
|  | * can be sent with __hci_cmd_sync_ev() which returns the sk_buff of | 
|  | * last expected event. | 
|  | */ | 
|  | while (remain > HCI_EVENT_HDR_SIZE && *fw_ptr[0] == 0x02) { | 
|  | (*fw_ptr)++; | 
|  | remain--; | 
|  |  | 
|  | evt = (struct hci_event_hdr *)(*fw_ptr); | 
|  | *fw_ptr += sizeof(*evt); | 
|  | remain -= sizeof(*evt); | 
|  |  | 
|  | if (remain < evt->plen) { | 
|  | bt_dev_err(hdev, "Intel fw corrupted: invalid evt len"); | 
|  | return -EFAULT; | 
|  | } | 
|  |  | 
|  | evt_param = *fw_ptr; | 
|  | *fw_ptr += evt->plen; | 
|  | remain -= evt->plen; | 
|  | } | 
|  |  | 
|  | /* Every HCI commands in the firmware file has its correspond event. | 
|  | * If event is not found or remain is smaller than zero, the firmware | 
|  | * file is corrupted. | 
|  | */ | 
|  | if (!evt || !evt_param || remain < 0) { | 
|  | bt_dev_err(hdev, "Intel fw corrupted: invalid evt read"); | 
|  | return -EFAULT; | 
|  | } | 
|  |  | 
|  | skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen, | 
|  | cmd_param, evt->evt, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "sending Intel patch command (0x%4.4x) failed (%ld)", | 
|  | cmd->opcode, PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  |  | 
|  | /* It ensures that the returned event matches the event data read from | 
|  | * the firmware file. At fist, it checks the length and then | 
|  | * the contents of the event. | 
|  | */ | 
|  | if (skb->len != evt->plen) { | 
|  | bt_dev_err(hdev, "mismatch event length (opcode 0x%4.4x)", | 
|  | le16_to_cpu(cmd->opcode)); | 
|  | kfree_skb(skb); | 
|  | return -EFAULT; | 
|  | } | 
|  |  | 
|  | if (memcmp(skb->data, evt_param, evt->plen)) { | 
|  | bt_dev_err(hdev, "mismatch event parameter (opcode 0x%4.4x)", | 
|  | le16_to_cpu(cmd->opcode)); | 
|  | kfree_skb(skb); | 
|  | return -EFAULT; | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_legacy_rom_setup(struct hci_dev *hdev, | 
|  | struct intel_version *ver) | 
|  | { | 
|  | const struct firmware *fw; | 
|  | const u8 *fw_ptr; | 
|  | int disable_patch, err; | 
|  | struct intel_version new_ver; | 
|  |  | 
|  | BT_DBG("%s", hdev->name); | 
|  |  | 
|  | /* fw_patch_num indicates the version of patch the device currently | 
|  | * have. If there is no patch data in the device, it is always 0x00. | 
|  | * So, if it is other than 0x00, no need to patch the device again. | 
|  | */ | 
|  | if (ver->fw_patch_num) { | 
|  | bt_dev_info(hdev, | 
|  | "Intel device is already patched. patch num: %02x", | 
|  | ver->fw_patch_num); | 
|  | goto complete; | 
|  | } | 
|  |  | 
|  | /* Opens the firmware patch file based on the firmware version read | 
|  | * from the controller. If it fails to open the matching firmware | 
|  | * patch file, it tries to open the default firmware patch file. | 
|  | * If no patch file is found, allow the device to operate without | 
|  | * a patch. | 
|  | */ | 
|  | fw = btintel_legacy_rom_get_fw(hdev, ver); | 
|  | if (!fw) | 
|  | goto complete; | 
|  | fw_ptr = fw->data; | 
|  |  | 
|  | /* Enable the manufacturer mode of the controller. | 
|  | * Only while this mode is enabled, the driver can download the | 
|  | * firmware patch data and configuration parameters. | 
|  | */ | 
|  | err = btintel_enter_mfg(hdev); | 
|  | if (err) { | 
|  | release_firmware(fw); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | disable_patch = 1; | 
|  |  | 
|  | /* The firmware data file consists of list of Intel specific HCI | 
|  | * commands and its expected events. The first byte indicates the | 
|  | * type of the message, either HCI command or HCI event. | 
|  | * | 
|  | * It reads the command and its expected event from the firmware file, | 
|  | * and send to the controller. Once __hci_cmd_sync_ev() returns, | 
|  | * the returned event is compared with the event read from the firmware | 
|  | * file and it will continue until all the messages are downloaded to | 
|  | * the controller. | 
|  | * | 
|  | * Once the firmware patching is completed successfully, | 
|  | * the manufacturer mode is disabled with reset and activating the | 
|  | * downloaded patch. | 
|  | * | 
|  | * If the firmware patching fails, the manufacturer mode is | 
|  | * disabled with reset and deactivating the patch. | 
|  | * | 
|  | * If the default patch file is used, no reset is done when disabling | 
|  | * the manufacturer. | 
|  | */ | 
|  | while (fw->size > fw_ptr - fw->data) { | 
|  | int ret; | 
|  |  | 
|  | ret = btintel_legacy_rom_patching(hdev, fw, &fw_ptr, | 
|  | &disable_patch); | 
|  | if (ret < 0) | 
|  | goto exit_mfg_deactivate; | 
|  | } | 
|  |  | 
|  | release_firmware(fw); | 
|  |  | 
|  | if (disable_patch) | 
|  | goto exit_mfg_disable; | 
|  |  | 
|  | /* Patching completed successfully and disable the manufacturer mode | 
|  | * with reset and activate the downloaded firmware patches. | 
|  | */ | 
|  | err = btintel_exit_mfg(hdev, true, true); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | /* Need build number for downloaded fw patches in | 
|  | * every power-on boot | 
|  | */ | 
|  | err = btintel_read_version(hdev, &new_ver); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | bt_dev_info(hdev, "Intel BT fw patch 0x%02x completed & activated", | 
|  | new_ver.fw_patch_num); | 
|  |  | 
|  | goto complete; | 
|  |  | 
|  | exit_mfg_disable: | 
|  | /* Disable the manufacturer mode without reset */ | 
|  | err = btintel_exit_mfg(hdev, false, false); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | bt_dev_info(hdev, "Intel firmware patch completed"); | 
|  |  | 
|  | goto complete; | 
|  |  | 
|  | exit_mfg_deactivate: | 
|  | release_firmware(fw); | 
|  |  | 
|  | /* Patching failed. Disable the manufacturer mode with reset and | 
|  | * deactivate the downloaded firmware patches. | 
|  | */ | 
|  | err = btintel_exit_mfg(hdev, true, false); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | bt_dev_info(hdev, "Intel firmware patch completed and deactivated"); | 
|  |  | 
|  | complete: | 
|  | /* Set the event mask for Intel specific vendor events. This enables | 
|  | * a few extra events that are useful during general operation. | 
|  | */ | 
|  | btintel_set_event_mask_mfg(hdev, false); | 
|  |  | 
|  | btintel_check_bdaddr(hdev); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_download_wait(struct hci_dev *hdev, ktime_t calltime, int msec) | 
|  | { | 
|  | ktime_t delta, rettime; | 
|  | unsigned long long duration; | 
|  | int err; | 
|  |  | 
|  | btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); | 
|  |  | 
|  | bt_dev_info(hdev, "Waiting for firmware download to complete"); | 
|  |  | 
|  | err = btintel_wait_on_flag_timeout(hdev, INTEL_DOWNLOADING, | 
|  | TASK_INTERRUPTIBLE, | 
|  | msecs_to_jiffies(msec)); | 
|  | if (err == -EINTR) { | 
|  | bt_dev_err(hdev, "Firmware loading interrupted"); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | if (err) { | 
|  | bt_dev_err(hdev, "Firmware loading timeout"); | 
|  | return -ETIMEDOUT; | 
|  | } | 
|  |  | 
|  | if (btintel_test_flag(hdev, INTEL_FIRMWARE_FAILED)) { | 
|  | bt_dev_err(hdev, "Firmware loading failed"); | 
|  | return -ENOEXEC; | 
|  | } | 
|  |  | 
|  | 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); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec) | 
|  | { | 
|  | ktime_t delta, rettime; | 
|  | unsigned long long duration; | 
|  | int err; | 
|  |  | 
|  | bt_dev_info(hdev, "Waiting for device to boot"); | 
|  |  | 
|  | err = btintel_wait_on_flag_timeout(hdev, INTEL_BOOTING, | 
|  | TASK_INTERRUPTIBLE, | 
|  | msecs_to_jiffies(msec)); | 
|  | if (err == -EINTR) { | 
|  | bt_dev_err(hdev, "Device boot interrupted"); | 
|  | return -EINTR; | 
|  | } | 
|  |  | 
|  | if (err) { | 
|  | bt_dev_err(hdev, "Device boot timeout"); | 
|  | return -ETIMEDOUT; | 
|  | } | 
|  |  | 
|  | rettime = ktime_get(); | 
|  | delta = ktime_sub(rettime, calltime); | 
|  | duration = (unsigned long long) ktime_to_ns(delta) >> 10; | 
|  |  | 
|  | bt_dev_info(hdev, "Device booted in %llu usecs", duration); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_boot(struct hci_dev *hdev, u32 boot_addr) | 
|  | { | 
|  | ktime_t calltime; | 
|  | int err; | 
|  |  | 
|  | calltime = ktime_get(); | 
|  |  | 
|  | btintel_set_flag(hdev, INTEL_BOOTING); | 
|  |  | 
|  | err = btintel_send_intel_reset(hdev, boot_addr); | 
|  | 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. | 
|  | * | 
|  | * Booting into operational firmware should not take longer than | 
|  | * 1 second. However if that happens, then just fail the setup | 
|  | * since something went wrong. | 
|  | */ | 
|  | err = btintel_boot_wait(hdev, calltime, 1000); | 
|  | if (err == -ETIMEDOUT) | 
|  | btintel_reset_to_bootloader(hdev); | 
|  |  | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static int btintel_get_fw_name(struct intel_version *ver, | 
|  | struct intel_boot_params *params, | 
|  | char *fw_name, size_t len, | 
|  | const char *suffix) | 
|  | { | 
|  | switch (ver->hw_variant) { | 
|  | case 0x0b:	/* SfP */ | 
|  | case 0x0c:	/* WsP */ | 
|  | snprintf(fw_name, len, "intel/ibt-%u-%u.%s", | 
|  | le16_to_cpu(ver->hw_variant), | 
|  | le16_to_cpu(params->dev_revid), | 
|  | suffix); | 
|  | break; | 
|  | case 0x11:	/* JfP */ | 
|  | case 0x12:	/* ThP */ | 
|  | case 0x13:	/* HrP */ | 
|  | case 0x14:	/* CcP */ | 
|  | snprintf(fw_name, len, "intel/ibt-%u-%u-%u.%s", | 
|  | le16_to_cpu(ver->hw_variant), | 
|  | le16_to_cpu(ver->hw_revision), | 
|  | le16_to_cpu(ver->fw_revision), | 
|  | suffix); | 
|  | break; | 
|  | default: | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int btintel_download_fw(struct hci_dev *hdev, | 
|  | struct intel_version *ver, | 
|  | struct intel_boot_params *params, | 
|  | u32 *boot_param) | 
|  | { | 
|  | const struct firmware *fw; | 
|  | char fwname[64]; | 
|  | int err; | 
|  | ktime_t calltime; | 
|  |  | 
|  | if (!ver || !params) | 
|  | return -EINVAL; | 
|  |  | 
|  | /* 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 | 
|  | * 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->fw_variant == 0x23) { | 
|  | btintel_clear_flag(hdev, INTEL_BOOTLOADER); | 
|  | btintel_check_bdaddr(hdev); | 
|  |  | 
|  | /* SfP and WsP don't seem to update the firmware version on file | 
|  | * so version checking is currently possible. | 
|  | */ | 
|  | switch (ver->hw_variant) { | 
|  | case 0x0b:	/* SfP */ | 
|  | case 0x0c:	/* WsP */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Proceed to download to check if the version matches */ | 
|  | goto download; | 
|  | } | 
|  |  | 
|  | /* Read the secure boot parameters to identify the operating | 
|  | * details of the bootloader. | 
|  | */ | 
|  | err = btintel_read_boot_params(hdev, params); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | /* 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 (params->limited_cce != 0x00) { | 
|  | bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)", | 
|  | 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)) { | 
|  | bt_dev_info(hdev, "No device address configured"); | 
|  | set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); | 
|  | } | 
|  |  | 
|  | download: | 
|  | /* With this Intel bootloader only the hardware variant and device | 
|  | * revision information are used to select the right firmware for SfP | 
|  | * and WsP. | 
|  | * | 
|  | * The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi. | 
|  | * | 
|  | * Currently the supported hardware variants are: | 
|  | *   11 (0x0b) for iBT3.0 (LnP/SfP) | 
|  | *   12 (0x0c) for iBT3.5 (WsP) | 
|  | * | 
|  | * For ThP/JfP and for future SKU's, the FW name varies based on HW | 
|  | * variant, HW revision and FW revision, as these are dependent on CNVi | 
|  | * and RF Combination. | 
|  | * | 
|  | *   17 (0x11) for iBT3.5 (JfP) | 
|  | *   18 (0x12) for iBT3.5 (ThP) | 
|  | * | 
|  | * The firmware file name for these will be | 
|  | * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi. | 
|  | * | 
|  | */ | 
|  | err = btintel_get_fw_name(ver, params, fwname, sizeof(fwname), "sfi"); | 
|  | if (err < 0) { | 
|  | if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) { | 
|  | /* Firmware has already been loaded */ | 
|  | btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | bt_dev_err(hdev, "Unsupported Intel firmware naming"); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | err = firmware_request_nowarn(&fw, fwname, &hdev->dev); | 
|  | if (err < 0) { | 
|  | if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) { | 
|  | /* Firmware has already been loaded */ | 
|  | btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", | 
|  | fwname, 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; | 
|  | } | 
|  |  | 
|  | calltime = ktime_get(); | 
|  |  | 
|  | btintel_set_flag(hdev, INTEL_DOWNLOADING); | 
|  |  | 
|  | /* Start firmware downloading and get boot parameter */ | 
|  | err = btintel_download_firmware(hdev, ver, fw, boot_param); | 
|  | if (err < 0) { | 
|  | if (err == -EALREADY) { | 
|  | /* Firmware has already been loaded */ | 
|  | btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); | 
|  | err = 0; | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | /* When FW download fails, send Intel Reset to retry | 
|  | * FW download. | 
|  | */ | 
|  | btintel_reset_to_bootloader(hdev); | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | /* 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 | 
|  | * INTEL_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 = btintel_download_wait(hdev, calltime, 5000); | 
|  | if (err == -ETIMEDOUT) | 
|  | btintel_reset_to_bootloader(hdev); | 
|  |  | 
|  | done: | 
|  | release_firmware(fw); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static int btintel_bootloader_setup(struct hci_dev *hdev, | 
|  | struct intel_version *ver) | 
|  | { | 
|  | struct intel_version new_ver; | 
|  | struct intel_boot_params params; | 
|  | u32 boot_param; | 
|  | char ddcname[64]; | 
|  | 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; | 
|  |  | 
|  | btintel_set_flag(hdev, INTEL_BOOTLOADER); | 
|  |  | 
|  | err = btintel_download_fw(hdev, ver, ¶ms, &boot_param); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | /* controller is already having an operational firmware */ | 
|  | if (ver->fw_variant == 0x23) | 
|  | goto finish; | 
|  |  | 
|  | err = btintel_boot(hdev, boot_param); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | btintel_clear_flag(hdev, INTEL_BOOTLOADER); | 
|  |  | 
|  | err = btintel_get_fw_name(ver, ¶ms, ddcname, | 
|  | sizeof(ddcname), "ddc"); | 
|  |  | 
|  | if (err < 0) { | 
|  | 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. | 
|  | */ | 
|  | err = btintel_read_debug_features(hdev, &features); | 
|  | if (!err) { | 
|  | /* Set DDC mask for available debug features */ | 
|  | btintel_set_debug_features(hdev, &features); | 
|  | } | 
|  |  | 
|  | /* Read the Intel version information after loading the FW  */ | 
|  | err = btintel_read_version(hdev, &new_ver); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | btintel_version_info(hdev, &new_ver); | 
|  |  | 
|  | finish: | 
|  | /* Set the event mask for Intel specific vendor events. This enables | 
|  | * a few extra events that are useful during general operation. It | 
|  | * does not enable any debugging related events. | 
|  | * | 
|  | * The device will function correctly without these events enabled | 
|  | * and thus no need to fail the setup. | 
|  | */ | 
|  | btintel_set_event_mask(hdev, false); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void btintel_get_fw_name_tlv(const struct intel_version_tlv *ver, | 
|  | char *fw_name, size_t len, | 
|  | const char *suffix) | 
|  | { | 
|  | /* The firmware file name for new generation controllers will be | 
|  | * ibt-<cnvi_top type+cnvi_top step>-<cnvr_top type+cnvr_top step> | 
|  | */ | 
|  | snprintf(fw_name, len, "intel/ibt-%04x-%04x.%s", | 
|  | INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvi_top), | 
|  | INTEL_CNVX_TOP_STEP(ver->cnvi_top)), | 
|  | INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvr_top), | 
|  | INTEL_CNVX_TOP_STEP(ver->cnvr_top)), | 
|  | suffix); | 
|  | } | 
|  |  | 
|  | static int btintel_prepare_fw_download_tlv(struct hci_dev *hdev, | 
|  | struct intel_version_tlv *ver, | 
|  | u32 *boot_param) | 
|  | { | 
|  | const struct firmware *fw; | 
|  | char fwname[64]; | 
|  | int err; | 
|  | ktime_t calltime; | 
|  |  | 
|  | if (!ver || !boot_param) | 
|  | 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) { | 
|  | btintel_clear_flag(hdev, INTEL_BOOTLOADER); | 
|  | btintel_check_bdaddr(hdev); | 
|  | } | 
|  |  | 
|  | /* 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); | 
|  | } | 
|  |  | 
|  | btintel_get_fw_name_tlv(ver, fwname, sizeof(fwname), "sfi"); | 
|  | err = firmware_request_nowarn(&fw, fwname, &hdev->dev); | 
|  | if (err < 0) { | 
|  | if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) { | 
|  | /* Firmware has already been loaded */ | 
|  | btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", | 
|  | fwname, 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; | 
|  | } | 
|  |  | 
|  | calltime = ktime_get(); | 
|  |  | 
|  | btintel_set_flag(hdev, INTEL_DOWNLOADING); | 
|  |  | 
|  | /* Start firmware downloading and get boot parameter */ | 
|  | err = btintel_download_fw_tlv(hdev, ver, fw, boot_param, | 
|  | INTEL_HW_VARIANT(ver->cnvi_bt), | 
|  | ver->sbe_type); | 
|  | if (err < 0) { | 
|  | if (err == -EALREADY) { | 
|  | /* Firmware has already been loaded */ | 
|  | btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); | 
|  | err = 0; | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | /* When FW download fails, send Intel Reset to retry | 
|  | * FW download. | 
|  | */ | 
|  | btintel_reset_to_bootloader(hdev); | 
|  | goto done; | 
|  | } | 
|  |  | 
|  | /* 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 = btintel_download_wait(hdev, calltime, 5000); | 
|  | if (err == -ETIMEDOUT) | 
|  | btintel_reset_to_bootloader(hdev); | 
|  |  | 
|  | done: | 
|  | release_firmware(fw); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, | 
|  | struct intel_version_tlv *ver) | 
|  | { | 
|  | u32 boot_param; | 
|  | char ddcname[64]; | 
|  | int err; | 
|  | struct intel_debug_features features; | 
|  | struct intel_version_tlv new_ver; | 
|  |  | 
|  | bt_dev_dbg(hdev, ""); | 
|  |  | 
|  | /* 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; | 
|  |  | 
|  | btintel_set_flag(hdev, INTEL_BOOTLOADER); | 
|  |  | 
|  | err = btintel_prepare_fw_download_tlv(hdev, ver, &boot_param); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | /* check if controller is already having an operational firmware */ | 
|  | if (ver->img_type == 0x03) | 
|  | goto finish; | 
|  |  | 
|  | err = btintel_boot(hdev, boot_param); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | btintel_clear_flag(hdev, INTEL_BOOTLOADER); | 
|  |  | 
|  | btintel_get_fw_name_tlv(ver, ddcname, sizeof(ddcname), "ddc"); | 
|  | /* 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. | 
|  | */ | 
|  | err = btintel_read_debug_features(hdev, &features); | 
|  | if (!err) { | 
|  | /* Set DDC mask for available debug features */ | 
|  | btintel_set_debug_features(hdev, &features); | 
|  | } | 
|  |  | 
|  | /* Read the Intel version information after loading the FW  */ | 
|  | err = btintel_read_version_tlv(hdev, &new_ver); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | btintel_version_info_tlv(hdev, &new_ver); | 
|  |  | 
|  | finish: | 
|  | /* Set the event mask for Intel specific vendor events. This enables | 
|  | * a few extra events that are useful during general operation. It | 
|  | * does not enable any debugging related events. | 
|  | * | 
|  | * The device will function correctly without these events enabled | 
|  | * and thus no need to fail the setup. | 
|  | */ | 
|  | btintel_set_event_mask(hdev, false); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant) | 
|  | { | 
|  | switch (hw_variant) { | 
|  | /* Legacy bootloader devices that supports MSFT Extension */ | 
|  | case 0x11:	/* JfP */ | 
|  | case 0x12:	/* ThP */ | 
|  | case 0x13:	/* HrP */ | 
|  | case 0x14:	/* CcP */ | 
|  | /* All Intel new genration controllers support the Microsoft vendor | 
|  | * extension are using 0xFC1E for VsMsftOpCode. | 
|  | */ | 
|  | case 0x17: | 
|  | case 0x18: | 
|  | case 0x19: | 
|  | hci_set_msft_opcode(hdev, 0xFC1E); | 
|  | break; | 
|  | default: | 
|  | /* Not supported */ | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | static int btintel_setup_combined(struct hci_dev *hdev) | 
|  | { | 
|  | const u8 param[1] = { 0xFF }; | 
|  | struct intel_version ver; | 
|  | struct intel_version_tlv ver_tlv; | 
|  | struct sk_buff *skb; | 
|  | int err; | 
|  |  | 
|  | BT_DBG("%s", hdev->name); | 
|  |  | 
|  | /* The some controllers have a bug with the first HCI command sent to it | 
|  | * returning number of completed commands as zero. This would stall the | 
|  | * command processing in the Bluetooth core. | 
|  | * | 
|  | * As a workaround, send HCI Reset command first which will reset the | 
|  | * number of completed commands and allow normal command processing | 
|  | * from now on. | 
|  | * | 
|  | * Regarding the INTEL_BROKEN_SHUTDOWN_LED flag, these devices maybe | 
|  | * in the SW_RFKILL ON state as a workaround of fixing LED issue during | 
|  | * the shutdown() procedure, and once the device is in SW_RFKILL ON | 
|  | * state, the only way to exit out of it is sending the HCI_Reset | 
|  | * command. | 
|  | */ | 
|  | if (btintel_test_flag(hdev, INTEL_BROKEN_INITIAL_NCMD) || | 
|  | btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { | 
|  | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, | 
|  | HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, | 
|  | "sending initial HCI reset failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  | kfree_skb(skb); | 
|  | } | 
|  |  | 
|  | /* Starting from TyP device, the command parameter and response are | 
|  | * changed even though the OCF for HCI_Intel_Read_Version command | 
|  | * remains same. The legacy devices can handle even if the | 
|  | * command has a parameter and returns a correct version information. | 
|  | * So, it uses new format to support both legacy and new format. | 
|  | */ | 
|  | skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "Reading Intel version command failed (%ld)", | 
|  | PTR_ERR(skb)); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  |  | 
|  | /* Check the status */ | 
|  | if (skb->data[0]) { | 
|  | bt_dev_err(hdev, "Intel Read Version command failed (%02x)", | 
|  | skb->data[0]); | 
|  | err = -EIO; | 
|  | goto exit_error; | 
|  | } | 
|  |  | 
|  | /* Apply the common HCI quirks for Intel device */ | 
|  | set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); | 
|  | set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); | 
|  | set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); | 
|  |  | 
|  | /* For Legacy device, check the HW platform value and size */ | 
|  | if (skb->len == sizeof(ver) && skb->data[1] == 0x37) { | 
|  | bt_dev_dbg(hdev, "Read the legacy Intel version information"); | 
|  |  | 
|  | memcpy(&ver, skb->data, sizeof(ver)); | 
|  |  | 
|  | /* Display version information */ | 
|  | btintel_version_info(hdev, &ver); | 
|  |  | 
|  | /* 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 (ver.hw_variant) { | 
|  | case 0x07:	/* WP */ | 
|  | case 0x08:	/* StP */ | 
|  | /* Legacy ROM product */ | 
|  | btintel_set_flag(hdev, INTEL_ROM_LEGACY); | 
|  |  | 
|  | /* Apply the device specific HCI quirks | 
|  | * | 
|  | * WBS for SdP - For the Legacy ROM products, only SdP | 
|  | * supports the WBS. But the version information is not | 
|  | * enough to use here because the StP2 and SdP have same | 
|  | * hw_variant and fw_variant. So, this flag is set by | 
|  | * the transport driver (btusb) based on the HW info | 
|  | * (idProduct) | 
|  | */ | 
|  | if (!btintel_test_flag(hdev, | 
|  | INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) | 
|  | set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, | 
|  | &hdev->quirks); | 
|  |  | 
|  | err = btintel_legacy_rom_setup(hdev, &ver); | 
|  | break; | 
|  | case 0x0b:      /* SfP */ | 
|  | case 0x0c:      /* WsP */ | 
|  | case 0x11:      /* JfP */ | 
|  | case 0x12:      /* ThP */ | 
|  | case 0x13:      /* HrP */ | 
|  | case 0x14:      /* CcP */ | 
|  | /* Apply the device specific HCI quirks | 
|  | * | 
|  | * All Legacy bootloader devices support WBS | 
|  | */ | 
|  | set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, | 
|  | &hdev->quirks); | 
|  |  | 
|  | /* Valid LE States quirk for JfP/ThP familiy */ | 
|  | if (ver.hw_variant == 0x11 || ver.hw_variant == 0x12) | 
|  | set_bit(HCI_QUIRK_VALID_LE_STATES, | 
|  | &hdev->quirks); | 
|  |  | 
|  | /* Setup MSFT Extension support */ | 
|  | btintel_set_msft_opcode(hdev, ver.hw_variant); | 
|  |  | 
|  | err = btintel_bootloader_setup(hdev, &ver); | 
|  | break; | 
|  | default: | 
|  | bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", | 
|  | ver.hw_variant); | 
|  | err = -EINVAL; | 
|  | } | 
|  |  | 
|  | goto exit_error; | 
|  | } | 
|  |  | 
|  | /* For TLV type device, parse the tlv data */ | 
|  | err = btintel_parse_version_tlv(hdev, &ver_tlv, skb); | 
|  | if (err) { | 
|  | bt_dev_err(hdev, "Failed to parse TLV version information"); | 
|  | goto exit_error; | 
|  | } | 
|  |  | 
|  | if (INTEL_HW_PLATFORM(ver_tlv.cnvi_bt) != 0x37) { | 
|  | bt_dev_err(hdev, "Unsupported Intel hardware platform (0x%2x)", | 
|  | INTEL_HW_PLATFORM(ver_tlv.cnvi_bt)); | 
|  | err = -EINVAL; | 
|  | goto exit_error; | 
|  | } | 
|  |  | 
|  | /* 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_tlv.cnvi_bt)) { | 
|  | case 0x11:      /* JfP */ | 
|  | case 0x12:      /* ThP */ | 
|  | case 0x13:      /* HrP */ | 
|  | case 0x14:      /* CcP */ | 
|  | /* Some legacy bootloader devices starting from JfP, | 
|  | * the operational firmware supports both old and TLV based | 
|  | * HCI_Intel_Read_Version command based on the command | 
|  | * parameter. | 
|  | * | 
|  | * For upgrading firmware case, the TLV based version cannot | 
|  | * be used because the firmware filename for legacy bootloader | 
|  | * is based on the old format. | 
|  | * | 
|  | * Also, it is not easy to convert TLV based version from the | 
|  | * legacy version format. | 
|  | * | 
|  | * So, as a workaround for those devices, use the legacy | 
|  | * HCI_Intel_Read_Version to get the version information and | 
|  | * run the legacy bootloader setup. | 
|  | */ | 
|  | err = btintel_read_version(hdev, &ver); | 
|  | if (err) | 
|  | return err; | 
|  |  | 
|  | /* Apply the device specific HCI quirks | 
|  | * | 
|  | * All Legacy bootloader devices support WBS | 
|  | */ | 
|  | set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); | 
|  |  | 
|  | /* Valid LE States quirk for JfP/ThP familiy */ | 
|  | if (ver.hw_variant == 0x11 || ver.hw_variant == 0x12) | 
|  | set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); | 
|  |  | 
|  | /* Setup MSFT Extension support */ | 
|  | btintel_set_msft_opcode(hdev, ver.hw_variant); | 
|  |  | 
|  | err = btintel_bootloader_setup(hdev, &ver); | 
|  | break; | 
|  | case 0x17: | 
|  | case 0x18: | 
|  | case 0x19: | 
|  | /* Display version information of TLV type */ | 
|  | btintel_version_info_tlv(hdev, &ver_tlv); | 
|  |  | 
|  | /* Apply the device specific HCI quirks for TLV based devices | 
|  | * | 
|  | * All TLV based devices support WBS | 
|  | */ | 
|  | set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); | 
|  |  | 
|  | /* Valid LE States quirk for GfP */ | 
|  | if (INTEL_HW_VARIANT(ver_tlv.cnvi_bt) == 0x18) | 
|  | set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); | 
|  |  | 
|  | /* Setup MSFT Extension support */ | 
|  | btintel_set_msft_opcode(hdev, | 
|  | INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); | 
|  |  | 
|  | err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); | 
|  | break; | 
|  | default: | 
|  | bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", | 
|  | INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | exit_error: | 
|  | kfree_skb(skb); | 
|  |  | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static int btintel_shutdown_combined(struct hci_dev *hdev) | 
|  | { | 
|  | struct sk_buff *skb; | 
|  | int ret; | 
|  |  | 
|  | /* Send HCI Reset to the controller to stop any BT activity which | 
|  | * were triggered. This will help to save power and maintain the | 
|  | * sync b/w Host and controller | 
|  | */ | 
|  | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | bt_dev_err(hdev, "HCI reset during shutdown failed"); | 
|  | return PTR_ERR(skb); | 
|  | } | 
|  | kfree_skb(skb); | 
|  |  | 
|  |  | 
|  | /* Some platforms have an issue with BT LED when the interface is | 
|  | * down or BT radio is turned off, which takes 5 seconds to BT LED | 
|  | * goes off. As a workaround, sends HCI_Intel_SW_RFKILL to put the | 
|  | * device in the RFKILL ON state which turns off the BT LED immediately. | 
|  | */ | 
|  | if (btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { | 
|  | skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT); | 
|  | if (IS_ERR(skb)) { | 
|  | ret = PTR_ERR(skb); | 
|  | bt_dev_err(hdev, "turning off Intel device LED failed"); | 
|  | return ret; | 
|  | } | 
|  | kfree_skb(skb); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int btintel_configure_setup(struct hci_dev *hdev) | 
|  | { | 
|  | hdev->manufacturer = 2; | 
|  | hdev->setup = btintel_setup_combined; | 
|  | hdev->shutdown = btintel_shutdown_combined; | 
|  | hdev->hw_error = btintel_hw_error; | 
|  | hdev->set_diag = btintel_set_diag_combined; | 
|  | hdev->set_bdaddr = btintel_set_bdaddr; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_configure_setup); | 
|  |  | 
|  | void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len) | 
|  | { | 
|  | const struct intel_bootup *evt = ptr; | 
|  |  | 
|  | if (len != sizeof(*evt)) | 
|  | return; | 
|  |  | 
|  | if (btintel_test_and_clear_flag(hdev, INTEL_BOOTING)) | 
|  | btintel_wake_up_flag(hdev, INTEL_BOOTING); | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_bootup); | 
|  |  | 
|  | void btintel_secure_send_result(struct hci_dev *hdev, | 
|  | const void *ptr, unsigned int len) | 
|  | { | 
|  | const struct intel_secure_send_result *evt = ptr; | 
|  |  | 
|  | if (len != sizeof(*evt)) | 
|  | return; | 
|  |  | 
|  | if (evt->result) | 
|  | btintel_set_flag(hdev, INTEL_FIRMWARE_FAILED); | 
|  |  | 
|  | if (btintel_test_and_clear_flag(hdev, INTEL_DOWNLOADING) && | 
|  | btintel_test_flag(hdev, INTEL_FIRMWARE_LOADED)) | 
|  | btintel_wake_up_flag(hdev, INTEL_DOWNLOADING); | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(btintel_secure_send_result); | 
|  |  | 
|  | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | 
|  | MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); | 
|  | MODULE_VERSION(VERSION); | 
|  | MODULE_LICENSE("GPL"); | 
|  | MODULE_FIRMWARE("intel/ibt-11-5.sfi"); | 
|  | MODULE_FIRMWARE("intel/ibt-11-5.ddc"); | 
|  | MODULE_FIRMWARE("intel/ibt-12-16.sfi"); | 
|  | MODULE_FIRMWARE("intel/ibt-12-16.ddc"); |