Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups
@ 2026-07-25  8:54 Zijun Hu
  2026-07-25  8:54 ` [PATCH 01/11] Bluetooth: btintel: Fix diagnostics event detection Zijun Hu
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

This series collects simple, independent fixes and cleanups for the
Bluetooth core and USB/SDIO transport drivers.

Every patch is simple and self-contained: two bug fixes for btintel,
the rest are readability cleanups and two trivial ACL helpers
(hci_acl_handle()/hci_acl_dlen()) with their users.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
Zijun Hu (11):
      Bluetooth: btintel: Fix diagnostics event detection
      Bluetooth: btintel: Validate length before parsing diagnostics TLV
      Bluetooth: coredump: Introduce and apply hci_devcd_state_name()
      Bluetooth: btusb: Make btusb_recv_{event,acl}() take struct hci_dev *
      Bluetooth: btusb: Add a simple static btusb_prepare_reset()
      Bluetooth: hci: Introduce hci_acl_handle() and hci_acl_dlen() helpers
      Bluetooth: hci_core: Simplify hci_recv_frame() by hci_acl_handle()
      Bluetooth: btusb: Simplify btusb_recv_bulk() by hci_acl_dlen()
      Bluetooth: btintel: Simplify btintel_classify_pkt_type() by hci_acl_handle()
      Bluetooth: btmrvl_sdio: Do not free HCI_VENDOR_PKT frame by hci_recv_frame()
      Bluetooth: hci_core: Don't treat HCI_DRV_PKT/HCI_DIAG_PKT as unknown type

 drivers/bluetooth/btintel.c      |  9 ++++----
 drivers/bluetooth/btmrvl_sdio.c  |  2 +-
 drivers/bluetooth/btusb.c        | 31 +++++++++++++++++----------
 include/net/bluetooth/coredump.h |  7 +++++++
 include/net/bluetooth/hci.h      | 10 +++++++++
 net/bluetooth/coredump.c         | 45 +++++++++++++++++++++++++++++++++-------
 net/bluetooth/hci_core.c         | 11 ++++++++--
 7 files changed, 90 insertions(+), 25 deletions(-)
---
base-commit: a3ad01d51d4be186484a9d8203e2e232f76326a9
change-id: 20260724-generic_fix-6f13710b92ea

Best regards,
--  
Zijun Hu <zijun.hu@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 01/11] Bluetooth: btintel: Fix diagnostics event detection
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 02/11] Bluetooth: btintel: Validate length before parsing diagnostics TLV Zijun Hu
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

For a diagnostics VSE, diagnostics_hdr[] sits at the start of the event
payload, skb->data[2], but btintel_recv_event() wrongly guards its
memcmp with @len, which is measured from skb->data[3] for the earlier
INTEL_BOOTLOADER check.

Fix by using @hdr->plen, which is the event payload length, instead.

Fixes: af395330abed ("Bluetooth: btintel: Add Intel devcoredump support")
Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
 drivers/bluetooth/btintel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 5e9cac090bd8..d7baf1b9d852 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -3826,17 +3826,17 @@ int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
 				kfree_skb(skb);
 				return 0;
 			}
 		}
 
 		/* Handle all diagnostics events separately. May still call
 		 * hci_recv_frame.
 		 */
-		if (len >= sizeof(diagnostics_hdr) &&
+		if (hdr->plen >= sizeof(diagnostics_hdr) &&
 		    memcmp(&skb->data[2], diagnostics_hdr,
 			   sizeof(diagnostics_hdr)) == 0) {
 			return btintel_diagnostics(hdev, skb);
 		}
 	}
 
 	return hci_recv_frame(hdev, skb);
 }

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 02/11] Bluetooth: btintel: Validate length before parsing diagnostics TLV
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
  2026-07-25  8:54 ` [PATCH 01/11] Bluetooth: btintel: Fix diagnostics event detection Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 03/11] Bluetooth: coredump: Introduce and apply hci_devcd_state_name() Zijun Hu
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

btintel_diagnostics() accesses tlv->val[0] without first validating
that the diagnostics VSE is long enough to contain that field, so
may cause reading data beyond the received frame.

Fix by validating the length before access.

Fixes: af395330abed ("Bluetooth: btintel: Add Intel devcoredump support")
Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
 drivers/bluetooth/btintel.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index d7baf1b9d852..dbcb3f138477 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -3766,16 +3766,19 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(btintel_configure_setup);
 
 static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct intel_tlv *tlv = (void *)&skb->data[5];
 
