diff options
Diffstat (limited to 'net/bluetooth/rfcomm/tty.c')
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 8fcca08cef8e..ec22ebe0c2c8 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -77,6 +77,8 @@ struct rfcomm_dev { | |||
77 | struct device *tty_dev; | 77 | struct device *tty_dev; |
78 | 78 | ||
79 | atomic_t wmem_alloc; | 79 | atomic_t wmem_alloc; |
80 | |||
81 | struct sk_buff_head pending; | ||
80 | }; | 82 | }; |
81 | 83 | ||
82 | static LIST_HEAD(rfcomm_dev_list); | 84 | static LIST_HEAD(rfcomm_dev_list); |
@@ -264,7 +266,25 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
264 | init_waitqueue_head(&dev->wait); | 266 | init_waitqueue_head(&dev->wait); |
265 | tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev); | 267 | tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev); |
266 | 268 | ||
269 | skb_queue_head_init(&dev->pending); | ||
270 | |||
267 | rfcomm_dlc_lock(dlc); | 271 | rfcomm_dlc_lock(dlc); |
272 | |||
273 | if (req->flags & (1 << RFCOMM_REUSE_DLC)) { | ||
274 | struct sock *sk = dlc->owner; | ||
275 | struct sk_buff *skb; | ||
276 | |||
277 | BUG_ON(!sk); | ||
278 | |||
279 | rfcomm_dlc_throttle(dlc); | ||
280 | |||
281 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | ||
282 | skb_orphan(skb); | ||
283 | skb_queue_tail(&dev->pending, skb); | ||
284 | atomic_sub(skb->len, &sk->sk_rmem_alloc); | ||
285 | } | ||
286 | } | ||
287 | |||
268 | dlc->data_ready = rfcomm_dev_data_ready; | 288 | dlc->data_ready = rfcomm_dev_data_ready; |
269 | dlc->state_change = rfcomm_dev_state_change; | 289 | dlc->state_change = rfcomm_dev_state_change; |
270 | dlc->modem_status = rfcomm_dev_modem_status; | 290 | dlc->modem_status = rfcomm_dev_modem_status; |
@@ -542,11 +562,16 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) | |||
542 | struct rfcomm_dev *dev = dlc->owner; | 562 | struct rfcomm_dev *dev = dlc->owner; |
543 | struct tty_struct *tty; | 563 | struct tty_struct *tty; |
544 | 564 | ||
545 | if (!dev || !(tty = dev->tty)) { | 565 | if (!dev) { |
546 | kfree_skb(skb); | 566 | kfree_skb(skb); |
547 | return; | 567 | return; |
548 | } | 568 | } |
549 | 569 | ||
570 | if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) { | ||
571 | skb_queue_tail(&dev->pending, skb); | ||
572 | return; | ||
573 | } | ||
574 | |||
550 | BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len); | 575 | BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len); |
551 | 576 | ||
552 | tty_insert_flip_string(tty, skb->data, skb->len); | 577 | tty_insert_flip_string(tty, skb->data, skb->len); |
@@ -630,6 +655,30 @@ static void rfcomm_tty_wakeup(unsigned long arg) | |||
630 | #endif | 655 | #endif |
631 | } | 656 | } |
632 | 657 | ||
658 | static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev) | ||
659 | { | ||
660 | struct tty_struct *tty = dev->tty; | ||
661 | struct sk_buff *skb; | ||
662 | int inserted = 0; | ||
663 | |||
664 | if (!tty) | ||
665 | return; | ||
666 | |||
667 | BT_DBG("dev %p tty %p", dev, tty); | ||
668 | |||
669 | rfcomm_dlc_lock(dev->dlc); | ||
670 | |||
671 | while ((skb = skb_dequeue(&dev->pending))) { | ||
672 | inserted += tty_insert_flip_string(tty, skb->data, skb->len); | ||
673 | kfree_skb(skb); | ||
674 | } | ||
675 | |||
676 | rfcomm_dlc_unlock(dev->dlc); | ||
677 | |||
678 | if (inserted > 0) | ||
679 | tty_flip_buffer_push(tty); | ||
680 | } | ||
681 | |||
633 | static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | 682 | static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) |
634 | { | 683 | { |
635 | DECLARE_WAITQUEUE(wait, current); | 684 | DECLARE_WAITQUEUE(wait, current); |
@@ -694,6 +743,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
694 | if (err == 0) | 743 | if (err == 0) |
695 | device_move(dev->tty_dev, rfcomm_get_device(dev)); | 744 | device_move(dev->tty_dev, rfcomm_get_device(dev)); |
696 | 745 | ||
746 | rfcomm_tty_copy_pending(dev); | ||
747 | |||
748 | rfcomm_dlc_unthrottle(dev->dlc); | ||
749 | |||
697 | return err; | 750 | return err; |
698 | } | 751 | } |
699 | 752 | ||