aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
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 /net/bluetooth
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>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap.c187
1 files changed, 166 insertions, 21 deletions
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) 3410 if (!pi->sdu)
3396 goto disconnect; 3411 goto disconnect;
3397 3412
3398 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); 3413 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
3414 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3399 3415
3400 pi->conn_state &= ~L2CAP_CONN_SAR_SDU; 3416 pi->partial_sdu_len += skb->len;
3401 pi->partial_sdu_len += skb->len;
3402 3417
3403 if (pi->partial_sdu_len > pi->imtu) 3418 if (pi->partial_sdu_len > pi->imtu)
3404 goto drop; 3419 goto drop;
3405 3420
3406 if (pi->partial_sdu_len != pi->sdu_len) 3421 if (pi->partial_sdu_len != pi->sdu_len)
3407 goto drop; 3422 goto drop;
3423 }
3408 3424
3409 _skb = skb_clone(pi->sdu, GFP_ATOMIC); 3425 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3426 if (!_skb) {
3427 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3428 return -ENOMEM;
3429 }
3430
3410 err = sock_queue_rcv_skb(sk, _skb); 3431 err = sock_queue_rcv_skb(sk, _skb);
3411 if (err < 0) 3432 if (err < 0) {
3412 kfree_skb(_skb); 3433 kfree_skb(_skb);
3434 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
3435 return err;
3436 }
3437
3438 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3439 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3413 3440
3414 kfree_skb(pi->sdu); 3441 kfree_skb(pi->sdu);
3415 break; 3442 break;
3416 } 3443 }
3417 3444
3418 kfree_skb(skb); 3445 kfree_skb(skb);
3419 return err; 3446 return 0;
3420 3447
3421drop: 3448drop:
3422 kfree_skb(pi->sdu); 3449 kfree_skb(pi->sdu);
@@ -3428,6 +3455,115 @@ disconnect:
3428 return 0; 3455 return 0;
3429} 3456}
3430 3457
3458static void l2cap_busy_work(struct work_struct *work)
3459{
3460 DECLARE_WAITQUEUE(wait, current);
3461 struct l2cap_pinfo *pi =
3462 container_of(work, struct l2cap_pinfo, busy_work);
3463 struct sock *sk = (struct sock *)pi;
3464 int n_tries = 0, timeo = HZ/5, err;
3465 struct sk_buff *skb;
3466 u16 control;
3467
3468 lock_sock(sk);
3469
3470 add_wait_queue(sk->sk_sleep, &wait);
3471 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3472 set_current_state(TASK_INTERRUPTIBLE);
3473
3474 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3475 err = -EBUSY;
3476 l2cap_send_disconn_req(pi->conn, sk);
3477 goto done;
3478 }
3479
3480 if (!timeo)
3481 timeo = HZ/5;
3482
3483 if (signal_pending(current)) {
3484 err = sock_intr_errno(timeo);
3485 goto done;
3486 }
3487
3488 release_sock(sk);
3489 timeo = schedule_timeout(timeo);
3490 lock_sock(sk);
3491
3492 err = sock_error(sk);
3493 if (err)
3494 goto done;
3495
3496 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
3497 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3498 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3499 if (err < 0) {
3500 skb_queue_head(BUSY_QUEUE(sk), skb);
3501 break;
3502 }
3503
3504 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3505 }
3506
3507 if (!skb)
3508 break;
3509 }
3510
3511 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
3512 goto done;
3513
3514 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3515 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
3516 l2cap_send_sframe(pi, control);
3517 l2cap_pi(sk)->retry_count = 1;
3518
3519 del_timer(&pi->retrans_timer);
3520 __mod_monitor_timer();
3521
3522 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
3523
3524done:
3525 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3526 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
3527
3528 set_current_state(TASK_RUNNING);
3529 remove_wait_queue(sk->sk_sleep, &wait);
3530
3531 release_sock(sk);
3532}
3533
3534static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3535{
3536 struct l2cap_pinfo *pi = l2cap_pi(sk);
3537 int sctrl, err;
3538
3539 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3540 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3541 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3542 return -EBUSY;
3543 }
3544
3545 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3546 if (err >= 0) {
3547 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3548 return err;
3549 }
3550
3551 /* Busy Condition */
3552 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3553 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3554 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3555
3556 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3557 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3558 l2cap_send_sframe(pi, sctrl);
3559
3560 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3561
3562 queue_work(_busy_wq, &pi->busy_work);
3563
3564 return err;
3565}
3566
3431static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) 3567static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
3432{ 3568{
3433 struct l2cap_pinfo *pi = l2cap_pi(sk); 3569 struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -3614,6 +3750,9 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
3614 goto drop; 3750 goto drop;
3615 } 3751 }
3616 3752
3753 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3754 goto drop;
3755
3617 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { 3756 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3618 struct srej_list *first; 3757 struct srej_list *first;
3619 3758
@@ -3662,6 +3801,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
3662 pi->buffer_seq_srej = pi->buffer_seq; 3801 pi->buffer_seq_srej = pi->buffer_seq;
3663 3802
3664 __skb_queue_head_init(SREJ_QUEUE(sk)); 3803 __skb_queue_head_init(SREJ_QUEUE(sk));
3804 __skb_queue_head_init(BUSY_QUEUE(sk));
3665 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); 3805 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3666 3806
3667 pi->conn_state |= L2CAP_CONN_SEND_PBIT; 3807 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
@@ -3691,11 +3831,9 @@ expected:
3691 } 3831 }
3692 } 3832 }
3693 3833
3694 pi->buffer_seq = (pi->buffer_seq + 1) % 64; 3834 err = l2cap_push_rx_skb(sk, skb, rx_control);
3695
3696 err = l2cap_ertm_reassembly_sdu(sk, skb, rx_control);
3697 if (err < 0) 3835 if (err < 0)
3698 return err; 3836 return 0;
3699 3837
3700 __mod_ack_timer(); 3838 __mod_ack_timer();
3701 3839
@@ -4406,6 +4544,10 @@ static int __init l2cap_init(void)
4406 if (err < 0) 4544 if (err < 0)
4407 return err; 4545 return err;
4408 4546
4547 _busy_wq = create_singlethread_workqueue("l2cap");
4548 if (!_busy_wq)
4549 goto error;
4550
4409 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); 4551 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
4410 if (err < 0) { 4552 if (err < 0) {
4411 BT_ERR("L2CAP socket registration failed"); 4553 BT_ERR("L2CAP socket registration failed");
@@ -4440,6 +4582,9 @@ static void __exit l2cap_exit(void)
4440{ 4582{
4441 debugfs_remove(l2cap_debugfs); 4583 debugfs_remove(l2cap_debugfs);
4442 4584
4585 flush_workqueue(_busy_wq);
4586 destroy_workqueue(_busy_wq);
4587
4443 if (bt_sock_unregister(BTPROTO_L2CAP) < 0) 4588 if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
4444 BT_ERR("L2CAP socket unregistration failed"); 4589 BT_ERR("L2CAP socket unregistration failed");
4445 4590