+	if (skb->len < 5 + sizeof(*tlv) + sizeof(tlv->val[0]))
+		goto recv_frame;
+
 	/* The first event is always an event type TLV */
 	if (tlv->type != INTEL_TLV_TYPE_ID)
 		goto recv_frame;
 
 	switch (tlv->val[0]) {
 	case INTEL_TLV_SYSTEM_EXCEPTION:
 	case INTEL_TLV_FATAL_EXCEPTION:
 	case INTEL_TLV_DEBUG_EXCEPTION:

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 03/11] Bluetooth: coredump: Introduce and apply hci_devcd_state_name()
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
  2026-07-25  8:54 ` [PATCH 01/11] Bluetooth: btintel: Fix diagnostics event detection Zijun Hu
  2026-07-25  8:54 ` [PATCH 02/11] Bluetooth: btintel: Validate length before parsing diagnostics TLV Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 04/11] Bluetooth: btusb: Make btusb_recv_{event,acl}() take struct hci_dev * Zijun Hu
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Introduce hci_devcd_state_name() to describe the devcoredump state by a
string name instead of a plain number, for several reasons:

1) Applying it in coredump.c makes the devcoredump state in log messages
   more readable than a plain number.
2) Transport drivers may need to show the devcoredump state name too.
3) In future, the universal state name could be notified to userspace
   via uevent, allowing a universal application (e.g. a daemon) to be
   developed to save the coredump, which is otherwise discarded by the
   device coredump core after 5 minutes (DEVCD_TIMEOUT); see
   nxp_coredump_notify().

Also drop a trailing space from two bt_dev_dbg() format strings while
applying it in coredump.c.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
Previous version:
https://lore.kernel.org/all/20260713-btusb_prep_qcc2072-v2-1-bbcb651285f2@oss.qualcomm.com

Changes since previous version:
- Improve commit title and message.
---
 include/net/bluetooth/coredump.h |  7 +++++++
 net/bluetooth/coredump.c         | 45 +++++++++++++++++++++++++++++++++-------
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/include/net/bluetooth/coredump.h b/include/net/bluetooth/coredump.h
index 72f51b587a04..ab85a6adfffd 100644
--- a/include/net/bluetooth/coredump.h
+++ b/include/net/bluetooth/coredump.h
@@ -55,30 +55,37 @@ struct hci_devcoredump {
 
 	coredump_t		coredump;
 	dmp_hdr_t		dmp_hdr;
 	notify_change_t		notify_change;
 };
 
 #ifdef CONFIG_DEV_COREDUMP
 
+const char *hci_devcd_state_name(enum devcoredump_state state);
+
 void hci_devcd_reset(struct hci_dev *hdev);
 void hci_devcd_rx(struct work_struct *work);
 void hci_devcd_timeout(struct work_struct *work);
 
 int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump,
 		       dmp_hdr_t dmp_hdr, notify_change_t notify_change);
 int hci_devcd_init(struct hci_dev *hdev, u32 dump_size);
 int hci_devcd_append(struct hci_dev *hdev, struct sk_buff *skb);
 int hci_devcd_append_pattern(struct hci_dev *hdev, u8 pattern, u32 len);
 int hci_devcd_complete(struct hci_dev *hdev);
 int hci_devcd_abort(struct hci_dev *hdev);
 
 #else
 
