All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO
@ 2025-03-12 15:14 Luiz Augusto von Dentz
  2025-03-12 15:14 ` [PATCH v2 2/2] Bluetooth: hci_vhci: Mark Sync Flow Control as supported Luiz Augusto von Dentz
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2025-03-12 15:14 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This enables buffer flow control for SCO/eSCO
(see: Bluetooth Core 6.0 spec: 6.22. Synchronous Flow Control Enable),
recently this has caused the following problem and is actually a nice
addition for the likes of Socket TX complete:

< HCI Command: Read Buffer Size (0x04|0x0005) plen 0
> HCI Event: Command Complete (0x0e) plen 11
      Read Buffer Size (0x04|0x0005) ncmd 1
        Status: Success (0x00)
        ACL MTU: 1021 ACL max packet: 5
        SCO MTU: 240  SCO max packet: 8
...
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
< SCO Data TX: Handle 257 flags 0x00 dlen 120
> HCI Event: Hardware Error (0x10) plen 1
        Code: 0x0a

To fix the code will now attempt to enable buffer flow control when
HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED is set by the driver:

< HCI Command: Write Sync Fl.. (0x03|0x002f) plen 1
        Flow control: Enabled (0x01)
> HCI Event: Command Complete (0x0e) plen 4
      Write Sync Flow Control Enable (0x03|0x002f) ncmd 1
        Status: Success (0x00)

On success then HCI_SCO_FLOWCTL would be set which indicates sco_cnt
shall be used for flow contro.

Fixes: 7fedd3bb6b77 ("Bluetooth: Prioritize SCO traffic")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h      | 13 +++++++
 include/net/bluetooth/hci_core.h |  1 +
 net/bluetooth/hci_core.c         | 62 +++++++++++++++-----------------
 net/bluetooth/hci_event.c        |  2 ++
 net/bluetooth/hci_sync.c         | 24 +++++++++++++
 5 files changed, 68 insertions(+), 34 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b99818df8ee7..3c8f95174fcf 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -208,6 +208,13 @@ enum {
 	 */
 	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
 
+	/* When this quirk is set consider Sync Flow Control as supported by
+	 * the driver.
+	 *
+	 * This quirk must be set before hci_register_dev is called.
+	 */
+	HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED,
+
 	/* When this quirk is set, the LE states reported through the
 	 * HCI_LE_READ_SUPPORTED_STATES are invalid/broken.
 	 *
@@ -448,6 +455,7 @@ enum {
 	HCI_WIDEBAND_SPEECH_ENABLED,
 	HCI_EVENT_FILTER_CONFIGURED,
 	HCI_PA_SYNC,
+	HCI_SCO_FLOWCTL,
 
 	HCI_DUT_MODE,
 	HCI_VENDOR_DIAG,
@@ -1544,6 +1552,11 @@ struct hci_rp_read_tx_power {
 	__s8     tx_power;
 } __packed;
 
+#define HCI_OP_WRITE_SYNC_FLOWCTL	0x0c2f
+struct hci_cp_write_sync_flowctl {
+	__u8     enable;
+} __packed;
+
 #define HCI_OP_READ_PAGE_SCAN_TYPE	0x0c46
 struct hci_rp_read_page_scan_type {
 	__u8     status;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 7966db4038cc..f78e4298e39a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1858,6 +1858,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_hold_capable(dev)      ((dev)->features[0][0] & LMP_HOLD)
 #define lmp_sniff_capable(dev)     ((dev)->features[0][0] & LMP_SNIFF)
 #define lmp_park_capable(dev)      ((dev)->features[0][1] & LMP_PARK)
+#define lmp_sco_capable(dev)       ((dev)->features[0][1] & LMP_SCO)
 #define lmp_inq_rssi_capable(dev)  ((dev)->features[0][3] & LMP_RSSI_INQ)
 #define lmp_esco_capable(dev)      ((dev)->features[0][3] & LMP_ESCO)
 #define lmp_bredr_capable(dev)     (!((dev)->features[0][4] & LMP_NO_BREDR))
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 012fc107901a..94d9147612da 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3552,18 +3552,27 @@ static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
 }
 
 /* Schedule SCO */
-static void hci_sched_sco(struct hci_dev *hdev)
+static void hci_sched_sco(struct hci_dev *hdev, __u8 type)
 {
 	struct hci_conn *conn;
 	struct sk_buff *skb;
-	int quote;
+	int quote, *cnt;
+	unsigned int pkts = hdev->sco_pkts;
 
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "type %u", type);
 
-	if (!hci_conn_num(hdev, SCO_LINK))
+	if (!hci_conn_num(hdev, type) || !pkts)
 		return;
 
-	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
+	/* Use sco_pkts if flow control has not been enabled which will limit
+	 * the amount of buffer sent in a row.
+	 */
+	if (!hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL))
+		cnt = &pkts;
+	else
+		cnt = &hdev->sco_cnt;
+
+	while (*cnt && (conn = hci_low_sent(hdev, type, &quote))) {
 		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
 			BT_DBG("skb %p len %d", skb, skb->len);
 			hci_send_frame(hdev, skb);
@@ -3571,32 +3580,17 @@ static void hci_sched_sco(struct hci_dev *hdev)
 			conn->sent++;
 			if (conn->sent == ~0)
 				conn->sent = 0;
+			(*cnt)--;
 		}
 	}
-}
 
-static void hci_sched_esco(struct hci_dev *hdev)
-{
-	struct hci_conn *conn;
-	struct sk_buff *skb;
-	int quote;
-
-	BT_DBG("%s", hdev->name);
-
-	if (!hci_conn_num(hdev, ESCO_LINK))
-		return;
-
-	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
-						     &quote))) {
-		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
-			BT_DBG("skb %p len %d", skb, skb->len);
-			hci_send_frame(hdev, skb);
-
-			conn->sent++;
-			if (conn->sent == ~0)
-				conn->sent = 0;
-		}
-	}
+	/* Rescheduled if all packets were sent and flow control is not enabled
+	 * as there could be more packets queued that could not be sent and
+	 * since no HCI_EV_NUM_COMP_PKTS event will be generated the reschedule
+	 * needs to be forced.
+	 */
+	if (!pkts && !hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL))
+		queue_work(hdev->workqueue, &hdev->tx_work);
 }
 
 static void hci_sched_acl_pkt(struct hci_dev *hdev)
@@ -3632,8 +3626,8 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
 			chan->conn->sent++;
 
 			/* Send pending SCO packets right away */
-			hci_sched_sco(hdev);
-			hci_sched_esco(hdev);
+			hci_sched_sco(hdev, SCO_LINK);
+			hci_sched_sco(hdev, ESCO_LINK);
 		}
 	}
 
@@ -3688,8 +3682,8 @@ static void hci_sched_le(struct hci_dev *hdev)
 			chan->conn->sent++;
 
 			/* Send pending SCO packets right away */
-			hci_sched_sco(hdev);
-			hci_sched_esco(hdev);
+			hci_sched_sco(hdev, SCO_LINK);
+			hci_sched_sco(hdev, ESCO_LINK);
 		}
 	}
 
@@ -3734,8 +3728,8 @@ static void hci_tx_work(struct work_struct *work)
 
 	if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
 		/* Schedule queues and send stuff to HCI driver */
-		hci_sched_sco(hdev);
-		hci_sched_esco(hdev);
+		hci_sched_sco(hdev, SCO_LINK);
+		hci_sched_sco(hdev, ESCO_LINK);
 		hci_sched_iso(hdev);
 		hci_sched_acl(hdev);
 		hci_sched_le(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 19e19c9f5e68..6d0138b778aa 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4445,9 +4445,11 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
 			break;
 
 		case SCO_LINK:
+		case ESCO_LINK:
 			hdev->sco_cnt += count;
 			if (hdev->sco_cnt > hdev->sco_pkts)
 				hdev->sco_cnt = hdev->sco_pkts;
+
 			break;
 
 		case ISO_LINK:
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index c4c2cf51b219..609b035e5c90 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -3769,6 +3769,28 @@ static int hci_write_ca_timeout_sync(struct hci_dev *hdev)
 				     sizeof(param), &param, HCI_CMD_TIMEOUT);
 }
 
+/* Enable SCO flow control if supported */
+static int hci_write_sync_flowctl_sync(struct hci_dev *hdev)
+{
+	struct hci_cp_write_sync_flowctl cp;
+	int err;
+
+	/* Check if the controller supports SCO and HCI_OP_WRITE_SYNC_FLOWCTL */
+	if (!lmp_sco_capable(hdev) || !(hdev->commands[10] & BIT(4)) ||
+	    !test_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks))
+		return 0;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.enable = 0x01;
+
+	err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_SYNC_FLOWCTL,
+				    sizeof(cp), &cp, HCI_CMD_TIMEOUT);
+	if (!err)
+		hci_dev_set_flag(hdev, HCI_SCO_FLOWCTL);
+
+	return err;
+}
+
 /* BR Controller init stage 2 command sequence */
 static const struct hci_init_stage br_init2[] = {
 	/* HCI_OP_READ_BUFFER_SIZE */
@@ -3787,6 +3809,8 @@ static const struct hci_init_stage br_init2[] = {
 	HCI_INIT(hci_clear_event_filter_sync),
 	/* HCI_OP_WRITE_CA_TIMEOUT */
 	HCI_INIT(hci_write_ca_timeout_sync),
+	/* HCI_OP_WRITE_SYNC_FLOWCTL */
+	HCI_INIT(hci_write_sync_flowctl_sync),
 	{}
 };
 
-- 
2.48.1


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

* [PATCH v2 2/2] Bluetooth: hci_vhci: Mark Sync Flow Control as supported
  2025-03-12 15:14 [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO Luiz Augusto von Dentz
@ 2025-03-12 15:14 ` Luiz Augusto von Dentz
  2025-03-12 15:37 ` [v2,1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO bluez.test.bot
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2025-03-12 15:14 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This sets HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED which indicates that
controllers created by vhci driver support Sync Flow Control.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 drivers/bluetooth/hci_vhci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 963741490106..a51935d37e5d 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -416,6 +416,7 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
 	hdev->wakeup = vhci_wakeup;
 	hdev->setup = vhci_setup;
 	set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
+	set_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks);
 
 	/* bit 6 is for external configuration */
 	if (opcode & 0x40)
-- 
2.48.1


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

* RE: [v2,1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO
  2025-03-12 15:14 [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO Luiz Augusto von Dentz
  2025-03-12 15:14 ` [PATCH v2 2/2] Bluetooth: hci_vhci: Mark Sync Flow Control as supported Luiz Augusto von Dentz
@ 2025-03-12 15:37 ` bluez.test.bot
  2025-03-12 20:00 ` [PATCH v2 1/2] " Pauli Virtanen
  2025-03-13 14:00 ` patchwork-bot+bluetooth
  3 siblings, 0 replies; 6+ messages in thread
From: bluez.test.bot @ 2025-03-12 15:37 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

[-- Attachment #1: Type: text/plain, Size: 2394 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=943172

---Test result---

Test Summary:
CheckPatch                    PENDING   0.34 seconds
GitLint                       PENDING   0.23 seconds
SubjectPrefix                 PASS      0.24 seconds
BuildKernel                   PASS      24.83 seconds
CheckAllWarning               PASS      27.76 seconds
CheckSparse                   WARNING   31.09 seconds
BuildKernel32                 PASS      24.87 seconds
TestRunnerSetup               PASS      556.27 seconds
TestRunner_l2cap-tester       PASS      27.73 seconds
TestRunner_iso-tester         PASS      62.24 seconds
TestRunner_bnep-tester        PASS      7.68 seconds
TestRunner_mgmt-tester        FAIL      177.90 seconds
TestRunner_rfcomm-tester      PASS      13.22 seconds
TestRunner_sco-tester         PASS      17.96 seconds
TestRunner_ioctl-tester       PASS      15.13 seconds
TestRunner_mesh-tester        PASS      10.95 seconds
TestRunner_smp-tester         PASS      11.66 seconds
TestRunner_userchan-tester    PASS      8.43 seconds
IncrementalBuild              PENDING   0.69 seconds

Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:

##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:

##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:
net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 490, Passed: 482 (98.4%), Failed: 4, Not Run: 4

Failed Test Cases
LL Privacy - Add Device 2 (2 Devices to AL)          Failed       0.329 seconds
LL Privacy - Set Flags 3 (2 Devices to RL)           Failed       0.345 seconds
LL Privacy - Set Flags 4 (RL is full)                Failed       0.424 seconds
LL Privacy - Remove Device 3 (Disable RL)            Failed       0.382 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:



---
Regards,
Linux Bluetooth


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

* Re: [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO
  2025-03-12 15:14 [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO Luiz Augusto von Dentz
  2025-03-12 15:14 ` [PATCH v2 2/2] Bluetooth: hci_vhci: Mark Sync Flow Control as supported Luiz Augusto von Dentz
  2025-03-12 15:37 ` [v2,1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO bluez.test.bot
@ 2025-03-12 20:00 ` Pauli Virtanen
  2025-03-12 20:30   ` Luiz Augusto von Dentz
  2025-03-13 14:00 ` patchwork-bot+bluetooth
  3 siblings, 1 reply; 6+ messages in thread
