aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/rfcomm/core.c2
-rw-r--r--net/bluetooth/rfcomm/tty.c55
2 files changed, 55 insertions, 2 deletions
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index fcd2cafe70c8..b6b3d9b4066f 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -53,7 +53,7 @@
53#define BT_DBG(D...) 53#define BT_DBG(D...)
54#endif 54#endif
55 55
56#define VERSION "1.9" 56#define VERSION "1.10"
57 57
58static int disable_cfc = 0; 58static int disable_cfc = 0;
59static int channel_mtu = -1; 59static int channel_mtu = -1;
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
82static LIST_HEAD(rfcomm_dev_list); 84static 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
658static 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
633static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) 682static 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