diff options
Diffstat (limited to 'drivers/bluetooth')
34 files changed, 2297 insertions, 538 deletions
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index cab93935cc7f..8df310983bf6 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -365,9 +365,8 @@ static void bfusb_rx_complete(struct urb *urb) buf += 3; } - if (count < len) { + if (count < len) bt_dev_err(data->hdev, "block extends over URB buffer ranges"); - } if ((hdr & 0xe1) == 0xc1) bfusb_recv_block(data, hdr, buf, len); @@ -671,7 +670,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i hdev->flush = bfusb_flush; hdev->send = bfusb_send_frame; - set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_COMMANDS); if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 36eabf61717f..1e3a56e9b139 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -158,7 +158,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev); static void bluecard_activity_led_timeout(struct timer_list *t) { - struct bluecard_info *info = from_timer(info, t, timer); + struct bluecard_info *info = timer_container_of(info, t, timer); unsigned int iobase = info->p_dev->resource[0]->start; if (test_bit(CARD_ACTIVITY, &(info->hw_state))) { @@ -638,7 +638,7 @@ static int bluecard_hci_close(struct hci_dev *hdev) bluecard_hci_flush(hdev); /* Stop LED timer */ - del_timer_sync(&(info->timer)); + timer_delete_sync(&(info->timer)); /* Disable power LED */ outb(0x00, iobase + 0x30); @@ -885,7 +885,7 @@ static void bluecard_release(struct pcmcia_device *link) bluecard_close(info); - del_timer_sync(&(info->timer)); + timer_delete_sync(&(info->timer)); pcmcia_disable_device(link); } diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 1fa58c059cbf..8b43dfc755de 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -398,7 +398,7 @@ static int bpa10x_probe(struct usb_interface *intf, hdev->send = bpa10x_send_frame; hdev->set_diag = bpa10x_set_diag; - set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); err = hci_register_dev(hdev); if (err < 0) { diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 0a60660fc8ce..3a3a56ddbb06 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -135,7 +135,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) if (btbcm_set_bdaddr_from_efi(hdev) != 0) { bt_dev_info(hdev, "BCM: Using default device address (%pMR)", &bda->bdaddr); - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); } } @@ -467,7 +467,7 @@ static int btbcm_print_controller_features(struct hci_dev *hdev) /* Read DMI and disable broken Read LE Min/Max Tx Power */ if (dmi_first_match(disable_broken_read_transmit_power)) - set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER); return 0; } @@ -706,7 +706,7 @@ int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_m btbcm_check_bdaddr(hdev); - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); return 0; } @@ -769,7 +769,7 @@ int btbcm_setup_apple(struct hci_dev *hdev) kfree_skb(skb); } - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); return 0; } diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index d496cf2c3411..6aceecf5a13d 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/firmware.h> #include <linux/regmap.h> +#include <linux/string_choices.h> #include <linux/acpi.h> #include <acpi/acpi_bus.h> #include <linux/unaligned.h> @@ -34,6 +35,11 @@ enum { DSM_SET_RESET_METHOD = 3, }; +#define BTINTEL_BT_DOMAIN 0x12 +#define BTINTEL_SAR_LEGACY 0 +#define BTINTEL_SAR_INC_PWR 1 +#define BTINTEL_SAR_INC_PWR_SUPPORTED 0 + #define CMD_WRITE_BOOT_PARAMS 0xfc0e struct cmd_write_boot_params { __le32 boot_addr; @@ -82,7 +88,7 @@ int btintel_check_bdaddr(struct hci_dev *hdev) 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); + hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); } kfree_skb(skb); @@ -477,6 +483,7 @@ int btintel_version_info_tlv(struct hci_dev *hdev, case 0x1c: /* Gale Peak (GaP) */ case 0x1d: /* BlazarU (BzrU) */ case 0x1e: /* BlazarI (Bzr) */ + case 0x1f: /* Scorpious Peak */ break; default: bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)", @@ -506,13 +513,13 @@ int btintel_version_info_tlv(struct hci_dev *hdev, 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"); + str_enabled_disabled(version->secure_boot)); bt_dev_info(hdev, "OTP lock is %s", - version->otp_lock ? "enabled" : "disabled"); + str_enabled_disabled(version->otp_lock)); bt_dev_info(hdev, "API lock is %s", - version->api_lock ? "enabled" : "disabled"); + str_enabled_disabled(version->api_lock)); bt_dev_info(hdev, "Debug lock is %s", - version->debug_lock ? "enabled" : "disabled"); + str_enabled_disabled(version->debug_lock)); 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); @@ -882,7 +889,7 @@ int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param) params.boot_param = cpu_to_le32(boot_param); - skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), ¶ms, + skb = __hci_cmd_sync(hdev, BTINTEL_HCI_OP_RESET, sizeof(params), ¶ms, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { bt_dev_err(hdev, "Failed to send Intel Reset command"); @@ -927,16 +934,16 @@ int btintel_read_boot_params(struct hci_dev *hdev, le16_to_cpu(params->dev_revid)); bt_dev_info(hdev, "Secure boot is %s", - params->secure_boot ? "enabled" : "disabled"); + str_enabled_disabled(params->secure_boot)); bt_dev_info(hdev, "OTP lock is %s", - params->otp_lock ? "enabled" : "disabled"); + str_enabled_disabled(params->otp_lock)); bt_dev_info(hdev, "API lock is %s", - params->api_lock ? "enabled" : "disabled"); + str_enabled_disabled(params->api_lock)); bt_dev_info(hdev, "Debug lock is %s", - params->debug_lock ? "enabled" : "disabled"); + str_enabled_disabled(params->debug_lock)); bt_dev_info(hdev, "Minimum firmware build %u week %u %u", params->min_fw_build_nn, params->min_fw_build_cw, @@ -1280,7 +1287,7 @@ static void btintel_reset_to_bootloader(struct hci_dev *hdev) params.boot_option = 0x00; params.boot_param = cpu_to_le32(0x00000000); - skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), + skb = __hci_cmd_sync(hdev, BTINTEL_HCI_OP_RESET, sizeof(params), ¶ms, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { bt_dev_err(hdev, "FW download error recovery failed (%ld)", @@ -2020,7 +2027,7 @@ static int btintel_download_fw(struct hci_dev *hdev, */ if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { bt_dev_info(hdev, "No device address configured"); - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); } download: @@ -2288,7 +2295,7 @@ static int btintel_prepare_fw_download_tlv(struct hci_dev *hdev, */ if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) { bt_dev_info(hdev, "No device address configured"); - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); } } @@ -2663,7 +2670,7 @@ static u8 btintel_classify_pkt_type(struct hci_dev *hdev, struct sk_buff *skb) * Distinguish ISO data packets form ACL data packets * based on their connection handle value range. */ - if (hci_skb_pkt_type(skb) == HCI_ACLDATA_PKT) { + if (iso_capable(hdev) && hci_skb_pkt_type(skb) == HCI_ACLDATA_PKT) { __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle); if (hci_handle(handle) >= BTINTEL_ISODATA_HANDLE_BASE) @@ -2712,7 +2719,7 @@ static int btintel_uefi_get_dsbr(u32 *dsbr_var) } __packed data; efi_status_t status; - unsigned long data_size = 0; + unsigned long data_size = sizeof(data); efi_guid_t guid = EFI_GUID(0xe65d8884, 0xd4af, 0x4b20, 0x8d, 0x03, 0x77, 0x2e, 0xcc, 0x3d, 0xa5, 0x31); @@ -2723,15 +2730,9 @@ static int btintel_uefi_get_dsbr(u32 *dsbr_var) return -EOPNOTSUPP; status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size, - NULL); - - if (status != EFI_BUFFER_TOO_SMALL || !data_size) - return -EIO; - - status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size, &data); - if (status != EFI_SUCCESS) + if (status != EFI_SUCCESS || data_size != sizeof(data)) return -ENXIO; *dsbr_var = data.dsbr; @@ -2755,6 +2756,7 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver) /* DSBR command needs to be sent for, * 1. BlazarI or BlazarIW + B0 step product in IML image. * 2. Gale Peak2 or BlazarU in OP image. + * 3. Scorpious Peak in IML image. */ switch (cnvi) { @@ -2770,6 +2772,10 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver) hdev->bus == HCI_USB) break; return 0; + case BTINTEL_CNVI_SCP: + if (ver->img_type == BTINTEL_IMG_IML) + break; + return 0; default: return 0; } @@ -2799,6 +2805,331 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver) return 0; } +#ifdef CONFIG_ACPI +static acpi_status btintel_evaluate_acpi_method(struct hci_dev *hdev, + acpi_string method, + union acpi_object **ptr, + u8 pkg_size) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *p; + acpi_status status; + acpi_handle handle; + + handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev)); + if (!handle) { + bt_dev_dbg(hdev, "ACPI-BT: No ACPI support for Bluetooth device"); + return AE_NOT_EXIST; + } + + status = acpi_evaluate_object(handle, method, NULL, &buffer); + + if (ACPI_FAILURE(status)) { + bt_dev_dbg(hdev, "ACPI-BT: ACPI Failure: %s method: %s", + acpi_format_exception(status), method); + return status; + } + + p = buffer.pointer; + + if (p->type != ACPI_TYPE_PACKAGE || p->package.count < pkg_size) { + bt_dev_warn(hdev, "ACPI-BT: Invalid object type: %d or package count: %d", + p->type, p->package.count); + kfree(buffer.pointer); + return AE_ERROR; + } + + *ptr = buffer.pointer; + return 0; +} + +static union acpi_object *btintel_acpi_get_bt_pkg(union acpi_object *buffer) +{ + union acpi_object *domain, *bt_pkg; + int i; + + for (i = 1; i < buffer->package.count; i++) { + bt_pkg = &buffer->package.elements[i]; + domain = &bt_pkg->package.elements[0]; + if (domain->type == ACPI_TYPE_INTEGER && + domain->integer.value == BTINTEL_BT_DOMAIN) + return bt_pkg; + } + return ERR_PTR(-ENOENT); +} + +static int btintel_send_sar_ddc(struct hci_dev *hdev, struct btintel_cp_ddc_write *data, u8 len) +{ + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, 0xfc8b, len, data, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_warn(hdev, "Failed to send sar ddc id:0x%4.4x (%ld)", + le16_to_cpu(data->id), PTR_ERR(skb)); + return PTR_ERR(skb); + } + kfree_skb(skb); + return 0; +} + +static int btintel_send_edr(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd, + int id, struct btintel_sar_inc_pwr *sar) +{ + cmd->len = 5; + cmd->id = cpu_to_le16(id); + cmd->data[0] = sar->br >> 3; + cmd->data[1] = sar->edr2 >> 3; + cmd->data[2] = sar->edr3 >> 3; + return btintel_send_sar_ddc(hdev, cmd, 6); +} + +static int btintel_send_le(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd, + int id, struct btintel_sar_inc_pwr *sar) +{ + cmd->len = 3; + cmd->id = cpu_to_le16(id); + cmd->data[0] = min3(sar->le, sar->le_lr, sar->le_2mhz) >> 3; + return btintel_send_sar_ddc(hdev, cmd, 4); +} + +static int btintel_send_br(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd, + int id, struct btintel_sar_inc_pwr *sar) +{ + cmd->len = 3; + cmd->id = cpu_to_le16(id); + cmd->data[0] = sar->br >> 3; + return btintel_send_sar_ddc(hdev, cmd, 4); +} + +static int btintel_send_br_mutual(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd, + int id, struct btintel_sar_inc_pwr *sar) +{ + cmd->len = 3; + cmd->id = cpu_to_le16(id); + cmd->data[0] = sar->br; + return btintel_send_sar_ddc(hdev, cmd, 4); +} + +static int btintel_send_edr2(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd, + int id, struct btintel_sar_inc_pwr *sar) +{ + cmd->len = 3; + cmd->id = cpu_to_le16(id); + cmd->data[0] = sar->edr2; + return btintel_send_sar_ddc(hdev, cmd, 4); +} + +static int btintel_send_edr3(struct hci_dev *hdev, struct btintel_cp_ddc_write *cmd, + int id, struct btintel_sar_inc_pwr *sar) +{ + cmd->len = 3; + cmd->id = cpu_to_le16(id); + cmd->data[0] = sar->edr3; + return btintel_send_sar_ddc(hdev, cmd, 4); +} + +static int btintel_set_legacy_sar(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar) +{ + struct btintel_cp_ddc_write *cmd; + u8 buffer[64]; + int ret; + + cmd = (void *)buffer; + ret = btintel_send_br(hdev, cmd, 0x0131, sar); + if (ret) + return ret; + + ret = btintel_send_br(hdev, cmd, 0x0132, sar); + if (ret) + return ret; + + ret = btintel_send_le(hdev, cmd, 0x0133, sar); + if (ret) + return ret; + + ret = btintel_send_edr(hdev, cmd, 0x0137, sar); + if (ret) + return ret; + + ret = btintel_send_edr(hdev, cmd, 0x0138, sar); + if (ret) + return ret; + + ret = btintel_send_edr(hdev, cmd, 0x013b, sar); + if (ret) + return ret; + + ret = btintel_send_edr(hdev, cmd, 0x013c, sar); + + return ret; +} + +static int btintel_set_mutual_sar(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar) +{ + struct btintel_cp_ddc_write *cmd; + struct sk_buff *skb; + u8 buffer[64]; + bool enable; + int ret; + + cmd = (void *)buffer; + + cmd->len = 3; + cmd->id = cpu_to_le16(0x019e); + + if (sar->revision == BTINTEL_SAR_INC_PWR && + sar->inc_power_mode == BTINTEL_SAR_INC_PWR_SUPPORTED) + cmd->data[0] = 0x01; + else + cmd->data[0] = 0x00; + + ret = btintel_send_sar_ddc(hdev, cmd, 4); + if (ret) + return ret; + + if (sar->revision == BTINTEL_SAR_INC_PWR && + sar->inc_power_mode == BTINTEL_SAR_INC_PWR_SUPPORTED) { + cmd->len = 3; + cmd->id = cpu_to_le16(0x019f); + cmd->data[0] = sar->sar_2400_chain_a; + + ret = btintel_send_sar_ddc(hdev, cmd, 4); + if (ret) + return ret; + } + + ret = btintel_send_br_mutual(hdev, cmd, 0x01a0, sar); + if (ret) + return ret; + + ret = btintel_send_edr2(hdev, cmd, 0x01a1, sar); + if (ret) + return ret; + + ret = btintel_send_edr3(hdev, cmd, 0x01a2, sar); + if (ret) + return ret; + + ret = btintel_send_le(hdev, cmd, 0x01a3, sar); + if (ret) + return ret; + + enable = true; + skb = __hci_cmd_sync(hdev, 0xfe25, 1, &enable, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_warn(hdev, "Failed to send Intel SAR Enable (%ld)", PTR_ERR(skb)); + return PTR_ERR(skb); + } + + kfree_skb(skb); + return 0; +} + +static int btintel_sar_send_to_device(struct hci_dev *hdev, struct btintel_sar_inc_pwr *sar, + struct intel_version_tlv *ver) +{ + u16 cnvi, cnvr; + int ret; + + cnvi = ver->cnvi_top & 0xfff; + cnvr = ver->cnvr_top & 0xfff; + + if (cnvi < BTINTEL_CNVI_BLAZARI && cnvr < BTINTEL_CNVR_FMP2) { + bt_dev_info(hdev, "Applying legacy Bluetooth SAR"); + ret = btintel_set_legacy_sar(hdev, sar); + } else if (cnvi == BTINTEL_CNVI_GAP || cnvr == BTINTEL_CNVR_FMP2) { + bt_dev_info(hdev, "Applying mutual Bluetooth SAR"); + ret = btintel_set_mutual_sar(hdev, sar); + } else { + ret = -EOPNOTSUPP; + } + + return ret; +} + +static int btintel_acpi_set_sar(struct hci_dev *hdev, struct intel_version_tlv *ver) +{ + union acpi_object *bt_pkg, *buffer = NULL; + struct btintel_sar_inc_pwr sar; + acpi_status status; + u8 revision; + int ret; + + status = btintel_evaluate_acpi_method(hdev, "BRDS", &buffer, 2); + if (ACPI_FAILURE(status)) + return -ENOENT; + + bt_pkg = btintel_acpi_get_bt_pkg(buffer); + + if (IS_ERR(bt_pkg)) { + ret = PTR_ERR(bt_pkg); + goto error; + } + + if (!bt_pkg->package.count) { + ret = -EINVAL; + goto error; + } + + revision = buffer->package.elements[0].integer.value; + + if (revision > BTINTEL_SAR_INC_PWR) { + bt_dev_dbg(hdev, "BT_SAR: revision: 0x%2.2x not supported", revision); + ret = -EOPNOTSUPP; + goto error; + } + + memset(&sar, 0, sizeof(sar)); + + if (revision == BTINTEL_SAR_LEGACY && bt_pkg->package.count == 8) { + sar.revision = revision; + sar.bt_sar_bios = bt_pkg->package.elements[1].integer.value; + sar.br = bt_pkg->package.elements[2].integer.value; + sar.edr2 = bt_pkg->package.elements[3].integer.value; + sar.edr3 = bt_pkg->package.elements[4].integer.value; + sar.le = bt_pkg->package.elements[5].integer.value; + sar.le_2mhz = bt_pkg->package.elements[6].integer.value; + sar.le_lr = bt_pkg->package.elements[7].integer.value; + + } else if (revision == BTINTEL_SAR_INC_PWR && bt_pkg->package.count == 10) { + sar.revision = revision; + sar.bt_sar_bios = bt_pkg->package.elements[1].integer.value; + sar.inc_power_mode = bt_pkg->package.elements[2].integer.value; + sar.sar_2400_chain_a = bt_pkg->package.elements[3].integer.value; + sar.br = bt_pkg->package.elements[4].integer.value; + sar.edr2 = bt_pkg->package.elements[5].integer.value; + sar.edr3 = bt_pkg->package.elements[6].integer.value; + sar.le = bt_pkg->package.elements[7].integer.value; + sar.le_2mhz = bt_pkg->package.elements[8].integer.value; + sar.le_lr = bt_pkg->package.elements[9].integer.value; + } else { + ret = -EINVAL; + goto error; + } + + /* Apply only if it is enabled in BIOS */ + if (sar.bt_sar_bios != 1) { + bt_dev_dbg(hdev, "Bluetooth SAR is not enabled"); + ret = -EOPNOTSUPP; + goto error; + } + + ret = btintel_sar_send_to_device(hdev, &sar, ver); +error: + kfree(buffer); + return ret; +} +#endif /* CONFIG_ACPI */ + +static int btintel_set_specific_absorption_rate(struct hci_dev *hdev, + struct intel_version_tlv *ver) +{ +#ifdef CONFIG_ACPI + return btintel_acpi_set_sar(hdev, ver); +#endif + return 0; +} + int btintel_bootloader_setup_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver) { @@ -2876,6 +3207,9 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev, hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); + /* Send sar values to controller */ + btintel_set_specific_absorption_rate(hdev, ver); + /* Set PPAG feature */ btintel_set_ppag(hdev, ver); @@ -2918,6 +3252,7 @@ void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant) case 0x1c: case 0x1d: case 0x1e: + case 0x1f: hci_set_msft_opcode(hdev, 0xFC1E); break; default: @@ -3100,9 +3435,9 @@ static int btintel_setup_combined(struct hci_dev *hdev) } /* 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); + hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_DIAG); /* Set up the quality report callback for Intel devices */ hdev->set_quality_report = btintel_set_quality_report; @@ -3140,8 +3475,8 @@ static int btintel_setup_combined(struct hci_dev *hdev) */ if (!btintel_test_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, - &hdev->quirks); + hci_set_quirk(hdev, + HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); err = btintel_legacy_rom_setup(hdev, &ver); break; @@ -3156,11 +3491,11 @@ static int btintel_setup_combined(struct hci_dev *hdev) * * All Legacy bootloader devices support WBS */ - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, - &hdev->quirks); + hci_set_quirk(hdev, + HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); /* These variants don't seem to support LE Coded PHY */ - set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_CODED); /* Setup MSFT Extension support */ btintel_set_msft_opcode(hdev, ver.hw_variant); @@ -3236,10 +3571,10 @@ static int btintel_setup_combined(struct hci_dev *hdev) * * All Legacy bootloader devices support WBS */ - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); /* These variants don't seem to support LE Coded PHY */ - set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_CODED); /* Setup MSFT Extension support */ btintel_set_msft_opcode(hdev, ver.hw_variant); @@ -3257,6 +3592,7 @@ static int btintel_setup_combined(struct hci_dev *hdev) case 0x1b: case 0x1d: case 0x1e: + case 0x1f: /* Display version information of TLV type */ btintel_version_info_tlv(hdev, &ver_tlv); @@ -3264,7 +3600,7 @@ static int btintel_setup_combined(struct hci_dev *hdev) * * All TLV based devices support WBS */ - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); /* Setup MSFT Extension support */ btintel_set_msft_opcode(hdev, @@ -3346,7 +3682,7 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name) } EXPORT_SYMBOL_GPL(btintel_configure_setup); -int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) +static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) { struct intel_tlv *tlv = (void *)&skb->data[5]; @@ -3374,7 +3710,6 @@ int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) recv_frame: return hci_recv_frame(hdev, skb); } -EXPORT_SYMBOL_GPL(btintel_diagnostics); int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb) { diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index fa43eb137821..431998049e68 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -52,10 +52,16 @@ struct intel_tlv { u8 val[]; } __packed; +#define BTINTEL_HCI_OP_RESET 0xfc01 + #define BTINTEL_CNVI_BLAZARI 0x900 #define BTINTEL_CNVI_BLAZARIW 0x901 #define BTINTEL_CNVI_GAP 0x910 #define BTINTEL_CNVI_BLAZARU 0x930 +#define BTINTEL_CNVI_SCP 0xA00 + +/* CNVR */ +#define BTINTEL_CNVR_FMP2 0x910 #define BTINTEL_IMG_BOOTLOADER 0x01 /* Bootloader image */ #define BTINTEL_IMG_IML 0x02 /* Intermediate image */ @@ -164,6 +170,26 @@ struct hci_ppag_enable_cmd { #define INTEL_TLV_DEBUG_EXCEPTION 0x02 #define INTEL_TLV_TEST_EXCEPTION 0xDE +struct btintel_cp_ddc_write { + u8 len; + __le16 id; + u8 data[]; +} __packed; + +/* Bluetooth SAR feature (BRDS), Revision 1 */ +struct btintel_sar_inc_pwr { + u8 revision; + u32 bt_sar_bios; /* Mode of SAR control to be used, 1:enabled in bios */ + u32 inc_power_mode; /* Increased power mode */ + u8 sar_2400_chain_a; /* Sar power restriction LB */ + u8 br; + u8 edr2; + u8 edr3; + u8 le; + u8 le_2mhz; + u8 le_lr; +}; + #define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8)) #define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16)) #define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff) @@ -253,7 +279,6 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev, int btintel_shutdown_combined(struct hci_dev *hdev); void btintel_hw_error(struct hci_dev *hdev, u8 code); void btintel_print_fseq_info(struct hci_dev *hdev); -int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb); #else static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@ -387,9 +412,4 @@ static inline void btintel_hw_error(struct hci_dev *hdev, u8 code) static inline void btintel_print_fseq_info(struct hci_dev *hdev) { } - -static inline int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) -{ - return -EOPNOTSUPP; -} #endif diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index 091ffe3e1495..7f789937a764 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -36,6 +36,7 @@ /* Intel Bluetooth PCIe device id table */ static const struct pci_device_id btintel_pcie_table[] = { { BTINTEL_PCI_DEVICE(0xA876, PCI_ANY_ID) }, + { BTINTEL_PCI_DEVICE(0xE476, PCI_ANY_ID) }, { 0 } }; MODULE_DEVICE_TABLE(pci, btintel_pcie_table); @@ -48,6 +49,19 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table); #define BTINTEL_PCIE_HCI_EVT_PKT 0x00000004 #define BTINTEL_PCIE_HCI_ISO_PKT 0x00000005 +#define BTINTEL_PCIE_MAGIC_NUM 0xA5A5A5A5 + +#define BTINTEL_PCIE_BLZR_HWEXP_SIZE 1024 +#define BTINTEL_PCIE_BLZR_HWEXP_DMP_ADDR 0xB00A7C00 + +#define BTINTEL_PCIE_SCP_HWEXP_SIZE 4096 +#define BTINTEL_PCIE_SCP_HWEXP_DMP_ADDR 0xB030F800 + +#define BTINTEL_PCIE_MAGIC_NUM 0xA5A5A5A5 + +#define BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER 0x17A2 +#define BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT 0x1E61 + /* Alive interrupt context */ enum { BTINTEL_PCIE_ROM, @@ -59,6 +73,83 @@ enum { BTINTEL_PCIE_D3 }; +/* Structure for dbgc fragment buffer + * @buf_addr_lsb: LSB of the buffer's physical address + * @buf_addr_msb: MSB of the buffer's physical address + * @buf_size: Total size of the buffer + */ +struct btintel_pcie_dbgc_ctxt_buf { + u32 buf_addr_lsb; + u32 buf_addr_msb; + u32 buf_size; +}; + +/* Structure for dbgc fragment + * @magic_num: 0XA5A5A5A5 + * @ver: For Driver-FW compatibility + * @total_size: Total size of the payload debug info + * @num_buf: Num of allocated debug bufs + * @bufs: All buffer's addresses and sizes + */ +struct btintel_pcie_dbgc_ctxt { + u32 magic_num; + u32 ver; + u32 total_size; + u32 num_buf; + struct btintel_pcie_dbgc_ctxt_buf bufs[BTINTEL_PCIE_DBGC_BUFFER_COUNT]; +}; + +/* This function initializes the memory for DBGC buffers and formats the + * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and + * size as the payload + */ +static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data) +{ + struct btintel_pcie_dbgc_ctxt db_frag; + struct data_buf *buf; + int i; + + data->dbgc.count = BTINTEL_PCIE_DBGC_BUFFER_COUNT; + data->dbgc.bufs = devm_kcalloc(&data->pdev->dev, data->dbgc.count, + sizeof(*buf), GFP_KERNEL); + if (!data->dbgc.bufs) + return -ENOMEM; + + data->dbgc.buf_v_addr = dmam_alloc_coherent(&data->pdev->dev, + data->dbgc.count * + BTINTEL_PCIE_DBGC_BUFFER_SIZE, + &data->dbgc.buf_p_addr, + GFP_KERNEL | __GFP_NOWARN); + if (!data->dbgc.buf_v_addr) + return -ENOMEM; + + data->dbgc.frag_v_addr = dmam_alloc_coherent(&data->pdev->dev, + sizeof(struct btintel_pcie_dbgc_ctxt), + &data->dbgc.frag_p_addr, + GFP_KERNEL | __GFP_NOWARN); + if (!data->dbgc.frag_v_addr) + return -ENOMEM; + + data->dbgc.frag_size = sizeof(struct btintel_pcie_dbgc_ctxt); + + db_frag.magic_num = BTINTEL_PCIE_MAGIC_NUM; + db_frag.ver = BTINTEL_PCIE_DBGC_FRAG_VERSION; + db_frag.total_size = BTINTEL_PCIE_DBGC_FRAG_PAYLOAD_SIZE; + db_frag.num_buf = BTINTEL_PCIE_DBGC_FRAG_BUFFER_COUNT; + + for (i = 0; i < data->dbgc.count; i++) { + buf = &data->dbgc.bufs[i]; + buf->data_p_addr = data->dbgc.buf_p_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE; + buf->data = data->dbgc.buf_v_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE; + db_frag.bufs[i].buf_addr_lsb = lower_32_bits(buf->data_p_addr); + db_frag.bufs[i].buf_addr_msb = upper_32_bits(buf->data_p_addr); + db_frag.bufs[i].buf_size = BTINTEL_PCIE_DBGC_BUFFER_SIZE; + } + + memcpy(data->dbgc.frag_v_addr, &db_frag, sizeof(db_frag)); + return 0; +} + static inline void ipc_print_ia_ring(struct hci_dev *hdev, struct ia *ia, u16 queue_num) { @@ -117,6 +208,96 @@ static void btintel_pcie_prepare_tx(struct txq *txq, u16 tfd_index, memcpy(buf->data, skb->data, tfd->size); } +static inline void btintel_pcie_dump_debug_registers(struct hci_dev *hdev) +{ + struct btintel_pcie_data *data = hci_get_drvdata(hdev); + u16 cr_hia, cr_tia; + u32 reg, mbox_reg; + struct sk_buff *skb; + u8 buf[80]; + + skb = alloc_skb(1024, GFP_ATOMIC); + if (!skb) + return; + + snprintf(buf, sizeof(buf), "%s", "---- Dump of debug registers ---"); + bt_dev_dbg(hdev, "%s", buf); + skb_put_data(skb, buf, strlen(buf)); + + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_BOOT_STAGE_REG); + snprintf(buf, sizeof(buf), "boot stage: 0x%8.8x", reg); + bt_dev_dbg(hdev, "%s", buf); + skb_put_data(skb, buf, strlen(buf)); + data->boot_stage_cache = reg; + + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_IPC_STATUS_REG); + snprintf(buf, sizeof(buf), "ipc status: 0x%8.8x", reg); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_IPC_CONTROL_REG); + snprintf(buf, sizeof(buf), "ipc control: 0x%8.8x", reg); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG); + snprintf(buf, sizeof(buf), "ipc sleep control: 0x%8.8x", reg); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + + /*Read the Mail box status and registers*/ + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_MBOX_STATUS_REG); + snprintf(buf, sizeof(buf), "mbox status: 0x%8.8x", reg); + skb_put_data(skb, buf, strlen(buf)); + if (reg & BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX1) { + mbox_reg = btintel_pcie_rd_reg32(data, + BTINTEL_PCIE_CSR_MBOX_1_REG); + snprintf(buf, sizeof(buf), "mbox_1: 0x%8.8x", mbox_reg); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + } + + if (reg & BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX2) { + mbox_reg = btintel_pcie_rd_reg32(data, + BTINTEL_PCIE_CSR_MBOX_2_REG); + snprintf(buf, sizeof(buf), "mbox_2: 0x%8.8x", mbox_reg); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + } + + if (reg & BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX3) { + mbox_reg = btintel_pcie_rd_reg32(data, + BTINTEL_PCIE_CSR_MBOX_3_REG); + snprintf(buf, sizeof(buf), "mbox_3: 0x%8.8x", mbox_reg); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + } + + if (reg & BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX4) { + mbox_reg = btintel_pcie_rd_reg32(data, + BTINTEL_PCIE_CSR_MBOX_4_REG); + snprintf(buf, sizeof(buf), "mbox_4: 0x%8.8x", mbox_reg); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + } + + cr_hia = data->ia.cr_hia[BTINTEL_PCIE_RXQ_NUM]; + cr_tia = data->ia.cr_tia[BTINTEL_PCIE_RXQ_NUM]; + snprintf(buf, sizeof(buf), "rxq: cr_tia: %u cr_hia: %u", cr_tia, cr_hia); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + + cr_hia = data->ia.cr_hia[BTINTEL_PCIE_TXQ_NUM]; + cr_tia = data->ia.cr_tia[BTINTEL_PCIE_TXQ_NUM]; + snprintf(buf, sizeof(buf), "txq: cr_tia: %u cr_hia: %u", cr_tia, cr_hia); + skb_put_data(skb, buf, strlen(buf)); + bt_dev_dbg(hdev, "%s", buf); + snprintf(buf, sizeof(buf), "--------------------------------"); + bt_dev_dbg(hdev, "%s", buf); + + hci_recv_diag(hdev, skb); +} + static int btintel_pcie_send_sync(struct btintel_pcie_data *data, struct sk_buff *skb) { @@ -146,8 +327,11 @@ static int btintel_pcie_send_sync(struct btintel_pcie_data *data, /* Wait for the complete interrupt - URBD0 */ ret = wait_event_timeout(data->tx_wait_q, data->tx_wait_done, msecs_to_jiffies(BTINTEL_PCIE_TX_WAIT_TIMEOUT_MS)); - if (!ret) + if (!ret) { + bt_dev_err(data->hdev, "tx completion timeout"); + btintel_pcie_dump_debug_registers(data->hdev); return -ETIME; + } return 0; } @@ -212,8 +396,13 @@ static int btintel_pcie_submit_rx(struct btintel_pcie_data *data) static int btintel_pcie_start_rx(struct btintel_pcie_data *data) { int i, ret; + struct rxq *rxq = &data->rxq; + + /* Post (BTINTEL_PCIE_RX_DESCS_COUNT - 3) buffers to overcome the + * hardware issues leading to race condition at the firmware. + */ - for (i = 0; i < BTINTEL_PCIE_RX_MAX_QUEUE; i++) { + for (i = 0; i < rxq->count - 3; i++) { ret = btintel_pcie_submit_rx(data); if (ret) return ret; @@ -273,6 +462,271 @@ static int btintel_pcie_reset_bt(struct btintel_pcie_data *data) return reg == 0 ? 0 : -ENODEV; } +static void btintel_pcie_mac_init(struct btintel_pcie_data *data) +{ + u32 reg; + + /* Set MAC_INIT bit to start primary bootloader */ + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG); + reg &= ~(BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT | + BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON | + BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET); + reg |= (BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_ENA | + BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT); + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg); +} + +static int btintel_pcie_add_dmp_data(struct hci_dev *hdev, const void *data, int size) +{ + struct sk_buff *skb; + int err; + + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, data, size); + err = hci_devcd_append(hdev, skb); + if (err) { + bt_dev_err(hdev, "Failed to append data in the coredump"); + return err; + } + + return 0; +} + +static int btintel_pcie_get_mac_access(struct btintel_pcie_data *data) +{ + u32 reg; + int retry = 15; + + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG); + + reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS; + reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ; + if ((reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS) == 0) + reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ; + + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg); + + do { + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG); + if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS) + return 0; + /* Need delay here for Target Access harwdware to settle down*/ + usleep_range(1000, 1200); + + } while (--retry > 0); + + return -ETIME; +} + +static void btintel_pcie_release_mac_access(struct btintel_pcie_data *data) +{ + u32 reg; + + reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG); + + if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ) + reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ; + + if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS) + reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS; + + if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ) + reg &= ~BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ; + + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg); +} + +static void btintel_pcie_copy_tlv(struct sk_buff *skb, enum btintel_pcie_tlv_type type, + void *data, int size) +{ + struct intel_tlv *tlv; + + tlv = skb_put(skb, sizeof(*tlv) + size); + tlv->type = type; + tlv->len = size; + memcpy(tlv->val, data, tlv->len); +} + +static int btintel_pcie_read_dram_buffers(struct btintel_pcie_data *data) +{ + u32 offset, prev_size, wr_ptr_status, dump_size, i; + struct btintel_pcie_dbgc *dbgc = &data->dbgc; + u8 buf_idx, dump_time_len, fw_build; + struct hci_dev *hdev = data->hdev; + struct intel_tlv *tlv; + struct timespec64 now; + struct sk_buff *skb; + struct tm tm_now; + char buf[256]; + u16 hdr_len; + int ret; + + wr_ptr_status = btintel_pcie_rd_dev_mem(data, BTINTEL_PCIE_DBGC_CUR_DBGBUFF_STATUS); + offset = wr_ptr_status & BTINTEL_PCIE_DBG_OFFSET_BIT_MASK; + + buf_idx = BTINTEL_PCIE_DBGC_DBG_BUF_IDX(wr_ptr_status); + if (buf_idx > dbgc->count) { + bt_dev_warn(hdev, "Buffer index is invalid"); + return -EINVAL; + } + + prev_size = buf_idx * BTINTEL_PCIE_DBGC_BUFFER_SIZE; + if (prev_size + offset >= prev_size) + data->dmp_hdr.write_ptr = prev_size + offset; + else + return -EINVAL; + + ktime_get_real_ts64(&now); + time64_to_tm(now.tv_sec, 0, &tm_now); + dump_time_len = snprintf(buf, sizeof(buf), "Dump Time: %02d-%02d-%04ld %02d:%02d:%02d", + tm_now.tm_mday, tm_now.tm_mon + 1, tm_now.tm_year + 1900, + tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec); + + fw_build = snprintf(buf + dump_time_len, sizeof(buf) - dump_time_len, + "Firmware Timestamp: Year %u WW %02u buildtype %u build %u", + 2000 + (data->dmp_hdr.fw_timestamp >> 8), + data->dmp_hdr.fw_timestamp & 0xff, data->dmp_hdr.fw_build_type, + data->dmp_hdr.fw_build_num); + + hdr_len = sizeof(*tlv) + sizeof(data->dmp_hdr.cnvi_bt) + + sizeof(*tlv) + sizeof(data->dmp_hdr.write_ptr) + + sizeof(*tlv) + sizeof(data->dmp_hdr.wrap_ctr) + + sizeof(*tlv) + sizeof(data->dmp_hdr.trigger_reason) + + sizeof(*tlv) + sizeof(data->dmp_hdr.fw_git_sha1) + + sizeof(*tlv) + sizeof(data->dmp_hdr.cnvr_top) + + sizeof(*tlv) + sizeof(data->dmp_hdr.cnvi_top) + + sizeof(*tlv) + dump_time_len + + sizeof(*tlv) + fw_build; + + dump_size = hdr_len + sizeof(hdr_len); + + skb = alloc_skb(dump_size, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + /* Add debug buffers data length to dump size */ + dump_size += BTINTEL_PCIE_DBGC_BUFFER_SIZE * dbgc->count; + + ret = hci_devcd_init(hdev, dump_size); + if (ret) { + bt_dev_err(hdev, "Failed to init devcoredump, err %d", ret); + kfree_skb(skb); + return ret; + } + + skb_put_data(skb, &hdr_len, sizeof(hdr_len)); + + btintel_pcie_copy_tlv(skb, BTINTEL_CNVI_BT, &data->dmp_hdr.cnvi_bt, + sizeof(data->dmp_hdr.cnvi_bt)); + + btintel_pcie_copy_tlv(skb, BTINTEL_WRITE_PTR, &data->dmp_hdr.write_ptr, + sizeof(data->dmp_hdr.write_ptr)); + + data->dmp_hdr.wrap_ctr = btintel_pcie_rd_dev_mem(data, + BTINTEL_PCIE_DBGC_DBGBUFF_WRAP_ARND); + + btintel_pcie_copy_tlv(skb, BTINTEL_WRAP_CTR, &data->dmp_hdr.wrap_ctr, + sizeof(data->dmp_hdr.wrap_ctr)); + + btintel_pcie_copy_tlv(skb, BTINTEL_TRIGGER_REASON, &data->dmp_hdr.trigger_reason, + sizeof(data->dmp_hdr.trigger_reason)); + + btintel_pcie_copy_tlv(skb, BTINTEL_FW_SHA, &data->dmp_hdr.fw_git_sha1, + sizeof(data->dmp_hdr.fw_git_sha1)); + + btintel_pcie_copy_tlv(skb, BTINTEL_CNVR_TOP, &data->dmp_hdr.cnvr_top, + sizeof(data->dmp_hdr.cnvr_top)); + + btintel_pcie_copy_tlv(skb, BTINTEL_CNVI_TOP, &data->dmp_hdr.cnvi_top, + sizeof(data->dmp_hdr.cnvi_top)); + + btintel_pcie_copy_tlv(skb, BTINTEL_DUMP_TIME, buf, dump_time_len); + + btintel_pcie_copy_tlv(skb, BTINTEL_FW_BUILD, buf + dump_time_len, fw_build); + + ret = hci_devcd_append(hdev, skb); + if (ret) + goto exit_err; + + for (i = 0; i < dbgc->count; i++) { + ret = btintel_pcie_add_dmp_data(hdev, dbgc->bufs[i].data, + BTINTEL_PCIE_DBGC_BUFFER_SIZE); + if (ret) + break; + } + +exit_err: + hci_devcd_complete(hdev); + return ret; +} + +static void btintel_pcie_dump_traces(struct hci_dev *hdev) +{ + struct btintel_pcie_data *data = hci_get_drvdata(hdev); + int ret = 0; + + ret = btintel_pcie_get_mac_access(data); + if (ret) { + bt_dev_err(hdev, "Failed to get mac access: (%d)", ret); + return; + } + + ret = btintel_pcie_read_dram_buffers(data); + + btintel_pcie_release_mac_access(data); + + if (ret) + bt_dev_err(hdev, "Failed to dump traces: (%d)", ret); +} + +static void btintel_pcie_dump_hdr(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btintel_pcie_data *data = hci_get_drvdata(hdev); + u16 len = skb->len; + u16 *hdrlen_ptr; + char buf[80]; + + hdrlen_ptr = skb_put_zero(skb, sizeof(len)); + + snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n", + INTEL_HW_VARIANT(data->dmp_hdr.cnvi_bt)); + skb_put_data(skb, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Firmware Build Number: %u\n", + data->dmp_hdr.fw_build_num); + skb_put_data(skb, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Driver: %s\n", data->dmp_hdr.driver_name); + skb_put_data(skb, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Vendor: Intel\n"); + skb_put_data(skb, buf, strlen(buf)); + + *hdrlen_ptr = skb->len - len; +} + +static void btintel_pcie_dump_notify(struct hci_dev *hdev, int state) +{ + struct btintel_pcie_data *data = hci_get_drvdata(hdev); + + switch (state) { + case HCI_DEVCOREDUMP_IDLE: + data->dmp_hdr.state = HCI_DEVCOREDUMP_IDLE; + break; + case HCI_DEVCOREDUMP_ACTIVE: + data->dmp_hdr.state = HCI_DEVCOREDUMP_ACTIVE; + break; + case HCI_DEVCOREDUMP_TIMEOUT: + case HCI_DEVCOREDUMP_ABORT: + case HCI_DEVCOREDUMP_DONE: + data->dmp_hdr.state = HCI_DEVCOREDUMP_IDLE; + break; + } +} + /* This function enables BT function by setting BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT bit in * BTINTEL_PCIE_CSR_FUNC_CTRL_REG register and wait for MSI-X with * BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0. @@ -329,20 +783,6 @@ static int btintel_pcie_enable_bt(struct btintel_pcie_data *data) return 0; } -/* BIT(0) - ROM, BIT(1) - IML and BIT(3) - OP - * Sometimes during firmware image switching from ROM to IML or IML to OP image, - * the previous image bit is not cleared by firmware when alive interrupt is - * received. Driver needs to take care of these sticky bits when deciding the - * current image running on controller. - * Ex: 0x10 and 0x11 - both represents that controller is running IML - */ -static inline bool btintel_pcie_in_rom(struct btintel_pcie_data *data) -{ - return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ROM && - !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML) && - !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW); -} - static inline bool btintel_pcie_in_op(struct btintel_pcie_data *data) { return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW; @@ -393,6 +833,47 @@ static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt) } } +static int btintel_pcie_read_device_mem(struct btintel_pcie_data *data, + void *buf, u32 dev_addr, int len) +{ + int err; + u32 *val = buf; + + /* Get device mac access */ + err = btintel_pcie_get_mac_access(data); + if (err) { + bt_dev_err(data->hdev, "Failed to get mac access %d", err); + return err; + } + + for (; len > 0; len -= 4, dev_addr += 4, val++) + *val = btintel_pcie_rd_dev_mem(data, dev_addr); + + btintel_pcie_release_mac_access(data); + + return 0; +} + +static inline bool btintel_pcie_in_lockdown(struct btintel_pcie_data *data) +{ + return (data->boot_stage_cache & + BTINTEL_PCIE_CSR_BOOT_STAGE_ROM_LOCKDOWN) || + (data->boot_stage_cache & + BTINTEL_PCIE_CSR_BOOT_STAGE_IML_LOCKDOWN); +} + +static inline bool btintel_pcie_in_error(struct btintel_pcie_data *data) +{ + return (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_ERR) || + (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER); +} + +static void btintel_pcie_msix_gp1_handler(struct btintel_pcie_data *data) +{ + bt_dev_err(data->hdev, "Received gp1 mailbox interrupt"); + btintel_pcie_dump_debug_registers(data->hdev); +} + /* This function handles the MSI-X interrupt for gp0 cause (bit 0 in * BTINTEL_PCIE_CSR_MSIX_HW_INT_CAUSES) which is sent for boot stage and image response. */ @@ -416,6 +897,18 @@ static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data) if (reg != data->img_resp_cache) data->img_resp_cache = reg; + if (btintel_pcie_in_error(data)) { + bt_dev_err(data->hdev, "Controller in error state"); + btintel_pcie_dump_debug_registers(data->hdev); + return; + } + + if (btintel_pcie_in_lockdown(data)) { + bt_dev_err(data->hdev, "Controller in lockdown state"); + btintel_pcie_dump_debug_registers(data->hdev); + return; + } + data->gp0_received = true; old_ctxt = data->alive_intr_ctxt; @@ -435,11 +928,13 @@ static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data) case BTINTEL_PCIE_INTEL_HCI_RESET1: if (btintel_pcie_in_op(data)) { submit_rx = true; + signal_waitq = true; break; } if (btintel_pcie_in_iml(data)) { submit_rx = true; + signal_waitq = true; data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL; break; } @@ -526,7 +1021,6 @@ static void btintel_pcie_msix_tx_handle(struct btintel_pcie_data *data) static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_event_hdr *hdr = (void *)skb->data; - const char diagnostics_hdr[] = { 0x87, 0x80, 0x03 }; struct btintel_pcie_data *data = hci_get_drvdata(hdev); if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff && @@ -582,20 +1076,13 @@ static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb) } } - /* Handle all diagnostics events separately. May still call - * hci_recv_frame. - */ - if (len >= sizeof(diagnostics_hdr) && - memcmp(&skb->data[2], diagnostics_hdr, - sizeof(diagnostics_hdr)) == 0) { - return btintel_diagnostics(hdev, skb); - } - /* This is a debug event that comes from IML and OP image when it * starts execution. There is no need pass this event to stack. */ - if (skb->data[2] == 0x97) + if (skb->data[2] == 0x97) { + hci_recv_diag(hdev, skb); return 0; + } } return hci_recv_frame(hdev, skb); @@ -611,7 +1098,6 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data, u8 pkt_type; u16 plen; u32 pcie_pkt_type; - struct sk_buff *new_skb; void *pdata; struct hci_dev *hdev = data->hdev; @@ -688,24 +1174,20 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data, bt_dev_dbg(hdev, "pkt_type: 0x%2.2x len: %u", pkt_type, plen); - new_skb = bt_skb_alloc(plen, GFP_ATOMIC); - if (!new_skb) { - bt_dev_err(hdev, "Failed to allocate memory for skb of len: %u", - skb->len); - ret = -ENOMEM; - goto exit_error; - } - - hci_skb_pkt_type(new_skb) = pkt_type; - skb_put_data(new_skb, skb->data, plen); + hci_skb_pkt_type(skb) = pkt_type; hdev->stat.byte_rx += plen; + skb_trim(skb, plen); if (pcie_pkt_type == BTINTEL_PCIE_HCI_EVT_PKT) - ret = btintel_pcie_recv_event(hdev, new_skb); + ret = btintel_pcie_recv_event(hdev, skb); else - ret = hci_recv_frame(hdev, new_skb); + ret = hci_recv_frame(hdev, skb); + skb = NULL; /* skb is freed in the callee */ exit_error: + if (skb) + kfree_skb(skb); + if (ret) hdev->stat.err_rx++; @@ -714,21 +1196,152 @@ exit_error: return ret; } +static void btintel_pcie_read_hwexp(struct btintel_pcie_data *data) +{ + int len, err, offset, pending; + struct sk_buff *skb; + u8 *buf, prefix[64]; + u32 addr, val; + u16 pkt_len; + + struct tlv { + u8 type; + __le16 len; + u8 val[]; + } __packed; + + struct tlv *tlv; + + switch (data->dmp_hdr.cnvi_top & 0xfff) { + case BTINTEL_CNVI_BLAZARI: + case BTINTEL_CNVI_BLAZARIW: + /* only from step B0 onwards */ + if (INTEL_CNVX_TOP_STEP(data->dmp_hdr.cnvi_top) != 0x01) + return; + len = BTINTEL_PCIE_BLZR_HWEXP_SIZE; /* exception data length */ + addr = BTINTEL_PCIE_BLZR_HWEXP_DMP_ADDR; + break; + case BTINTEL_CNVI_SCP: + len = BTINTEL_PCIE_SCP_HWEXP_SIZE; + addr = BTINTEL_PCIE_SCP_HWEXP_DMP_ADDR; + break; + default: + bt_dev_err(data->hdev, "Unsupported cnvi 0x%8.8x", data->dmp_hdr.cnvi_top); + return; + } + + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + goto exit_on_error; + + btintel_pcie_mac_init(data); + + err = btintel_pcie_read_device_mem(data, buf, addr, len); + if (err) + goto exit_on_error; + + val = get_unaligned_le32(buf); + if (val != BTINTEL_PCIE_MAGIC_NUM) { + bt_dev_err(data->hdev, "Invalid exception dump signature: 0x%8.8x", + val); + goto exit_on_error; + } + + snprintf(prefix, sizeof(prefix), "Bluetooth: %s: ", bt_dev_name(data->hdev)); + + offset = 4; + do { + pending = len - offset; + if (pending < sizeof(*tlv)) + break; + tlv = (struct tlv *)(buf + offset); + + /* If type == 0, then there are no more TLVs to be parsed */ + if (!tlv->type) { + bt_dev_dbg(data->hdev, "Invalid TLV type 0"); + break; + } + pkt_len = le16_to_cpu(tlv->len); + offset += sizeof(*tlv); + pending = len - offset; + if (pkt_len > pending) + break; + + offset += pkt_len; + + /* Only TLVs of type == 1 are HCI events, no need to process other + * TLVs + */ + if (tlv->type != 1) + continue; + + bt_dev_dbg(data->hdev, "TLV packet length: %u", pkt_len); + if (pkt_len > HCI_MAX_EVENT_SIZE) + break; + skb = bt_skb_alloc(pkt_len, GFP_KERNEL); + if (!skb) + goto exit_on_error; + hci_skb_pkt_type(skb) = HCI_EVENT_PKT; + skb_put_data(skb, tlv->val, pkt_len); + + /* copy Intel specific pcie packet type */ + val = BTINTEL_PCIE_HCI_EVT_PKT; + memcpy(skb_push(skb, BTINTEL_PCIE_HCI_TYPE_LEN), &val, + BTINTEL_PCIE_HCI_TYPE_LEN); + + print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_OFFSET, 16, 1, + tlv->val, pkt_len, false); + + btintel_pcie_recv_frame(data, skb); + } while (offset < len); + +exit_on_error: + kfree(buf); +} + +static void btintel_pcie_msix_hw_exp_handler(struct btintel_pcie_data *data) +{ + bt_dev_err(data->hdev, "Received hw exception interrupt"); + + if (test_and_set_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags)) + return; + + if (test_and_set_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) + return; + + /* Trigger device core dump when there is HW exception */ + if (!test_and_set_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags)) + data->dmp_hdr.trigger_reason = BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT; + + queue_work(data->workqueue, &data->rx_work); +} + static void btintel_pcie_rx_work(struct work_struct *work) { struct btintel_pcie_data *data = container_of(work, struct btintel_pcie_data, rx_work); struct sk_buff *skb; - int err; - struct hci_dev *hdev = data->hdev; + + if (test_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) { + /* Unlike usb products, controller will not send hardware + * exception event on exception. Instead controller writes the + * hardware event to device memory along with optional debug + * events, raises MSIX and halts. Driver shall read the + * exception event from device memory and passes it stack for + * further processing. + */ + btintel_pcie_read_hwexp(data); + clear_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags); + } + + if (test_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags)) { + btintel_pcie_dump_traces(data->hdev); + clear_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags); + } /* Process the sk_buf in queue and send to the HCI layer */ while ((skb = skb_dequeue(&data->rx_skb_q))) { - err = btintel_pcie_recv_frame(data, skb); - if (err) - bt_dev_err(hdev, "Failed to send received frame: %d", - err); - kfree_skb(skb); + btintel_pcie_recv_frame(data, skb); } } @@ -781,10 +1394,8 @@ static void btintel_pcie_msix_rx_handle(struct btintel_pcie_data *data) bt_dev_dbg(hdev, "RXQ: cr_hia: %u cr_tia: %u", cr_hia, cr_tia); /* Check CR_TIA and CR_HIA for change */ - if (cr_tia == cr_hia) { - bt_dev_warn(hdev, "RXQ: no new CD found"); + if (cr_tia == cr_hia) return; - } rxq = &data->rxq; @@ -820,6 +1431,16 @@ static irqreturn_t btintel_pcie_msix_isr(int irq, void *data) return IRQ_WAKE_THREAD; } +static inline bool btintel_pcie_is_rxq_empty(struct btintel_pcie_data *data) +{ + return data->ia.cr_hia[BTINTEL_PCIE_RXQ_NUM] == data->ia.cr_tia[BTINTEL_PCIE_RXQ_NUM]; +} + +static inline bool btintel_pcie_is_txackq_empty(struct btintel_pcie_data *data) +{ + return data->ia.cr_tia[BTINTEL_PCIE_TXQ_NUM] == data->ia.cr_hia[BTINTEL_PCIE_TXQ_NUM]; +} + static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id) { struct msix_entry *entry = dev_id; @@ -840,6 +1461,13 @@ static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id) return IRQ_NONE; } + /* This interrupt is raised when there is an hardware exception */ + if (intr_hw & BTINTEL_PCIE_MSIX_HW_INT_CAUSES_HWEXP) + btintel_pcie_msix_hw_exp_handler(data); + + if (intr_hw & BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP1) + btintel_pcie_msix_gp1_handler(data); + /* This interrupt is triggered by the firmware after updating * boot_stage register and image_response register */ @@ -847,12 +1475,18 @@ static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id) btintel_pcie_msix_gp0_handler(data); /* For TX */ - if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0) + if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0) { btintel_pcie_msix_tx_handle(data); + if (!btintel_pcie_is_rxq_empty(data)) + btintel_pcie_msix_rx_handle(data); + } /* For RX */ - if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_1) + if (intr_fh & BTINTEL_PCIE_MSIX_FH_INT_CAUSES_1) { btintel_pcie_msix_rx_handle(data); + if (!btintel_pcie_is_txackq_empty(data)) + btintel_pcie_msix_tx_handle(data); + } /* * Before sending the interrupt the HW disables it to prevent a nested @@ -920,7 +1554,8 @@ struct btintel_pcie_causes_list { static struct btintel_pcie_causes_list causes_list[] = { { BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, 0x00 }, { BTINTEL_PCIE_MSIX_FH_INT_CAUSES_1, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, 0x01 }, - { BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, 0x20 }, + { BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, 0x20 }, + { BTINTEL_PCIE_MSIX_HW_INT_CAUSES_HWEXP, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, 0x23 }, }; /* This function configures the interrupt masks for both HW_INT_CAUSES and @@ -1007,6 +1642,11 @@ static void btintel_pcie_init_ci(struct btintel_pcie_data *data, ci->addr_urbdq1 = data->rxq.urbd1s_p_addr; ci->num_urbdq1 = data->rxq.count; ci->urbdq_db_vec = BTINTEL_PCIE_RXQ_NUM; + + ci->dbg_output_mode = 0x01; + ci->dbgc_addr = data->dbgc.frag_p_addr; + ci->dbgc_size = data->dbgc.frag_size; + ci->dbg_preset = 0x00; } static void btintel_pcie_free_txq_bufs(struct btintel_pcie_data *data, @@ -1149,8 +1789,8 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) * + size of index * Number of queues(2) * type of index array(4) * + size of context information */ - total = (sizeof(struct tfd) + sizeof(struct urbd0) + sizeof(struct frbd) - + sizeof(struct urbd1)) * BTINTEL_DESCS_COUNT; + total = (sizeof(struct tfd) + sizeof(struct urbd0)) * BTINTEL_PCIE_TX_DESCS_COUNT; + total += (sizeof(struct frbd) + sizeof(struct urbd1)) * BTINTEL_PCIE_RX_DESCS_COUNT; /* Add the sum of size of index array and size of ci struct */ total += (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4) + sizeof(struct ctx_info); @@ -1175,36 +1815,36 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) data->dma_v_addr = v_addr; /* Setup descriptor count */ - data->txq.count = BTINTEL_DESCS_COUNT; - data->rxq.count = BTINTEL_DESCS_COUNT; + data->txq.count = BTINTEL_PCIE_TX_DESCS_COUNT; + data->rxq.count = BTINTEL_PCIE_RX_DESCS_COUNT; /* Setup tfds */ data->txq.tfds_p_addr = p_addr; data->txq.tfds = v_addr; - p_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); + v_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); /* Setup urbd0 */ data->txq.urbd0s_p_addr = p_addr; data->txq.urbd0s = v_addr; - p_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); + v_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); /* Setup FRBD*/ data->rxq.frbds_p_addr = p_addr; data->rxq.frbds = v_addr; - p_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); + v_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); /* Setup urbd1 */ data->rxq.urbd1s_p_addr = p_addr; data->rxq.urbd1s = v_addr; - p_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); + v_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); /* Setup data buffers for txq */ err = btintel_pcie_setup_txq_bufs(data, &data->txq); @@ -1219,6 +1859,11 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) /* Setup Index Array */ btintel_pcie_setup_ia(data, p_addr, v_addr, &data->ia); + /* Setup data buffers for dbgc */ + err = btintel_pcie_setup_dbgc(data); + if (err) + goto exit_error_txq; + /* Setup Context Information */ p_addr += sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4; v_addr += sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4; @@ -1312,16 +1957,19 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, struct hci_command_hdr *cmd = (void *)skb->data; __u16 opcode = le16_to_cpu(cmd->opcode); - /* When the 0xfc01 command is issued to boot into - * the operational firmware, it will actually not - * send a command complete event. To keep the flow + /* When the BTINTEL_HCI_OP_RESET command is issued to + * boot into the operational firmware, it will actually + * not send a command complete event. To keep the flow * control working inject that event here. */ - if (opcode == 0xfc01) + if (opcode == BTINTEL_HCI_OP_RESET) btintel_pcie_inject_cmd_complete(hdev, opcode); } - /* Firmware raises alive interrupt on HCI_OP_RESET */ - if (opcode == HCI_OP_RESET) + + /* Firmware raises alive interrupt on HCI_OP_RESET or + * BTINTEL_HCI_OP_RESET + */ + if (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET) data->gp0_received = false; hdev->stat.cmd_tx++; @@ -1352,25 +2000,24 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, } if (type == BTINTEL_PCIE_HCI_CMD_PKT && - (opcode == HCI_OP_RESET || opcode == 0xfc01)) { + (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET)) { old_ctxt = data->alive_intr_ctxt; data->alive_intr_ctxt = - (opcode == 0xfc01 ? BTINTEL_PCIE_INTEL_HCI_RESET1 : + (opcode == BTINTEL_HCI_OP_RESET ? BTINTEL_PCIE_INTEL_HCI_RESET1 : BTINTEL_PCIE_HCI_RESET); bt_dev_dbg(data->hdev, "sent cmd: 0x%4.4x alive context changed: %s -> %s", opcode, btintel_pcie_alivectxt_state2str(old_ctxt), btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); - if (opcode == HCI_OP_RESET) { - ret = wait_event_timeout(data->gp0_wait_q, - data->gp0_received, - msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); - if (!ret) { - hdev->stat.err_tx++; - bt_dev_err(hdev, "No alive interrupt received for %s", - btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); - ret = -ETIME; - goto exit_error; - } + ret = wait_event_timeout(data->gp0_wait_q, + data->gp0_received, + msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); + if (!ret) { + hdev->stat.err_tx++; + bt_dev_err(hdev, "Timeout on alive interrupt (%u ms). Alive context: %s", + BTINTEL_DEFAULT_INTR_TIMEOUT_MS, + btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); + ret = -ETIME; + goto exit_error; } } hdev->stat.byte_tx += skb->len; @@ -1390,8 +2037,31 @@ static void btintel_pcie_release_hdev(struct btintel_pcie_data *data) data->hdev = NULL; } +static void btintel_pcie_disable_interrupts(struct btintel_pcie_data *data) +{ + spin_lock(&data->irq_lock); + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, data->fh_init_mask); + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, data->hw_init_mask); + spin_unlock(&data->irq_lock); +} + +static void btintel_pcie_enable_interrupts(struct btintel_pcie_data *data) +{ + spin_lock(&data->irq_lock); + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, ~data->fh_init_mask); + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, ~data->hw_init_mask); + spin_unlock(&data->irq_lock); +} + +static void btintel_pcie_synchronize_irqs(struct btintel_pcie_data *data) +{ + for (int i = 0; i < data->alloc_vecs; i++) + synchronize_irq(data->msix_entries[i].vector); +} + static int btintel_pcie_setup_internal(struct hci_dev *hdev) { + struct btintel_pcie_data *data = hci_get_drvdata(hdev); const u8 param[1] = { 0xFF }; struct intel_version_tlv ver_tlv; struct sk_buff *skb; @@ -1415,9 +2085,9 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev) } /* 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); + hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_DIAG); /* Set up the quality report callback for Intel devices */ hdev->set_quality_report = btintel_set_quality_report; @@ -1449,6 +2119,7 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev) */ switch (INTEL_HW_VARIANT(ver_tlv.cnvi_bt)) { case 0x1e: /* BzrI */ + case 0x1f: /* ScP */ /* Display version information of TLV type */ btintel_version_info_tlv(hdev, &ver_tlv); @@ -1456,7 +2127,7 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev) * * All TLV based devices support WBS */ - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); /* Setup MSFT Extension support */ btintel_set_msft_opcode(hdev, @@ -1474,6 +2145,23 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev) break; } + data->dmp_hdr.cnvi_top = ver_tlv.cnvi_top; + data->dmp_hdr.cnvr_top = ver_tlv.cnvr_top; + data->dmp_hdr.fw_timestamp = ver_tlv.timestamp; + data->dmp_hdr.fw_build_type = ver_tlv.build_type; + data->dmp_hdr.fw_build_num = ver_tlv.build_num; + data->dmp_hdr.cnvi_bt = ver_tlv.cnvi_bt; + + if (ver_tlv.img_type == 0x02 || ver_tlv.img_type == 0x03) + data->dmp_hdr.fw_git_sha1 = ver_tlv.git_sha1; + + err = hci_devcd_register(hdev, btintel_pcie_dump_traces, btintel_pcie_dump_hdr, + btintel_pcie_dump_notify); + if (err) { + bt_dev_err(hdev, "Failed to register coredump (%d)", err); + goto exit_error; + } + btintel_print_fseq_info(hdev); exit_error: kfree_skb(skb); @@ -1489,6 +2177,9 @@ static int btintel_pcie_setup(struct hci_dev *hdev) while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) { bt_dev_err(hdev, "Firmware download retry count: %d", fw_dl_retry); + btintel_pcie_dump_debug_registers(hdev); + btintel_pcie_disable_interrupts(data); + btintel_pcie_synchronize_irqs(data); err = btintel_pcie_reset_bt(data); if (err) { bt_dev_err(hdev, "Failed to do shr reset: %d", err); @@ -1496,6 +2187,7 @@ static int btintel_pcie_setup(struct hci_dev *hdev) } usleep_range(10000, 12000); btintel_pcie_reset_ia(data); + btintel_pcie_enable_interrupts(data); btintel_pcie_config_msix(data); err = btintel_pcie_enable_bt(data); if (err) { @@ -1538,6 +2230,7 @@ static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data) goto exit_error; } + data->dmp_hdr.driver_name = KBUILD_MODNAME; return 0; exit_error: @@ -1627,6 +2320,12 @@ static void btintel_pcie_remove(struct pci_dev *pdev) data = pci_get_drvdata(pdev); + btintel_pcie_disable_interrupts(data); + + btintel_pcie_synchronize_irqs(data); + + flush_work(&data->rx_work); + btintel_pcie_reset_bt(data); for (int i = 0; i < data->alloc_vecs; i++) { struct msix_entry *msix_entry; @@ -1639,8 +2338,6 @@ static void btintel_pcie_remove(struct pci_dev *pdev) btintel_pcie_release_hdev(data); - flush_work(&data->rx_work); - destroy_workqueue(data->workqueue); btintel_pcie_free(data); @@ -1650,11 +2347,28 @@ static void btintel_pcie_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } +#ifdef CONFIG_DEV_COREDUMP +static void btintel_pcie_coredump(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct btintel_pcie_data *data = pci_get_drvdata(pdev); + + if (test_and_set_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS, &data->flags)) + return; + + data->dmp_hdr.trigger_reason = BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER; + queue_work(data->workqueue, &data->rx_work); +} +#endif + static struct pci_driver btintel_pcie_driver = { .name = KBUILD_MODNAME, .id_table = btintel_pcie_table, .probe = btintel_pcie_probe, .remove = btintel_pcie_remove, +#ifdef CONFIG_DEV_COREDUMP + .driver.coredump = btintel_pcie_coredump +#endif }; module_pci_driver(btintel_pcie_driver); diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h index f9aada0543c4..7dad4523236c 100644 --- a/drivers/bluetooth/btintel_pcie.h +++ b/drivers/bluetooth/btintel_pcie.h @@ -12,10 +12,19 @@ #define BTINTEL_PCIE_CSR_HW_REV_REG (BTINTEL_PCIE_CSR_BASE + 0x028) #define BTINTEL_PCIE_CSR_RF_ID_REG (BTINTEL_PCIE_CSR_BASE + 0x09C) #define BTINTEL_PCIE_CSR_BOOT_STAGE_REG (BTINTEL_PCIE_CSR_BASE + 0x108) +#define BTINTEL_PCIE_CSR_IPC_CONTROL_REG (BTINTEL_PCIE_CSR_BASE + 0x10C) +#define BTINTEL_PCIE_CSR_IPC_STATUS_REG (BTINTEL_PCIE_CSR_BASE + 0x110) #define BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG (BTINTEL_PCIE_CSR_BASE + 0x114) #define BTINTEL_PCIE_CSR_CI_ADDR_LSB_REG (BTINTEL_PCIE_CSR_BASE + 0x118) #define BTINTEL_PCIE_CSR_CI_ADDR_MSB_REG (BTINTEL_PCIE_CSR_BASE + 0x11C) #define BTINTEL_PCIE_CSR_IMG_RESPONSE_REG (BTINTEL_PCIE_CSR_BASE + 0x12C) +#define BTINTEL_PCIE_CSR_MBOX_1_REG (BTINTEL_PCIE_CSR_BASE + 0x170) +#define BTINTEL_PCIE_CSR_MBOX_2_REG (BTINTEL_PCIE_CSR_BASE + 0x174) +#define BTINTEL_PCIE_CSR_MBOX_3_REG (BTINTEL_PCIE_CSR_BASE + 0x178) +#define BTINTEL_PCIE_CSR_MBOX_4_REG (BTINTEL_PCIE_CSR_BASE + 0x17C) +#define BTINTEL_PCIE_CSR_MBOX_STATUS_REG (BTINTEL_PCIE_CSR_BASE + 0x180) +#define BTINTEL_PCIE_PRPH_DEV_ADDR_REG (BTINTEL_PCIE_CSR_BASE + 0x440) +#define BTINTEL_PCIE_PRPH_DEV_RD_REG (BTINTEL_PCIE_CSR_BASE + 0x458) #define BTINTEL_PCIE_CSR_HBUS_TARG_WRPTR (BTINTEL_PCIE_CSR_BASE + 0x460) /* BTINTEL_PCIE_CSR Function Control Register */ @@ -23,6 +32,12 @@ #define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT (BIT(6)) #define BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT (BIT(7)) #define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS (BIT(20)) + +#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_REQ (BIT(21)) +/* Stop MAC Access disconnection request */ +#define BTINTEL_PCIE_CSR_FUNC_CTRL_STOP_MAC_ACCESS_DIS (BIT(22)) +#define BTINTEL_PCIE_CSR_FUNC_CTRL_XTAL_CLK_REQ (BIT(23)) + #define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_STS (BIT(28)) #define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON (BIT(29)) #define BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET (BIT(31)) @@ -33,6 +48,9 @@ #define BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW (BIT(2)) #define BTINTEL_PCIE_CSR_BOOT_STAGE_ROM_LOCKDOWN (BIT(10)) #define BTINTEL_PCIE_CSR_BOOT_STAGE_IML_LOCKDOWN (BIT(11)) +#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_ERR (BIT(12)) +#define BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER (BIT(13)) +#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_HALTED (BIT(14)) #define BTINTEL_PCIE_CSR_BOOT_STAGE_MAC_ACCESS_ON (BIT(16)) #define BTINTEL_PCIE_CSR_BOOT_STAGE_ALIVE (BIT(23)) #define BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY (BIT(24)) @@ -48,6 +66,30 @@ #define BTINTEL_PCIE_CSR_MSIX_IVAR_BASE (BTINTEL_PCIE_CSR_MSIX_BASE + 0x0880) #define BTINTEL_PCIE_CSR_MSIX_IVAR(cause) (BTINTEL_PCIE_CSR_MSIX_IVAR_BASE + (cause)) +/* IOSF Debug Register */ +#define BTINTEL_PCIE_DBGC_BASE_ADDR (0xf3800300) +#define BTINTEL_PCIE_DBGC_CUR_DBGBUFF_STATUS (BTINTEL_PCIE_DBGC_BASE_ADDR + 0x1C) +#define BTINTEL_PCIE_DBGC_DBGBUFF_WRAP_ARND (BTINTEL_PCIE_DBGC_BASE_ADDR + 0x2C) + +#define BTINTEL_PCIE_DBG_IDX_BIT_MASK 0x0F +#define BTINTEL_PCIE_DBGC_DBG_BUF_IDX(data) (((data) >> 24) & BTINTEL_PCIE_DBG_IDX_BIT_MASK) +#define BTINTEL_PCIE_DBG_OFFSET_BIT_MASK 0xFFFFFF + +/* The DRAM buffer count, each buffer size, and + * fragment buffer size + */ +#define BTINTEL_PCIE_DBGC_BUFFER_COUNT 16 +#define BTINTEL_PCIE_DBGC_BUFFER_SIZE (256 * 1024) /* 256 KB */ + +#define BTINTEL_PCIE_DBGC_FRAG_VERSION 1 +#define BTINTEL_PCIE_DBGC_FRAG_BUFFER_COUNT BTINTEL_PCIE_DBGC_BUFFER_COUNT + +/* Magic number(4), version(4), size of payload length(4) */ +#define BTINTEL_PCIE_DBGC_FRAG_HEADER_SIZE 12 + +/* Num of alloc Dbg buff (4) + (LSB(4), MSB(4), Size(4)) for each buffer */ +#define BTINTEL_PCIE_DBGC_FRAG_PAYLOAD_SIZE 196 + /* Causes for the FH register interrupts */ enum msix_fh_int_causes { BTINTEL_PCIE_MSIX_FH_INT_CAUSES_0 = BIT(0), /* cause 0 */ @@ -57,6 +99,8 @@ enum msix_fh_int_causes { /* Causes for the HW register interrupts */ enum msix_hw_int_causes { BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0 = BIT(0), /* cause 32 */ + BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP1 = BIT(1), /* cause 33 */ + BTINTEL_PCIE_MSIX_HW_INT_CAUSES_HWEXP = BIT(3), /* cause 35 */ }; /* PCIe device states @@ -69,6 +113,33 @@ enum { BTINTEL_PCIE_STATE_D3_HOT = 2, BTINTEL_PCIE_STATE_D3_COLD = 3, }; + +enum { + BTINTEL_PCIE_CORE_HALTED, + BTINTEL_PCIE_HWEXP_INPROGRESS, + BTINTEL_PCIE_COREDUMP_INPROGRESS +}; + +enum btintel_pcie_tlv_type { + BTINTEL_CNVI_BT, + BTINTEL_WRITE_PTR, + BTINTEL_WRAP_CTR, + BTINTEL_TRIGGER_REASON, + BTINTEL_FW_SHA, + BTINTEL_CNVR_TOP, + BTINTEL_CNVI_TOP, + BTINTEL_DUMP_TIME, + BTINTEL_FW_BUILD, +}; + +/* causes for the MBOX interrupts */ +enum msix_mbox_int_causes { + BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX1 = BIT(0), /* cause MBOX1 */ + BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX2 = BIT(1), /* cause MBOX2 */ + BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX3 = BIT(2), /* cause MBOX3 */ + BTINTEL_PCIE_CSR_MBOX_STATUS_MBOX4 = BIT(3), /* cause MBOX4 */ +}; + #define BTINTEL_PCIE_MSIX_NON_AUTO_CLEAR_CAUSE BIT(7) /* Minimum and Maximum number of MSI-X Vector @@ -83,8 +154,11 @@ enum { /* Default interrupt timeout in msec */ #define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000 -/* The number of descriptors in TX/RX queues */ -#define BTINTEL_DESCS_COUNT 16 +/* The number of descriptors in TX queues */ +#define BTINTEL_PCIE_TX_DESCS_COUNT 32 + +/* The number of descriptors in RX queues */ +#define BTINTEL_PCIE_RX_DESCS_COUNT 64 /* Number of Queue for TX and RX * It indicates the index of the IA(Index Array) @@ -106,9 +180,6 @@ enum { /* Doorbell vector for TFD */ #define BTINTEL_PCIE_TX_DB_VEC 0 -/* Number of pending RX requests for downlink */ -#define BTINTEL_PCIE_RX_MAX_QUEUE 6 - /* Doorbell vector for FRBD */ #define BTINTEL_PCIE_RX_DB_VEC 513 @@ -325,6 +396,37 @@ struct rxq { struct data_buf *bufs; }; +/* Structure for DRAM Buffer + * @count: Number of descriptors + * @buf: Array of data_buf structure + */ +struct btintel_pcie_dbgc { + u16 count; + + void *frag_v_addr; + dma_addr_t frag_p_addr; + u16 frag_size; + + dma_addr_t buf_p_addr; + void *buf_v_addr; + struct data_buf *bufs; +}; + +struct btintel_pcie_dump_header { + const char *driver_name; + u32 cnvi_top; + u32 cnvr_top; + u16 fw_timestamp; + u8 fw_build_type; + u32 fw_build_num; + u32 fw_git_sha1; + u32 cnvi_bt; + u32 write_ptr; + u32 wrap_ctr; + u16 trigger_reason; + int state; +}; + /* struct btintel_pcie_data * @pdev: pci device * @hdev: hdev device @@ -405,6 +507,8 @@ struct btintel_pcie_data { struct txq txq; struct rxq rxq; u32 alive_intr_ctxt; + struct btintel_pcie_dbgc dbgc; + struct btintel_pcie_dump_header dmp_hdr; }; static inline u32 btintel_pcie_rd_reg32(struct btintel_pcie_data *data, @@ -444,3 +548,11 @@ static inline void btintel_pcie_clr_reg_bits(struct btintel_pcie_data *data, r &= ~bits; iowrite32(r, data->base_addr + offset); } + +static inline u32 btintel_pcie_rd_dev_mem(struct btintel_pcie_data *data, + u32 addr) +{ + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_PRPH_DEV_ADDR_REG, addr); + return btintel_pcie_rd_reg32(data, BTINTEL_PCIE_PRPH_DEV_RD_REG); +} + diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 18f34998a120..e26b07a9387d 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/of.h> +#include <linux/string_choices.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> #include <linux/mmc/sdio_func.h> @@ -88,7 +89,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) else adapter->psmode = 0; BT_DBG("PS Mode:%s", - (adapter->psmode) ? "Enable" : "Disable"); + str_enable_disable(adapter->psmode)); } else { BT_DBG("PS Mode command failed"); } diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 07cd308f7abf..93932a0d8625 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -100,7 +100,9 @@ static int btmrvl_sdio_probe_of(struct device *dev, } /* Configure wakeup (enabled by default) */ - device_init_wakeup(dev, true); + ret = devm_device_init_wakeup(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to init wakeup\n"); } } diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c index 224eafc27dbe..4390fd571dbd 100644 --- a/drivers/bluetooth/btmtk.c +++ b/drivers/bluetooth/btmtk.c @@ -1329,15 +1329,8 @@ int btmtk_usb_setup(struct hci_dev *hdev) fwname = FIRMWARE_MT7668; break; case 0x7922: - case 0x7961: case 0x7925: - /* Reset the device to ensure it's in the initial state before - * downloading the firmware to ensure. - */ - - if (!test_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags)) - btmtk_usb_subsys_reset(hdev, dev_id); - + case 0x7961: btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id, fw_version, fw_flavor); @@ -1345,12 +1338,9 @@ int btmtk_usb_setup(struct hci_dev *hdev) btmtk_usb_hci_wmt_sync); if (err < 0) { bt_dev_err(hdev, "Failed to set up firmware (%d)", err); - clear_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags); return err; } - set_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags); - /* It's Device EndPoint Reset Option Register */ err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index a1dfcfe43d3a..4fc673640bfc 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -610,7 +610,8 @@ static void btmtksdio_txrx_work(struct work_struct *work) } while (int_status || time_is_before_jiffies(txrx_timeout)); /* Enable interrupt */ - sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); + if (bdev->func->irq_handler) + sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); sdio_release_host(bdev->func); @@ -722,6 +723,10 @@ static int btmtksdio_close(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); + /* Skip btmtksdio_close if BTMTKSDIO_FUNC_ENABLED isn't set */ + if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) + return 0; + sdio_claim_host(bdev->func); /* Disable interrupt */ @@ -1136,7 +1141,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) } /* Enable WBS with mSBC codec */ - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); /* Enable GPIO reset mechanism */ if (bdev->reset) { @@ -1249,7 +1254,7 @@ static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return 0; } -static void btmtksdio_cmd_timeout(struct hci_dev *hdev) +static void btmtksdio_reset(struct hci_dev *hdev) { struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); u32 status; @@ -1360,7 +1365,7 @@ static int btmtksdio_probe(struct sdio_func *func, hdev->open = btmtksdio_open; hdev->close = btmtksdio_close; - hdev->cmd_timeout = btmtksdio_cmd_timeout; + hdev->reset = btmtksdio_reset; hdev->flush = btmtksdio_flush; hdev->setup = btmtksdio_setup; hdev->shutdown = btmtksdio_shutdown; @@ -1379,7 +1384,7 @@ static int btmtksdio_probe(struct sdio_func *func, SET_HCIDEV_DEV(hdev, &func->dev); hdev->manufacturer = 70; - set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); sdio_set_drvdata(func, bdev); @@ -1409,7 +1414,7 @@ static int btmtksdio_probe(struct sdio_func *func, */ pm_runtime_put_noidle(bdev->dev); - err = device_init_wakeup(bdev->dev, true); + err = devm_device_init_wakeup(bdev->dev); if (err) bt_dev_err(hdev, "failed to initialize device wakeup"); @@ -1442,11 +1447,15 @@ static void btmtksdio_remove(struct sdio_func *func) if (!bdev) return; + hdev = bdev->hdev; + + /* Make sure to call btmtksdio_close before removing sdio card */ + if (test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) + btmtksdio_close(hdev); + /* Be consistent the state in btmtksdio_probe */ pm_runtime_get_noresume(bdev->dev); - hdev = bdev->hdev; - sdio_set_drvdata(func, NULL); hci_unregister_dev(hdev); hci_free_dev(hdev); diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index c97e260fcb0c..51400a891f6e 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -872,7 +872,7 @@ static int btmtkuart_probe(struct serdev_device *serdev) SET_HCIDEV_DEV(hdev, &serdev->dev); hdev->manufacturer = 70; - set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); if (btmtkuart_is_standalone(bdev)) { err = clk_prepare_enable(bdev->osc); diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index aa5ec1d444a9..24f9b52605a1 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * NXP Bluetooth driver - * Copyright 2023 NXP + * Copyright 2023-2025 NXP */ #include <linux/module.h> @@ -17,6 +17,7 @@ #include <linux/crc32.h> #include <linux/string_helpers.h> #include <linux/gpio/consumer.h> +#include <linux/of_irq.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -31,6 +32,7 @@ #define BTNXPUART_SERDEV_OPEN 4 #define BTNXPUART_IR_IN_PROGRESS 5 #define BTNXPUART_FW_DOWNLOAD_ABORT 6 +#define BTNXPUART_FW_DUMP_IN_PROGRESS 7 /* NXP HW err codes */ #define BTNXPUART_IR_HW_ERR 0xb0 @@ -98,14 +100,19 @@ #define PS_STATE_AWAKE 0 #define PS_STATE_SLEEP 1 -/* Bluetooth vendor command : Sleep mode */ +/* NXP Vendor Commands. Refer user manual UM11628 on nxp.com */ +/* Set custom BD Address */ +#define HCI_NXP_SET_BD_ADDR 0xfc22 +/* Set Auto-Sleep mode */ #define HCI_NXP_AUTO_SLEEP_MODE 0xfc23 -/* Bluetooth vendor command : Wakeup method */ +/* Set Wakeup method */ #define HCI_NXP_WAKEUP_METHOD 0xfc53 -/* Bluetooth vendor command : Set operational baudrate */ +/* Set operational baudrate */ #define HCI_NXP_SET_OPER_SPEED 0xfc09 -/* Bluetooth vendor command: Independent Reset */ +/* Independent Reset (Soft Reset) */ #define HCI_NXP_IND_RESET 0xfcfc +/* Bluetooth vendor command: Trigger FW dump */ +#define HCI_NXP_TRIGGER_DUMP 0xfe91 /* Bluetooth Power State : Vendor cmd params */ #define BT_PS_ENABLE 0x02 @@ -137,7 +144,9 @@ struct ps_data { bool driver_sent_cmd; u16 h2c_ps_interval; u16 c2h_ps_interval; + bool wakeup_source; struct gpio_desc *h2c_ps_gpio; + s32 irq_handler; struct hci_dev *hdev; struct work_struct work; struct timer_list ps_timer; @@ -162,6 +171,12 @@ struct btnxpuart_data { const char *fw_name_old; }; +enum bootloader_param_change { + not_changed, + cmd_sent, + changed +}; + struct btnxpuart_dev { struct hci_dev *hdev; struct serdev_device *serdev; @@ -177,6 +192,7 @@ struct btnxpuart_dev { u32 fw_v1_sent_bytes; u32 fw_dnld_v3_offset; u32 fw_v3_offset_correction; + u32 fw_v3_prev_sent; u32 fw_v1_expected_len; u32 boot_reg_offset; wait_queue_head_t fw_dnld_done_wait_q; @@ -185,8 +201,8 @@ struct btnxpuart_dev { u32 new_baudrate; u32 current_baudrate; u32 fw_init_baudrate; - bool timeout_changed; - bool baudrate_changed; + enum bootloader_param_change timeout_changed; + enum bootloader_param_change baudrate_changed; bool helper_downloaded; struct ps_data psdata; @@ -204,10 +220,11 @@ struct btnxpuart_dev { #define NXP_NAK_V3 0x7b #define NXP_CRC_ERROR_V3 0x7c -/* Bootloader signature error codes */ -#define NXP_ACK_RX_TIMEOUT 0x0002 /* ACK not received from host */ -#define NXP_HDR_RX_TIMEOUT 0x0003 /* FW Header chunk not received */ -#define NXP_DATA_RX_TIMEOUT 0x0004 /* FW Data chunk not received */ +/* Bootloader signature error codes: Refer AN12820 from nxp.com */ +#define NXP_CRC_RX_ERROR BIT(0) /* CRC error in previous packet */ +#define NXP_ACK_RX_TIMEOUT BIT(2) /* ACK not received from host */ +#define NXP_HDR_RX_TIMEOUT BIT(3) /* FW Header chunk not received */ +#define NXP_DATA_RX_TIMEOUT BIT(4) /* FW Data chunk not received */ #define HDR_LEN 16 @@ -310,6 +327,35 @@ union nxp_v3_rx_timeout_nak_u { u8 buf[6]; }; +struct nxp_v3_crc_nak { + u8 nak; + u8 crc; +} __packed; + +union nxp_v3_crc_nak_u { + struct nxp_v3_crc_nak pkt; + u8 buf[2]; +}; + +/* FW dump */ +#define NXP_FW_DUMP_SIZE (1024 * 1000) + +struct nxp_fw_dump_hdr { + __le16 seq_num; + __le16 reserved; + __le16 buf_type; + __le16 buf_len; +}; + +union nxp_set_bd_addr_payload { + struct { + u8 param_id; + u8 param_len; + u8 param[6]; + } __packed data; + u8 buf[8]; +}; + static u8 crc8_table[CRC8_TABLE_SIZE]; /* Default configurations */ @@ -421,7 +467,7 @@ static void ps_work_func(struct work_struct *work) static void ps_timeout_func(struct timer_list *t) { - struct ps_data *data = from_timer(data, t, ps_timer); + struct ps_data *data = timer_container_of(data, t, ps_timer); struct hci_dev *hdev = data->hdev; struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); @@ -433,12 +479,21 @@ static void ps_timeout_func(struct timer_list *t) } } +static irqreturn_t ps_host_wakeup_irq_handler(int irq, void *priv) +{ + struct btnxpuart_dev *nxpdev = (struct btnxpuart_dev *)priv; + + bt_dev_dbg(nxpdev->hdev, "Host wakeup interrupt"); + return IRQ_HANDLED; +} static int ps_setup(struct hci_dev *hdev) { struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); struct serdev_device *serdev = nxpdev->serdev; struct ps_data *psdata = &nxpdev->psdata; + int ret; + /* Out-Of-Band Device Wakeup */ psdata->h2c_ps_gpio = devm_gpiod_get_optional(&serdev->dev, "device-wakeup", GPIOD_OUT_LOW); if (IS_ERR(psdata->h2c_ps_gpio)) { @@ -447,8 +502,42 @@ static int ps_setup(struct hci_dev *hdev) return PTR_ERR(psdata->h2c_ps_gpio); } - if (!psdata->h2c_ps_gpio) + if (device_property_read_u8(&serdev->dev, "nxp,wakein-pin", &psdata->h2c_wakeup_gpio)) { + psdata->h2c_wakeup_gpio = 0xff; /* 0xff: use default pin/gpio */ + } else if (!psdata->h2c_ps_gpio) { + bt_dev_warn(hdev, "nxp,wakein-pin property without device-wakeup-gpios"); psdata->h2c_wakeup_gpio = 0xff; + } + + /* Out-Of-Band Host Wakeup */ + if (of_property_read_bool(serdev->dev.of_node, "wakeup-source")) { + psdata->irq_handler = of_irq_get_byname(serdev->dev.of_node, "wakeup"); + bt_dev_info(nxpdev->hdev, "irq_handler: %d", psdata->irq_handler); + if (psdata->irq_handler > 0) + psdata->wakeup_source = true; + } + + if (device_property_read_u8(&serdev->dev, "nxp,wakeout-pin", &psdata->c2h_wakeup_gpio)) { + psdata->c2h_wakeup_gpio = 0xff; + if (psdata->wakeup_source) { + bt_dev_warn(hdev, "host wakeup interrupt without nxp,wakeout-pin"); + psdata->wakeup_source = false; + } + } else if (!psdata->wakeup_source) { + bt_dev_warn(hdev, "nxp,wakeout-pin property without host wakeup interrupt"); + psdata->c2h_wakeup_gpio = 0xff; + } + + if (psdata->wakeup_source) { + ret = devm_request_irq(&serdev->dev, psdata->irq_handler, + ps_host_wakeup_irq_handler, + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + dev_name(&serdev->dev), nxpdev); + if (ret) + bt_dev_info(hdev, "error setting wakeup IRQ handler, ignoring\n"); + disable_irq(psdata->irq_handler); + device_init_wakeup(&serdev->dev, true); + } psdata->hdev = hdev; INIT_WORK(&psdata->work, ps_work_func); @@ -540,9 +629,11 @@ static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data) pcmd.c2h_wakeupmode = psdata->c2h_wakeupmode; pcmd.c2h_wakeup_gpio = psdata->c2h_wakeup_gpio; + pcmd.h2c_wakeup_gpio = 0xff; switch (psdata->h2c_wakeupmode) { case WAKEUP_METHOD_GPIO: pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_GPIO; + pcmd.h2c_wakeup_gpio = psdata->h2c_wakeup_gpio; break; case WAKEUP_METHOD_DTR: pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_DSR; @@ -552,7 +643,6 @@ static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data) pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_BREAK; break; } - pcmd.h2c_wakeup_gpio = 0xff; skb = nxp_drv_send_cmd(hdev, HCI_NXP_WAKEUP_METHOD, sizeof(pcmd), &pcmd); if (IS_ERR(skb)) { @@ -586,8 +676,11 @@ static void ps_init(struct hci_dev *hdev) usleep_range(5000, 10000); psdata->ps_state = PS_STATE_AWAKE; - psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_NONE; - psdata->c2h_wakeup_gpio = 0xff; + + if (psdata->c2h_wakeup_gpio != 0xff) + psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_GPIO; + else + psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_NONE; psdata->cur_h2c_wakeupmode = WAKEUP_METHOD_INVALID; if (psdata->h2c_ps_gpio) @@ -618,11 +711,6 @@ static void ps_init(struct hci_dev *hdev) psdata->cur_psmode = PS_MODE_DISABLE; psdata->target_ps_mode = DEFAULT_PS_MODE; - - if (psdata->cur_h2c_wakeupmode != psdata->h2c_wakeupmode) - hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL); - if (psdata->cur_psmode != psdata->target_ps_mode) - hci_cmd_sync_queue(hdev, send_ps_cmd, NULL, NULL); } /* NXP Firmware Download Feature */ @@ -637,8 +725,8 @@ static int nxp_download_firmware(struct hci_dev *hdev) nxpdev->boot_reg_offset = 0; nxpdev->fw_dnld_v3_offset = 0; nxpdev->fw_v3_offset_correction = 0; - nxpdev->baudrate_changed = false; - nxpdev->timeout_changed = false; + nxpdev->baudrate_changed = not_changed; + nxpdev->timeout_changed = not_changed; nxpdev->helper_downloaded = false; serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_PRI_BAUDRATE); @@ -651,8 +739,10 @@ static int nxp_download_firmware(struct hci_dev *hdev) &nxpdev->tx_state), msecs_to_jiffies(60000)); - release_firmware(nxpdev->fw); - memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name)); + if (nxpdev->fw && strlen(nxpdev->fw_name)) { + release_firmware(nxpdev->fw); + memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name)); + } if (err == 0) { bt_dev_err(hdev, "FW Download Timeout. offset: %d", @@ -767,6 +857,16 @@ static bool is_fw_downloading(struct btnxpuart_dev *nxpdev) return test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); } +static bool ind_reset_in_progress(struct btnxpuart_dev *nxpdev) +{ + return test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state); +} + +static bool fw_dump_in_progress(struct btnxpuart_dev *nxpdev) +{ + return test_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state); +} + static bool process_boot_signature(struct btnxpuart_dev *nxpdev) { if (test_bit(BTNXPUART_CHECK_BOOT_SIGNATURE, &nxpdev->tx_state)) { @@ -860,15 +960,14 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb) len = __le16_to_cpu(req->len); if (!nxp_data->helper_fw_name) { - if (!nxpdev->timeout_changed) { - nxpdev->timeout_changed = nxp_fw_change_timeout(hdev, - len); + if (nxpdev->timeout_changed != changed) { + nxp_fw_change_timeout(hdev, len); + nxpdev->timeout_changed = changed; goto free_skb; } - if (!nxpdev->baudrate_changed) { - nxpdev->baudrate_changed = nxp_fw_change_baudrate(hdev, - len); - if (nxpdev->baudrate_changed) { + if (nxpdev->baudrate_changed != changed) { + if (nxp_fw_change_baudrate(hdev, len)) { + nxpdev->baudrate_changed = changed; serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_SEC_BAUDRATE); serdev_device_set_flow_control(nxpdev->serdev, true); @@ -1047,32 +1146,35 @@ static void nxp_handle_fw_download_error(struct hci_dev *hdev, struct v3_data_re struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); __u32 offset = __le32_to_cpu(req->offset); __u16 err = __le16_to_cpu(req->error); - union nxp_v3_rx_timeout_nak_u nak_tx_buf; - - switch (err) { - case NXP_ACK_RX_TIMEOUT: - case NXP_HDR_RX_TIMEOUT: - case NXP_DATA_RX_TIMEOUT: - nak_tx_buf.pkt.nak = NXP_NAK_V3; - nak_tx_buf.pkt.offset = __cpu_to_le32(offset); - nak_tx_buf.pkt.crc = crc8(crc8_table, nak_tx_buf.buf, - sizeof(nak_tx_buf) - 1, 0xff); - serdev_device_write_buf(nxpdev->serdev, nak_tx_buf.buf, - sizeof(nak_tx_buf)); - break; - default: - bt_dev_dbg(hdev, "Unknown bootloader error code: %d", err); - break; - + union nxp_v3_rx_timeout_nak_u timeout_nak_buf; + union nxp_v3_crc_nak_u crc_nak_buf; + + if (err & NXP_CRC_RX_ERROR) { + crc_nak_buf.pkt.nak = NXP_CRC_ERROR_V3; + crc_nak_buf.pkt.crc = crc8(crc8_table, crc_nak_buf.buf, + sizeof(crc_nak_buf) - 1, 0xff); + serdev_device_write_buf(nxpdev->serdev, crc_nak_buf.buf, + sizeof(crc_nak_buf)); + } else if (err & NXP_ACK_RX_TIMEOUT || + err & NXP_HDR_RX_TIMEOUT || + err & NXP_DATA_RX_TIMEOUT) { + timeout_nak_buf.pkt.nak = NXP_NAK_V3; + timeout_nak_buf.pkt.offset = __cpu_to_le32(offset); + timeout_nak_buf.pkt.crc = crc8(crc8_table, timeout_nak_buf.buf, + sizeof(timeout_nak_buf) - 1, 0xff); + serdev_device_write_buf(nxpdev->serdev, timeout_nak_buf.buf, + sizeof(timeout_nak_buf)); + } else { + bt_dev_err(hdev, "Unknown bootloader error code: %d", err); } - } static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb) { struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); struct v3_data_req *req; - __u16 len; + __u16 len = 0; + __u16 err = 0; __u32 offset; if (!process_boot_signature(nxpdev)) @@ -1082,23 +1184,40 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb) if (!req || !nxpdev->fw) goto free_skb; - if (!req->error) { + err = __le16_to_cpu(req->error); + + if (!err) { nxp_send_ack(NXP_ACK_V3, hdev); + if (nxpdev->timeout_changed == cmd_sent) + nxpdev->timeout_changed = changed; + if (nxpdev->baudrate_changed == cmd_sent) + nxpdev->baudrate_changed = changed; } else { nxp_handle_fw_download_error(hdev, req); + if (nxpdev->timeout_changed == cmd_sent && + err == NXP_CRC_RX_ERROR) { + nxpdev->fw_v3_offset_correction -= nxpdev->fw_v3_prev_sent; + nxpdev->timeout_changed = not_changed; + } + if (nxpdev->baudrate_changed == cmd_sent && + err == NXP_CRC_RX_ERROR) { + nxpdev->fw_v3_offset_correction -= nxpdev->fw_v3_prev_sent; + nxpdev->baudrate_changed = not_changed; + } goto free_skb; } len = __le16_to_cpu(req->len); - if (!nxpdev->timeout_changed) { - nxpdev->timeout_changed = nxp_fw_change_timeout(hdev, len); + if (nxpdev->timeout_changed != changed) { + nxp_fw_change_timeout(hdev, len); + nxpdev->timeout_changed = cmd_sent; goto free_skb; } - if (!nxpdev->baudrate_changed) { - nxpdev->baudrate_changed = nxp_fw_change_baudrate(hdev, len); - if (nxpdev->baudrate_changed) { + if (nxpdev->baudrate_changed != changed) { + if (nxp_fw_change_baudrate(hdev, len)) { + nxpdev->baudrate_changed = cmd_sent; serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_SEC_BAUDRATE); serdev_device_set_flow_control(nxpdev->serdev, true); @@ -1130,6 +1249,7 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb) nxpdev->fw_dnld_v3_offset, len); free_skb: + nxpdev->fw_v3_prev_sent = len; kfree_skb(skb); return 0; } @@ -1168,7 +1288,7 @@ static int nxp_set_baudrate_cmd(struct hci_dev *hdev, void *data) static int nxp_check_boot_sign(struct btnxpuart_dev *nxpdev) { serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_PRI_BAUDRATE); - if (test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state)) + if (ind_reset_in_progress(nxpdev)) serdev_device_set_flow_control(nxpdev->serdev, false); else serdev_device_set_flow_control(nxpdev->serdev, true); @@ -1197,6 +1317,104 @@ static int nxp_set_ind_reset(struct hci_dev *hdev, void *data) return hci_recv_frame(hdev, skb); } +/* Firmware dump */ +static void nxp_coredump(struct hci_dev *hdev) +{ + struct sk_buff *skb; + u8 pcmd = 2; + + skb = nxp_drv_send_cmd(hdev, HCI_NXP_TRIGGER_DUMP, 1, &pcmd); + if (IS_ERR(skb)) + bt_dev_err(hdev, "Failed to trigger FW Dump. (%ld)", PTR_ERR(skb)); + else + kfree_skb(skb); +} + +static void nxp_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb) +{ + /* Nothing to be added in FW dump header */ +} + +static int nxp_process_fw_dump(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_acl_hdr *acl_hdr = (struct hci_acl_hdr *)skb_pull_data(skb, + sizeof(*acl_hdr)); + struct nxp_fw_dump_hdr *fw_dump_hdr = (struct nxp_fw_dump_hdr *)skb->data; + struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); + __u16 seq_num = __le16_to_cpu(fw_dump_hdr->seq_num); + __u16 buf_len = __le16_to_cpu(fw_dump_hdr->buf_len); + int err; + + if (seq_num == 0x0001) { + if (test_and_set_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state)) { + bt_dev_err(hdev, "FW dump already in progress"); + goto free_skb; + } + bt_dev_warn(hdev, "==== Start FW dump ==="); + err = hci_devcd_init(hdev, NXP_FW_DUMP_SIZE); + if (err < 0) + goto free_skb; + + schedule_delayed_work(&hdev->dump.dump_timeout, + msecs_to_jiffies(20000)); + } + + err = hci_devcd_append(hdev, skb_clone(skb, GFP_ATOMIC)); + if (err < 0) + goto free_skb; + + if (buf_len == 0) { + bt_dev_warn(hdev, "==== FW dump complete ==="); + clear_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state); + hci_devcd_complete(hdev); + nxp_set_ind_reset(hdev, NULL); + } + +free_skb: + kfree_skb(skb); + return 0; +} + +static int nxp_recv_acl_pkt(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle); + + /* FW dump chunks are ACL packets with conn handle 0xfff */ + if ((handle & 0x0FFF) == 0xFFF) + return nxp_process_fw_dump(hdev, skb); + else + return hci_recv_frame(hdev, skb); +} + +static int nxp_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) +{ + union nxp_set_bd_addr_payload pcmd; + int err; + + pcmd.data.param_id = 0xfe; + pcmd.data.param_len = 6; + memcpy(pcmd.data.param, bdaddr, 6); + + /* BD address can be assigned only after first reset command. */ + err = __hci_cmd_sync_status(hdev, HCI_OP_RESET, 0, NULL, + HCI_INIT_TIMEOUT); + if (err) { + bt_dev_err(hdev, + "Reset before setting local-bd-addr failed (%d)", + err); + return err; + } + + err = __hci_cmd_sync_status(hdev, HCI_NXP_SET_BD_ADDR, sizeof(pcmd), + pcmd.buf, HCI_CMD_TIMEOUT); + if (err) { + bt_dev_err(hdev, "Changing device address failed (%d)", err); + return err; + } + + return 0; +} + /* NXP protocol */ static int nxp_setup(struct hci_dev *hdev) { @@ -1216,11 +1434,6 @@ static int nxp_setup(struct hci_dev *hdev) serdev_device_set_baudrate(nxpdev->serdev, nxpdev->fw_init_baudrate); nxpdev->current_baudrate = nxpdev->fw_init_baudrate; - if (nxpdev->current_baudrate != HCI_NXP_SEC_BAUDRATE) { - nxpdev->new_baudrate = HCI_NXP_SEC_BAUDRATE; - hci_cmd_sync_queue(hdev, nxp_set_baudrate_cmd, NULL, NULL); - } - ps_init(hdev); if (test_and_clear_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state)) @@ -1229,6 +1442,22 @@ static int nxp_setup(struct hci_dev *hdev) return 0; } +static int nxp_post_init(struct hci_dev *hdev) +{ + struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); + struct ps_data *psdata = &nxpdev->psdata; + + if (nxpdev->current_baudrate != HCI_NXP_SEC_BAUDRATE) { + nxpdev->new_baudrate = HCI_NXP_SEC_BAUDRATE; + nxp_set_baudrate_cmd(hdev, NULL); + } + if (psdata->cur_h2c_wakeupmode != psdata->h2c_wakeupmode) + send_wakeup_method_cmd(hdev, NULL); + if (psdata->cur_psmode != psdata->target_ps_mode) + send_ps_cmd(hdev, NULL); + return 0; +} + static void nxp_hw_err(struct hci_dev *hdev, u8 code) { struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); @@ -1247,25 +1476,41 @@ static int nxp_shutdown(struct hci_dev *hdev) { struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); struct sk_buff *skb; - u8 *status; u8 pcmd = 0; - if (test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state)) { + if (ind_reset_in_progress(nxpdev)) { skb = nxp_drv_send_cmd(hdev, HCI_NXP_IND_RESET, 1, &pcmd); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - status = skb_pull_data(skb, 1); - if (status) { - serdev_device_set_flow_control(nxpdev->serdev, false); - set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); - } - kfree_skb(skb); + serdev_device_set_flow_control(nxpdev->serdev, false); + set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); + /* HCI_NXP_IND_RESET command may not returns any response */ + if (!IS_ERR(skb)) + kfree_skb(skb); } return 0; } +static bool nxp_wakeup(struct hci_dev *hdev) +{ + struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); + struct ps_data *psdata = &nxpdev->psdata; + + if (psdata->c2h_wakeupmode != BT_HOST_WAKEUP_METHOD_NONE) + return true; + + return false; +} + +static void nxp_reset(struct hci_dev *hdev) +{ + struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); + + if (!ind_reset_in_progress(nxpdev) && !fw_dump_in_progress(nxpdev)) { + bt_dev_dbg(hdev, "CMD Timeout detected. Resetting."); + nxp_set_ind_reset(hdev, NULL); + } +} + static int btnxpuart_queue_skb(struct hci_dev *hdev, struct sk_buff *skb) { struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); @@ -1286,6 +1531,9 @@ static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb) struct wakeup_cmd_payload wakeup_parm; __le32 baudrate_parm; + if (fw_dump_in_progress(nxpdev)) + return -EBUSY; + /* if vendor commands are received from user space (e.g. hcitool), update * driver flags accordingly and ask driver to re-send the command to FW. * In case the payload for any command does not match expected payload @@ -1454,7 +1702,7 @@ static int btnxpuart_flush(struct hci_dev *hdev) } static const struct h4_recv_pkt nxp_recv_pkts[] = { - { H4_RECV_ACL, .recv = hci_recv_frame }, + { H4_RECV_ACL, .recv = nxp_recv_acl_pkt }, { H4_RECV_SCO, .recv = hci_recv_frame }, { H4_RECV_EVENT, .recv = hci_recv_frame }, { H4_RECV_ISO, .recv = hci_recv_frame }, @@ -1476,11 +1724,13 @@ static size_t btnxpuart_receive_buf(struct serdev_device *serdev, if (IS_ERR(nxpdev->rx_skb)) { int err = PTR_ERR(nxpdev->rx_skb); /* Safe to ignore out-of-sync bootloader signatures */ - if (!is_fw_downloading(nxpdev)) + if (!is_fw_downloading(nxpdev) && + !ind_reset_in_progress(nxpdev)) bt_dev_err(nxpdev->hdev, "Frame reassembly failed (%d)", err); return count; } - if (!is_fw_downloading(nxpdev)) + if (!is_fw_downloading(nxpdev) && + !ind_reset_in_progress(nxpdev)) nxpdev->hdev->stat.byte_rx += count; return count; } @@ -1499,6 +1749,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev) { struct hci_dev *hdev; struct btnxpuart_dev *nxpdev; + bdaddr_t ba = {0}; nxpdev = devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL); if (!nxpdev) @@ -1543,11 +1794,21 @@ static int nxp_serdev_probe(struct serdev_device *serdev) hdev->close = btnxpuart_close; hdev->flush = btnxpuart_flush; hdev->setup = nxp_setup; + hdev->post_init = nxp_post_init; hdev->send = nxp_enqueue; hdev->hw_error = nxp_hw_err; hdev->shutdown = nxp_shutdown; + hdev->wakeup = nxp_wakeup; + hdev->reset = nxp_reset; + hdev->set_bdaddr = nxp_set_bdaddr; SET_HCIDEV_DEV(hdev, &serdev->dev); + device_property_read_u8_array(&nxpdev->serdev->dev, + "local-bd-address", + (u8 *)&ba, sizeof(ba)); + if (bacmp(&ba, BDADDR_ANY)) + hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); + if (hci_register_dev(hdev) < 0) { dev_err(&serdev->dev, "Can't register HCI device\n"); goto probe_fail; @@ -1556,6 +1817,8 @@ static int nxp_serdev_probe(struct serdev_device *serdev) if (ps_setup(hdev)) goto probe_fail; + hci_devcd_register(hdev, nxp_coredump, nxp_coredump_hdr, NULL); + return 0; probe_fail: @@ -1583,6 +1846,7 @@ static void nxp_serdev_remove(struct serdev_device *serdev) nxp_set_baudrate_cmd(hdev, NULL); } } + ps_cleanup(nxpdev); hci_unregister_dev(hdev); hci_free_dev(hdev); @@ -1595,6 +1859,11 @@ static int nxp_serdev_suspend(struct device *dev) struct ps_data *psdata = &nxpdev->psdata; ps_control(psdata->hdev, PS_STATE_SLEEP); + + if (psdata->wakeup_source) { + enable_irq_wake(psdata->irq_handler); + enable_irq(psdata->irq_handler); + } return 0; } @@ -1603,11 +1872,27 @@ static int nxp_serdev_resume(struct device *dev) struct btnxpuart_dev *nxpdev = dev_get_drvdata(dev); struct ps_data *psdata = &nxpdev->psdata; + if (psdata->wakeup_source) { + disable_irq(psdata->irq_handler); + disable_irq_wake(psdata->irq_handler); + } + ps_control(psdata->hdev, PS_STATE_AWAKE); return 0; } #endif +#ifdef CONFIG_DEV_COREDUMP +static void nxp_serdev_coredump(struct device *dev) +{ + struct btnxpuart_dev *nxpdev = dev_get_drvdata(dev); + struct hci_dev *hdev = nxpdev->hdev; + + if (hdev->dump.coredump) + hdev->dump.coredump(hdev); +} +#endif + static struct btnxpuart_data w8987_data __maybe_unused = { .helper_fw_name = NULL, .fw_name = FIRMWARE_W8987, @@ -1638,6 +1923,9 @@ static struct serdev_device_driver nxp_serdev_driver = { .name = "btnxpuart", .of_match_table = of_match_ptr(nxpuart_of_match_table), .pm = &nxp_pm_ops, +#ifdef CONFIG_DEV_COREDUMP + .coredump = nxp_serdev_coredump, +#endif }, }; diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 04d02c746ec0..7c958d6065be 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -739,7 +739,7 @@ static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *co bda = (struct hci_rp_read_bd_addr *)skb->data; if (!bacmp(&bda->bdaddr, &config->bdaddr)) - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); kfree_skb(skb); @@ -782,9 +782,10 @@ static void qca_get_nvm_name_by_board(char *fwname, size_t max_size, int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, enum qca_btsoc_type soc_type, struct qca_btsoc_version ver, - const char *firmware_name) + const char *firmware_name, const char *rampatch_name) { struct qca_fw_config config = {}; + const char *variant = ""; int err; u8 rom_ver = 0; u32 soc_ver; @@ -811,44 +812,52 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, /* Download rampatch file */ config.type = TLV_TYPE_PATCH; - switch (soc_type) { - case QCA_WCN3990: - case QCA_WCN3991: - case QCA_WCN3998: - snprintf(config.fwname, sizeof(config.fwname), - "qca/crbtfw%02x.tlv", rom_ver); - break; - case QCA_WCN3988: - snprintf(config.fwname, sizeof(config.fwname), - "qca/apbtfw%02x.tlv", rom_ver); - break; - case QCA_QCA2066: - snprintf(config.fwname, sizeof(config.fwname), - "qca/hpbtfw%02x.tlv", rom_ver); - break; - case QCA_QCA6390: - snprintf(config.fwname, sizeof(config.fwname), - "qca/htbtfw%02x.tlv", rom_ver); - break; - case QCA_WCN6750: - /* Choose mbn file by default.If mbn file is not found - * then choose tlv file - */ - config.type = ELF_TYPE_PATCH; - snprintf(config.fwname, sizeof(config.fwname), - "qca/msbtfw%02x.mbn", rom_ver); - break; - case QCA_WCN6855: - snprintf(config.fwname, sizeof(config.fwname), - "qca/hpbtfw%02x.tlv", rom_ver); - break; - case QCA_WCN7850: - snprintf(config.fwname, sizeof(config.fwname), - "qca/hmtbtfw%02x.tlv", rom_ver); - break; - default: - snprintf(config.fwname, sizeof(config.fwname), - "qca/rampatch_%08x.bin", soc_ver); + if (rampatch_name) { + snprintf(config.fwname, sizeof(config.fwname), "qca/%s", rampatch_name); + } else { + switch (soc_type) { + case QCA_WCN3950: + snprintf(config.fwname, sizeof(config.fwname), + "qca/cmbtfw%02x.tlv", rom_ver); + break; + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + snprintf(config.fwname, sizeof(config.fwname), + "qca/crbtfw%02x.tlv", rom_ver); + break; + case QCA_WCN3988: + snprintf(config.fwname, sizeof(config.fwname), + "qca/apbtfw%02x.tlv", rom_ver); + break; + case QCA_QCA2066: + snprintf(config.fwname, sizeof(config.fwname), + "qca/hpbtfw%02x.tlv", rom_ver); + break; + case QCA_QCA6390: + snprintf(config.fwname, sizeof(config.fwname), + "qca/htbtfw%02x.tlv", rom_ver); + break; + case QCA_WCN6750: + /* Choose mbn file by default.If mbn file is not found + * then choose tlv file + */ + config.type = ELF_TYPE_PATCH; + snprintf(config.fwname, sizeof(config.fwname), + "qca/msbtfw%02x.mbn", rom_ver); + break; + case QCA_WCN6855: + snprintf(config.fwname, sizeof(config.fwname), + "qca/hpbtfw%02x.tlv", rom_ver); + break; + case QCA_WCN7850: + snprintf(config.fwname, sizeof(config.fwname), + "qca/hmtbtfw%02x.tlv", rom_ver); + break; + default: + snprintf(config.fwname, sizeof(config.fwname), + "qca/rampatch_%08x.bin", soc_ver); + } } err = qca_download_firmware(hdev, &config, soc_type, rom_ver); @@ -876,16 +885,23 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, } } else { switch (soc_type) { + case QCA_WCN3950: + if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_T) + variant = "t"; + else if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_S) + variant = "s"; + + snprintf(config.fwname, sizeof(config.fwname), + "qca/cmnv%02x%s.bin", rom_ver, variant); + break; case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: - if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) { - snprintf(config.fwname, sizeof(config.fwname), - "qca/crnv%02xu.bin", rom_ver); - } else { - snprintf(config.fwname, sizeof(config.fwname), - "qca/crnv%02x.bin", rom_ver); - } + if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) + variant = "u"; + + snprintf(config.fwname, sizeof(config.fwname), + "qca/crnv%02x%s.bin", rom_ver, variant); break; case QCA_WCN3988: snprintf(config.fwname, sizeof(config.fwname), @@ -944,6 +960,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, * VsMsftOpCode. */ switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index bb5207d7a8c7..8f3c1b1c77b3 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -41,6 +41,9 @@ #define QCA_WCN3991_SOC_ID 0x40014320 +#define QCA_WCN3950_SOC_ID_T 0x40074130 +#define QCA_WCN3950_SOC_ID_S 0x40075130 + /* QCA chipset version can be decided by patch and SoC * version, combination with upper 2 bytes from SoC * and lower 2 bytes from patch will be used. @@ -145,6 +148,7 @@ enum qca_btsoc_type { QCA_INVALID = -1, QCA_AR3002, QCA_ROME, + QCA_WCN3950, QCA_WCN3988, QCA_WCN3990, QCA_WCN3998, @@ -161,7 +165,7 @@ enum qca_btsoc_type { int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, enum qca_btsoc_type soc_type, struct qca_btsoc_version ver, - const char *firmware_name); + const char *firmware_name, const char *rampatch_name); int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver, enum qca_btsoc_type); int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); @@ -176,7 +180,8 @@ static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdad static inline int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, enum qca_btsoc_type soc_type, struct qca_btsoc_version ver, - const char *firmware_name) + const char *firmware_name, + const char *rampatch_name) { return -EOPNOTSUPP; } diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index c0eb71d6ffd3..d2e13fcb6bab 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -117,7 +117,7 @@ static int btqcomsmd_setup(struct hci_dev *hdev) /* Devices do not have persistent storage for BD address. Retrieve * it from the firmware node property. */ - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); return 0; } diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index d3eba0d4a57d..4d182cf6e037 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -1215,6 +1215,8 @@ next: rtl_dev_err(hdev, "mandatory config file %s not found", btrtl_dev->ic_info->cfg_name); ret = btrtl_dev->cfg_len; + if (!ret) + ret = -EINVAL; goto err_free; } } @@ -1285,7 +1287,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) /* Enable controller to do both LE scan and BR/EDR inquiry * simultaneously. */ - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); /* Enable central-peripheral role (able to create new connections with * an existing connection in slave role). @@ -1299,7 +1301,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) case CHIP_ID_8851B: case CHIP_ID_8922A: case CHIP_ID_8852BT: - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); /* RTL8852C needs to transmit mSBC data continuously without * the zero length of USB packets for the ALT 6 supported chips @@ -1310,7 +1312,8 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) if (btrtl_dev->project_id == CHIP_ID_8852A || btrtl_dev->project_id == CHIP_ID_8852B || btrtl_dev->project_id == CHIP_ID_8852C) - set_bit(HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER, &hdev->quirks); + hci_set_quirk(hdev, + HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER); hci_set_aosp_capable(hdev); break; @@ -1329,8 +1332,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) * but it doesn't support any features from page 2 - * it either responds with garbage or with error status */ - set_bit(HCI_QUIRK_BROKEN_LOCAL_EXT_FEATURES_PAGE_2, - &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_EXT_FEATURES_PAGE_2); break; default: break; diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index a69feb08486a..8325655ce6aa 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -327,7 +327,7 @@ static int btsdio_probe(struct sdio_func *func, hdev->send = btsdio_send_frame; if (func->vendor == 0x0104 && func->device == 0x00c5) - set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); err = hci_register_dev(hdev); if (err < 0) { diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 72e85673b709..9efdd111baf5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -21,6 +21,7 @@ #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> +#include <net/bluetooth/hci_drv.h> #include "btintel.h" #include "btbcm.h" @@ -375,10 +376,38 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0f3), .driver_info = BTUSB_QCA_WCN6855 | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe100), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe103), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe10a), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe10d), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe11b), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe11c), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe11f), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe141), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe14a), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe14b), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe14d), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3623), .driver_info = BTUSB_QCA_WCN6855 | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3624), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x2c7c, 0x0130), .driver_info = BTUSB_QCA_WCN6855 | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x2c7c, 0x0131), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x2c7c, 0x0132), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, @@ -483,6 +512,15 @@ static const struct usb_device_id quirks_table[] = { { USB_DEVICE(0x13d3, 0x3549), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + /* Realtek 8851BE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0xb850), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x13d3, 0x3600), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x13d3, 0x3601), .driver_info = BTUSB_REALTEK }, + + /* Realtek 8851BU Bluetooth devices */ + { USB_DEVICE(0x3625, 0x010b), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + /* Realtek 8852AE Bluetooth devices */ { USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, @@ -602,6 +640,8 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3567), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3576), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3578), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3583), .driver_info = BTUSB_MEDIATEK | @@ -634,12 +674,18 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe152), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe153), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3584), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3605), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3607), .driver_info = BTUSB_MEDIATEK | @@ -664,6 +710,8 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe139), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe14e), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe14f), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe150), .driver_info = BTUSB_MEDIATEK | @@ -678,8 +726,12 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3608), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3613), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3628), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3630), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, /* Additional Realtek 8723AE Bluetooth devices */ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK }, @@ -885,7 +937,6 @@ struct btusb_data { int (*disconnect)(struct hci_dev *hdev); int oob_wake_irq; /* irq for out-of-band wake-on-bt */ - unsigned cmd_timeout_cnt; struct qca_dump_info qca_dump; }; @@ -895,11 +946,6 @@ static void btusb_reset(struct hci_dev *hdev) struct btusb_data *data; int err; - if (hdev->reset) { - hdev->reset(hdev); - return; - } - data = hci_get_drvdata(hdev); /* This is not an unbalanced PM reference since the device will reset */ err = usb_autopm_get_interface(data->intf); @@ -912,15 +958,12 @@ static void btusb_reset(struct hci_dev *hdev) usb_queue_reset_device(data->intf); } -static void btusb_intel_cmd_timeout(struct hci_dev *hdev) +static void btusb_intel_reset(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct gpio_desc *reset_gpio = data->reset_gpio; struct btintel_data *intel_data = hci_get_priv(hdev); - if (++data->cmd_timeout_cnt < 5) - return; - if (intel_data->acpi_reset_method) { if (test_and_set_bit(INTEL_ACPI_RESET_ACTIVE, intel_data->flags)) { bt_dev_err(hdev, "acpi: last reset failed ? Not resetting again"); @@ -993,7 +1036,7 @@ static inline void btusb_rtl_alloc_devcoredump(struct hci_dev *hdev, } } -static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) +static void btusb_rtl_reset(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct gpio_desc *reset_gpio = data->reset_gpio; @@ -1003,9 +1046,6 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0); - if (++data->cmd_timeout_cnt < 5) - return; - if (!reset_gpio) { btusb_reset(hdev); return; @@ -1040,19 +1080,16 @@ static void btusb_rtl_hw_error(struct hci_dev *hdev, u8 code) btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0); } -static void btusb_qca_cmd_timeout(struct hci_dev *hdev) +static void btusb_qca_reset(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct gpio_desc *reset_gpio = data->reset_gpio; if (test_bit(BTUSB_HW_SSR_ACTIVE, &data->flags)) { - bt_dev_info(hdev, "Ramdump in progress, defer cmd_timeout"); + bt_dev_info(hdev, "Ramdump in progress, defer reset"); return; } - if (++data->cmd_timeout_cnt < 5) - return; - if (reset_gpio) { bt_dev_err(hdev, "Reset qca device via bt_en gpio"); @@ -2112,7 +2149,8 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return submit_or_queue_tx_urb(hdev, urb); case HCI_SCODATA_PKT: - if (hci_conn_num(hdev, SCO_LINK) < 1) + if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + hci_conn_num(hdev, SCO_LINK) < 1) return -ENODEV; urb = alloc_isoc_urb(hdev, skb); @@ -2441,16 +2479,18 @@ static int btusb_setup_csr(struct hci_dev *hdev) * Probably will need to be expanded in the future; * without these the controller will lock up. */ - set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks); - set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ERR_DATA_REPORTING); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL); + hci_set_quirk(hdev, HCI_QUIRK_NO_SUSPEND_NOTIFIER); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_VOICE_SETTING); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE); /* Clear the reset quirk since this is not an actual * early Bluetooth 1.1 device from CSR. */ - clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); - clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + hci_clear_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); + hci_clear_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); /* * Special workaround for these BT 4.0 chip clones, and potentially more: @@ -2561,12 +2601,12 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) else urb = alloc_ctrl_urb(hdev, skb); - /* When the 0xfc01 command is issued to boot into - * the operational firmware, it will actually not - * send a command complete event. To keep the flow + /* When the BTINTEL_HCI_OP_RESET command is issued to + * boot into the operational firmware, it will actually + * not send a command complete event. To keep the flow * control working inject that event here. */ - if (opcode == 0xfc01) + if (opcode == BTINTEL_HCI_OP_RESET) inject_cmd_complete(hdev, opcode); } else { urb = alloc_ctrl_urb(hdev, skb); @@ -2586,7 +2626,8 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) return submit_or_queue_tx_urb(hdev, urb); case HCI_SCODATA_PKT: - if (hci_conn_num(hdev, SCO_LINK) < 1) + if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + hci_conn_num(hdev, SCO_LINK) < 1) return -ENODEV; urb = alloc_isoc_urb(hdev, skb); @@ -2655,7 +2696,7 @@ static void btusb_mtk_claim_iso_intf(struct btusb_data *data) device_unlock(&btmtk_data->isopkt_intf->dev); if (err < 0) { btmtk_data->isopkt_intf = NULL; - bt_dev_err(data->hdev, "Failed to claim iso interface"); + bt_dev_err(data->hdev, "Failed to claim iso interface: %d", err); return; } @@ -2943,55 +2984,27 @@ static void btusb_coredump_qca(struct hci_dev *hdev) bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err); } -/* - * ==0: not a dump pkt. - * < 0: fails to handle a dump pkt - * > 0: otherwise. - */ +/* Return: 0 on success, negative errno on failure. */ static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb) { - int ret = 1; + int ret = 0; + unsigned int skip = 0; u8 pkt_type; - u8 *sk_ptr; - unsigned int sk_len; u16 seqno; u32 dump_size; - struct hci_event_hdr *event_hdr; - struct hci_acl_hdr *acl_hdr; struct qca_dump_hdr *dump_hdr; struct btusb_data *btdata = hci_get_drvdata(hdev); struct usb_device *udev = btdata->udev; pkt_type = hci_skb_pkt_type(skb); - sk_ptr = skb->data; - sk_len = skb->len; + skip = sizeof(struct hci_event_hdr); + if (pkt_type == HCI_ACLDATA_PKT) + skip += sizeof(struct hci_acl_hdr); - if (pkt_type == HCI_ACLDATA_PKT) { - acl_hdr = hci_acl_hdr(skb); - if (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE) - return 0; - sk_ptr += HCI_ACL_HDR_SIZE; - sk_len -= HCI_ACL_HDR_SIZE; - event_hdr = (struct hci_event_hdr *)sk_ptr; - } else { - event_hdr = hci_event_hdr(skb); - } - - if ((event_hdr->evt != HCI_VENDOR_PKT) - || (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE))) - return 0; + skb_pull(skb, skip); + dump_hdr = (struct qca_dump_hdr *)skb->data; - sk_ptr += HCI_EVENT_HDR_SIZE; - sk_len -= HCI_EVENT_HDR_SIZE; - - dump_hdr = (struct qca_dump_hdr *)sk_ptr; - if ((sk_len < offsetof(struct qca_dump_hdr, data)) - || (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) - || (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) - return 0; - - /*it is dump pkt now*/ seqno = le16_to_cpu(dump_hdr->seqno); if (seqno == 0) { set_bit(BTUSB_HW_SSR_ACTIVE, &btdata->flags); @@ -3011,16 +3024,15 @@ static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb) btdata->qca_dump.ram_dump_size = dump_size; btdata->qca_dump.ram_dump_seqno = 0; - sk_ptr += offsetof(struct qca_dump_hdr, data0); - sk_len -= offsetof(struct qca_dump_hdr, data0); + + skb_pull(skb, offsetof(struct qca_dump_hdr, data0)); usb_disable_autosuspend(udev); bt_dev_info(hdev, "%s memdump size(%u)\n", (pkt_type == HCI_ACLDATA_PKT) ? "ACL" : "event", dump_size); } else { - sk_ptr += offsetof(struct qca_dump_hdr, data); - sk_len -= offsetof(struct qca_dump_hdr, data); + skb_pull(skb, offsetof(struct qca_dump_hdr, data)); } if (!btdata->qca_dump.ram_dump_size) { @@ -3040,7 +3052,6 @@ static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb) return ret; } - skb_pull(skb, skb->len - sk_len); hci_devcd_append(hdev, skb); btdata->qca_dump.ram_dump_seqno++; if (seqno == QCA_LAST_SEQUENCE_NUM) { @@ -3065,17 +3076,74 @@ out: return ret; } +/* Return: true if the ACL packet is a dump packet, false otherwise. */ +static bool acl_pkt_is_dump_qca(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_event_hdr *event_hdr; + struct hci_acl_hdr *acl_hdr; + struct qca_dump_hdr *dump_hdr; + struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); + bool is_dump = false; + + if (!clone) + return false; + + acl_hdr = skb_pull_data(clone, sizeof(*acl_hdr)); + if (!acl_hdr || (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE)) + goto out; + + event_hdr = skb_pull_data(clone, sizeof(*event_hdr)); + if (!event_hdr || (event_hdr->evt != HCI_VENDOR_PKT)) + goto out; + + dump_hdr = skb_pull_data(clone, sizeof(*dump_hdr)); + if (!dump_hdr || (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || + (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) + goto out; + + is_dump = true; +out: + consume_skb(clone); + return is_dump; +} + +/* Return: true if the event packet is a dump packet, false otherwise. */ +static bool evt_pkt_is_dump_qca(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_event_hdr *event_hdr; + struct qca_dump_hdr *dump_hdr; + struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); + bool is_dump = false; + + if (!clone) + return false; + + event_hdr = skb_pull_data(clone, sizeof(*event_hdr)); + if (!event_hdr || (event_hdr->evt != HCI_VENDOR_PKT)) + goto out; + + dump_hdr = skb_pull_data(clone, sizeof(*dump_hdr)); + if (!dump_hdr || (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || + (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) + goto out; + + is_dump = true; +out: + consume_skb(clone); + return is_dump; +} + static int btusb_recv_acl_qca(struct hci_dev *hdev, struct sk_buff *skb) { - if (handle_dump_pkt_qca(hdev, skb)) - return 0; + if (acl_pkt_is_dump_qca(hdev, skb)) + return handle_dump_pkt_qca(hdev, skb); return hci_recv_frame(hdev, skb); } static int btusb_recv_evt_qca(struct hci_dev *hdev, struct sk_buff *skb) { - if (handle_dump_pkt_qca(hdev, skb)) - return 0; + if (evt_pkt_is_dump_qca(hdev, skb)) + return handle_dump_pkt_qca(hdev, skb); return hci_recv_frame(hdev, skb); } @@ -3131,6 +3199,32 @@ static const struct qca_device_info qca_devices_table[] = { { 0x00190200, 40, 4, 16 }, /* WCN785x 2.0 */ }; +static u16 qca_extract_board_id(const struct qca_version *ver) +{ + u16 flag = le16_to_cpu(ver->flag); + u16 board_id = 0; + + if (((flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) { + /* The board_id should be split into two bytes + * The 1st byte is chip ID, and the 2nd byte is platform ID + * For example, board ID 0x010A, 0x01 is platform ID. 0x0A is chip ID + * we have several platforms, and platform IDs are continuously added + * Platform ID: + * 0x00 is for Mobile + * 0x01 is for X86 + * 0x02 is for Automotive + * 0x03 is for Consumer electronic + */ + board_id = (ver->chip_id << 8) + ver->platform_id; + } + + /* Take 0xffff as invalid board ID */ + if (board_id == 0xffff) + board_id = 0; + + return board_id; +} + static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request, void *data, u16 size) { @@ -3287,44 +3381,28 @@ static void btusb_generate_qca_nvm_name(char *fwname, size_t max_size, const struct qca_version *ver) { u32 rom_version = le32_to_cpu(ver->rom_version); - u16 flag = le16_to_cpu(ver->flag); - - if (((flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) { - /* The board_id should be split into two bytes - * The 1st byte is chip ID, and the 2nd byte is platform ID - * For example, board ID 0x010A, 0x01 is platform ID. 0x0A is chip ID - * we have several platforms, and platform IDs are continuously added - * Platform ID: - * 0x00 is for Mobile - * 0x01 is for X86 - * 0x02 is for Automotive - * 0x03 is for Consumer electronic - */ - u16 board_id = (ver->chip_id << 8) + ver->platform_id; - const char *variant; + const char *variant; + int len; + u16 board_id; - switch (le32_to_cpu(ver->ram_version)) { - case WCN6855_2_0_RAM_VERSION_GF: - case WCN6855_2_1_RAM_VERSION_GF: - variant = "_gf"; - break; - default: - variant = ""; - break; - } + board_id = qca_extract_board_id(ver); - if (board_id == 0) { - snprintf(fwname, max_size, "qca/nvm_usb_%08x%s.bin", - rom_version, variant); - } else { - snprintf(fwname, max_size, "qca/nvm_usb_%08x%s_%04x.bin", - rom_version, variant, board_id); - } - } else { - snprintf(fwname, max_size, "qca/nvm_usb_%08x.bin", - rom_version); + switch (le32_to_cpu(ver->ram_version)) { + case WCN6855_2_0_RAM_VERSION_GF: + case WCN6855_2_1_RAM_VERSION_GF: + variant = "_gf"; + break; + default: + variant = NULL; + break; } + len = snprintf(fwname, max_size, "qca/nvm_usb_%08x", rom_version); + if (variant) + len += snprintf(fwname + len, max_size - len, "%s", variant); + if (board_id) + len += snprintf(fwname + len, max_size - len, "_%04x", board_id); + len += snprintf(fwname + len, max_size - len, ".bin"); } static int btusb_setup_qca_load_nvm(struct hci_dev *hdev, @@ -3433,7 +3511,7 @@ static int btusb_setup_qca(struct hci_dev *hdev) /* Mark HCI_OP_ENHANCED_SETUP_SYNC_CONN as broken as it doesn't seem to * work with the likes of HSP/HFP mSBC. */ - set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN); return 0; } @@ -3652,12 +3730,143 @@ static ssize_t force_poll_sync_write(struct file *file, } static const struct file_operations force_poll_sync_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_poll_sync_read, .write = force_poll_sync_write, .llseek = default_llseek, }; +#define BTUSB_HCI_DRV_OP_SUPPORTED_ALTSETTINGS \ + hci_opcode_pack(HCI_DRV_OGF_DRIVER_SPECIFIC, 0x0000) +#define BTUSB_HCI_DRV_SUPPORTED_ALTSETTINGS_SIZE 0 +struct btusb_hci_drv_rp_supported_altsettings { + __u8 num; + __u8 altsettings[]; +} __packed; + +#define BTUSB_HCI_DRV_OP_SWITCH_ALTSETTING \ + hci_opcode_pack(HCI_DRV_OGF_DRIVER_SPECIFIC, 0x0001) +#define BTUSB_HCI_DRV_SWITCH_ALTSETTING_SIZE 1 +struct btusb_hci_drv_cmd_switch_altsetting { + __u8 altsetting; +} __packed; + +static const struct { + u16 opcode; + const char *desc; +} btusb_hci_drv_supported_commands[] = { + /* Common commands */ + { HCI_DRV_OP_READ_INFO, "Read Info" }, + + /* Driver specific commands */ + { BTUSB_HCI_DRV_OP_SUPPORTED_ALTSETTINGS, "Supported Altsettings" }, + { BTUSB_HCI_DRV_OP_SWITCH_ALTSETTING, "Switch Altsetting" }, +}; +static int btusb_hci_drv_read_info(struct hci_dev *hdev, void *data, + u16 data_len) +{ + struct hci_drv_rp_read_info *rp; + size_t rp_size; + int err, i; + u16 opcode, num_supported_commands = + ARRAY_SIZE(btusb_hci_drv_supported_commands); + + rp_size = sizeof(*rp) + num_supported_commands * 2; + + rp = kmalloc(rp_size, GFP_KERNEL); + if (!rp) + return -ENOMEM; + + strscpy_pad(rp->driver_name, btusb_driver.name); + + rp->num_supported_commands = cpu_to_le16(num_supported_commands); + for (i = 0; i < num_supported_commands; i++) { + opcode = btusb_hci_drv_supported_commands[i].opcode; + bt_dev_info(hdev, + "Supported HCI Drv command (0x%02x|0x%04x): %s", + hci_opcode_ogf(opcode), + hci_opcode_ocf(opcode), + btusb_hci_drv_supported_commands[i].desc); + rp->supported_commands[i] = cpu_to_le16(opcode); + } + + err = hci_drv_cmd_complete(hdev, HCI_DRV_OP_READ_INFO, + HCI_DRV_STATUS_SUCCESS, rp, rp_size); + + kfree(rp); + return err; +} + +static int btusb_hci_drv_supported_altsettings(struct hci_dev *hdev, void *data, + u16 data_len) +{ + struct btusb_data *drvdata = hci_get_drvdata(hdev); + struct btusb_hci_drv_rp_supported_altsettings *rp; + size_t rp_size; + int err; + u8 i; + + /* There are at most 7 alt (0 - 6) */ + rp = kmalloc(sizeof(*rp) + 7, GFP_KERNEL); + if (!rp) + return -ENOMEM; + + rp->num = 0; + if (!drvdata->isoc) + goto done; + + for (i = 0; i <= 6; i++) { + if (btusb_find_altsetting(drvdata, i)) + rp->altsettings[rp->num++] = i; + } + +done: + rp_size = sizeof(*rp) + rp->num; + + err = hci_drv_cmd_complete(hdev, BTUSB_HCI_DRV_OP_SUPPORTED_ALTSETTINGS, + HCI_DRV_STATUS_SUCCESS, rp, rp_size); + kfree(rp); + return err; +} + +static int btusb_hci_drv_switch_altsetting(struct hci_dev *hdev, void *data, + u16 data_len) +{ + struct btusb_hci_drv_cmd_switch_altsetting *cmd = data; + u8 status; + + if (cmd->altsetting > 6) { + status = HCI_DRV_STATUS_INVALID_PARAMETERS; + } else { + if (btusb_switch_alt_setting(hdev, cmd->altsetting)) + status = HCI_DRV_STATUS_UNSPECIFIED_ERROR; + else + status = HCI_DRV_STATUS_SUCCESS; + } + + return hci_drv_cmd_status(hdev, BTUSB_HCI_DRV_OP_SWITCH_ALTSETTING, + status); +} + +static const struct hci_drv_handler btusb_hci_drv_common_handlers[] = { + { btusb_hci_drv_read_info, HCI_DRV_READ_INFO_SIZE }, +}; + +static const struct hci_drv_handler btusb_hci_drv_specific_handlers[] = { + { btusb_hci_drv_supported_altsettings, + BTUSB_HCI_DRV_SUPPORTED_ALTSETTINGS_SIZE }, + { btusb_hci_drv_switch_altsetting, + BTUSB_HCI_DRV_SWITCH_ALTSETTING_SIZE }, +}; + +static struct hci_drv btusb_hci_drv = { + .common_handler_count = ARRAY_SIZE(btusb_hci_drv_common_handlers), + .common_handlers = btusb_hci_drv_common_handlers, + .specific_handler_count = ARRAY_SIZE(btusb_hci_drv_specific_handlers), + .specific_handlers = btusb_hci_drv_specific_handlers, +}; + static int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -3797,12 +4006,13 @@ static int btusb_probe(struct usb_interface *intf, data->reset_gpio = reset_gpio; } - hdev->open = btusb_open; - hdev->close = btusb_close; - hdev->flush = btusb_flush; - hdev->send = btusb_send_frame; - hdev->notify = btusb_notify; - hdev->wakeup = btusb_wakeup; + hdev->open = btusb_open; + hdev->close = btusb_close; + hdev->flush = btusb_flush; + hdev->send = btusb_send_frame; + hdev->notify = btusb_notify; + hdev->wakeup = btusb_wakeup; + hdev->hci_drv = &btusb_hci_drv; #ifdef CONFIG_PM err = btusb_config_oob_wake(hdev); @@ -3817,10 +4027,10 @@ static int btusb_probe(struct usb_interface *intf, } #endif if (id->driver_info & BTUSB_CW6622) - set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY); if (id->driver_info & BTUSB_BCM2045) - set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY); if (id->driver_info & BTUSB_BCM92035) hdev->setup = btusb_setup_bcm92035; @@ -3854,7 +4064,7 @@ static int btusb_probe(struct usb_interface *intf, /* Transport specific configuration */ hdev->send = btusb_send_frame_intel; - hdev->cmd_timeout = btusb_intel_cmd_timeout; + hdev->reset = btusb_intel_reset; if (id->driver_info & BTUSB_INTEL_NO_WBS_SUPPORT) btintel_set_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT); @@ -3874,11 +4084,11 @@ static int btusb_probe(struct usb_interface *intf, hdev->setup = btusb_mtk_setup; hdev->shutdown = btusb_mtk_shutdown; hdev->manufacturer = 70; - hdev->cmd_timeout = btmtk_reset_sync; + hdev->reset = btmtk_reset_sync; hdev->set_bdaddr = btmtk_set_bdaddr; hdev->send = btusb_send_frame_mtk; - set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); - set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); data->recv_acl = btmtk_usb_recv_acl; data->suspend = btmtk_usb_suspend; data->resume = btmtk_usb_resume; @@ -3886,28 +4096,28 @@ static int btusb_probe(struct usb_interface *intf, } if (id->driver_info & BTUSB_SWAVE) { - set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_FIXUP_INQUIRY_MODE); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_COMMANDS); } if (id->driver_info & BTUSB_INTEL_BOOT) { hdev->manufacturer = 2; - set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); } if (id->driver_info & BTUSB_ATH3012) { data->setup_on_usb = btusb_setup_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); + hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); } if (id->driver_info & BTUSB_QCA_ROME) { data->setup_on_usb = btusb_setup_qca; hdev->shutdown = btusb_shutdown_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; - hdev->cmd_timeout = btusb_qca_cmd_timeout; - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + hdev->reset = btusb_qca_reset; + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); btusb_check_needs_reset_resume(intf); } @@ -3920,8 +4130,8 @@ static int btusb_probe(struct usb_interface *intf, data->setup_on_usb = btusb_setup_qca; hdev->shutdown = btusb_shutdown_qca; hdev->set_bdaddr = btusb_set_bdaddr_wcn6855; - hdev->cmd_timeout = btusb_qca_cmd_timeout; - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + hdev->reset = btusb_qca_reset; + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); hci_set_msft_opcode(hdev, 0xFD70); } @@ -3939,7 +4149,7 @@ static int btusb_probe(struct usb_interface *intf, btrtl_set_driver_name(hdev, btusb_driver.name); hdev->setup = btusb_setup_realtek; hdev->shutdown = btrtl_shutdown_realtek; - hdev->cmd_timeout = btusb_rtl_cmd_timeout; + hdev->reset = btusb_rtl_reset; hdev->hw_error = btusb_rtl_hw_error; /* Realtek devices need to set remote wakeup on auto-suspend */ @@ -3949,35 +4159,35 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_ACTIONS_SEMI) { /* Support is advertised, but not implemented */ - set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ERR_DATA_REPORTING); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_CREATE_CONN); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT); } if (!reset) - set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) { if (!disable_scofix) - set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_FIXUP_BUFFER_SIZE); } if (id->driver_info & BTUSB_BROKEN_ISOC) data->isoc = NULL; if (id->driver_info & BTUSB_WIDEBAND_SPEECH) - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); if (id->driver_info & BTUSB_INVALID_LE_STATES) - set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES); if (id->driver_info & BTUSB_DIGIANSWER) { data->cmdreq_type = USB_TYPE_VENDOR; - set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); } if (id->driver_info & BTUSB_CSR) { @@ -3986,10 +4196,10 @@ static int btusb_probe(struct usb_interface *intf, /* Old firmware would otherwise execute USB reset */ if (bcdDevice < 0x117) - set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); /* This must be set first in case we disable it for fakes */ - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); /* Fake CSR devices with broken commands */ if (le16_to_cpu(udev->descriptor.idVendor) == 0x0a12 && @@ -4002,7 +4212,7 @@ static int btusb_probe(struct usb_interface *intf, /* New sniffer firmware has crippled HCI interface */ if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) - set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); } if (id->driver_info & BTUSB_INTEL_BOOT) { diff --git a/drivers/bluetooth/hci_aml.c b/drivers/bluetooth/hci_aml.c index dc9541e76d81..707e90f80130 100644 --- a/drivers/bluetooth/hci_aml.c +++ b/drivers/bluetooth/hci_aml.c @@ -313,8 +313,7 @@ static int aml_download_firmware(struct hci_dev *hdev, const char *fw_name) goto exit; exit: - if (firmware) - release_firmware(firmware); + release_firmware(firmware); return ret; } @@ -425,7 +424,7 @@ static int aml_check_bdaddr(struct hci_dev *hdev) if (!bacmp(&paddr->bdaddr, AML_BDADDR_DEFAULT)) { bt_dev_info(hdev, "amlbt using default bdaddr (%pM)", &paddr->bdaddr); - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); } exit: diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 9684eb16059b..f96617b85d87 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -643,8 +643,8 @@ static int bcm_setup(struct hci_uart *hu) * Allow the bootloader to set a valid address through the * device tree. */ - if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks)) - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); + if (hci_test_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR)) + hci_set_quirk(hu->hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); if (!bcm_request_irq(bcm)) err = bcm_setup_sleep(hu); diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c index 9bce53e49cfa..8a9aa33776b0 100644 --- a/drivers/bluetooth/hci_bcm4377.c +++ b/drivers/bluetooth/hci_bcm4377.c @@ -1435,7 +1435,7 @@ static int bcm4377_check_bdaddr(struct bcm4377_data *bcm4377) bda = (struct hci_rp_read_bd_addr *)skb->data; if (!bcm4377_is_valid_bdaddr(bcm4377, &bda->bdaddr)) - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &bcm4377->hdev->quirks); + hci_set_quirk(bcm4377->hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); kfree_skb(skb); return 0; @@ -2389,13 +2389,13 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id) hdev->setup = bcm4377_hci_setup; if (bcm4377->hw->broken_mws_transport_config) - set_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG); if (bcm4377->hw->broken_ext_scan) - set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); if (bcm4377->hw->broken_le_coded) - set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_CODED); if (bcm4377->hw->broken_le_ext_adv_report_phy) - set_bit(HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY); pci_set_drvdata(pdev, bcm4377); hci_set_drvdata(hdev, bcm4377); diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 76878119d910..664d82d1e613 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -382,7 +382,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) } if (skb_queue_empty(&bcsp->unack)) - del_timer(&bcsp->tbcsp); + timer_delete(&bcsp->tbcsp); spin_unlock_irqrestore(&bcsp->unack.lock, flags); @@ -688,7 +688,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) /* Arrange to retransmit all messages in the relq. */ static void bcsp_timed_event(struct timer_list *t) { - struct bcsp_struct *bcsp = from_timer(bcsp, t, tbcsp); + struct bcsp_struct *bcsp = timer_container_of(bcsp, t, tbcsp); struct hci_uart *hu = bcsp->hu; struct sk_buff *skb; unsigned long flags; diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index c0436881a533..d0d4420c1a0f 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -149,7 +149,7 @@ static void h5_timed_event(struct timer_list *t) { const unsigned char sync_req[] = { 0x01, 0x7e }; unsigned char conf_req[3] = { 0x03, 0xfc }; - struct h5 *h5 = from_timer(h5, t, timer); + struct h5 *h5 = timer_container_of(h5, t, timer); struct hci_uart *hu = h5->hu; struct sk_buff *skb; unsigned long flags; @@ -197,7 +197,7 @@ static void h5_peer_reset(struct hci_uart *hu) h5->state = H5_UNINITIALIZED; - del_timer(&h5->timer); + timer_delete(&h5->timer); skb_queue_purge(&h5->rel); skb_queue_purge(&h5->unrel); @@ -254,7 +254,7 @@ static int h5_close(struct hci_uart *hu) { struct h5 *h5 = hu->priv; - del_timer_sync(&h5->timer); + timer_delete_sync(&h5->timer); skb_queue_purge(&h5->unack); skb_queue_purge(&h5->rel); @@ -318,7 +318,7 @@ static void h5_pkt_cull(struct h5 *h5) } if (skb_queue_empty(&h5->unack)) - del_timer(&h5->timer); + timer_delete(&h5->timer); unlock: spin_unlock_irqrestore(&h5->unack.lock, flags); diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 811f33701f84..9b353c3d6442 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -660,7 +660,7 @@ static int intel_setup(struct hci_uart *hu) */ if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) { bt_dev_info(hdev, "No device address configured"); - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); } /* With this Intel bootloader only the hardware variant and device @@ -1029,12 +1029,12 @@ static struct sk_buff *intel_dequeue(struct hci_uart *hu) struct hci_command_hdr *cmd = (void *)skb->data; __u16 opcode = le16_to_cpu(cmd->opcode); - /* When the 0xfc01 command is issued to boot into - * the operational firmware, it will actually not - * send a command complete event. To keep the flow - * control working inject that event here. + /* When the BTINTEL_HCI_OP_RESET command is issued to boot into + * the operational firmware, it will actually not send a command + * complete event. To keep the flow control working inject that + * event here. */ - if (opcode == 0xfc01) + if (opcode == BTINTEL_HCI_OP_RESET) inject_cmd_complete(hu->hdev, opcode); } diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index d2d6ba8d2f8b..d0adae3267b4 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu) if (!skb) { percpu_down_read(&hu->proto_lock); - if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) || + test_bit(HCI_UART_PROTO_INIT, &hu->flags)) skb = hu->proto->dequeue(hu); percpu_up_read(&hu->proto_lock); @@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu) if (!percpu_down_read_trylock(&hu->proto_lock)) return 0; - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) && + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) goto no_schedule; set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); @@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) percpu_down_read(&hu->proto_lock); - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) && + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) { percpu_up_read(&hu->proto_lock); return -EUNATCH; } @@ -585,7 +588,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) if (tty != hu->tty) return; - if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) || + test_bit(HCI_UART_PROTO_INIT, &hu->flags)) hci_uart_tx_wakeup(hu); } @@ -611,7 +615,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, percpu_down_read(&hu->proto_lock); - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) && + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) { percpu_up_read(&hu->proto_lock); return; } @@ -662,13 +667,13 @@ static int hci_uart_register_dev(struct hci_uart *hu) SET_HCIDEV_DEV(hdev, hu->tty->dev); if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) - set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) - set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG); if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) - set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); /* Only call open() for the protocol after hdev is fully initialized as * open() (or a timer/workqueue it starts) may attempt to reference it. @@ -707,12 +712,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) hu->proto = p; + set_bit(HCI_UART_PROTO_INIT, &hu->flags); + err = hci_uart_register_dev(hu); if (err) { return err; } set_bit(HCI_UART_PROTO_READY, &hu->flags); + clear_bit(HCI_UART_PROTO_INIT, &hu->flags); + return 0; } diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index e19e9bd49555..7044c86325ce 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -649,11 +649,11 @@ static int ll_setup(struct hci_uart *hu) /* This means that there was an error getting the BD address * during probe, so mark the device as having a bad address. */ - set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); + hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR); } else if (bacmp(&lldev->bdaddr, BDADDR_ANY)) { err = ll_set_bdaddr(hu->hdev, &lldev->bdaddr); if (err) - set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); + hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR); } /* Operational speed if any */ diff --git a/drivers/bluetooth/hci_nokia.c b/drivers/bluetooth/hci_nokia.c index 9fc10a16fd96..cd7575c20f65 100644 --- a/drivers/bluetooth/hci_nokia.c +++ b/drivers/bluetooth/hci_nokia.c @@ -439,7 +439,7 @@ static int nokia_setup(struct hci_uart *hu) if (btdev->man_id == NOKIA_ID_BCM2048) { hu->hdev->set_bdaddr = btbcm_set_bdaddr; - set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); + hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR); dev_dbg(dev, "bcm2048 has invalid bluetooth address!"); } diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 37129e6cb0eb..33c43503714b 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -31,6 +31,7 @@ #include <linux/pwrseq/consumer.h> #include <linux/regulator/consumer.h> #include <linux/serdev.h> +#include <linux/string_choices.h> #include <linux/mutex.h> #include <linux/unaligned.h> @@ -228,7 +229,7 @@ struct qca_serdev { u32 init_speed; u32 oper_speed; bool bdaddr_property_broken; - const char *firmware_name; + const char *firmware_name[2]; }; static int qca_regulator_enable(struct qca_serdev *qcadev); @@ -258,7 +259,18 @@ static const char *qca_get_firmware_name(struct hci_uart *hu) if (hu->serdev) { struct qca_serdev *qsd = serdev_device_get_drvdata(hu->serdev); - return qsd->firmware_name; + return qsd->firmware_name[0]; + } else { + return NULL; + } +} + +static const char *qca_get_rampatch_name(struct hci_uart *hu) +{ + if (hu->serdev) { + struct qca_serdev *qsd = serdev_device_get_drvdata(hu->serdev); + + return qsd->firmware_name[1]; } else { return NULL; } @@ -332,8 +344,8 @@ static void serial_clock_vote(unsigned long vote, struct hci_uart *hu) else __serial_clock_off(hu->tty); - BT_DBG("Vote serial clock %s(%s)", new_vote ? "true" : "false", - vote ? "true" : "false"); + BT_DBG("Vote serial clock %s(%s)", str_true_false(new_vote), + str_true_false(vote)); diff = jiffies_to_msecs(jiffies - qca->vote_last_jif); @@ -462,7 +474,7 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work) static void hci_ibs_tx_idle_timeout(struct timer_list *t) { - struct qca_data *qca = from_timer(qca, t, tx_idle_timer); + struct qca_data *qca = timer_container_of(qca, t, tx_idle_timer); struct hci_uart *hu = qca->hu; unsigned long flags; @@ -495,7 +507,7 @@ static void hci_ibs_tx_idle_timeout(struct timer_list *t) static void hci_ibs_wake_retrans_timeout(struct timer_list *t) { - struct qca_data *qca = from_timer(qca, t, wake_retrans_timer); + struct qca_data *qca = timer_container_of(qca, t, wake_retrans_timer); struct hci_uart *hu = qca->hu; unsigned long flags, retrans_delay; bool retransmit = false; @@ -611,6 +623,7 @@ static int qca_open(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); switch (qcadev->btsoc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -854,7 +867,7 @@ static void device_woke_up(struct hci_uart *hu) skb_queue_tail(&qca->txq, skb); /* Switch timers and change state to HCI_IBS_TX_AWAKE */ - del_timer(&qca->wake_retrans_timer); + timer_delete(&qca->wake_retrans_timer); idle_delay = msecs_to_jiffies(qca->tx_idle_delay); mod_timer(&qca->tx_idle_timer, jiffies + idle_delay); qca->tx_ibs_state = HCI_IBS_TX_AWAKE; @@ -1354,6 +1367,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) /* Give the controller time to process the request */ switch (qca_soc_type(hu)) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1440,6 +1454,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, static int qca_check_speeds(struct hci_uart *hu) { switch (qca_soc_type(hu)) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1482,6 +1497,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) * changing the baudrate of chip and host. */ switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1516,6 +1532,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) error: switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1638,7 +1655,7 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) clear_bit(QCA_HW_ERROR_EVENT, &qca->flags); } -static void qca_cmd_timeout(struct hci_dev *hdev) +static void qca_reset(struct hci_dev *hdev) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; @@ -1734,6 +1751,7 @@ static int qca_regulator_init(struct hci_uart *hu) } switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1764,6 +1782,7 @@ static int qca_regulator_init(struct hci_uart *hu) qca_set_speed(hu, QCA_INIT_SPEED); switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1795,6 +1814,7 @@ static int qca_power_on(struct hci_dev *hdev) return 0; switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1855,6 +1875,7 @@ static int qca_setup(struct hci_uart *hu) unsigned int retries = 0; enum qca_btsoc_type soc_type = qca_soc_type(hu); const char *firmware_name = qca_get_firmware_name(hu); + const char *rampatch_name = qca_get_rampatch_name(hu); int ret; struct qca_btsoc_version ver; struct qca_serdev *qcadev; @@ -1871,13 +1892,14 @@ static int qca_setup(struct hci_uart *hu) /* Enable controller to do both LE scan and BR/EDR inquiry * simultaneously. */ - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); switch (soc_type) { case QCA_QCA2066: soc_name = "qca2066"; break; + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1912,6 +1934,7 @@ retry: clear_bit(QCA_SSR_TRIGGERED, &qca->flags); switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1921,7 +1944,7 @@ retry: case QCA_WCN7850: qcadev = serdev_device_get_drvdata(hu->serdev); if (qcadev->bdaddr_property_broken) - set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN); hci_set_aosp_capable(hdev); @@ -1945,6 +1968,7 @@ retry: } switch (soc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -1963,12 +1987,12 @@ retry: /* Setup patch / NVM configurations */ ret = qca_uart_setup(hdev, qca_baudrate, soc_type, ver, - firmware_name); + firmware_name, rampatch_name); if (!ret) { clear_bit(QCA_IBS_DISABLED, &qca->flags); qca_debugfs_init(hdev); hu->hdev->hw_error = qca_hw_error; - hu->hdev->cmd_timeout = qca_cmd_timeout; + hu->hdev->reset = qca_reset; if (hu->serdev) { if (device_can_wakeup(hu->serdev->ctrl->dev.parent)) hu->hdev->wakeup = qca_wakeup; @@ -2033,6 +2057,17 @@ static const struct hci_uart_proto qca_proto = { .dequeue = qca_dequeue, }; +static const struct qca_device_data qca_soc_data_wcn3950 __maybe_unused = { + .soc_type = QCA_WCN3950, + .vregs = (struct qca_vreg []) { + { "vddio", 15000 }, + { "vddxo", 60000 }, + { "vddrf", 155000 }, + { "vddch0", 585000 }, + }, + .num_vregs = 4, +}; + static const struct qca_device_data qca_soc_data_wcn3988 __maybe_unused = { .soc_type = QCA_WCN3988, .vregs = (struct qca_vreg []) { @@ -2202,10 +2237,10 @@ static int qca_power_off(struct hci_dev *hdev) enum qca_btsoc_type soc_type = qca_soc_type(hu); hu->hdev->hw_error = NULL; - hu->hdev->cmd_timeout = NULL; + hu->hdev->reset = NULL; - del_timer_sync(&qca->wake_retrans_timer); - del_timer_sync(&qca->tx_idle_timer); + timer_delete_sync(&qca->wake_retrans_timer); + timer_delete_sync(&qca->tx_idle_timer); /* Stop sending shutdown command if soc crashes. */ if (soc_type != QCA_ROME @@ -2309,8 +2344,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->serdev_hu.serdev = serdev; data = device_get_match_data(&serdev->dev); serdev_device_set_drvdata(serdev, qcadev); - device_property_read_string(&serdev->dev, "firmware-name", - &qcadev->firmware_name); + device_property_read_string_array(&serdev->dev, "firmware-name", + qcadev->firmware_name, ARRAY_SIZE(qcadev->firmware_name)); device_property_read_u32(&serdev->dev, "max-speed", &qcadev->oper_speed); if (!qcadev->oper_speed) @@ -2325,6 +2360,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->btsoc_type = QCA_ROME; switch (qcadev->btsoc_type) { + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -2346,6 +2382,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) switch (qcadev->btsoc_type) { case QCA_WCN6855: case QCA_WCN7850: + case QCA_WCN6750: if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the @@ -2355,17 +2392,24 @@ static int qca_serdev_probe(struct serdev_device *serdev) */ qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev, "bluetooth"); - if (IS_ERR(qcadev->bt_power->pwrseq)) - return PTR_ERR(qcadev->bt_power->pwrseq); - break; + /* + * Some modules have BT_EN enabled via a hardware pull-up, + * meaning it is not defined in the DTS and is not controlled + * through the power sequence. In such cases, fall through + * to follow the legacy flow. + */ + if (IS_ERR(qcadev->bt_power->pwrseq)) + qcadev->bt_power->pwrseq = NULL; + else + break; } fallthrough; + case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: - case QCA_WCN6750: qcadev->bt_power->dev = &serdev->dev; err = qca_init_regulators(qcadev->bt_power, data->vregs, data->num_vregs); @@ -2378,14 +2422,14 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(qcadev->bt_en) && - (data->soc_type == QCA_WCN6750 || - data->soc_type == QCA_WCN6855)) { - dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); - return PTR_ERR(qcadev->bt_en); - } + if (IS_ERR(qcadev->bt_en)) + return dev_err_probe(&serdev->dev, + PTR_ERR(qcadev->bt_en), + "failed to acquire BT_EN gpio\n"); - if (!qcadev->bt_en) + if (!qcadev->bt_en && + (data->soc_type == QCA_WCN6750 || + data->soc_type == QCA_WCN6855)) power_ctrl_enabled = false; qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", @@ -2443,7 +2487,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) hdev = qcadev->serdev_hu.hdev; if (power_ctrl_enabled) { - set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); hdev->shutdown = qca_power_off; } @@ -2452,11 +2496,11 @@ static int qca_serdev_probe(struct serdev_device *serdev) * be queried via hci. Same with the valid le states quirk. */ if (data->capabilities & QCA_CAP_WIDEBAND_SPEECH) - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, - &hdev->quirks); + hci_set_quirk(hdev, + HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); if (!(data->capabilities & QCA_CAP_VALID_LE_STATES)) - set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES); } return 0; @@ -2506,7 +2550,7 @@ static void qca_serdev_shutdown(struct device *dev) * invoked and the SOC is already in the initial state, so * don't also need to send the VSC. */ - if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks) || + if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP) || hci_dev_test_flag(hdev, HCI_SETUP)) return; @@ -2592,10 +2636,10 @@ static int __maybe_unused qca_suspend(struct device *dev) switch (qca->tx_ibs_state) { case HCI_IBS_TX_WAKING: - del_timer(&qca->wake_retrans_timer); + timer_delete(&qca->wake_retrans_timer); fallthrough; case HCI_IBS_TX_AWAKE: - del_timer(&qca->tx_idle_timer); + timer_delete(&qca->tx_idle_timer); serdev_device_write_flush(hu->serdev); cmd = HCI_IBS_SLEEP_IND; @@ -2670,6 +2714,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390}, { .compatible = "qcom,qca9377-bt" }, + { .compatible = "qcom,wcn3950-bt", .data = &qca_soc_data_wcn3950}, { .compatible = "qcom,wcn3988-bt", .data = &qca_soc_data_wcn3988}, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991}, diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 89a22e9b3253..593d9cefbbf9 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -152,7 +152,7 @@ static int hci_uart_close(struct hci_dev *hdev) * BT SOC is completely powered OFF during BT OFF, holding port * open may drain the battery. */ - if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) { + if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) { clear_bit(HCI_UART_PROTO_READY, &hu->flags); serdev_device_close(hu->serdev); } @@ -358,13 +358,13 @@ int hci_uart_register_device_priv(struct hci_uart *hu, SET_HCIDEV_DEV(hdev, &hu->serdev->dev); if (test_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags)) - set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_NO_SUSPEND_NOTIFIER); if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) - set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) - set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG); if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) return 0; diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index fbf3079b92a5..5ea5dd80e297 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -90,6 +90,7 @@ struct hci_uart { #define HCI_UART_REGISTERED 1 #define HCI_UART_PROTO_READY 2 #define HCI_UART_NO_SUSPEND_NOTIFIER 3 +#define HCI_UART_PROTO_INIT 4 /* TX states */ #define HCI_UART_SENDING 1 diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 7651321d351c..f7d8c3c00655 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -289,18 +289,18 @@ static void vhci_coredump(struct hci_dev *hdev) static void vhci_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb) { - char buf[80]; + const char *buf; - snprintf(buf, sizeof(buf), "Controller Name: vhci_ctrl\n"); + buf = "Controller Name: vhci_ctrl\n"; skb_put_data(skb, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Firmware Version: vhci_fw\n"); + buf = "Firmware Version: vhci_fw\n"; skb_put_data(skb, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Driver: vhci_drv\n"); + buf = "Driver: vhci_drv\n"; skb_put_data(skb, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Vendor: vhci\n"); + buf = "Vendor: vhci\n"; skb_put_data(skb, buf, strlen(buf)); } @@ -316,7 +316,7 @@ static inline void force_devcd_timeout(struct hci_dev *hdev, unsigned int timeout) { #ifdef CONFIG_DEV_COREDUMP - hdev->dump.timeout = msecs_to_jiffies(timeout * 1000); + hdev->dump.timeout = secs_to_jiffies(timeout); #endif } @@ -415,15 +415,16 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) hdev->get_codec_config_data = vhci_get_codec_config_data; hdev->wakeup = vhci_wakeup; hdev->setup = vhci_setup; - set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); + hci_set_quirk(hdev, HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED); /* bit 6 is for external configuration */ if (opcode & 0x40) - set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG); /* bit 7 is for raw device */ if (opcode & 0x80) - set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); @@ -645,7 +646,7 @@ static int vhci_open(struct inode *inode, struct file *file) file->private_data = data; nonseekable_open(inode, file); - schedule_delayed_work(&data->open_timeout, msecs_to_jiffies(1000)); + schedule_delayed_work(&data->open_timeout, secs_to_jiffies(1)); return 0; } diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c index 756f292df9e8..6f1a37e85c6a 100644 --- a/drivers/bluetooth/virtio_bt.c +++ b/drivers/bluetooth/virtio_bt.c @@ -327,17 +327,17 @@ static int virtbt_probe(struct virtio_device *vdev) hdev->setup = virtbt_setup_intel; hdev->shutdown = virtbt_shutdown_generic; hdev->set_bdaddr = virtbt_set_bdaddr_intel; - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); break; case VIRTIO_BT_CONFIG_VENDOR_REALTEK: hdev->manufacturer = 93; hdev->setup = virtbt_setup_realtek; hdev->shutdown = virtbt_shutdown_generic; - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); + hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); break; } } |