Commit e6b21901 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

 - qca: set power_ctrl_enabled on NULL returned by gpiod_get_optional()
 - hci_sync: Using hci_cmd_sync_submit when removing Adv Monitor
 - qca: fix invalid device address check
 - hci_sync: Use advertised PHYs on hci_le_ext_create_conn_sync
 - Fix type of len in {l2cap,sco}_sock_getsockopt_old()
 - btusb: mediatek: Fix double free of skb in coredump
 - btusb: Add Realtek RTL8852BE support ID 0x0bda:0x4853
 - btusb: Fix triggering coredump implementation for QCA

* tag 'for-net-2024-04-24' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: qca: set power_ctrl_enabled on NULL returned by gpiod_get_optional()
  Bluetooth: hci_sync: Using hci_cmd_sync_submit when removing Adv Monitor
  Bluetooth: qca: fix NULL-deref on non-serdev setup
  Bluetooth: qca: fix NULL-deref on non-serdev suspend
  Bluetooth: btusb: mediatek: Fix double free of skb in coredump
  Bluetooth: MGMT: Fix failing to MGMT_OP_ADD_UUID/MGMT_OP_REMOVE_UUID
  Bluetooth: qca: fix invalid device address check
  Bluetooth: hci_event: Fix sending HCI_OP_READ_ENC_KEY_SIZE
  Bluetooth: btusb: Fix triggering coredump implementation for QCA
  Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0bda:0x4853
  Bluetooth: hci_sync: Use advertised PHYs on hci_le_ext_create_conn_sync
  Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old()
====================

Link: https://lore.kernel.org/r/20240424204102.2319483-1-luiz.dentz@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 73011773 3d05fc82
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -380,8 +380,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
	switch (data->cd_info.state) {
	case HCI_DEVCOREDUMP_IDLE:
		err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
		if (err < 0)
		if (err < 0) {
			kfree_skb(skb);
			break;
		}
		data->cd_info.cnt = 0;

		/* It is supposed coredump can be done within 5 seconds */
@@ -407,9 +409,6 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
		break;
	}

	if (err < 0)
		kfree_skb(skb);

	return err;
}
EXPORT_SYMBOL_GPL(btmtk_process_coredump);
+38 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@

#define VERSION "0.1"

#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})

int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
			 enum qca_btsoc_type soc_type)
{
@@ -612,6 +614,38 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);

static int qca_check_bdaddr(struct hci_dev *hdev)
{
	struct hci_rp_read_bd_addr *bda;
	struct sk_buff *skb;
	int err;

	if (bacmp(&hdev->public_addr, BDADDR_ANY))
		return 0;

	skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
			     HCI_INIT_TIMEOUT);
	if (IS_ERR(skb)) {
		err = PTR_ERR(skb);
		bt_dev_err(hdev, "Failed to read device address (%d)", err);
		return err;
	}

	if (skb->len != sizeof(*bda)) {
		bt_dev_err(hdev, "Device address length mismatch");
		kfree_skb(skb);
		return -EIO;
	}

	bda = (struct hci_rp_read_bd_addr *)skb->data;
	if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT))
		set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);

	kfree_skb(skb);

	return 0;
}

static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
		struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
{
@@ -818,6 +852,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
		break;
	}

	err = qca_check_bdaddr(hdev);
	if (err)
		return err;

	bt_dev_info(hdev, "QCA setup on UART is completed");

	return 0;
+6 −5
Original line number Diff line number Diff line
@@ -542,6 +542,8 @@ static const struct usb_device_id quirks_table[] = {
	/* Realtek 8852BE Bluetooth devices */
	{ USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
						     BTUSB_WIDEBAND_SPEECH },
	{ USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
						     BTUSB_WIDEBAND_SPEECH },
	{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
						     BTUSB_WIDEBAND_SPEECH },
	{ USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
@@ -3480,13 +3482,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb)

static void btusb_coredump_qca(struct hci_dev *hdev)
{
	int err;
	static const u8 param[] = { 0x26 };
	struct sk_buff *skb;

	skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT);
	if (IS_ERR(skb))
		bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb));
	kfree_skb(skb);
	err = __hci_cmd_send(hdev, 0xfc0c, 1, param);
	if (err < 0)
		bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err);
}

/*
+20 −9
Original line number Diff line number Diff line
@@ -1672,6 +1672,9 @@ static bool qca_wakeup(struct hci_dev *hdev)
	struct hci_uart *hu = hci_get_drvdata(hdev);
	bool wakeup;

	if (!hu->serdev)
		return true;

	/* BT SoC attached through the serial bus is handled by the serdev driver.
	 * So we need to use the device handle of the serdev driver to get the
	 * status of device may wakeup.
@@ -1905,8 +1908,6 @@ static int qca_setup(struct hci_uart *hu)
	case QCA_WCN6750:
	case QCA_WCN6855:
	case QCA_WCN7850:
		set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);

		qcadev = serdev_device_get_drvdata(hu->serdev);
		if (qcadev->bdaddr_property_broken)
			set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks);
@@ -1957,8 +1958,10 @@ static int qca_setup(struct hci_uart *hu)
		qca_debugfs_init(hdev);
		hu->hdev->hw_error = qca_hw_error;
		hu->hdev->cmd_timeout = qca_cmd_timeout;
		if (hu->serdev) {
			if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
				hu->hdev->wakeup = qca_wakeup;
		}
	} else if (ret == -ENOENT) {
		/* No patch/nvm-config found, run with original fw/config */
		set_bit(QCA_ROM_FW, &qca->flags);
@@ -2329,16 +2332,21 @@ static int qca_serdev_probe(struct serdev_device *serdev)
		    (data->soc_type == QCA_WCN6750 ||
		     data->soc_type == QCA_WCN6855)) {
			dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n");
			power_ctrl_enabled = false;
			return PTR_ERR(qcadev->bt_en);
		}

		if (!qcadev->bt_en)
			power_ctrl_enabled = false;

		qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",
					       GPIOD_IN);
		if (IS_ERR(qcadev->sw_ctrl) &&
		    (data->soc_type == QCA_WCN6750 ||
		     data->soc_type == QCA_WCN6855 ||
		     data->soc_type == QCA_WCN7850))
			dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
		     data->soc_type == QCA_WCN7850)) {
			dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
			return PTR_ERR(qcadev->sw_ctrl);
		}

		qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
		if (IS_ERR(qcadev->susclk)) {
@@ -2357,10 +2365,13 @@ 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)) {
			dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
			power_ctrl_enabled = false;
			dev_err(&serdev->dev, "failed to acquire enable gpio\n");
			return PTR_ERR(qcadev->bt_en);
		}

		if (!qcadev->bt_en)
			power_ctrl_enabled = false;

		qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
		if (IS_ERR(qcadev->susclk)) {
			dev_warn(&serdev->dev, "failed to acquire clk\n");
+7 −1
Original line number Diff line number Diff line
@@ -738,6 +738,8 @@ struct hci_conn {
	__u8		le_per_adv_data[HCI_MAX_PER_AD_TOT_LEN];
	__u16		le_per_adv_data_len;
	__u16		le_per_adv_data_offset;
	__u8		le_adv_phy;
	__u8		le_adv_sec_phy;
	__u8		le_tx_phy;
	__u8		le_rx_phy;
	__s8		rssi;
@@ -1512,7 +1514,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
				     enum conn_reasons conn_reason);
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
				u8 dst_type, bool dst_resolved, u8 sec_level,
				u16 conn_timeout, u8 role);
				u16 conn_timeout, u8 role, u8 phy, u8 sec_phy);
void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status);
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
				 u8 sec_level, u8 auth_type,
@@ -1905,6 +1907,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define privacy_mode_capable(dev) (use_ll_privacy(dev) && \
				   (hdev->commands[39] & 0x04))

#define read_key_size_capable(dev) \
	((dev)->commands[20] & 0x10 && \
	 !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks))

/* Use enhanced synchronous connection if command is supported and its quirk
 * has not been set.
 */
Loading