aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2011-07-07 12:39:03 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-07-07 14:29:06 -0400
commitfadd192e81b0a8d8086531b8c11bd88b311b68c2 (patch)
treefc1cf6a8183382801e49a48f0440c589cfb16645 /net
parente328140fdacbba43292a59a22fb55d9185288318 (diff)
Bluetooth: Remove L2CAP busy queue
The ERTM receive buffer is now handled in a way that does not require the busy queue and the associated polling code. Signed-off-by: Mat Martineau <mathewm@codeaurora.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c125
1 files changed, 8 insertions, 117 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ea9c7d061046..2c5d335bde87 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -61,13 +61,9 @@ int disable_ertm;
61static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; 61static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
62static u8 l2cap_fixed_chan[8] = { 0x02, }; 62static u8 l2cap_fixed_chan[8] = { 0x02, };
63 63
64static struct workqueue_struct *_busy_wq;
65
66static LIST_HEAD(chan_list); 64static LIST_HEAD(chan_list);
67static DEFINE_RWLOCK(chan_list_lock); 65static DEFINE_RWLOCK(chan_list_lock);
68 66
69static void l2cap_busy_work(struct work_struct *work);
70
71static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 67static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data); 68 u8 code, u8 ident, u16 dlen, void *data);
73static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, 69static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
@@ -395,7 +391,6 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
395 __clear_ack_timer(chan); 391 __clear_ack_timer(chan);
396 392
397 skb_queue_purge(&chan->srej_q); 393 skb_queue_purge(&chan->srej_q);
398 skb_queue_purge(&chan->busy_q);
399 394
400 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { 395 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
401 list_del(&l->list); 396 list_del(&l->list);
@@ -1873,11 +1868,9 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan)
1873 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan); 1868 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
1874 1869
1875 skb_queue_head_init(&chan->srej_q); 1870 skb_queue_head_init(&chan->srej_q);
1876 skb_queue_head_init(&chan->busy_q);
1877 1871
1878 INIT_LIST_HEAD(&chan->srej_l); 1872 INIT_LIST_HEAD(&chan->srej_l);
1879 1873
1880 INIT_WORK(&chan->busy_work, l2cap_busy_work);
1881 1874
1882 sk->sk_backlog_rcv = l2cap_ertm_data_rcv; 1875 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
1883} 1876}
@@ -3182,32 +3175,27 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
3182 if (!chan->sdu) 3175 if (!chan->sdu)
3183 goto disconnect; 3176 goto disconnect;
3184 3177
3185 if (!test_bit(CONN_SAR_RETRY, &chan->conn_state)) { 3178 chan->partial_sdu_len += skb->len;
3186 chan->partial_sdu_len += skb->len;
3187 3179
3188 if (chan->partial_sdu_len > chan->imtu) 3180 if (chan->partial_sdu_len > chan->imtu)
3189 goto drop; 3181 goto drop;
3190 3182
3191 if (chan->partial_sdu_len != chan->sdu_len) 3183 if (chan->partial_sdu_len != chan->sdu_len)
3192 goto drop; 3184 goto drop;
3193 3185
3194 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); 3186 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
3195 }
3196 3187
3197 _skb = skb_clone(chan->sdu, GFP_ATOMIC); 3188 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
3198 if (!_skb) { 3189 if (!_skb) {
3199 set_bit(CONN_SAR_RETRY, &chan->conn_state);
3200 return -ENOMEM; 3190 return -ENOMEM;
3201 } 3191 }
3202 3192
3203 err = chan->ops->recv(chan->data, _skb); 3193 err = chan->ops->recv(chan->data, _skb);
3204 if (err < 0) { 3194 if (err < 0) {
3205 kfree_skb(_skb); 3195 kfree_skb(_skb);
3206 set_bit(CONN_SAR_RETRY, &chan->conn_state);
3207 return err; 3196 return err;
3208 } 3197 }
3209 3198
3210 clear_bit(CONN_SAR_RETRY, &chan->conn_state);
3211 clear_bit(CONN_SAR_SDU, &chan->conn_state); 3199 clear_bit(CONN_SAR_SDU, &chan->conn_state);
3212 3200
3213 kfree_skb(chan->sdu); 3201 kfree_skb(chan->sdu);
@@ -3268,93 +3256,6 @@ done:
3268 BT_DBG("chan %p, Exit local busy", chan); 3256 BT_DBG("chan %p, Exit local busy", chan);
3269} 3257}
3270 3258
3271static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
3272{
3273 struct sk_buff *skb;
3274 u16 control;
3275 int err;
3276
3277 while ((skb = skb_dequeue(&chan->busy_q))) {
3278 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3279 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3280 if (err < 0) {
3281 skb_queue_head(&chan->busy_q, skb);
3282 return -EBUSY;
3283 }
3284
3285 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
3286 }
3287
3288 l2cap_ertm_exit_local_busy(chan);
3289
3290 return 0;
3291}
3292
3293static void l2cap_busy_work(struct work_struct *work)
3294{
3295 DECLARE_WAITQUEUE(wait, current);
3296 struct l2cap_chan *chan =
3297 container_of(work, struct l2cap_chan, busy_work);
3298 struct sock *sk = chan->sk;
3299 int n_tries = 0, timeo = HZ/5, err;
3300 struct sk_buff *skb;
3301
3302 lock_sock(sk);
3303
3304 add_wait_queue(sk_sleep(sk), &wait);
3305 while ((skb = skb_peek(&chan->busy_q))) {
3306 set_current_state(TASK_INTERRUPTIBLE);
3307
3308 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3309 err = -EBUSY;
3310 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
3311 break;
3312 }
3313
3314 if (!timeo)
3315 timeo = HZ/5;
3316
3317 if (signal_pending(current)) {
3318 err = sock_intr_errno(timeo);
3319 break;
3320 }
3321
3322 release_sock(sk);
3323 timeo = schedule_timeout(timeo);
3324 lock_sock(sk);
3325
3326 err = sock_error(sk);
3327 if (err)
3328 break;
3329
3330 if (l2cap_try_push_rx_skb(chan) == 0)
3331 break;
3332 }
3333
3334 set_current_state(TASK_RUNNING);
3335 remove_wait_queue(sk_sleep(sk), &wait);
3336
3337 release_sock(sk);
3338}
3339
3340static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3341{
3342 int err;
3343
3344 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3345 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3346 __skb_queue_tail(&chan->busy_q, skb);
3347 return l2cap_try_push_rx_skb(chan);
3348
3349
3350 }
3351
3352 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3353 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
3354
3355 return err;
3356}
3357
3358void l2cap_chan_busy(struct l2cap_chan *chan, int busy) 3259void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
3359{ 3260{
3360 if (chan->mode == L2CAP_MODE_ERTM) { 3261 if (chan->mode == L2CAP_MODE_ERTM) {
@@ -3612,7 +3513,6 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
3612 chan->buffer_seq_srej = chan->buffer_seq; 3513 chan->buffer_seq_srej = chan->buffer_seq;
3613 3514
3614 __skb_queue_head_init(&chan->srej_q); 3515 __skb_queue_head_init(&chan->srej_q);
3615 __skb_queue_head_init(&chan->busy_q);
3616 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); 3516 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
3617 3517
3618 set_bit(CONN_SEND_PBIT, &chan->conn_state); 3518 set_bit(CONN_SEND_PBIT, &chan->conn_state);
@@ -3633,7 +3533,8 @@ expected:
3633 return 0; 3533 return 0;
3634 } 3534 }
3635 3535
3636 err = l2cap_push_rx_skb(chan, skb, rx_control); 3536 err = l2cap_ertm_reassembly_sdu(chan, skb, rx_control);
3537 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
3637 if (err < 0) { 3538 if (err < 0) {
3638 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 3539 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3639 return err; 3540 return err;
@@ -4439,12 +4340,6 @@ int __init l2cap_init(void)
4439 if (err < 0) 4340 if (err < 0)
4440 return err; 4341 return err;
4441 4342
4442 _busy_wq = create_singlethread_workqueue("l2cap");
4443 if (!_busy_wq) {
4444 err = -ENOMEM;
4445 goto error;
4446 }
4447
4448 err = hci_register_proto(&l2cap_hci_proto); 4343 err = hci_register_proto(&l2cap_hci_proto);
4449 if (err < 0) { 4344 if (err < 0) {
4450 BT_ERR("L2CAP protocol registration failed"); 4345 BT_ERR("L2CAP protocol registration failed");
@@ -4462,7 +4357,6 @@ int __init l2cap_init(void)
4462 return 0; 4357 return 0;
4463 4358
4464error: 4359error:
4465 destroy_workqueue(_busy_wq);
4466 l2cap_cleanup_sockets(); 4360 l2cap_cleanup_sockets();
4467 return err; 4361 return err;
4468} 4362}
@@ -4471,9 +4365,6 @@ void l2cap_exit(void)
4471{ 4365{
4472 debugfs_remove(l2cap_debugfs); 4366 debugfs_remove(l2cap_debugfs);
4473 4367
4474 flush_workqueue(_busy_wq);
4475 destroy_workqueue(_busy_wq);
4476
4477 if (hci_unregister_proto(&l2cap_hci_proto) < 0) 4368 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4478 BT_ERR("L2CAP protocol unregistration failed"); 4369 BT_ERR("L2CAP protocol unregistration failed");
4479 4370