+static inline const char *hci_devcd_state_name(enum devcoredump_state state)
+{
+	return "";
+}
+
 static inline void hci_devcd_reset(struct hci_dev *hdev) {}
 static inline void hci_devcd_rx(struct work_struct *work) {}
 static inline void hci_devcd_timeout(struct work_struct *work) {}
 
 static inline int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump,
 				     dmp_hdr_t dmp_hdr,
 				     notify_change_t notify_change)
 {
diff --git a/net/bluetooth/coredump.c b/net/bluetooth/coredump.c
index c0f027fab583..913bbba559f8 100644
--- a/net/bluetooth/coredump.c
+++ b/net/bluetooth/coredump.c
@@ -25,18 +25,19 @@ struct hci_devcoredump_skb_pattern {
 	u8 pattern;
 	u32 len;
 } __packed;
 
 #define hci_dmp_cb(skb)	((struct hci_devcoredump_skb_cb *)((skb)->cb))
 
 #define DBG_UNEXPECTED_STATE() \
 	bt_dev_dbg(hdev, \
-		   "Unexpected packet (%d) for state (%d). ", \
-		   hci_dmp_cb(skb)->pkt_type, hdev->dump.state)
+		   "Unexpected packet (%d) for state %s.", \
+		   hci_dmp_cb(skb)->pkt_type, \
+		   hci_devcd_state_name(hdev->dump.state))
 
 #define MAX_DEVCOREDUMP_HDR_SIZE	512	/* bytes */
 
 static int hci_devcd_update_hdr_state(char *buf, size_t size, int state)
 {
 	int len = 0;
 
 	if (!buf)
@@ -45,18 +46,19 @@ static int hci_devcd_update_hdr_state(char *buf, size_t size, int state)
 	len = scnprintf(buf, size, "Bluetooth devcoredump\nState: %d\n", state);
 
 	return len + 1; /* scnprintf adds \0 at the end upon state rewrite */
 }
 
 /* Call with hci_dev_lock only. */
 static int hci_devcd_update_state(struct hci_dev *hdev, int state)
 {
-	bt_dev_dbg(hdev, "Updating devcoredump state from %d to %d.",
-		   hdev->dump.state, state);
+	bt_dev_dbg(hdev, "Updating devcoredump state from %s to %s.",
+		   hci_devcd_state_name(hdev->dump.state),
+		   hci_devcd_state_name(state));
 
 	hdev->dump.state = state;
 
 	return hci_devcd_update_hdr_state(hdev->dump.head,
 					  hdev->dump.alloc_size, state);
 }
 
 static int hci_devcd_mkheader(struct hci_dev *hdev, struct sk_buff *skb)
@@ -240,17 +242,17 @@ static void hci_devcd_handle_pkt_pattern(struct hci_dev *hdev,
 		bt_dev_dbg(hdev, "Failed to set pattern");
 }
 
 static void hci_devcd_dump(struct hci_dev *hdev)
 {
 	struct sk_buff *skb;
 	u32 size;
 
-	bt_dev_dbg(hdev, "state %d", hdev->dump.state);
+	bt_dev_dbg(hdev, "state %s", hci_devcd_state_name(hdev->dump.state));
 
 	size = hdev->dump.tail - hdev->dump.head;
 
 	/* Send a copy to monitor as a diagnostic packet */
 	skb = bt_skb_alloc(size, GFP_ATOMIC);
 	if (skb) {
 		skb_put_data(skb, hdev->dump.head, size);
 		hci_recv_diag(hdev, skb);
@@ -363,18 +365,19 @@ void hci_devcd_rx(struct work_struct *work)
 			hci_devcd_handle_pkt_complete(hdev, skb);
 			break;
 
 		case HCI_DEVCOREDUMP_PKT_ABORT:
 			hci_devcd_handle_pkt_abort(hdev, skb);
 			break;
 
 		default:
-			bt_dev_dbg(hdev, "Unknown packet (%d) for state (%d). ",
-				   hci_dmp_cb(skb)->pkt_type, hdev->dump.state);
+			bt_dev_dbg(hdev, "Unknown packet (%d) for state %s.",
+				   hci_dmp_cb(skb)->pkt_type,
+				   hci_devcd_state_name(hdev->dump.state));
 			break;
 		}
 
 		hci_dev_unlock(hdev);
 		kfree_skb(skb);
 
 		/* Notify the driver about any state changes before resetting
 		 * the state machine
@@ -544,8 +547,36 @@ int hci_devcd_abort(struct hci_dev *hdev)
 	hci_dmp_cb(skb)->pkt_type = HCI_DEVCOREDUMP_PKT_ABORT;
 
 	skb_queue_tail(&hdev->dump.dump_q, skb);
 	queue_work(hdev->workqueue, &hdev->dump.dump_rx);
 
 	return 0;
 }
 EXPORT_SYMBOL(hci_devcd_abort);
+
+const char *hci_devcd_state_name(enum devcoredump_state state)
+{
+	const char *state_name = "Unknown";
+
+	switch (state) {
+	case HCI_DEVCOREDUMP_IDLE:
+		state_name = "IDLE";
+		break;
+	case HCI_DEVCOREDUMP_ACTIVE:
+		state_name = "ACTIVE";
+		break;
+	case HCI_DEVCOREDUMP_DONE:
+		state_name = "DONE";
+		break;
+	case HCI_DEVCOREDUMP_ABORT:
+		state_name = "ABORT";
+		break;
+	case HCI_DEVCOREDUMP_TIMEOUT:
+		state_name = "TIMEOUT";
+		break;
+	default:
+		break;
+	}
+
+	return state_name;
+}
+EXPORT_SYMBOL(hci_devcd_state_name);

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 04/11] Bluetooth: btusb: Make btusb_recv_{event,acl}() take struct hci_dev *
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (2 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 03/11] Bluetooth: coredump: Introduce and apply hci_devcd_state_name() Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 05/11] Bluetooth: btusb: Add a simple static btusb_prepare_reset() Zijun Hu
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Both helpers currently take struct btusb_data *, which is private to
btusb.c, as parameter type as below:

  int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
  int btusb_recv_acl(struct btusb_data *data, struct sk_buff *skb)

To allow vendor USB-transport-specific source files to share them as
well, change the type to struct hci_dev *.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
Previous version:
https://lore.kernel.org/all/20260713-btusb_prep_qcc2072-v2-4-bbcb651285f2@oss.qualcomm.com

Changes since previous version:
- Improve commit title and message.
---
 drivers/bluetooth/btusb.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 4d59b28ab30f..2ea1d6bbea39 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1247,24 +1247,26 @@ static inline void btusb_free_frags(struct btusb_data *data)
 	data->acl_skb = NULL;
 
 	dev_kfree_skb_irq(data->sco_skb);
 	data->sco_skb = NULL;
 
 	spin_unlock_irqrestore(&data->rxlock, flags);
 }
 
-static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
+static int btusb_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
 {
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
 	if (data->intr_interval) {
 		/* Trigger dequeue immediately if an event is received */
 		schedule_delayed_work(&data->rx_work, 0);
 	}
 
