diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-20 20:43:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-20 20:43:29 -0400 |
commit | db6d8c7a4027b48d797b369a53f8470aaeed7063 (patch) | |
tree | e140c104a89abc2154e1f41a7db8ebecbb6fa0b4 /net/bluetooth/rfcomm/tty.c | |
parent | 3a533374283aea50eab3976d8a6d30532175f009 (diff) | |
parent | fb65a7c091529bfffb1262515252c0d0f6241c5c (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (1232 commits)
iucv: Fix bad merging.
net_sched: Add size table for qdiscs
net_sched: Add accessor function for packet length for qdiscs
net_sched: Add qdisc_enqueue wrapper
highmem: Export totalhigh_pages.
ipv6 mcast: Omit redundant address family checks in ip6_mc_source().
net: Use standard structures for generic socket address structures.
ipv6 netns: Make several "global" sysctl variables namespace aware.
netns: Use net_eq() to compare net-namespaces for optimization.
ipv6: remove unused macros from net/ipv6.h
ipv6: remove unused parameter from ip6_ra_control
tcp: fix kernel panic with listening_get_next
tcp: Remove redundant checks when setting eff_sacks
tcp: options clean up
tcp: Fix MD5 signatures for non-linear skbs
sctp: Update sctp global memory limit allocations.
sctp: remove unnecessary byteshifting, calculate directly in big-endian
sctp: Allow only 1 listening socket with SO_REUSEADDR
sctp: Do not leak memory on multiple listen() calls
sctp: Support ipv6only AF_INET6 sockets.
...
Diffstat (limited to 'net/bluetooth/rfcomm/tty.c')
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 0a387f2eb7a9..d3340dd52bcf 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -23,8 +23,6 @@ | |||
23 | 23 | ||
24 | /* | 24 | /* |
25 | * RFCOMM TTY. | 25 | * RFCOMM TTY. |
26 | * | ||
27 | * $Id: tty.c,v 1.24 2002/10/03 01:54:38 holtmann Exp $ | ||
28 | */ | 26 | */ |
29 | 27 | ||
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
@@ -77,6 +75,8 @@ struct rfcomm_dev { | |||
77 | struct device *tty_dev; | 75 | struct device *tty_dev; |
78 | 76 | ||
79 | atomic_t wmem_alloc; | 77 | atomic_t wmem_alloc; |
78 | |||
79 | struct sk_buff_head pending; | ||
80 | }; | 80 | }; |
81 | 81 | ||
82 | static LIST_HEAD(rfcomm_dev_list); | 82 | static LIST_HEAD(rfcomm_dev_list); |
@@ -264,13 +264,34 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
264 | init_waitqueue_head(&dev->wait); | 264 | init_waitqueue_head(&dev->wait); |
265 | tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev); | 265 | tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev); |
266 | 266 | ||
267 | skb_queue_head_init(&dev->pending); | ||
268 | |||
267 | rfcomm_dlc_lock(dlc); | 269 | rfcomm_dlc_lock(dlc); |
270 | |||
271 | if (req->flags & (1 << RFCOMM_REUSE_DLC)) { | ||
272 | struct sock *sk = dlc->owner; | ||
273 | struct sk_buff *skb; | ||
274 | |||
275 | BUG_ON(!sk); | ||
276 | |||
277 | rfcomm_dlc_throttle(dlc); | ||
278 | |||
279 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | ||
280 | skb_orphan(skb); | ||
281 | skb_queue_tail(&dev->pending, skb); | ||
282 | atomic_sub(skb->len, &sk->sk_rmem_alloc); | ||
283 | } | ||
284 | } | ||
285 | |||
268 | dlc->data_ready = rfcomm_dev_data_ready; | 286 | dlc->data_ready = rfcomm_dev_data_ready; |
269 | dlc->state_change = rfcomm_dev_state_change; | 287 | dlc->state_change = rfcomm_dev_state_change; |
270 | dlc->modem_status = rfcomm_dev_modem_status; | 288 | dlc->modem_status = rfcomm_dev_modem_status; |
271 | 289 | ||
272 | dlc->owner = dev; | 290 | dlc->owner = dev; |
273 | dev->dlc = dlc; | 291 | dev->dlc = dlc; |
292 | |||
293 | rfcomm_dev_modem_status(dlc, dlc->remote_v24_sig); | ||
294 | |||
274 | rfcomm_dlc_unlock(dlc); | 295 | rfcomm_dlc_unlock(dlc); |
275 | 296 | ||
276 | /* It's safe to call __module_get() here because socket already | 297 | /* It's safe to call __module_get() here because socket already |
@@ -539,11 +560,16 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) | |||
539 | struct rfcomm_dev *dev = dlc->owner; | 560 | struct rfcomm_dev *dev = dlc->owner; |
540 | struct tty_struct *tty; | 561 | struct tty_struct *tty; |
541 | 562 | ||
542 | if (!dev || !(tty = dev->tty)) { | 563 | if (!dev) { |
543 | kfree_skb(skb); | 564 | kfree_skb(skb); |
544 | return; | 565 | return; |
545 | } | 566 | } |
546 | 567 | ||
568 | if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) { | ||
569 | skb_queue_tail(&dev->pending, skb); | ||
570 | return; | ||
571 | } | ||
572 | |||
547 | BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len); | 573 | BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len); |
548 | 574 | ||
549 | tty_insert_flip_string(tty, skb->data, skb->len); | 575 | tty_insert_flip_string(tty, skb->data, skb->len); |
@@ -620,6 +646,30 @@ static void rfcomm_tty_wakeup(unsigned long arg) | |||
620 | tty_wakeup(tty); | 646 | tty_wakeup(tty); |
621 | } | 647 | } |
622 | 648 | ||
649 | static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev) | ||
650 | { | ||
651 | struct tty_struct *tty = dev->tty; | ||
652 | struct sk_buff *skb; | ||
653 | int inserted = 0; | ||
654 | |||
655 | if (!tty) | ||
656 | return; | ||
657 | |||
658 | BT_DBG("dev %p tty %p", dev, tty); | ||
659 | |||
660 | rfcomm_dlc_lock(dev->dlc); | ||
661 | |||
662 | while ((skb = skb_dequeue(&dev->pending))) { | ||
663 | inserted += tty_insert_flip_string(tty, skb->data, skb->len); | ||
664 | kfree_skb(skb); | ||
665 | } | ||
666 | |||
667 | rfcomm_dlc_unlock(dev->dlc); | ||
668 | |||
669 | if (inserted > 0) | ||
670 | tty_flip_buffer_push(tty); | ||
671 | } | ||
672 | |||
623 | static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | 673 | static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) |
624 | { | 674 | { |
625 | DECLARE_WAITQUEUE(wait, current); | 675 | DECLARE_WAITQUEUE(wait, current); |
@@ -684,6 +734,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
684 | if (err == 0) | 734 | if (err == 0) |
685 | device_move(dev->tty_dev, rfcomm_get_device(dev)); | 735 | device_move(dev->tty_dev, rfcomm_get_device(dev)); |
686 | 736 | ||
737 | rfcomm_tty_copy_pending(dev); | ||
738 | |||
739 | rfcomm_dlc_unthrottle(dev->dlc); | ||
740 | |||
687 | return err; | 741 | return err; |
688 | } | 742 | } |
689 | 743 | ||
@@ -1114,6 +1168,7 @@ int rfcomm_init_ttys(void) | |||
1114 | rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 1168 | rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
1115 | rfcomm_tty_driver->init_termios = tty_std_termios; | 1169 | rfcomm_tty_driver->init_termios = tty_std_termios; |
1116 | rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 1170 | rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
1171 | rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; | ||
1117 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); | 1172 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); |
1118 | 1173 | ||
1119 | if (tty_register_driver(rfcomm_tty_driver)) { | 1174 | if (tty_register_driver(rfcomm_tty_driver)) { |