Skip to content

Commit 7fedd3b

Browse files
apanditholtmann
authored andcommitted
Bluetooth: Prioritize SCO traffic
When scheduling TX packets, send all SCO/eSCO packets first, check for pending SCO/eSCO packets after every ACL/LE packet and send them if any are pending. This is done to make sure that we can meet SCO deadlines on slow interfaces like UART. If we were to queue up multiple ACL packets without checking for a SCO packet, we might miss the SCO timing. For example: The time it takes to send a maximum size ACL packet (1024 bytes): t = 10/8 * 1024 bytes * 8 bits/byte * 1 packet / baudrate where 10/8 is uart overhead due to start/stop bits per byte Replace t = 3.75ms (SCO deadline), which gives us a baudrate of 2730666. At a baudrate of 3000000, if we didn't check for SCO packets within 1024 bytes, we would miss the 3.75ms timing window. Signed-off-by: Abhishek Pandit-Subedi <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 81bd5d0 commit 7fedd3b

File tree

1 file changed

+57
-49
lines changed

1 file changed

+57
-49
lines changed

net/bluetooth/hci_core.c

Lines changed: 57 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4240,6 +4240,54 @@ static void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
42404240
}
42414241
}
42424242

4243+
/* Schedule SCO */
4244+
static void hci_sched_sco(struct hci_dev *hdev)
4245+
{
4246+
struct hci_conn *conn;
4247+
struct sk_buff *skb;
4248+
int quote;
4249+
4250+
BT_DBG("%s", hdev->name);
4251+
4252+
if (!hci_conn_num(hdev, SCO_LINK))
4253+
return;
4254+
4255+
while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
4256+
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
4257+
BT_DBG("skb %p len %d", skb, skb->len);
4258+
hci_send_frame(hdev, skb);
4259+
4260+
conn->sent++;
4261+
if (conn->sent == ~0)
4262+
conn->sent = 0;
4263+
}
4264+
}
4265+
}
4266+
4267+
static void hci_sched_esco(struct hci_dev *hdev)
4268+
{
4269+
struct hci_conn *conn;
4270+
struct sk_buff *skb;
4271+
int quote;
4272+
4273+
BT_DBG("%s", hdev->name);
4274+
4275+
if (!hci_conn_num(hdev, ESCO_LINK))
4276+
return;
4277+
4278+
while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
4279+
&quote))) {
4280+
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
4281+
BT_DBG("skb %p len %d", skb, skb->len);
4282+
hci_send_frame(hdev, skb);
4283+
4284+
conn->sent++;
4285+
if (conn->sent == ~0)
4286+
conn->sent = 0;
4287+
}
4288+
}
4289+
}
4290+
42434291
static void hci_sched_acl_pkt(struct hci_dev *hdev)
42444292
{
42454293
unsigned int cnt = hdev->acl_cnt;
@@ -4271,6 +4319,10 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
42714319
hdev->acl_cnt--;
42724320
chan->sent++;
42734321
chan->conn->sent++;
4322+
4323+
/* Send pending SCO packets right away */
4324+
hci_sched_sco(hdev);
4325+
hci_sched_esco(hdev);
42744326
}
42754327
}
42764328

@@ -4355,54 +4407,6 @@ static void hci_sched_acl(struct hci_dev *hdev)
43554407
}
43564408
}
43574409

4358-
/* Schedule SCO */
4359-
static void hci_sched_sco(struct hci_dev *hdev)
4360-
{
4361-
struct hci_conn *conn;
4362-
struct sk_buff *skb;
4363-
int quote;
4364-
4365-
BT_DBG("%s", hdev->name);
4366-
4367-
if (!hci_conn_num(hdev, SCO_LINK))
4368-
return;
4369-
4370-
while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
4371-
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
4372-
BT_DBG("skb %p len %d", skb, skb->len);
4373-
hci_send_frame(hdev, skb);
4374-
4375-
conn->sent++;
4376-
if (conn->sent == ~0)
4377-
conn->sent = 0;
4378-
}
4379-
}
4380-
}
4381-
4382-
static void hci_sched_esco(struct hci_dev *hdev)
4383-
{
4384-
struct hci_conn *conn;
4385-
struct sk_buff *skb;
4386-
int quote;
4387-
4388-
BT_DBG("%s", hdev->name);
4389-
4390-
if (!hci_conn_num(hdev, ESCO_LINK))
4391-
return;
4392-
4393-
while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
4394-
&quote))) {
4395-
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
4396-
BT_DBG("skb %p len %d", skb, skb->len);
4397-
hci_send_frame(hdev, skb);
4398-
4399-
conn->sent++;
4400-
if (conn->sent == ~0)
4401-
conn->sent = 0;
4402-
}
4403-
}
4404-
}
4405-
44064410
static void hci_sched_le(struct hci_dev *hdev)
44074411
{
44084412
struct hci_chan *chan;
@@ -4437,6 +4441,10 @@ static void hci_sched_le(struct hci_dev *hdev)
44374441
cnt--;
44384442
chan->sent++;
44394443
chan->conn->sent++;
4444+
4445+
/* Send pending SCO packets right away */
4446+
hci_sched_sco(hdev);
4447+
hci_sched_esco(hdev);
44404448
}
44414449
}
44424450

@@ -4459,9 +4467,9 @@ static void hci_tx_work(struct work_struct *work)
44594467

44604468
if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
44614469
/* Schedule queues and send stuff to HCI driver */
4462-
hci_sched_acl(hdev);
44634470
hci_sched_sco(hdev);
44644471
hci_sched_esco(hdev);
4472+
hci_sched_acl(hdev);
44654473
hci_sched_le(hdev);
44664474
}
44674475

0 commit comments

Comments
 (0)