Commit aa637b2c authored by Paolo Abeni's avatar Paolo Abeni
Browse files
Luiz Augusto von Dentz says:

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

 - L2CAP: Fix deadlock in l2cap_conn_del()
 - L2CAP: Fix ERTM re-init and zero pdu_len infinite loop
 - L2CAP: Fix send LE flow credits in ACL link
 - btintel: serialize btintel_hw_error() with hci_req_sync_lock
 - btusb: clamp SCO altsetting table indices

* tag 'for-net-2026-03-25' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: btusb: clamp SCO altsetting table indices
  Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop
  Bluetooth: L2CAP: Fix deadlock in l2cap_conn_del()
  Bluetooth: btintel: serialize btintel_hw_error() with hci_req_sync_lock
  Bluetooth: L2CAP: Fix send LE flow credits in ACL link
====================

Link: https://patch.msgid.link/20260325194358.618892-1-luiz.dentz@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 84a8335d 129fa608
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -251,11 +251,13 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)

	bt_dev_err(hdev, "Hardware error 0x%2.2x", code);

	hci_req_sync_lock(hdev);

	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
	if (IS_ERR(skb)) {
		bt_dev_err(hdev, "Reset after hardware error failed (%ld)",
			   PTR_ERR(skb));
		return;
		goto unlock;
	}
	kfree_skb(skb);

@@ -263,18 +265,21 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
	if (IS_ERR(skb)) {
		bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)",
			   PTR_ERR(skb));
		return;
		goto unlock;
	}

	if (skb->len != 13) {
		bt_dev_err(hdev, "Exception info size mismatch");
		kfree_skb(skb);
		return;
		goto unlock;
	}

	bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1));

	kfree_skb(skb);

unlock:
	hci_req_sync_unlock(hdev);
}
EXPORT_SYMBOL_GPL(btintel_hw_error);

+4 −1
Original line number Diff line number Diff line
@@ -2376,8 +2376,11 @@ static void btusb_work(struct work_struct *work)
		if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) {
			if (hdev->voice_setting & 0x0020) {
				static const int alts[3] = { 2, 4, 5 };
				unsigned int sco_idx;

				new_alts = alts[data->sco_num - 1];
				sco_idx = min_t(unsigned int, data->sco_num - 1,
						ARRAY_SIZE(alts) - 1);
				new_alts = alts[sco_idx];
			} else {
				new_alts = data->sco_num;
			}
+19 −12
Original line number Diff line number Diff line
@@ -1771,6 +1771,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)

	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);

	disable_delayed_work_sync(&conn->info_timer);
	disable_delayed_work_sync(&conn->id_addr_timer);

	mutex_lock(&conn->lock);

	kfree_skb(conn->rx_skb);
@@ -1786,8 +1789,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)

	ida_destroy(&conn->tx_ida);

	cancel_delayed_work_sync(&conn->id_addr_timer);

	l2cap_unregister_all_users(conn);

	/* Force the connection to be immediately dropped */
@@ -1806,9 +1807,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
		l2cap_chan_put(chan);
	}

	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
		cancel_delayed_work_sync(&conn->info_timer);

	hci_chan_del(conn->hchan);
	conn->hchan = NULL;

@@ -2400,6 +2398,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
	/* Remote device may have requested smaller PDUs */
	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);

	if (!pdu_len)
		return -EINVAL;

	if (len <= pdu_len) {
		sar = L2CAP_SAR_UNSEGMENTED;
		sdu_len = 0;
@@ -4335,6 +4336,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
		set_default_fcs(chan);

		if (chan->state != BT_CONNECTED) {
			if (chan->mode == L2CAP_MODE_ERTM ||
			    chan->mode == L2CAP_MODE_STREAMING)
				err = l2cap_ertm_init(chan);
@@ -4343,6 +4345,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
				l2cap_send_disconn_req(chan, -err);
			else
				l2cap_chan_ready(chan);
		}

		goto unlock;
	}
@@ -6630,6 +6633,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
	struct l2cap_le_credits pkt;
	u16 return_credits = l2cap_le_rx_credits(chan);

	if (chan->mode != L2CAP_MODE_LE_FLOWCTL &&
	    chan->mode != L2CAP_MODE_EXT_FLOWCTL)
		return;

	if (chan->rx_credits >= return_credits)
		return;