diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 07fabaa5aa29793ce8392bad48b6d5fbcaa2e8e7..d9ceca7a7935c51cbbcefbefcc953f037e8fe128 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -363,6 +363,18 @@ static const struct dmi_system_id disable_broken_read_transmit_power[] = { DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,4"), }, }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,1"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,2"), + }, + }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index e1f96df847b8fcced9da8cc703154c54e2efeeb0..1a4f8b227eac0b589edd9bf4798d48c01838af9d 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -2355,8 +2355,15 @@ static int btintel_setup_combined(struct hci_dev *hdev) * As a workaround, send HCI Reset command first which will reset the * number of completed commands and allow normal command processing * from now on. + * + * Regarding the INTEL_BROKEN_SHUTDOWN_LED flag, these devices maybe + * in the SW_RFKILL ON state as a workaround of fixing LED issue during + * the shutdown() procedure, and once the device is in SW_RFKILL ON + * state, the only way to exit out of it is sending the HCI_Reset + * command. */ - if (btintel_test_flag(hdev, INTEL_BROKEN_INITIAL_NCMD)) { + if (btintel_test_flag(hdev, INTEL_BROKEN_INITIAL_NCMD) || + btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { @@ -2428,12 +2435,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); - /* These devices have an issue with LED which doesn't - * go off immediately during shutdown. Set the flag - * here to send the LED OFF command during shutdown. - */ - btintel_set_flag(hdev, INTEL_BROKEN_LED); - err = btintel_legacy_rom_setup(hdev, &ver); break; case 0x0b: /* SfP */ @@ -2586,9 +2587,10 @@ static int btintel_shutdown_combined(struct hci_dev *hdev) /* Some platforms have an issue with BT LED when the interface is * down or BT radio is turned off, which takes 5 seconds to BT LED - * goes off. This command turns off the BT LED immediately. + * goes off. As a workaround, sends HCI_Intel_SW_RFKILL to put the + * device in the RFKILL ON state which turns off the BT LED immediately. */ - if (btintel_test_flag(hdev, INTEL_BROKEN_LED)) { + if (btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index e500c0d7a7298484b04314cec6103714f2b94c1d..c9b24e9299e2afd7aaf6ee66a2bee77a74a258fa 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -150,7 +150,7 @@ enum { INTEL_FIRMWARE_FAILED, INTEL_BOOTING, INTEL_BROKEN_INITIAL_NCMD, - INTEL_BROKEN_LED, + INTEL_BROKEN_SHUTDOWN_LED, INTEL_ROM_LEGACY, __INTEL_NUM_FLAGS, diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index f7bf311d79102048ddecdedc23e9725d744cb3fb..c9064d34d8308f29e725929d31238366d8d8f3aa 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -142,6 +142,50 @@ static int qca_read_fw_build_info(struct hci_dev *hdev) return err; } +static int qca_send_patch_config_cmd(struct hci_dev *hdev) +{ + const u8 cmd[] = { EDL_PATCH_CONFIG_CMD, 0x01, 0, 0, 0 }; + struct sk_buff *skb; + struct edl_event_hdr *edl; + int err; + + bt_dev_dbg(hdev, "QCA Patch config"); + + skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, sizeof(cmd), + cmd, HCI_EV_VENDOR, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "Sending QCA Patch config failed (%d)", err); + return err; + } + + if (skb->len != 2) { + bt_dev_err(hdev, "QCA Patch config cmd size mismatch len %d", skb->len); + err = -EILSEQ; + goto out; + } + + edl = (struct edl_event_hdr *)(skb->data); + if (!edl) { + bt_dev_err(hdev, "QCA Patch config with no header"); + err = -EILSEQ; + goto out; + } + + if (edl->cresp != EDL_PATCH_CONFIG_RES_EVT || edl->rtype != EDL_PATCH_CONFIG_CMD) { + bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp, + edl->rtype); + err = -EIO; + goto out; + } + + err = 0; + +out: + kfree_skb(skb); + return err; +} + static int qca_send_reset(struct hci_dev *hdev) { struct sk_buff *skb; @@ -552,6 +596,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, */ rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f); + if (soc_type == QCA_WCN6750) + qca_send_patch_config_cmd(hdev); + /* Download rampatch file */ config.type = TLV_TYPE_PATCH; if (qca_is_wcn399x(soc_type)) { diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 30afa7703afd3a0c636df5d2fe8652f43020213a..61e9a50e66ae1f7687d9f0968247b01b87d6d5d4 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -13,6 +13,7 @@ #define EDL_PATCH_TLV_REQ_CMD (0x1E) #define EDL_GET_BUILD_INFO_CMD (0x20) #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01) +#define EDL_PATCH_CONFIG_CMD (0x28) #define MAX_SIZE_PER_TLV_SEGMENT (243) #define QCA_PRE_SHUTDOWN_CMD (0xFC08) #define QCA_DISABLE_LOGGING (0xFC17) @@ -24,6 +25,7 @@ #define EDL_CMD_EXE_STATUS_EVT (0x00) #define EDL_SET_BAUDRATE_RSP_EVT (0x92) #define EDL_NVM_ACCESS_CODE_EVT (0x0B) +#define EDL_PATCH_CONFIG_RES_EVT (0x00) #define QCA_DISABLE_LOGGING_SUB_OP (0x14) #define EDL_TAG_ID_HCI (17) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 74ec7ca96b692517bd48801769a5eb145585fb8a..c30d131da7847c23d4d0166f0cb349c0f29f089a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -60,6 +60,7 @@ static struct usb_driver btusb_driver; #define BTUSB_WIDEBAND_SPEECH 0x400000 #define BTUSB_VALID_LE_STATES 0x800000 #define BTUSB_QCA_WCN6855 0x1000000 +#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED 0x2000000 #define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000 static const struct usb_device_id btusb_table[] = { @@ -311,6 +312,9 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x10ab, 0x9409), .driver_info = BTUSB_QCA_WCN6855 | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, + { USB_DEVICE(0x0489, 0xe0d0), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, @@ -381,10 +385,13 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED | - BTUSB_INTEL_BROKEN_INITIAL_NCMD }, - { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED }, + BTUSB_INTEL_BROKEN_INITIAL_NCMD | + BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, + { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED | + BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED }, - { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED }, + { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED | + BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED }, /* Other Intel Bluetooth devices */ @@ -3732,6 +3739,9 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD) btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD); + + if (id->driver_info & BTUSB_INTEL_BROKEN_SHUTDOWN_LED) + btintel_set_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED); } if (id->driver_info & BTUSB_MARVELL) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 7852abf15ddf63ec3ec0d65471efa01b19f0f94c..d634a27bc850f1cfcdfeba21469840a9e655b690 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -1188,7 +1188,12 @@ static int bcm_probe(struct platform_device *pdev) return -ENOMEM; dev->dev = &pdev->dev; - dev->irq = platform_get_irq(pdev, 0); + + ret = platform_get_irq(pdev, 0); + if (ret < 0) + return ret; + + dev->irq = ret; /* Initialize routing field to an unused value */ dev->pcm_int_params[0] = 0xff; diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 9e99311038ae8e953e689bd3d435403acf2b906c..f6e91fb432a3b59a2585c7ed5fe2aa89af908e3c 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2059,14 +2059,14 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); - if (!qcadev->bt_en && data->soc_type == QCA_WCN6750) { + if (IS_ERR_OR_NULL(qcadev->bt_en) && data->soc_type == QCA_WCN6750) { dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); power_ctrl_enabled = false; } qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", GPIOD_IN); - if (!qcadev->sw_ctrl && data->soc_type == QCA_WCN6750) + if (IS_ERR_OR_NULL(qcadev->sw_ctrl) && data->soc_type == QCA_WCN6750) dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); @@ -2088,7 +2088,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); - if (!qcadev->bt_en) { + if (IS_ERR_OR_NULL(qcadev->bt_en)) { dev_warn(&serdev->dev, "failed to acquire enable gpio\n"); power_ctrl_enabled = false; } diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index e2b06bb79e2edb8a57ee7ff54b875b81c72094aa..35c073d44ec5a868653e61562c9a6380d896d169 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2233,11 +2233,7 @@ struct inquiry_info_rssi_pscan { } __packed; struct hci_ev_inquiry_result_rssi { __u8 num; - struct inquiry_info_rssi info[]; -} __packed; -struct hci_ev_inquiry_result_rssi_pscan { - __u8 num; - struct inquiry_info_rssi_pscan info[]; + __u8 data[]; } __packed; #define HCI_EV_REMOTE_EXT_FEATURES 0x23 diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index f1082b7c02183377cdb35b0c902f0009f1e4dca2..fc30f4c03d292610614367370bca8856d332f610 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4507,16 +4507,13 @@ static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, void *data, static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, void *edata, struct sk_buff *skb) { - union { - struct hci_ev_inquiry_result_rssi *res1; - struct hci_ev_inquiry_result_rssi_pscan *res2; - } *ev = edata; + struct hci_ev_inquiry_result_rssi *ev = edata; struct inquiry_data data; int i; - bt_dev_dbg(hdev, "num_rsp %d", ev->res1->num); + bt_dev_dbg(hdev, "num_rsp %d", ev->num); - if (!ev->res1->num) + if (!ev->num) return; if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) @@ -4524,10 +4521,11 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, void *edata, hci_dev_lock(hdev); - if (skb->len == flex_array_size(ev, res2->info, ev->res2->num)) { + if (skb->len == array_size(ev->num, + sizeof(struct inquiry_info_rssi_pscan))) { struct inquiry_info_rssi_pscan *info; - for (i = 0; i < ev->res2->num; i++) { + for (i = 0; i < ev->num; i++) { u32 flags; info = hci_ev_skb_pull(hdev, skb, @@ -4554,10 +4552,11 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, void *edata, info->dev_class, info->rssi, flags, NULL, 0, NULL, 0); } - } else if (skb->len == flex_array_size(ev, res1->info, ev->res1->num)) { + } else if (skb->len == array_size(ev->num, + sizeof(struct inquiry_info_rssi))) { struct inquiry_info_rssi *info; - for (i = 0; i < ev->res1->num; i++) { + for (i = 0; i < ev->num; i++) { u32 flags; info = hci_ev_skb_pull(hdev, skb, diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 446573a125711fe6d52247a9c768e4ec03fcc930..33b3c0ffc3399dbb6eab07a7b378b9441647116d 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1911,7 +1911,8 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int len) { struct sock *sk = sock->sk; - int err = 0, opt = 0; + int err = 0; + u16 opt; BT_DBG("sk %p, opt %d", sk, optname); @@ -1937,7 +1938,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, goto done; } - if (copy_from_sockptr(&opt, optval, sizeof(u16))) { + if (copy_from_sockptr(&opt, optval, sizeof(opt))) { err = -EFAULT; break; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 188e4d4813b0cd9c4ee1cb05d0a4b042ef43f852..ca8f07f3542b824facc811a3bfc13bc6ecbc1ad2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -904,6 +904,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, struct l2cap_conn *conn; int len, err = 0; u32 opt; + u16 mtu; + u8 mode; BT_DBG("sk %p", sk); @@ -1086,16 +1088,16 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u16))) { + if (copy_from_sockptr(&mtu, optval, sizeof(u16))) { err = -EFAULT; break; } if (chan->mode == L2CAP_MODE_EXT_FLOWCTL && sk->sk_state == BT_CONNECTED) - err = l2cap_chan_reconfigure(chan, opt); + err = l2cap_chan_reconfigure(chan, mtu); else - chan->imtu = opt; + chan->imtu = mtu; break; @@ -1117,14 +1119,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u8))) { + if (copy_from_sockptr(&mode, optval, sizeof(u8))) { err = -EFAULT; break; } - BT_DBG("opt %u", opt); + BT_DBG("mode %u", mode); - err = l2cap_set_mode(chan, opt); + err = l2cap_set_mode(chan, mode); if (err) break;