aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-05-01 15:15:44 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-05-10 03:28:53 -0400
commit1890d36bb556a27684ad29654a9898ab9a5f57ee (patch)
tree9ff2c7d2f2e4288fa781f9f1802def01f7c530c9
parent9b53350d3cf5b330c3261d89b5e62a2dc25c5653 (diff)
Bluetooth: Implement Local Busy Condition handling
Supports Local Busy condition handling through a waitqueue that wake ups each 200ms and try to push the packets to the upper layer. If it can push all the queue then it leaves the Local Busy state. The patch modifies the behaviour of l2cap_ertm_reassembly_sdu() to support retry of the push operation. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/l2cap.h6
-rw-r--r--net/bluetooth/l2cap.c187
2 files changed, 172 insertions, 21 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 8942c2ffc58b..d0185cc04c14 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -35,6 +35,7 @@
35#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ 35#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
36#define L2CAP_DEFAULT_MAX_PDU_SIZE 672 36#define L2CAP_DEFAULT_MAX_PDU_SIZE 672
37#define L2CAP_DEFAULT_ACK_TO 200 37#define L2CAP_DEFAULT_ACK_TO 200
38#define L2CAP_LOCAL_BUSY_TRIES 12
38 39
39#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ 40#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */
40#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ 41#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
@@ -294,6 +295,7 @@ struct l2cap_conn {
294#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) 295#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
295#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) 296#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue)
296#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) 297#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue)
298#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue)
297#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) 299#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list)
298 300
299struct srej_list { 301struct srej_list {
@@ -356,6 +358,8 @@ struct l2cap_pinfo {
356 struct timer_list ack_timer; 358 struct timer_list ack_timer;
357 struct sk_buff_head tx_queue; 359 struct sk_buff_head tx_queue;
358 struct sk_buff_head srej_queue; 360 struct sk_buff_head srej_queue;
361 struct sk_buff_head busy_queue;
362 struct work_struct busy_work;
359 struct srej_list srej_l; 363 struct srej_list srej_l;
360 struct l2cap_conn *conn; 364 struct l2cap_conn *conn;
361 struct sock *next_c; 365 struct sock *next_c;
@@ -383,6 +387,8 @@ struct l2cap_pinfo {
383#define L2CAP_CONN_LOCAL_BUSY 0x0040 387#define L2CAP_CONN_LOCAL_BUSY 0x0040
384#define L2CAP_CONN_REJ_ACT 0x0080 388#define L2CAP_CONN_REJ_ACT 0x0080
385#define L2CAP_CONN_SEND_FBIT 0x0100 389#define L2CAP_CONN_SEND_FBIT 0x0100
390#define L2CAP_CONN_RNR_SENT 0x0200
391#define L2CAP_CONN_SAR_RETRY 0x0400
386 392
387#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ 393#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
388 jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); 394 jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 481cec22ef96..103e4b54a86a 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -68,10 +68,14 @@ static u8 l2cap_fixed_chan[8] = { 0x02, };
68 68
69static const struct proto_ops l2cap_sock_ops; 69static const struct proto_ops l2cap_sock_ops;
70 70
71static struct workqueue_struct *_busy_wq;
72
71static struct bt_sock_list l2cap_sk_list = { 73static struct bt_sock_list l2cap_sk_list = {
72 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) 74 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
73}; 75};
74 76
77static void l2cap_busy_work(struct work_struct *work);
78
75static void __l2cap_sock_close(struct sock *sk, int reason); 79static void __l2cap_sock_close(struct sock *sk, int reason);
76static void l2cap_sock_close(struct sock *sk); 80static void l2cap_sock_close(struct sock *sk);
77static void l2cap_sock_kill(struct sock *sk); 81static void l2cap_sock_kill(struct sock *sk);
@@ -386,9 +390,10 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
386 390
387static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) 391static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
388{ 392{
389 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) 393 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
390 control |= L2CAP_SUPER_RCV_NOT_READY; 394 control |= L2CAP_SUPER_RCV_NOT_READY;
391 else 395 pi->conn_state |= L2CAP_CONN_RNR_SENT;
396 } else
392 control |= L2CAP_SUPER_RCV_READY; 397 control |= L2CAP_SUPER_RCV_READY;
393 398
394 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; 399 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
@@ -816,6 +821,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
816 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; 821 pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
817 skb_queue_head_init(TX_QUEUE(sk)); 822 skb_queue_head_init(TX_QUEUE(sk));
818 skb_queue_head_init(SREJ_QUEUE(sk)); 823 skb_queue_head_init(SREJ_QUEUE(sk));
824 skb_queue_head_init(BUSY_QUEUE(sk));
819 INIT_LIST_HEAD(SREJ_LIST(sk)); 825 INIT_LIST_HEAD(SREJ_LIST(sk));
820} 826}
821 827
@@ -1439,6 +1445,7 @@ static void l2cap_send_ack(struct l2cap_pinfo *pi)
1439 1445
1440 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { 1446 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1441 control |= L2CAP_SUPER_RCV_NOT_READY; 1447 control |= L2CAP_SUPER_RCV_NOT_READY;
1448 pi->conn_state |= L2CAP_CONN_RNR_SENT;
1442 l2cap_send_sframe(pi, control); 1449 l2cap_send_sframe(pi, control);
1443 return; 1450 return;
1444 } else if (l2cap_ertm_send(sk) == 0) { 1451 } else if (l2cap_ertm_send(sk) == 0) {
@@ -2279,6 +2286,9 @@ static inline void l2cap_ertm_init(struct sock *sk)
2279 l2cap_ack_timeout, (unsigned long) sk); 2286 l2cap_ack_timeout, (unsigned long) sk);
2280 2287
2281 __skb_queue_head_init(SREJ_QUEUE(sk)); 2288 __skb_queue_head_init(SREJ_QUEUE(sk));
2289 __skb_queue_head_init(BUSY_QUEUE(sk));
2290
2291 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
2282} 2292}
2283 2293
2284static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 2294static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
@@ -3046,6 +3056,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
3046 3056
3047 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { 3057 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
3048 skb_queue_purge(SREJ_QUEUE(sk)); 3058 skb_queue_purge(SREJ_QUEUE(sk));
3059 skb_queue_purge(BUSY_QUEUE(sk));
3049 del_timer(&l2cap_pi(sk)->retrans_timer); 3060 del_timer(&l2cap_pi(sk)->retrans_timer);
3050 del_timer(&l2cap_pi(sk)->monitor_timer); 3061 del_timer(&l2cap_pi(sk)->monitor_timer);
3051 del_timer(&l2cap_pi(sk)->ack_timer); 3062 del_timer(&l2cap_pi(sk)->ack_timer);
@@ -3077,6 +3088,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
3077 3088
3078 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { 3089 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
3079 skb_queue_purge(SREJ_QUEUE(sk)); 3090 skb_queue_purge(SREJ_QUEUE(sk));
3091 skb_queue_purge(BUSY_QUEUE(sk));
3080 del_timer(&l2cap_pi(sk)->retrans_timer); 3092 del_timer(&l2cap_pi(sk)->retrans_timer);
3081 del_timer(&l2cap_pi(sk)->monitor_timer); 3093 del_timer(&l2cap_pi(sk)->monitor_timer);
3082 del_timer(&l2cap_pi(sk)->ack_timer); 3094 del_timer(&l2cap_pi(sk)->ack_timer);
@@ -3287,6 +3299,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3287 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { 3299 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3288 control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL; 3300 control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
3289 l2cap_send_sframe(pi, control); 3301 l2cap_send_sframe(pi, control);
3302 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3290 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; 3303 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
3291 } 3304 }
3292 3305
@@ -3338,7 +3351,7 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
3338{ 3351{
3339 struct l2cap_pinfo *pi = l2cap_pi(sk); 3352 struct l2cap_pinfo *pi = l2cap_pi(sk);
3340 struct sk_buff *_skb; 3353 struct sk_buff *_skb;
3341 int err = 0; 3354 int err;
3342 3355
3343 switch (control & L2CAP_CTRL_SAR) { 3356 switch (control & L2CAP_CTRL_SAR) {
3344 case L2CAP_SDU_UNSEGMENTED: 3357 case L2CAP_SDU_UNSEGMENTED:
@@ -3356,16 +3369,18 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
3356 goto drop; 3369 goto drop;
3357 3370
3358 pi->sdu_len = get_unaligned_le16(skb->data); 3371 pi->sdu_len = get_unaligned_le16(skb->data);
3359 skb_pull(skb, 2);
3360 3372
3361 if (pi->sdu_len > pi->imtu) 3373 if (pi->sdu_len > pi->imtu)
3362 goto disconnect; 3374 goto disconnect;
3363 3375
3364 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); 3376 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3365 if (!pi->sdu) { 3377 if (!pi->sdu)
3366 err = -ENOMEM; 3378 return -ENOMEM;
3367 break; 3379
3368 } 3380 /* pull sdu_len bytes only after alloc, because of Local Busy
3381 * condition we have to be sure that this will be executed
3382 * only once, i.e., when alloc does not fail */
3383 skb_pull(skb, 2);
3369 3384
3370 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); 3385 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3371 3386
@@ -3395,28 +3410,40 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
3395 if (!pi->sdu) 3