From d38e165c46d630c3ac148a63f006602fe60cc76b Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Tue, 25 Jul 2017 13:57:42 +0800 Subject: [PATCH] Bluetooth: btintel: Create common Intel Version Read function BugLink: http://bugs.launchpad.net/bugs/1705633 The Intel Version Read command is used to retrieve information about hardware and firmware version/revision of Intel Bluetooth controllers. This is an Intel generic command used in USB and UART drivers. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann (backported from commit 6c483de1b3c41e939b735df1861759815e125304) Signed-off-by: AceLan Kao Acked-by: Stefan Bader Acked-by: Aaron Ma Signed-off-by: Kleber Sacilotto de Souza --- drivers/bluetooth/btintel.c | 25 +++++++++++ drivers/bluetooth/btintel.h | 7 +++ drivers/bluetooth/btusb.c | 82 ++++++++++------------------------- drivers/bluetooth/hci_intel.c | 46 +++++--------------- 4 files changed, 67 insertions(+), 93 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 1f13e617bf56..82932eb6a441 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -343,6 +343,31 @@ 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) +{ + 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); + /* ------- REGMAP IBT SUPPORT ------- */ #define IBT_REG_MODE_8BIT 0x00 diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 07e58e05a7fa..8de77ed862f9 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -83,6 +83,7 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, 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); struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, u16 opcode_write); @@ -140,6 +141,12 @@ static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) return -EOPNOTSUPP; } +static inline int btintel_read_version(struct hci_dev *hdev, + struct intel_version *ver) +{ + return -EOPNOTSUPP; +} + static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, u16 opcode_write) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d4c38a86d5be..88eac50da0a3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1659,8 +1659,8 @@ static int btusb_setup_intel(struct hci_dev *hdev) struct sk_buff *skb; const struct firmware *fw; const u8 *fw_ptr; - int disable_patch; - struct intel_version *ver; + int disable_patch, err; + struct intel_version ver; const u8 mfg_enable[] = { 0x01, 0x00 }; const u8 mfg_disable[] = { 0x00, 0x00 }; @@ -1691,35 +1691,22 @@ static int btusb_setup_intel(struct hci_dev *hdev) * The returned information are hardware variant and revision plus * firmware variant, revision and build number. */ - skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - BT_ERR("%s reading Intel fw version command failed (%ld)", - hdev->name, PTR_ERR(skb)); - return PTR_ERR(skb); - } - - if (skb->len != sizeof(*ver)) { - BT_ERR("%s Intel version event length mismatch", hdev->name); - kfree_skb(skb); - return -EIO; - } - - ver = (struct intel_version *)skb->data; + err = btintel_read_version(hdev, &ver); + if (err) + return err; BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x", - hdev->name, 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, - ver->fw_patch_num); + hdev->name, 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, ver.fw_patch_num); /* 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) { + if (ver.fw_patch_num) { BT_INFO("%s: Intel device is already patched. patch num: %02x", - hdev->name, ver->fw_patch_num); - kfree_skb(skb); + hdev->name, ver.fw_patch_num); goto complete; } @@ -1729,15 +1716,11 @@ static int btusb_setup_intel(struct hci_dev *hdev) * If no patch file is found, allow the device to operate without * a patch. */ - fw = btusb_setup_intel_get_fw(hdev, ver); - if (!fw) { - kfree_skb(skb); + fw = btusb_setup_intel_get_fw(hdev, &ver); + if (!fw) goto complete; - } fw_ptr = fw->data; - kfree_skb(skb); - /* This Intel specific command enables the manufacturer mode of the * controller. * @@ -2022,7 +2005,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) 0x00, 0x08, 0x04, 0x00 }; struct btusb_data *data = hci_get_drvdata(hdev); struct sk_buff *skb; - struct intel_version *ver; + struct intel_version ver; struct intel_boot_params *params; const struct firmware *fw; const u8 *fw_ptr; @@ -2040,28 +2023,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * is in bootloader mode or if it already has operational firmware * loaded. */ - skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - BT_ERR("%s: Reading Intel version information failed (%ld)", - hdev->name, PTR_ERR(skb)); - return PTR_ERR(skb); - } - - if (skb->len != sizeof(*ver)) { - BT_ERR("%s: Intel version event size mismatch", hdev->name); - kfree_skb(skb); - return -EILSEQ; - } - - ver = (struct intel_version *)skb->data; + err = btintel_read_version(hdev, &ver); + if (err) + return err; /* The hardware platform number has a fixed value of 0x37 and * for now only accept this single value. */ - if (ver->hw_platform != 0x37) { + if (ver.hw_platform != 0x37) { BT_ERR("%s: Unsupported Intel hardware platform (%u)", - hdev->name, ver->hw_platform); - kfree_skb(skb); + hdev->name, ver.hw_platform); return -EINVAL; } @@ -2071,14 +2042,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * This check has been put in place to ensure correct forward * compatibility options when newer hardware variants come along. */ - if (ver->hw_variant != 0x0b && ver->hw_variant != 0x0c) { + if (ver.hw_variant != 0x0b && ver.hw_variant != 0x0c) { BT_ERR("%s: Unsupported Intel hardware variant (%u)", - hdev->name, ver->hw_variant); - kfree_skb(skb); + hdev->name, ver.hw_variant); return -EINVAL; } - btintel_version_info(hdev, ver); + 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 @@ -2093,8 +2063,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * 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) { - kfree_skb(skb); + if (ver.fw_variant == 0x23) { clear_bit(BTUSB_BOOTLOADER, &data->flags); btintel_check_bdaddr(hdev); return 0; @@ -2103,15 +2072,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) /* If the device is not in bootloader mode, then the only possible * choice is to return an error and abort the device initialization. */ - if (ver->fw_variant != 0x06) { + if (ver.fw_variant != 0x06) { BT_ERR("%s: Unsupported Intel firmware variant (%u)", - hdev->name, ver->fw_variant); - kfree_skb(skb); + hdev->name, ver.fw_variant); return -ENODEV; } - kfree_skb(skb); - /* Read the secure boot parameters to identify the operating * details of the bootloader. */ diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 0c63fce0c1e0..863cdbc79c7c 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -548,7 +548,7 @@ static int intel_setup(struct hci_uart *hu) struct intel_device *idev = NULL; struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; - struct intel_version *ver; + struct intel_version ver; struct intel_boot_params *params; struct list_head *p; const struct firmware *fw; @@ -596,35 +596,16 @@ static int intel_setup(struct hci_uart *hu) * is in bootloader mode or if it already has operational firmware * loaded. */ - skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_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; - } - - ver = (struct intel_version *)skb->data; - if (ver->status) { - bt_dev_err(hdev, "Intel version command failure (%02x)", - ver->status); - err = -bt_to_errno(ver->status); - kfree_skb(skb); + err = btintel_read_version(hdev, &ver); + if (err) return err; - } /* The hardware platform number has a fixed value of 0x37 and * for now only accept this single value. */ - if (ver->hw_platform != 0x37) { + if (ver.hw_platform != 0x37) { bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)", - ver->hw_platform); - kfree_skb(skb); + ver.hw_platform); return -EINVAL; } @@ -633,14 +614,13 @@ static int intel_setup(struct hci_uart *hu) * put in place to ensure correct forward compatibility options * when newer hardware variants come along. */ - if (ver->hw_variant != 0x0b) { + if (ver.hw_variant != 0x0b) { bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", - ver->hw_variant); - kfree_skb(skb); + ver.hw_variant); return -EINVAL; } - btintel_version_info(hdev, ver); + 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 @@ -655,8 +635,7 @@ static int intel_setup(struct hci_uart *hu) * 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) { - kfree_skb(skb); + if (ver.fw_variant == 0x23) { clear_bit(STATE_BOOTLOADER, &intel->flags); btintel_check_bdaddr(hdev); return 0; @@ -665,15 +644,12 @@ static int intel_setup(struct hci_uart *hu) /* If the device is not in bootloader mode, then the only possible * choice is to return an error and abort the device initialization. */ - if (ver->fw_variant != 0x06) { + if (ver.fw_variant != 0x06) { bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)", - ver->fw_variant); - kfree_skb(skb); + ver.fw_variant); return -ENODEV; } - kfree_skb(skb); - /* Read the secure boot parameters to identify the operating * details of the bootloader. */ -- 2.39.5