bluetooth-next pull request for net-next:
- Add support for Foxconn QCA 0xe0d0 - Fix HCI init sequence on MacBook Air 8,1 and 8,2 - Fix Intel firmware loading on legacy ROM devices -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmHYqGkZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKaluD/wMeLJEZFGBK1Wwek4UPE8U 2ytS3n7EfebtIMHpXMPMH+lxsY6+GxH9bzc6JK5yWXr1S/Fny2U6spQFnRra/dvI Y6aauMjcCLKJiZvA7l9n79W3Cx3WpszT3Jqcz3ozvcQQG3+tOxdBsisKFi3YCdx8 U8TWHyajM3a+3Rmi5uCdpZkFC927vtta1GfgrnKhtztBPLilyRKPekjZ0vFv3CmG 5IvCglLJPqJtw8UtkXT5TENQptcQhMeFLy5JcGKdbFX9H4y2TobRSHpUtBOE0xOg f8lENUGRr3TFK2HmQfKK/jS88TS4yhSjsI1ejKoto5f0csUcwIbznoAqiGV4S+AZ t9+t9fq9iAHfr8X9ccm4t9x+ggdMIUgmSNaO9uk1bDsJSB+eTqwBfuGGEMgkc1HN Wrg/XOaAd6aOi+sXjnDegpWRhuC/KsTjp0P9gRkLK+1OiM5qcfMnBRoUk5kmazFq j2QRFORRSGHamqBWDvwymVUKeZ3odRr4qiMkIYHyzsVx7XvMpxL5WAgwr2p0KC4d rh/X6xTHIF9aDing5L9SjLJH6Zia/5mdToMPDLkV9Y8mfXFXg+Dc46lNmSBY0row atQZNd4QLIUr44ahcAvWW0zX4r7wbOft8epWm/Lf6qEUReHHCRtt0PC1givnqy0I J1CfiKLibsLI5FzhuH2b6w== =q2FV -----END PGP SIGNATURE----- Merge tag 'for-net-next-2022-01-07' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next Luiz Augusto von Dentz says: ==================== bluetooth-next pull request for net-next: - Add support for Foxconn QCA 0xe0d0 - Fix HCI init sequence on MacBook Air 8,1 and 8,2 - Fix Intel firmware loading on legacy ROM devices * tag 'for-net-next-2022-01-07' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: Bluetooth: hci_sock: fix endian bug in hci_sock_setsockopt() Bluetooth: L2CAP: uninitialized variables in l2cap_sock_setsockopt() Bluetooth: btqca: sequential validation Bluetooth: btusb: Add support for Foxconn QCA 0xe0d0 Bluetooth: btintel: Fix broken LED quirk for legacy ROM devices Bluetooth: hci_event: Rework hci_inquiry_result_with_rssi_evt Bluetooth: btbcm: disable read tx power for MacBook Air 8,1 and 8,2 Bluetooth: hci_qca: Fix NULL vs IS_ERR_OR_NULL check in qca_serdev_probe Bluetooth: hci_bcm: Check for error irq ==================== Link: https://lore.kernel.org/r/20220107210942.3750887-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
9f3248c9dd
|
@ -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."),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -142,6 +142,50 @@ out:
|
|||
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)) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue