aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2011-11-02 09:52:01 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-11-07 14:24:56 -0500
commit73d80deb7bdf0171f22e76dc2429c1f99eff90e2 (patch)
tree17a65f2bf28e1e5a107503f361a7fb061e2ad2f4 /net/bluetooth
parent3c32fa93e5a54cd54e52541892857b0c7164a61e (diff)
Bluetooth: prioritizing data over HCI
This implement priority based scheduler using skbuffer priority set via SO_PRIORITY socket option. It introduces hci_chan_hash (list of HCI Channel/hci_chan) per connection, each item in this list refer to a L2CAP connection and it is used to queue the data for transmission. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.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.c53
-rw-r--r--net/bluetooth/hci_core.c143
-rw-r--r--net/bluetooth/l2cap_core.c63
-rw-r--r--net/bluetooth/smp.c3
4 files changed, 208 insertions, 54 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6e98ff3da2a4..e545376379c5 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -374,6 +374,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
374 374
375 skb_queue_head_init(&conn->data_q); 375 skb_queue_head_init(&conn->data_q);
376 376
377 hci_chan_hash_init(conn);
378
377 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); 379 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
378 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); 380 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
379 setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, 381 setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
@@ -432,6 +434,8 @@ int hci_conn_del(struct hci_conn *conn)
432 434
433 tasklet_disable(&hdev->tx_task); 435 tasklet_disable(&hdev->tx_task);
434 436
437 hci_chan_hash_flush(conn);
438
435 hci_conn_hash_del(hdev, conn); 439 hci_conn_hash_del(hdev, conn);
436 if (hdev->notify) 440 if (hdev->notify)
437 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); 441 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
@@ -950,3 +954,52 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
950 954
951 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0; 955 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
952} 956}
957
958struct hci_chan *hci_chan_create(struct hci_conn *conn)
959{
960 struct hci_dev *hdev = conn->hdev;
961 struct hci_chan *chan;
962
963 BT_DBG("%s conn %p", hdev->name, conn);
964
965 chan = kzalloc(sizeof(struct hci_chan), GFP_ATOMIC);
966 if (!chan)
967 return NULL;
968
969 chan->conn = conn;
970 skb_queue_head_init(&chan->data_q);
971
972 tasklet_disable(&hdev->tx_task);
973 hci_chan_hash_add(conn, chan);
974 tasklet_enable(&hdev->tx_task);
975
976 return chan;
977}
978
979int hci_chan_del(struct hci_chan *chan)
980{
981 struct hci_conn *conn = chan->conn;
982 struct hci_dev *hdev = conn->hdev;
983
984 BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
985
986 tasklet_disable(&hdev->tx_task);
987 hci_chan_hash_del(conn, chan);
988 tasklet_enable(&hdev->tx_task);
989
990 skb_queue_purge(&chan->data_q);
991 kfree(chan);
992
993 return 0;
994}
995
996void hci_chan_hash_flush(struct hci_conn *conn)
997{
998 struct hci_chan_hash *h = &conn->chan_hash;
999 struct hci_chan *chan, *tmp;
1000
1001 BT_DBG("conn %p", conn);
1002
1003 list_for_each_entry_safe(chan, tmp, &h->list, list)
1004 hci_chan_del(chan);
1005}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f2ec434971f6..631327dc7fed 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1937,23 +1937,18 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
1937 hdr->dlen = cpu_to_le16(len); 1937 hdr->dlen = cpu_to_le16(len);
1938} 1938}
1939 1939
1940void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) 1940static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
1941 struct sk_buff *skb, __u16 flags)
1941{ 1942{
1942 struct hci_dev *hdev = conn->hdev; 1943 struct hci_dev *hdev = conn->hdev;
1943 struct sk_buff *list; 1944 struct sk_buff *list;
1944 1945
1945 BT_DBG("%s conn %p flags 0x%x", hdev->name, conn, flags);
1946
1947 skb->dev = (void *) hdev;
1948 bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
1949 hci_add_acl_hdr(skb, conn->handle, flags);
1950
1951 list = skb_shinfo(skb)->frag_list; 1946 list = skb_shinfo(skb)->frag_list;
1952 if (!list) { 1947 if (!list) {
1953 /* Non fragmented */ 1948 /* Non fragmented */
1954 BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len); 1949 BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);
1955 1950
1956 skb_queue_tail(&conn->data_q, skb); 1951 skb_queue_tail(queue, skb);
1957 } else { 1952 } else {
1958 /* Fragmented */ 1953 /* Fragmented */
1959 BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); 1954 BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
@@ -1961,9 +1956,9 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
1961 skb_shinfo(skb)->frag_list = NULL; 1956 skb_shinfo(skb)->frag_list = NULL;
1962 1957
1963 /* Queue all fragments atomically */ 1958 /* Queue all fragments atomically */
1964 spin_lock_bh(&conn->data_q.lock); 1959 spin_lock_bh(&queue->lock);
1965 1960
1966 __skb_queue_tail(&conn->data_q, skb); 1961 __skb_queue_tail(queue, skb);
1967 1962
1968 flags &= ~ACL_START; 1963 flags &= ~ACL_START;
1969 flags |= ACL_CONT; 1964 flags |= ACL_CONT;
@@ -1976,11 +1971,25 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
1976 1971
1977 BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); 1972 BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
1978 1973
1979 __skb_queue_tail(&conn->data_q, skb); 1974 __skb_queue_tail(queue, skb);
1980 } while (list); 1975 } while (list);
1981 1976
1982 spin_unlock_bh(&conn->data_q.lock); 1977 spin_unlock_bh(&queue->lock);
1983 } 1978 }
1979}
1980
1981void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
1982{
1983 struct hci_conn *conn = chan->conn;
1984 struct hci_dev *hdev = conn->hdev;
1985
1986 BT_DBG("%s chan %p flags 0x%x", hdev->name, chan, flags);
1987
1988 skb->dev = (void *) hdev;
1989 bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
1990 hci_add_acl_hdr(skb, conn->handle, flags);
1991
1992 hci_queue_acl(conn, &chan->data_q, skb, flags);
1984 1993
1985 tasklet_schedule(&hdev->tx_task); 1994 tasklet_schedule(&hdev->tx_task);
1986} 1995}
@@ -2083,11 +2092,90 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
2083 } 2092 }
2084} 2093}
2085 2094
2086static inline void hci_sched_acl(struct hci_dev *hdev) 2095static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
2096 int *quote)
2087{ 2097{
2098 struct hci_conn_hash *h = &hdev->conn_hash;
2099 struct hci_chan *chan = NULL;
2100 int num = 0, min = ~0, cur_prio = 0;
2088 struct hci_conn *conn; 2101 struct hci_conn *conn;
2102 int cnt, q, conn_num = 0;
2103
2104 BT_DBG("%s", hdev->name);
2105
2106 list_for_each_entry(conn, &h->list, list) {
2107 struct hci_chan_hash *ch;
2108 struct hci_chan *tmp;
2109
2110 if (conn->type != type)
2111 continue;
2112
2113 if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
2114 continue;
2115
2116 conn_num++;
2117
2118 ch = &conn->chan_hash;
2119
2120 list_for_each_entry(tmp, &ch->list, list) {
2121 struct sk_buff *skb;
2122
2123 if (skb_queue_empty(&tmp->data_q))
2124 continue;
2125
2126 skb = skb_peek(&tmp->data_q);
2127 if (skb->priority < cur_prio)
2128 continue;
2129
2130 if (skb->priority > cur_prio) {
2131 num = 0;
2132 min = ~0;
2133 cur_prio = skb->priority;
2134 }
2135
2136 num++;
2137
2138 if (conn->sent < min) {
2139 min = conn->sent;
2140 chan = tmp;
2141 }
2142 }
2143
2144 if (hci_conn_num(hdev, type) == conn_num)
2145 break;
2146 }
2147
2148 if (!chan)
2149 return NULL;
2150
2151 switch (chan->conn->type) {
2152 case ACL_LINK:
2153 cnt = hdev->acl_cnt;
2154 break;
2155 case SCO_LINK:
2156 case ESCO_LINK:
2157 cnt = hdev->sco_cnt;
2158 break;
2159 case LE_LINK:
2160 cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
2161 break;
2162 default:
2163 cnt = 0;
2164 BT_ERR("Unknown link type");
2165 }
2166
2167 q = cnt / num;
2168 *quote = q ? q : 1;
2169 BT_DBG("chan %p quote %d", chan, *quote);
2170 return chan;
2171}
2172
2173static inline void hci_sched_acl(struct hci_dev *hdev)
2174{
2175 struct hci_chan *chan;
2089 struct sk_buff *skb; 2176 struct sk_buff *skb;
2090 int quote; 2177 int quote;
2178 unsigned int cnt;
2091 2179
2092 BT_DBG("%s", hdev->name); 2180 BT_DBG("%s", hdev->name);
2093 2181
@@ -2101,17 +2189,23 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
2101 hci_link_tx_to(hdev, ACL_LINK); 2189 hci_link_tx_to(hdev, ACL_LINK);
2102 } 2190 }
2103 2191
2104 while (hdev->acl_cnt && (conn = hci_low_sent(hdev, ACL_LINK, &quote))) { 2192 cnt = hdev->acl_cnt;
2105 while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
2106 BT_DBG("skb %p len %d", skb, skb->len);
2107 2193
2108 hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active); 2194 while (hdev->acl_cnt &&
2195 (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
2196 while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
2197 BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
2198 skb->len, skb->priority);
2199
2200 hci_conn_enter_active_mode(chan->conn,
2201 bt_cb(skb)->force_active);
2109 2202
2110 hci_send_frame(skb); 2203 hci_send_frame(skb);
2111 hdev->acl_last_tx = jiffies; 2204 hdev->acl_last_tx = jiffies;
2112 2205
2113 hdev->acl_cnt--; 2206 hdev->acl_cnt--;
2114 conn->sent++; 2207 chan->sent++;
2208 chan->conn->sent++;
2115 } 2209 }
2116 } 2210 }
2117} 2211}
@@ -2165,7 +2259,7 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
2165 2259
2166static inline void hci_sched_le(struct hci_dev *hdev) 2260static inline void hci_sched_le(struct hci_dev *hdev)
2167{ 2261{
2168 struct hci_conn *conn; 2262 struct hci_chan *chan;
2169 struct sk_buff *skb; 2263 struct sk_buff *skb;
2170 int quote, cnt; 2264 int quote, cnt;
2171 2265
@@ -2183,17 +2277,20 @@ static inline void hci_sched_le(struct hci_dev *hdev)
2183 } 2277 }
2184 2278
2185 cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; 2279 cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
2186 while (cnt && (conn = hci_low_sent(hdev, LE_LINK, &quote))) { 2280 while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, &quote))) {
2187 while (quote-- && (skb = skb_dequeue(&conn->data_q))) { 2281 while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
2188 BT_DBG("skb %p len %d", skb, skb->len); 2282 BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
2283 skb->len, skb->priority);
2189 2284
2190 hci_send_frame(skb); 2285 hci_send_frame(skb);
2191 hdev->le_last_tx = jiffies; 2286 hdev->le_last_tx = jiffies;
2192 2287
2193 cnt--; 2288 cnt--;
2194 conn->sent++; 2289 chan->sent++;
2290 chan->conn->sent++;
2195 } 2291 }
2196 } 2292 }
2293
2197 if (hdev->le_pkts) 2294 if (hdev->le_pkts)
2198 hdev->le_cnt = cnt; 2295 hdev->le_cnt = cnt;
2199 else 2296 else
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ac2c41ada0fe..15751fa5e914 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -566,7 +566,25 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
566 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON; 566 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
567 skb->priority = HCI_PRIO_MAX; 567 skb->priority = HCI_PRIO_MAX;
568 568
569 hci_send_acl(conn->hcon, skb, flags); 569 hci_send_acl(conn->hchan, skb, flags);
570}
571
572static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
573{
574 struct hci_conn *hcon = chan->conn->hcon;
575 u16 flags;
576
577 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
578 skb->priority);
579
580 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
581 lmp_no_flush_capable(hcon->hdev))
582 flags = ACL_START_NO_FLUSH;
583 else
584 flags = ACL_START;
585
586 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
587 hci_send_acl(chan->conn->hchan, skb, flags);
570} 588}
571 589
572static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) 590static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
@@ -575,7 +593,6 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
575 struct l2cap_hdr *lh; 593 struct l2cap_hdr *lh;
576 struct l2cap_conn *conn = chan->conn; 594 struct l2cap_conn *conn = chan->conn;
577 int count, hlen; 595 int count, hlen;
578 u8 flags;
579 596
580 if (chan->state != BT_CONNECTED) 597 if (chan->state != BT_CONNECTED)
581 return; 598 return;
@@ -615,14 +632,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
615 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); 632 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
616 } 633 }
617 634
618 if (lmp_no_flush_capable(conn->hcon->hdev)) 635 skb->priority = HCI_PRIO_MAX;
619 flags = ACL_START_NO_FLUSH; 636 l2cap_do_send(chan, skb);
620 else
621 flags = ACL_START;
622
623 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
624
625 hci_send_acl(chan->conn->hcon, skb, flags);
626} 637}
627 638
628static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) 639static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
@@ -1002,6 +1013,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
1002 chan->ops->close(chan->data); 1013 chan->ops->close(chan->data);
1003 } 1014 }
1004 1015
1016 hci_chan_del(conn->hchan);
1017
1005 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) 1018 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1006 del_timer_sync(&conn->info_timer); 1019 del_timer_sync(&conn->info_timer);
1007 1020
@@ -1024,18 +1037,26 @@ static void security_timeout(unsigned long arg)
1024static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) 1037static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1025{ 1038{
1026 struct l2cap_conn *conn = hcon->l2cap_data; 1039 struct l2cap_conn *conn = hcon->l2cap_data;
1040 struct hci_chan *hchan;
1027 1041
1028 if (conn || status) 1042 if (conn || status)
1029 return conn; 1043 return conn;
1030 1044
1045 hchan = hci_chan_create(hcon);
1046 if (!hchan)
1047 return NULL;
1048
1031 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); 1049 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1032 if (!conn) 1050 if (!conn) {
1051 hci_chan_del(hchan);
1033 return NULL; 1052 return NULL;
1053 }
1034 1054
1035 hcon->l2cap_data = conn; 1055 hcon->l2cap_data = conn;
1036 conn->hcon = hcon; 1056 conn->hcon = hcon;
1057 conn->hchan = hchan;
1037 1058
1038 BT_DBG("hcon %p conn %p", hcon, conn); 1059 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
1039 1060
1040 if (hcon->hdev->le_mtu && hcon->type == LE_LINK) 1061 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1041 conn->mtu = hcon->hdev->le_mtu; 1062 conn->mtu = hcon->hdev->le_mtu;
@@ -1261,24 +1282,6 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
1261 __clear_retrans_timer(chan); 1282 __clear_retrans_timer(chan);
1262} 1283}
1263 1284
1264static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
1265{
1266 struct hci_conn *hcon = chan->conn->hcon;
1267 u16 flags;
1268
1269 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
1270 skb->priority);
1271
1272 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1273 lmp_no_flush_capable(hcon->hdev))
1274 flags = ACL_START_NO_FLUSH;
1275 else
1276 flags = ACL_START;
1277
1278 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
1279 hci_send_acl(hcon, skb, flags);
1280}
1281
1282static void l2cap_streaming_send(struct l2cap_chan *chan) 1285static void l2cap_streaming_send(struct l2cap_chan *chan)
1283{ 1286{
1284 struct sk_buff *skb; 1287 struct sk_buff *skb;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 759b63572641..94e94ca35384 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -181,7 +181,8 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
181 if (!skb) 181 if (!skb)
182 return; 182 return;
183 183
184 hci_send_acl(conn->hcon, skb, 0); 184 skb->priority = HCI_PRIO_MAX;
185 hci_send_acl(conn->hchan, skb, 0);
185 186
186 mod_timer(&conn->security_timer, jiffies + 187 mod_timer(&conn->security_timer, jiffies +
187 msecs_to_jiffies(SMP_TIMEOUT)); 188 msecs_to_jiffies(SMP_TIMEOUT));