-	return data->recv_event(data->hdev, skb);
+	return data->recv_event(hdev, skb);
 }
 
 static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
 {
 	struct sk_buff *skb;
 	unsigned long flags;
 	int err = 0;
 
@@ -1314,34 +1316,36 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
 			if (count && count < HCI_EVENT_HDR_SIZE) {
 				bt_dev_warn(data->hdev,
 					"Unexpected continuation: %d bytes",
 					count);
 				count = 0;
 			}
 
 			/* Complete frame */
-			btusb_recv_event(data, skb);
+			btusb_recv_event(data->hdev, skb);
 			skb = NULL;
 		}
 	}
 
 	data->evt_skb = skb;
 	spin_unlock_irqrestore(&data->rxlock, flags);
 
 	return err;
 }
 
-static int btusb_recv_acl(struct btusb_data *data, struct sk_buff *skb)
+static int btusb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb)
 {
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
 	/* Only queue ACL packet if intr_interval is set as it means
 	 * force_poll_sync has been enabled.
 	 */
 	if (!data->intr_interval)
-		return data->recv_acl(data->hdev, skb);
+		return data->recv_acl(hdev, skb);
 
 	skb_queue_tail(&data->acl_q, skb);
 	schedule_delayed_work(&data->rx_work, data->intr_interval);
 
 	return 0;
 }
 
 static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
@@ -1386,17 +1390,17 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
 
 				err = -EILSEQ;
 				break;
 			}
 		}
 
 		if (!hci_skb_expect(skb)) {
 			/* Complete frame */
-			btusb_recv_acl(data, skb);
+			btusb_recv_acl(data->hdev, skb);
 			skb = NULL;
 		}
 	}
 
 	data->acl_skb = skb;
 	spin_unlock_irqrestore(&data->rxlock, flags);
 
 	return err;

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 05/11] Bluetooth: btusb: Add a simple static btusb_prepare_reset()
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (3 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 04/11] Bluetooth: btusb: Make btusb_recv_{event,acl}() take struct hci_dev * Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 06/11] Bluetooth: hci: Introduce hci_acl_handle() and hci_acl_dlen() helpers Zijun Hu
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Add btusb_prepare_reset() to do cleanup before a reset, and
apply it to btusb_mtk_reset() as well.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
Previous version:
https://lore.kernel.org/all/20260713-btusb_prep_qcc2072-v2-5-bbcb651285f2@oss.qualcomm.com

