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. ...
This commit is contained in:
@ -23,8 +23,6 @@
|
||||
|
||||
/*
|
||||
* RFCOMM TTY.
|
||||
*
|
||||
* $Id: tty.c,v 1.24 2002/10/03 01:54:38 holtmann Exp $
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -77,6 +75,8 @@ struct rfcomm_dev {
|
||||
struct device *tty_dev;
|
||||
|
||||
atomic_t wmem_alloc;
|
||||
|
||||
struct sk_buff_head pending;
|
||||
};
|
||||
|
||||
static LIST_HEAD(rfcomm_dev_list);
|
||||
@ -264,13 +264,34 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
|
||||
init_waitqueue_head(&dev->wait);
|
||||
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
|
||||
|
||||
skb_queue_head_init(&dev->pending);
|
||||
|
||||
rfcomm_dlc_lock(dlc);
|
||||
|
||||
if (req->flags & (1 << RFCOMM_REUSE_DLC)) {
|
||||
struct sock *sk = dlc->owner;
|
||||
struct sk_buff *skb;
|
||||
|
||||
BUG_ON(!sk);
|
||||
|
||||
rfcomm_dlc_throttle(dlc);
|
||||
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
|
||||
skb_orphan(skb);
|
||||
skb_queue_tail(&dev->pending, skb);
|
||||
atomic_sub(skb->len, &sk->sk_rmem_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
dlc->data_ready = rfcomm_dev_data_ready;
|
||||
dlc->state_change = rfcomm_dev_state_change;
|
||||
dlc->modem_status = rfcomm_dev_modem_status;
|
||||
|
||||
dlc->owner = dev;
|
||||
dev->dlc = dlc;
|
||||
|
||||
rfcomm_dev_modem_status(dlc, dlc->remote_v24_sig);
|
||||
|
||||
rfcomm_dlc_unlock(dlc);
|
||||
|
||||
/* 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)
|
||||
struct rfcomm_dev *dev = dlc->owner;
|
||||
struct tty_struct *tty;
|
||||
|
||||
if (!dev || !(tty = dev->tty)) {
|
||||
if (!dev) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) {
|
||||
skb_queue_tail(&dev->pending, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
|
||||
|
||||
tty_insert_flip_string(tty, skb->data, skb->len);
|
||||
@ -620,6 +646,30 @@ static void rfcomm_tty_wakeup(unsigned long arg)
|
||||
tty_wakeup(tty);
|
||||
}
|
||||
|
||||
static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
|
||||
{
|
||||
struct tty_struct *tty = dev->tty;
|
||||
struct sk_buff *skb;
|
||||
int inserted = 0;
|
||||
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
BT_DBG("dev %p tty %p", dev, tty);
|
||||
|
||||
rfcomm_dlc_lock(dev->dlc);
|
||||
|
||||
while ((skb = skb_dequeue(&dev->pending))) {
|
||||
inserted += tty_insert_flip_string(tty, skb->data, skb->len);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
rfcomm_dlc_unlock(dev->dlc);
|
||||
|
||||
if (inserted > 0)
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
|
||||
static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
@ -684,6 +734,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
if (err == 0)
|
||||
device_move(dev->tty_dev, rfcomm_get_device(dev));
|
||||
|
||||
rfcomm_tty_copy_pending(dev);
|
||||
|
||||
rfcomm_dlc_unthrottle(dev->dlc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1114,6 +1168,7 @@ int rfcomm_init_ttys(void)
|
||||
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
rfcomm_tty_driver->init_termios = tty_std_termios;
|
||||
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
|
||||
tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
|
||||
|
||||
if (tty_register_driver(rfcomm_tty_driver)) {
|
||||
|
Reference in New Issue
Block a user