From: Pauli Virtanen @ 2025-03-12 20:00 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, linux-bluetooth

Hi,

ke, 2025-03-12 kello 11:14 -0400, Luiz Augusto von Dentz kirjoitti:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> This enables buffer flow control for SCO/eSCO
> (see: Bluetooth Core 6.0 spec: 6.22. Synchronous Flow Control Enable),
> recently this has caused the following problem and is actually a nice
> addition for the likes of Socket TX complete:
> 
> < HCI Command: Read Buffer Size (0x04|0x0005) plen 0
> > HCI Event: Command Complete (0x0e) plen 11
>       Read Buffer Size (0x04|0x0005) ncmd 1
>         Status: Success (0x00)
>         ACL MTU: 1021 ACL max packet: 5
>         SCO MTU: 240  SCO max packet: 8
> ...
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > HCI Event: Hardware Error (0x10) plen 1
>         Code: 0x0a
> 
> To fix the code will now attempt to enable buffer flow control when
> HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED is set by the driver:
> 
> < HCI Command: Write Sync Fl.. (0x03|0x002f) plen 1
>         Flow control: Enabled (0x01)
> > HCI Event: Command Complete (0x0e) plen 4
>       Write Sync Flow Control Enable (0x03|0x002f) ncmd 1
>         Status: Success (0x00)
> 
> On success then HCI_SCO_FLOWCTL would be set which indicates sco_cnt
> shall be used for flow contro.

Tested-by: Pauli Virtanen <pav@iki.fi>

... to the degree that this does not break things on hardware that does
not support SCO flow control, and that the flow control case seemed to
be fine in the emulator.

I don't seem to have HW that support SCO flow control at hand, the
controllers I tested claim to support these commands, but either the
enable command reports success but the feature doesn't actually work
(Intel/Realtek), or the command fails (CSR, error code 0x11).

> 
> Fixes: 7fedd3bb6b77 ("Bluetooth: Prioritize SCO traffic")
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
>  include/net/bluetooth/hci.h      | 13 +++++++
>  include/net/bluetooth/hci_core.h |  1 +
>  net/bluetooth/hci_core.c         | 62 +++++++++++++++-----------------
>  net/bluetooth/hci_event.c        |  2 ++
>  net/bluetooth/hci_sync.c         | 24 +++++++++++++
>  5 files changed, 68 insertions(+), 34 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index b99818df8ee7..3c8f95174fcf 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -208,6 +208,13 @@ enum {
>  	 */
>  	HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
>  
> +	/* When this quirk is set consider Sync Flow Control as supported by
> +	 * the driver.
> +	 *
> +	 * This quirk must be set before hci_register_dev is called.
> +	 */
> +	HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED,
> +
>  	/* When this quirk is set, the LE states reported through the
>  	 * HCI_LE_READ_SUPPORTED_STATES are invalid/broken.
>  	 *
> @@ -448,6 +455,7 @@ enum {
>  	HCI_WIDEBAND_SPEECH_ENABLED,
>  	HCI_EVENT_FILTER_CONFIGURED,
>  	HCI_PA_SYNC,
> +	HCI_SCO_FLOWCTL,
>  
>  	HCI_DUT_MODE,
>  	HCI_VENDOR_DIAG,
> @@ -1544,6 +1552,11 @@ struct hci_rp_read_tx_power {
>  	__s8     tx_power;
>  } __packed;
>  
> +#define HCI_OP_WRITE_SYNC_FLOWCTL	0x0c2f
> +struct hci_cp_write_sync_flowctl {
> +	__u8     enable;
> +} __packed;
> +
>  #define HCI_OP_READ_PAGE_SCAN_TYPE	0x0c46
>  struct hci_rp_read_page_scan_type {
>  	__u8     status;
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 7966db4038cc..f78e4298e39a 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1858,6 +1858,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
>  #define lmp_hold_capable(dev)      ((dev)->features[0][0] & LMP_HOLD)
>  #define lmp_sniff_capable(dev)     ((dev)->features[0][0] & LMP_SNIFF)
>  #define lmp_park_capable(dev)      ((dev)->features[0][1] & LMP_PARK)
> +#define lmp_sco_capable(dev)       ((dev)->features[0][1] & LMP_SCO)
>  #define lmp_inq_rssi_capable(dev)  ((dev)->features[0][3] & LMP_RSSI_INQ)
>  #define lmp_esco_capable(dev)      ((dev)->features[0][3] & LMP_ESCO)
>  #define lmp_bredr_capable(dev)     (!((dev)->features[0][4] & LMP_NO_BREDR))
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 012fc107901a..94d9147612da 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -3552,18 +3552,27 @@ static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
>  }
>  
>  /* Schedule SCO */
> -static void hci_sched_sco(struct hci_dev *hdev)
> +static void hci_sched_sco(struct hci_dev *hdev, __u8 type)
>  {
>  	struct hci_conn *conn;
>  	struct sk_buff *skb;
> -	int quote;
> +	int quote, *cnt;
> +	unsigned int pkts = hdev->sco_pkts;
>  
> -	BT_DBG("%s", hdev->name);
> +	bt_dev_dbg(hdev, "type %u", type);
>  
> -	if (!hci_conn_num(hdev, SCO_LINK))
> +	if (!hci_conn_num(hdev, type) || !pkts)
>  		return;
>  
> -	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
> +	/* Use sco_pkts if flow control has not been enabled which will limit
> +	 * the amount of buffer sent in a row.
> +	 */
> +	if (!hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL))
> +		cnt = &pkts;
> +	else
> +		cnt = &hdev->sco_cnt;
> +
> +	while (*cnt && (conn = hci_low_sent(hdev, type, &quote))) {
>  		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
>  			BT_DBG("skb %p len %d", skb, skb->len);
>  			hci_send_frame(hdev, skb);
> @@ -3571,32 +3580,17 @@ static void hci_sched_sco(struct hci_dev *hdev)
>  			conn->sent++;
>  			if (conn->sent == ~0)
>  				conn->sent = 0;
> +			(*cnt)--;
>  		}
>  	}
> -}
>  
> -static void hci_sched_esco(struct hci_dev *hdev)
> -{
> -	struct hci_conn *conn;
> -	struct sk_buff *skb;
> -	int quote;
> -
> -	BT_DBG("%s", hdev->name);
> -
> -	if (!hci_conn_num(hdev, ESCO_LINK))
> -		return;
> -
> -	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
> -						     &quote))) {
> -		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
> -			BT_DBG("skb %p len %d", skb, skb->len);
> -			hci_send_frame(hdev, skb);
> -
> -			conn->sent++;
> -			if (conn->sent == ~0)
> -				conn->sent = 0;
> -		}
> -	}
> +	/* Rescheduled if all packets were sent and flow control is not enabled
> +	 * as there could be more packets queued that could not be sent and
> +	 * since no HCI_EV_NUM_COMP_PKTS event will be generated the reschedule
> +	 * needs to be forced.
> +	 */
> +	if (!pkts && !hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL))
> +		queue_work(hdev->workqueue, &hdev->tx_work);
>  }
>  
>  static void hci_sched_acl_pkt(struct hci_dev *hdev)
> @@ -3632,8 +3626,8 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
>  			chan->conn->sent++;
>  
>  			/* Send pending SCO packets right away */
> -			hci_sched_sco(hdev);
> -			hci_sched_esco(hdev);
> +			hci_sched_sco(hdev, SCO_LINK);
> +			hci_sched_sco(hdev, ESCO_LINK);
>  		}
>  	}
>  
> @@ -3688,8 +3682,8 @@ static void hci_sched_le(struct hci_dev *hdev)
>  			chan->conn->sent++;
>  
>  			/* Send pending SCO packets right away */
> -			hci_sched_sco(hdev);
> -			hci_sched_esco(hdev);
> +			hci_sched_sco(hdev, SCO_LINK);
> +			hci_sched_sco(hdev, ESCO_LINK);
>  		}
>  	}
>  
> @@ -3734,8 +3728,8 @@ static void hci_tx_work(struct work_struct *work)
>  
>  	if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
>  		/* Schedule queues and send stuff to HCI driver */
> -		hci_sched_sco(hdev);
> -		hci_sched_esco(hdev);
> +		hci_sched_sco(hdev, SCO_LINK);
> +		hci_sched_sco(hdev, ESCO_LINK);
>  		hci_sched_iso(hdev);
>  		hci_sched_acl(hdev);
>  		hci_sched_le(hdev);
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 19e19c9f5e68..6d0138b778aa 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -4445,9 +4445,11 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
>  			break;
>  
>  		case SCO_LINK:
> +		case ESCO_LINK:
>  			hdev->sco_cnt += count;
>  			if (hdev->sco_cnt > hdev->sco_pkts)
>  				hdev->sco_cnt = hdev->sco_pkts;
> +
>  			break;
>  
>  		case ISO_LINK:
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> index c4c2cf51b219..609b035e5c90 100644
> --- a/net/bluetooth/hci_sync.c
> +++ b/net/bluetooth/hci_sync.c
> @@ -3769,6 +3769,28 @@ static int hci_write_ca_timeout_sync(struct hci_dev *hdev)
>  				     sizeof(param), &param, HCI_CMD_TIMEOUT);
>  }
>  
> +/* Enable SCO flow control if supported */
> +static int hci_write_sync_flowctl_sync(struct hci_dev *hdev)
> +{
> +	struct hci_cp_write_sync_flowctl cp;
> +	int err;
> +
> +	/* Check if the controller supports SCO and HCI_OP_WRITE_SYNC_FLOWCTL */
> +	if (!lmp_sco_capable(hdev) || !(hdev->commands[10] & BIT(4)) ||
> +	    !test_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks))
> +		return 0;
> +
> +	memset(&cp, 0, sizeof(cp));
> +	cp.enable = 0x01;
> +
> +	err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_SYNC_FLOWCTL,
> +				    sizeof(cp), &cp, HCI_CMD_TIMEOUT);
> +	if (!err)
> +		hci_dev_set_flag(hdev, HCI_SCO_FLOWCTL);
> +
> +	return err;
> +}
> +
>  /* BR Controller init stage 2 command sequence */
>  static const struct hci_init_stage br_init2[] = {
>  	/* HCI_OP_READ_BUFFER_SIZE */
> @@ -3787,6 +3809,8 @@ static const struct hci_init_stage br_init2[] = {
>  	HCI_INIT(hci_clear_event_filter_sync),
>  	/* HCI_OP_WRITE_CA_TIMEOUT */
>  	HCI_INIT(hci_write_ca_timeout_sync),
> +	/* HCI_OP_WRITE_SYNC_FLOWCTL */
> +	HCI_INIT(hci_write_sync_flowctl_sync),
>  	{}
>  };
>  

-- 
Pauli Virtanen

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

* Re: [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO
  2025-03-12 20:00 ` [PATCH v2 1/2] " Pauli Virtanen
@ 2025-03-12 20:30   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2025-03-12 20:30 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: linux-bluetooth

Hi Pauli,

On Wed, Mar 12, 2025 at 4:00 PM Pauli Virtanen <pav@iki.fi> wrote:
>
> Hi,
>
> ke, 2025-03-12 kello 11:14 -0400, Luiz Augusto von Dentz kirjoitti:
> > From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> >
> > This enables buffer flow control for SCO/eSCO
> > (see: Bluetooth Core 6.0 spec: 6.22. Synchronous Flow Control Enable),
> > recently this has caused the following problem and is actually a nice
> > addition for the likes of Socket TX complete:
> >
> > < HCI Command: Read Buffer Size (0x04|0x0005) plen 0
> > > HCI Event: Command Complete (0x0e) plen 11
> >       Read Buffer Size (0x04|0x0005) ncmd 1
> >         Status: Success (0x00)
> >         ACL MTU: 1021 ACL max packet: 5
> >         SCO MTU: 240  SCO max packet: 8
> > ...
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > < SCO Data TX: Handle 257 flags 0x00 dlen 120
> > > HCI Event: Hardware Error (0x10) plen 1
> >         Code: 0x0a
> >
> > To fix the code will now attempt to enable buffer flow control when
> > HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED is set by the driver:
> >
> > < HCI Command: Write Sync Fl.. (0x03|0x002f) plen 1
> >         Flow control: Enabled (0x01)
> > > HCI Event: Command Complete (0x0e) plen 4
> >       Write Sync Flow Control Enable (0x03|0x002f) ncmd 1
> >         Status: Success (0x00)
> >
> > On success then HCI_SCO_FLOWCTL would be set which indicates sco_cnt
> > shall be used for flow contro.
>
> Tested-by: Pauli Virtanen <pav@iki.fi>
>
> ... to the degree that this does not break things on hardware that does
> not support SCO flow control, and that the flow control case seemed to
> be fine in the emulator.

Yes, thanks to you we have tests that cover both cases and with these
changes it can confirm if NOCP is being generated or not, so at least
it gives you the ability to implement the TX complete logic for SCO
using the emulator, right?

> I don't seem to have HW that support SCO flow control at hand, the
> controllers I tested claim to support these commands, but either the
> enable command reports success but the feature doesn't actually work
> (Intel/Realtek), or the command fails (CSR, error code 0x11).

Yeah, I am afraid we can't do much about that if the controller is
just not generating NOCP then we cannot enable the quirk, but at least
in the case of Intel it should work so perhaps there is something else
missing which I am trying to dig out.

> >
> > Fixes: 7fedd3bb6b77 ("Bluetooth: Prioritize SCO traffic")
> > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > ---
> >  include/net/bluetooth/hci.h      | 13 +++++++
> >  include/net/bluetooth/hci_core.h |  1 +
> >  net/bluetooth/hci_core.c         | 62 +++++++++++++++-----------------
> >  net/bluetooth/hci_event.c        |  2 ++
> >  net/bluetooth/hci_sync.c         | 24 +++++++++++++
> >  5 files changed, 68 insertions(+), 34 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> > index b99818df8ee7..3c8f95174fcf 100644
> > --- a/include/net/bluetooth/hci.h
> > +++ b/include/net/bluetooth/hci.h
> > @@ -208,6 +208,13 @@ enum {
> >        */
> >       HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
> >
> > +     /* When this quirk is set consider Sync Flow Control as supported by
> > +      * the driver.
> > +      *
> > +      * This quirk must be set before hci_register_dev is called.
> > +      */
> > +     HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED,
> > +
> >       /* When this quirk is set, the LE states reported through the
> >        * HCI_LE_READ_SUPPORTED_STATES are invalid/broken.
> >        *
> > @@ -448,6 +455,7 @@ enum {
> >       HCI_WIDEBAND_SPEECH_ENABLED,
> >       HCI_EVENT_FILTER_CONFIGURED,
> >       HCI_PA_SYNC,
> > +     HCI_SCO_FLOWCTL,
> >
> >       HCI_DUT_MODE,
> >       HCI_VENDOR_DIAG,
> > @@ -1544,6 +1552,11 @@ struct hci_rp_read_tx_power {
> >       __s8     tx_power;
> >  } __packed;
> >
> > +#define HCI_OP_WRITE_SYNC_FLOWCTL    0x0c2f
> > +struct hci_cp_write_sync_flowctl {
> > +     __u8     enable;
> > +} __packed;
> > +
> >  #define HCI_OP_READ_PAGE_SCAN_TYPE   0x0c46
> >  struct hci_rp_read_page_scan_type {
> >       __u8     status;
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index 7966db4038cc..f78e4298e39a 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -1858,6 +1858,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
> >  #define lmp_hold_capable(dev)      ((dev)->features[0][0] & LMP_HOLD)
> >  #define lmp_sniff_capable(dev)     ((dev)->features[0][0] & LMP_SNIFF)
> >  #define lmp_park_capable(dev)      ((dev)->features[0][1] & LMP_PARK)
> > +#define lmp_sco_capable(dev)       ((dev)->features[0][1] & LMP_SCO)
> >  #define lmp_inq_rssi_capable(dev)  ((dev)->features[0][3] & LMP_RSSI_INQ)
> >  #define lmp_esco_capable(dev)      ((dev)->features[0][3] & LMP_ESCO)
> >  #define lmp_bredr_capable(dev)     (!((dev)->features[0][4] & LMP_NO_BREDR))
> > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > index 012fc107901a..94d9147612da 100644
> > --- a/net/bluetooth/hci_core.c
> > +++ b/net/bluetooth/hci_core.c
> > @@ -3552,18 +3552,27 @@ static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
> >  }
> >
> >  /* Schedule SCO */
> > -static void hci_sched_sco(struct hci_dev *hdev)
> > +static void hci_sched_sco(struct hci_dev *hdev, __u8 type)
> >  {
> >       struct hci_conn *conn;
> >       struct sk_buff *skb;
> > -     int quote;
> > +     int quote, *cnt;
> > +     unsigned int pkts = hdev->sco_pkts;
> >
> > -     BT_DBG("%s", hdev->name);
> > +     bt_dev_dbg(hdev, "type %u", type);
> >
> > -     if (!hci_conn_num(hdev, SCO_LINK))
> > +     if (!hci_conn_num(hdev, type) || !pkts)
> >               return;
> >
> > -     while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
> > +     /* Use sco_pkts if flow control has not been enabled which will limit
> > +      * the amount of buffer sent in a row.
> > +      */
> > +     if (!hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL))
> > +             cnt = &pkts;
> > +     else
> > +             cnt = &hdev->sco_cnt;
> > +
> > +     while (*cnt && (conn = hci_low_sent(hdev, type, &quote))) {
> >               while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
> >                       BT_DBG("skb %p len %d", skb, skb->len);
> >                       hci_send_frame(hdev, skb);
> > @@ -3571,32 +3580,17 @@ static void hci_sched_sco(struct hci_dev *hdev)
> >                       conn->sent++;
> >                       if (conn->sent == ~0)
> >                               conn->sent = 0;
> > +                     (*cnt)--;
> >               }
> >       }
> > -}
> >
> > -static void hci_sched_esco(struct hci_dev *hdev)
> > -{
> > -     struct hci_conn *conn;
> > -     struct sk_buff *skb;
> > -     int quote;
> > -
> > -     BT_DBG("%s", hdev->name);
> > -
> > -     if (!hci_conn_num(hdev, ESCO_LINK))
> > -             return;
> > -
> > -     while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
> > -                                                  &quote))) {
> > -             while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
> > -                     BT_DBG("skb %p len %d", skb, skb->len);
> > -                     hci_send_frame(hdev, skb);
> > -
> > -                     conn->sent++;
> > -                     if (conn->sent == ~0)
> > -                             conn->sent = 0;
> > -             }
> > -     }
> > +     /* Rescheduled if all packets were sent and flow control is not enabled
> > +      * as there could be more packets queued that could not be sent and
> > +      * since no HCI_EV_NUM_COMP_PKTS event will be generated the reschedule
> > +      * needs to be forced.
> > +      */
> > +     if (!pkts && !hci_dev_test_flag(hdev, HCI_SCO_FLOWCTL))
> > +             queue_work(hdev->workqueue, &hdev->tx_work);
> >  }
> >
> >  static void hci_sched_acl_pkt(struct hci_dev *hdev)
> > @@ -3632,8 +3626,8 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
> >                       chan->conn->sent++;
> >
> >                       /* Send pending SCO packets right away */
> > -                     hci_sched_sco(hdev);
> > -                     hci_sched_esco(hdev);
> > +                     hci_sched_sco(hdev, SCO_LINK);
> > +                     hci_sched_sco(hdev, ESCO_LINK);
> >               }
> >       }
> >
> > @@ -3688,8 +3682,8 @@ static void hci_sched_le(struct hci_dev *hdev)
> >                       chan->conn->sent++;
> >
> >                       /* Send pending SCO packets right away */
> > -                     hci_sched_sco(hdev);
> > -                     hci_sched_esco(hdev);
> > +                     hci_sched_sco(hdev, SCO_LINK);
> > +                     hci_sched_sco(hdev, ESCO_LINK);
> >               }
> >       }
> >
> > @@ -3734,8 +3728,8 @@ static void hci_tx_work(struct work_struct *work)
> >
> >       if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
> >               /* Schedule queues and send stuff to HCI driver */
> > -             hci_sched_sco(hdev);
> > -             hci_sched_esco(hdev);
> > +             hci_sched_sco(hdev, SCO_LINK);
> > +             hci_sched_sco(hdev, ESCO_LINK);
> >               hci_sched_iso(hdev);
> >               hci_sched_acl(hdev);
> >               hci_sched_le(hdev);
> > diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> > index 19e19c9f5e68..6d0138b778aa 100644
> > --- a/net/bluetooth/hci_event.c
> > +++ b/net/bluetooth/hci_event.c
> > @@ -4445,9 +4445,11 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
> >                       break;
> >
> >               case SCO_LINK:
> > +             case ESCO_LINK:
> >                       hdev->sco_cnt += count;
> >                       if (hdev->sco_cnt > hdev->sco_pkts)
> >                               hdev->sco_cnt = hdev->sco_pkts;
> > +
> >                       break;
> >
> >               case ISO_LINK:
> > diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> > index c4c2cf51b219..609b035e5c90 100644
> > --- a/net/bluetooth/hci_sync.c
> > +++ b/net/bluetooth/hci_sync.c
> > @@ -3769,6 +3769,28 @@ static int hci_write_ca_timeout_sync(struct hci_dev *hdev)
> >                                    sizeof(param), &param, HCI_CMD_TIMEOUT);
> >  }
> >
> > +/* Enable SCO flow control if supported */
> > +static int hci_write_sync_flowctl_sync(struct hci_dev *hdev)
> > +{
> > +     struct hci_cp_write_sync_flowctl cp;
> > +     int err;
> > +
> > +     /* Check if the controller supports SCO and HCI_OP_WRITE_SYNC_FLOWCTL */
> > +     if (!lmp_sco_capable(hdev) || !(hdev->commands[10] & BIT(4)) ||
> > +         !test_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks))
> > +             return 0;
> > +
> > +     memset(&cp, 0, sizeof(cp));
> > +     cp.enable = 0x01;
> > +
> > +     err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_SYNC_FLOWCTL,
> > +                                 sizeof(cp), &cp, HCI_CMD_TIMEOUT);
> > +     if (!err)
> > +             hci_dev_set_flag(hdev, HCI_SCO_FLOWCTL);
> > +
> > +     return err;
> > +}
> > +
> >  /* BR Controller init stage 2 command sequence */
> >  static const struct hci_init_stage br_init2[] = {
> >       /* HCI_OP_READ_BUFFER_SIZE */
> > @@ -3787,6 +3809,8 @@ static const struct hci_init_stage br_init2[] = {
> >       HCI_INIT(hci_clear_event_filter_sync),
> >       /* HCI_OP_WRITE_CA_TIMEOUT */
> >       HCI_INIT(hci_write_ca_timeout_sync),
> > +     /* HCI_OP_WRITE_SYNC_FLOWCTL */
> > +     HCI_INIT(hci_write_sync_flowctl_sync),
> >       {}
> >  };
> >
>
> --
> Pauli Virtanen



-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO
  2025-03-12 15:14 [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2025-03-12 20:00 ` [PATCH v2 1/2] " Pauli Virtanen
@ 2025-03-13 14:00 ` patchwork-bot+bluetooth
  3 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+bluetooth @ 2025-03-13 14:00 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hello:

This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Wed, 12 Mar 2025 11:14:20 -0400 you wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> This enables buffer flow control for SCO/eSCO
> (see: Bluetooth Core 6.0 spec: 6.22. Synchronous Flow Control Enable),
> recently this has caused the following problem and is actually a nice
> addition for the likes of Socket TX complete:
> 
> [...]

Here is the summary with links:
  - [v2,1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO
    https://git.kernel.org/bluetooth/bluetooth-next/c/174f3c12f664
  - [v2,2/2] Bluetooth: hci_vhci: Mark Sync Flow Control as supported
    https://git.kernel.org/bluetooth/bluetooth-next/c/5c301fb00b84

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2025-03-13 13:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-12 15:14 [PATCH v2 1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO Luiz Augusto von Dentz
2025-03-12 15:14 ` [PATCH v2 2/2] Bluetooth: hci_vhci: Mark Sync Flow Control as supported Luiz Augusto von Dentz
2025-03-12 15:37 ` [v2,1/2] Bluetooth: hci_core: Enable buffer flow control for SCO/eSCO bluez.test.bot
2025-03-12 20:00 ` [PATCH v2 1/2] " Pauli Virtanen
2025-03-12 20:30   ` Luiz Augusto von Dentz
2025-03-13 14:00 ` patchwork-bot+bluetooth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.