Changes since previous version:
- Improve commit title and message.
---
 drivers/bluetooth/btusb.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2ea1d6bbea39..90336dec59a2 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2069,16 +2069,24 @@ static void btusb_stop_traffic(struct btusb_data *data)
 {
 	usb_kill_anchored_urbs(&data->intr_anchor);
 	usb_kill_anchored_urbs(&data->bulk_anchor);
 	usb_kill_anchored_urbs(&data->isoc_anchor);
 	usb_kill_anchored_urbs(&data->diag_anchor);
 	usb_kill_anchored_urbs(&data->ctrl_anchor);
 }
 
+static void btusb_prepare_reset(struct hci_dev *hdev)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+
+	btusb_stop_traffic(data);
+	usb_kill_anchored_urbs(&data->tx_anchor);
+}
+
 static int btusb_close(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
 	int err;
 
 	BT_DBG("%s", hdev->name);
 
 	cancel_delayed_work(&data->rx_work);
@@ -2913,18 +2921,17 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 
 	err = usb_autopm_get_interface(data->intf);
 	if (err < 0)
 		return err;
 
 	/* Release MediaTek ISO data interface */
 	btusb_mtk_release_iso_intf(hdev);
 
-	btusb_stop_traffic(data);
-	usb_kill_anchored_urbs(&data->tx_anchor);
+	btusb_prepare_reset(hdev);
 
 	/* Toggle the hard reset line. The MediaTek device is going to
 	 * yank itself off the USB and then replug. The cleanup is handled
 	 * correctly on the way out (standard USB disconnect), and the new
 	 * device is detected cleanly and bound to the driver again like
 	 * it should be.
 	 */
 	if (data->reset_gpio) {

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 06/11] Bluetooth: hci: Introduce hci_acl_handle() and hci_acl_dlen() helpers
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (4 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 05/11] Bluetooth: btusb: Add a simple static btusb_prepare_reset() Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 07/11] Bluetooth: hci_core: Simplify hci_recv_frame() by hci_acl_handle() Zijun Hu
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Introduce both helpers for ACL packet since:

both core and transport drivers extract the handle and data length
from its header in several places.

Both will be used later.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
 include/net/bluetooth/hci.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 50f0eef71fb1..d557bdf9ae57 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -3402,16 +3402,26 @@ static inline struct hci_iso_hdr *hci_iso_hdr(const struct sk_buff *skb)
 #define hci_opcode_ogf(op)		(op >> 10)
 #define hci_opcode_ocf(op)		(op & 0x03ff)
 
 /* ACL handle and flags pack/unpack */
 #define hci_handle_pack(h, f)	((__u16) ((h & 0x0fff)|(f << 12)))
 #define hci_handle(h)		(h & 0x0fff)
 #define hci_flags(h)		(h >> 12)
 
+static inline __u16 hci_acl_handle(const struct sk_buff *skb)
+{
+	return hci_handle(__le16_to_cpu(hci_acl_hdr(skb)->handle));
+}
+
+static inline __u16 hci_acl_dlen(const struct sk_buff *skb)
+{
+	return __le16_to_cpu(hci_acl_hdr(skb)->dlen);
+}
+
 /* ISO handle and flags pack/unpack */
 #define hci_iso_flags_pb(f)		(f & 0x0003)
 #define hci_iso_flags_ts(f)		((f >> 2) & 0x0001)
 #define hci_iso_flags_pack(pb, ts)	((pb & 0x03) | ((ts & 0x01) << 2))
 
 /* ISO data length and flags pack/unpack */
 #define hci_iso_data_len_pack(h, f)	((__u16) (((h) & 0x0fff) | \
 						  (((f) & 0x3) << 14)))

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 07/11] Bluetooth: hci_core: Simplify hci_recv_frame() by hci_acl_handle()
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (5 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 06/11] Bluetooth: hci: Introduce hci_acl_handle() and hci_acl_dlen() helpers Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 08/11] Bluetooth: btusb: Simplify btusb_recv_bulk() by hci_acl_dlen() Zijun Hu
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Simplify hci_recv_frame() by using hci_acl_handle() instead of:

__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
... hci_handle(handle) ...

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
 net/bluetooth/hci_core.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d1e78ae7728e..9d5adf882509 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2899,20 +2899,19 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
 	switch (hci_skb_pkt_type(skb)) {
 	case HCI_EVENT_PKT:
 		break;
 	case HCI_ACLDATA_PKT:
 		/* Detect if ISO packet has been sent as ACL */
 		if (hci_conn_num(hdev, CIS_LINK) ||
 		    hci_conn_num(hdev, BIS_LINK) ||
 			hci_conn_num(hdev, PA_LINK)) {
-			__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
 			__u8 type;
 
-			type = hci_conn_lookup_type(hdev, hci_handle(handle));
+			type = hci_conn_lookup_type(hdev, hci_acl_handle(skb));
 			if (type == CIS_LINK || type == BIS_LINK ||
 			    type == PA_LINK)
 				hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
 		}
 		break;
 	case HCI_SCODATA_PKT:
 		break;
 	case HCI_ISODATA_PKT:

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 08/11] Bluetooth: btusb: Simplify btusb_recv_bulk() by hci_acl_dlen()
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (6 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 07/11] Bluetooth: hci_core: Simplify hci_recv_frame() by hci_acl_handle() Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 09/11] Bluetooth: btintel: Simplify btintel_classify_pkt_type() by hci_acl_handle() Zijun Hu
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Simplify btusb_recv_bulk() by using hci_acl_dlen() instead of:

__le16 dlen = hci_acl_hdr(skb)->dlen;
... __le16_to_cpu(dlen) ...

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
 drivers/bluetooth/btusb.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 90336dec59a2..70593842d20b 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1374,20 +1374,18 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
 		len = min_t(uint, hci_skb_expect(skb), count);
 		skb_put_data(skb, buffer, len);
 
 		count -= len;
 		buffer += len;
 		hci_skb_expect(skb) -= len;
 
 		if (skb->len == HCI_ACL_HDR_SIZE) {
-			__le16 dlen = hci_acl_hdr(skb)->dlen;
-
 			/* Complete ACL header */
-			hci_skb_expect(skb) = __le16_to_cpu(dlen);
+			hci_skb_expect(skb) = hci_acl_dlen(skb);
 
 			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
 				kfree_skb(skb);
 				skb = NULL;
 
 				err = -EILSEQ;
 				break;
 			}

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 09/11] Bluetooth: btintel: Simplify btintel_classify_pkt_type() by hci_acl_handle()
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (7 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 08/11] Bluetooth: btusb: Simplify btusb_recv_bulk() by hci_acl_dlen() Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 10/11] Bluetooth: btmrvl_sdio: Do not free HCI_VENDOR_PKT frame by hci_recv_frame() Zijun Hu
  2026-07-25  8:54 ` [PATCH 11/11] Bluetooth: hci_core: Don't treat HCI_DRV_PKT/HCI_DIAG_PKT as unknown type Zijun Hu
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Simplify btintel_classify_pkt_type() by using hci_acl_handle() instead of:

__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
... hci_handle(handle) ...

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
 drivers/bluetooth/btintel.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index dbcb3f138477..87a6a11e5b59 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -2740,19 +2740,17 @@ static void btintel_set_dsm_reset_method(struct hci_dev *hdev,
 
 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 (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)
+		if (hci_acl_handle(skb) >= BTINTEL_ISODATA_HANDLE_BASE)
 			return HCI_ISODATA_PKT;
 	}
 
 	return hci_skb_pkt_type(skb);
 }
 
 /*
  * UefiCnvCommonDSBR UEFI variable provides information from the OEM platforms

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 10/11] Bluetooth: btmrvl_sdio: Do not free HCI_VENDOR_PKT frame by hci_recv_frame()
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (8 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 09/11] Bluetooth: btintel: Simplify btintel_classify_pkt_type() by hci_acl_handle() Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  2026-07-25  8:54 ` [PATCH 11/11] Bluetooth: hci_core: Don't treat HCI_DRV_PKT/HCI_DIAG_PKT as unknown type Zijun Hu
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

For a HCI_VENDOR_PKT frame, hci_recv_frame() does not accept it and
will kfree_skb() it directly.

But btmrvl_sdio_card_to_host() is still calling hci_recv_frame() for
the frame.

Fix by freeing it with kfree_skb() directly.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
Previous version:
https://lore.kernel.org/all/20260722-support_vendor_hci-v2-1-132b506460a4@oss.qualcomm.com

Changes since previous version:
- Improve commit title and message.
---
 drivers/bluetooth/btmrvl_sdio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 93932a0d8625..b91fc63bc9fe 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -794,17 +794,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 		break;
 
 	case MRVL_VENDOR_PKT:
 		hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
 		skb_put(skb, buf_len);
 		skb_pull(skb, SDIO_HEADER_LEN);
 
 		if (btmrvl_process_event(priv, skb))
