aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorVille Tervo <ville.tervo@nokia.com>2011-02-10 20:38:48 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-16 14:32:51 -0500
commit6ed58ec520ad2b2fe3f955c8a5fd0eecafccebdf (patch)
tree5e53b20a64214c811dda8625c14af394a7800718 /net/bluetooth
parentfcd89c09a59a054fb986861e0862aa2fff7d7c40 (diff)
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 <ville.tervo@nokia.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_conn.c5
-rw-r--r--net/bluetooth/hci_core.c74
-rw-r--r--net/bluetooth/hci_event.c33
3 files changed, 108 insertions, 4 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d0c470c18f9d..aecd78e6cceb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -326,6 +326,11 @@ int hci_conn_del(struct hci_conn *conn)
326 326
327 /* Unacked frames */ 327 /* Unacked frames */
328 hdev->acl_cnt += conn->sent; 328 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;
329 } else { 334 } else {
330 struct hci_conn *acl = conn->link; 335 struct hci_conn *acl = conn->link;
331 if (acl) { 336 if (acl) {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2f003224d2ea..92960532dea4 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -263,6 +263,14 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
263 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); 263 hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
264} 264}
265 265
266static 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
266static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) 274static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
267{ 275{
268 __u8 scan = opt; 276 __u8 scan = opt;
@@ -529,6 +537,10 @@ int hci_dev_open(__u16 dev)
529 ret = __hci_request(hdev, hci_init_req, 0, 537 ret = __hci_request(hdev, hci_init_req, 0,
530 msecs_to_jiffies(HCI_INIT_TIMEOUT)); 538 msecs_to_jiffies(HCI_INIT_TIMEOUT));
531 539
540 if (lmp_le_capable(hdev))
541 ret = __hci_request(hdev, hci_le_init_req, 0,
542 msecs_to_jiffies(HCI_INIT_TIMEOUT));
543
532 clear_bit(HCI_INIT, &hdev->flags); 544 clear_bit(HCI_INIT, &hdev->flags);
533 } 545 }
534 546
@@ -671,7 +683,7 @@ int hci_dev_reset(__u16 dev)
671 hdev->flush(hdev); 683 hdev->flush(hdev);
672 684
673 atomic_set(&hdev->cmd_cnt, 1); 685 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;
675 687
676 if (!test_bit(HCI_RAW, &hdev->flags)) 688 if (!test_bit(HCI_RAW, &hdev->flags))
677 ret = __hci_request(hdev, hci_reset_req, 0, 689 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
1672 } 1684 }
1673 1685
1674 if (conn) { 1686 if (conn) {
1675 int cnt = (type == ACL_LINK ? hdev->acl_cnt : hdev->sco_cnt); 1687 int cnt, q;
1676 int q = cnt / num; 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;
1677 *quote = q ? q : 1; 1706 *quote = q ? q : 1;
1678 } else 1707 } else
1679 *quote = 0; 1708 *quote = 0;
@@ -1772,6 +1801,40 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
1772 } 1801 }
1773} 1802}
1774 1803
1804static 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
1775static void hci_tx_task(unsigned long arg) 1838static void hci_tx_task(unsigned long arg)
1776{ 1839{
1777 struct hci_dev *hdev = (struct hci_dev *) arg; 1840 struct hci_dev *hdev = (struct hci_dev *) arg;
@@ -1779,7 +1842,8 @@ static void hci_tx_task(unsigned long arg)
1779 1842
1780 read_lock(&hci_task_lock); 1843 read_lock(&hci_task_lock);
1781 1844
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);
1783 1847
1784 /* Schedule queues and send stuff to HCI driver */ 1848 /* Schedule queues and send stuff to HCI driver */
1785 1849
@@ -1789,6 +1853,8 @@ static void hci_tx_task(unsigned long arg)
1789 1853
1790 hci_sched_esco(hdev); 1854 hci_sched_esco(hdev);
1791 1855
1856 hci_sched_le(hdev);
1857
1792 /* Send next queued raw (unknown type) packet */ 1858 /* Send next queued raw (unknown type) packet */
1793 while ((skb = skb_dequeue(&hdev->raw_q))) 1859 while ((skb = skb_dequeue(&hdev->raw_q)))
1794 hci_send_frame(skb); 1860 hci_send_frame(skb);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 47c6e9316ce8..3155ad588076 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -776,6 +776,25 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
776 mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr, 776 mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
777 rp->status); 777 rp->status);
778} 778}
779static 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}
779 798
780static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 799static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
781{ 800{
@@ -1704,6 +1723,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
1704 hci_cc_pin_code_neg_reply(hdev, skb); 1723 hci_cc_pin_code_neg_reply(hdev, skb);
1705 break; 1724 break;
1706 1725
1726 case HCI_OP_LE_READ_BUFFER_SIZE:
1727 hci_cc_le_read_buffer_size(hdev, skb);
1728 break;
1729
1707 default: 1730 default:
1708 BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1731 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1709 break; 1732 break;
@@ -1849,6 +1872,16 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
1849 hdev->acl_cnt += count; 1872 hdev->acl_cnt += count;
1850 if (hdev->acl_cnt > hdev->acl_pkts) 1873 if (hdev->acl_cnt > hdev->acl_pkts)
1851 hdev->acl_cnt = hdev->acl_pkts; 1874 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 }
1852 } else { 1885 } else {
1853 hdev->sco_cnt += count; 1886 hdev->sco_cnt += count;
1854 if (hdev->sco_cnt > hdev->sco_pkts) 1887 if (hdev->sco_cnt > hdev->sco_pkts)