Skip to content

Commit 6ed58ec

Browse files
Ville TervoGustavo F. Padovan
Ville Tervo
authored and
Gustavo F. Padovan
committed
Bluetooth: Use LE buffers for LE traffic
Bluetooth chips may have separate buffers for LE traffic. This patch add support to use LE buffers provided by the chip. Signed-off-by: Ville Tervo <[email protected]> Acked-by: Marcel Holtmann <[email protected]> Signed-off-by: Gustavo F. Padovan <[email protected]>
1 parent fcd89c0 commit 6ed58ec

File tree

4 files changed

+113
-4
lines changed

4 files changed

+113
-4
lines changed

include/net/bluetooth/hci_core.h

+5
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,19 @@ struct hci_dev {
123123
atomic_t cmd_cnt;
124124
unsigned int acl_cnt;
125125
unsigned int sco_cnt;
126+
unsigned int le_cnt;
126127

127128
unsigned int acl_mtu;
128129
unsigned int sco_mtu;
130+
unsigned int le_mtu;
129131
unsigned int acl_pkts;
130132
unsigned int sco_pkts;
133+
unsigned int le_pkts;
131134

132135
unsigned long cmd_last_tx;
133136
unsigned long acl_last_tx;
134137
unsigned long sco_last_tx;
138+
unsigned long le_last_tx;
135139

136140
struct workqueue_struct *workqueue;
137141

@@ -521,6 +525,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
521525
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
522526
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
523527
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
528+
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
524529

525530
/* ----- HCI protocols ----- */
526531
struct hci_proto {

net/bluetooth/hci_conn.c

+5
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,11 @@ int hci_conn_del(struct hci_conn *conn)
326326

327327
/* Unacked frames */
328328
hdev->acl_cnt += conn->sent;
329+
} else if (conn->type == LE_LINK) {
330+
if (hdev->le_pkts)
331+
hdev->le_cnt += conn->sent;
332+
else
333+
hdev->acl_cnt += conn->sent;
329334
} else {
330335
struct hci_conn *acl = conn->link;
331336
if (acl) {

net/bluetooth/hci_core.c

+70-4
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,14 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
263263
hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
264264
}
265265

266+
static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
267+
{
268+
BT_DBG("%s", hdev->name);
269+
270+
/* Read LE buffer size */
271+
hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
272+
}
273+
266274
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
267275
{
268276
__u8 scan = opt;
@@ -529,6 +537,10 @@ int hci_dev_open(__u16 dev)
529537
ret = __hci_request(hdev, hci_init_req, 0,
530538
msecs_to_jiffies(HCI_INIT_TIMEOUT));
531539

540+
if (lmp_le_capable(hdev))
541+
ret = __hci_request(hdev, hci_le_init_req, 0,
542+
msecs_to_jiffies(HCI_INIT_TIMEOUT));
543+
532544
clear_bit(HCI_INIT, &hdev->flags);
533545
}
534546

@@ -671,7 +683,7 @@ int hci_dev_reset(__u16 dev)
671683
hdev->flush(hdev);
672684

673685
atomic_set(&hdev->cmd_cnt, 1);
674-
hdev->acl_cnt = 0; hdev->sco_cnt = 0;
686+
hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
675687

676688
if (!test_bit(HCI_RAW, &hdev->flags))
677689
ret = __hci_request(hdev, hci_reset_req, 0,
@@ -1672,8 +1684,25 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
16721684
}
16731685

16741686
if (conn) {
1675-
int cnt = (type == ACL_LINK ? hdev->acl_cnt : hdev->sco_cnt);
1676-
int q = cnt / num;
1687+
int cnt, q;
1688+
1689+
switch (conn->type) {
1690+
case ACL_LINK:
1691+
cnt = hdev->acl_cnt;
1692+
break;
1693+
case SCO_LINK:
1694+
case ESCO_LINK:
1695+
cnt = hdev->sco_cnt;
1696+
break;
1697+
case LE_LINK:
1698+
cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
1699+
break;
1700+
default:
1701+
cnt = 0;
1702+
BT_ERR("Unknown link type");
1703+
}
1704+
1705+
q = cnt / num;
16771706
*quote = q ? q : 1;
16781707
} else
16791708
*quote = 0;
@@ -1772,14 +1801,49 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
17721801
}
17731802
}
17741803

1804+
static inline void hci_sched_le(struct hci_dev *hdev)
1805+
{
1806+
struct hci_conn *conn;
1807+
struct sk_buff *skb;
1808+
int quote, cnt;
1809+
1810+
BT_DBG("%s", hdev->name);
1811+
1812+
if (!test_bit(HCI_RAW, &hdev->flags)) {
1813+
/* LE tx timeout must be longer than maximum
1814+
* link supervision timeout (40.9 seconds) */
1815+
if (!hdev->le_cnt &&
1816+
time_after(jiffies, hdev->le_last_tx + HZ * 45))
1817+
hci_acl_tx_to(hdev);
1818+
}
1819+
1820+
cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
1821+
while (cnt && (conn = hci_low_sent(hdev, LE_LINK, &quote))) {
1822+
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
1823+
BT_DBG("skb %p len %d", skb, skb->len);
1824+
1825+
hci_send_frame(skb);
1826+
hdev->le_last_tx = jiffies;
1827+
1828+
cnt--;
1829+
conn->sent++;
1830+
}
1831+
}
1832+
if (hdev->le_pkts)
1833+
hdev->le_cnt = cnt;
1834+
else
1835+
hdev->acl_cnt = cnt;
1836+
}
1837+
17751838
static void hci_tx_task(unsigned long arg)
17761839
{
17771840
struct hci_dev *hdev = (struct hci_dev *) arg;
17781841
struct sk_buff *skb;
17791842

17801843
read_lock(&hci_task_lock);
17811844

1782-
BT_DBG("%s acl %d sco %d", hdev->name, hdev->acl_cnt, hdev->sco_cnt);
1845+
BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
1846+
hdev->sco_cnt, hdev->le_cnt);
17831847

17841848
/* Schedule queues and send stuff to HCI driver */
17851849

@@ -1789,6 +1853,8 @@ static void hci_tx_task(unsigned long arg)
17891853

17901854
hci_sched_esco(hdev);
17911855

1856+
hci_sched_le(hdev);
1857+
17921858
/* Send next queued raw (unknown type) packet */
17931859
while ((skb = skb_dequeue(&hdev->raw_q)))
17941860
hci_send_frame(skb);

net/bluetooth/hci_event.c

+33
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,25 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
776776
mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
777777
rp->status);
778778
}
779+
static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
780+
struct sk_buff *skb)
781+
{
782+
struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
783+
784+
BT_DBG("%s status 0x%x", hdev->name, rp->status);
785+
786+
if (rp->status)
787+
return;
788+
789+
hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
790+
hdev->le_pkts = rp->le_max_pkt;
791+
792+
hdev->le_cnt = hdev->le_pkts;
793+
794+
BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
795+
796+
hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
797+
}
779798

780799
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
781800
{
@@ -1704,6 +1723,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
17041723
hci_cc_pin_code_neg_reply(hdev, skb);
17051724
break;
17061725

1726+
case HCI_OP_LE_READ_BUFFER_SIZE:
1727+
hci_cc_le_read_buffer_size(hdev, skb);
1728+
break;
1729+
17071730
default:
17081731
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
17091732
break;
@@ -1849,6 +1872,16 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
18491872
hdev->acl_cnt += count;
18501873
if (hdev->acl_cnt > hdev->acl_pkts)
18511874
hdev->acl_cnt = hdev->acl_pkts;
1875+
} else if (conn->type == LE_LINK) {
1876+
if (hdev->le_pkts) {
1877+
hdev->le_cnt += count;
1878+
if (hdev->le_cnt > hdev->le_pkts)
1879+
hdev->le_cnt = hdev->le_pkts;
1880+
} else {
1881+
hdev->acl_cnt += count;
1882+
if (hdev->acl_cnt > hdev->acl_pkts)
1883+
hdev->acl_cnt = hdev->acl_pkts;
1884+
}
18521885
} else {
18531886
hdev->sco_cnt += count;
18541887
if (hdev->sco_cnt > hdev->sco_pkts)

0 commit comments

Comments
 (0)