-			hci_recv_frame(hdev, skb);
+			kfree_skb(skb);
 
 		hdev->stat.byte_rx += buf_len;
 		break;
 
 	default:
 		BT_ERR("Unknown packet type:%d", type);
 		BT_ERR("hex: %*ph", blksz * num_blocks, payload);
 

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 11/11] Bluetooth: hci_core: Don't treat HCI_DRV_PKT/HCI_DIAG_PKT as unknown type
  2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
                   ` (9 preceding siblings ...)
  2026-07-25  8:54 ` [PATCH 10/11] Bluetooth: btmrvl_sdio: Do not free HCI_VENDOR_PKT frame by hci_recv_frame() Zijun Hu
@ 2026-07-25  8:54 ` Zijun Hu
  10 siblings, 0 replies; 12+ messages in thread
From: Zijun Hu @ 2026-07-25  8:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Abhishek Pandit-Subedi,
	Chethan Tumkur Narayan, Manish Mandlik
  Cc: Zijun Hu, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
	Zijun Hu

Both HCI_DRV_PKT and HCI_DIAG_PKT reach hci_rx_work(), and leverage
the default switch case to free them silently. Relying on the default
case is prone to mislead readers into thinking either that:

1) they never arrive at hci_rx_work(), and the function does not
   handle them at all; or
2) they are unknown packet types, which normally fall into the
   default switch case.

Fix by giving both their own switch cases that free them explicitly.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
---
Previous version:
https://lore.kernel.org/all/20260719-fix_hci_rx_work-v1-1-2d7fdeed3640@oss.qualcomm.com

Changes since previous version:
- Improve commit title and message.
---
 net/bluetooth/hci_core.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9d5adf882509..85f1b44fed9b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -4051,16 +4051,24 @@ static void hci_rx_work(struct work_struct *work)
 			hci_scodata_packet(hdev, skb);
 			break;
 
 		case HCI_ISODATA_PKT:
 			BT_DBG("%s ISO data packet", hdev->name);
 			hci_isodata_packet(hdev, skb);
 			break;
 
+		case HCI_DRV_PKT:
+			kfree_skb(skb);
+			break;
+
+		case HCI_DIAG_PKT:
+			kfree_skb(skb);
+			break;
+
 		default:
 			kfree_skb(skb);
 			break;
 		}
 	}
 }
 
 static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-07-25  8:55 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-25  8:54 [PATCH 00/11] Bluetooth: Miscellaneous fixes and cleanups Zijun Hu
2026-07-25  8:54 ` [PATCH 01/11] Bluetooth: btintel: Fix diagnostics event detection Zijun Hu
2026-07-25  8:54 ` [PATCH 02/11] Bluetooth: btintel: Validate length before parsing diagnostics TLV Zijun Hu
2026-07-25  8:54 ` [PATCH 03/11] Bluetooth: coredump: Introduce and apply hci_devcd_state_name() Zijun Hu
2026-07-25  8:54 ` [PATCH 04/11] Bluetooth: btusb: Make btusb_recv_{event,acl}() take struct hci_dev * Zijun Hu
2026-07-25  8:54 ` [PATCH 05/11] Bluetooth: btusb: Add a simple static btusb_prepare_reset() Zijun Hu
2026-07-25  8:54 ` [PATCH 06/11] Bluetooth: hci: Introduce hci_acl_handle() and hci_acl_dlen() helpers Zijun Hu
2026-07-25  8:54 ` [PATCH 07/11] Bluetooth: hci_core: Simplify hci_recv_frame() by hci_acl_handle() Zijun Hu
2026-07-25  8:54 ` [PATCH 08/11] Bluetooth: btusb: Simplify btusb_recv_bulk() by hci_acl_dlen() Zijun Hu
2026-07-25  8:54 ` [PATCH 09/11] Bluetooth: btintel: Simplify btintel_classify_pkt_type() by hci_acl_handle() Zijun Hu
2026-07-25  8:54 ` [PATCH 10/11] Bluetooth: btmrvl_sdio: Do not free HCI_VENDOR_PKT frame by hci_recv_frame() Zijun Hu
2026-07-25  8:54 ` [PATCH 11/11] Bluetooth: hci_core: Don't treat HCI_DRV_PKT/HCI_DIAG_PKT as unknown type Zijun Hu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox