diff options
Diffstat (limited to 'drivers/net/slip')
| -rw-r--r-- | drivers/net/slip/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/net/slip/slhc.c | 1 | ||||
| -rw-r--r-- | drivers/net/slip/slip.c | 46 | ||||
| -rw-r--r-- | drivers/net/slip/slip.h | 1 |
4 files changed, 33 insertions, 16 deletions
diff --git a/drivers/net/slip/Kconfig b/drivers/net/slip/Kconfig index 211b160e4e9..48e68714eef 100644 --- a/drivers/net/slip/Kconfig +++ b/drivers/net/slip/Kconfig @@ -4,6 +4,7 @@ config SLIP tristate "SLIP (serial line) support" + depends on TTY ---help--- Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to connect to your Internet service provider or to connect to some diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index 0a0a6643cf3..1252d9c726a 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -75,7 +75,6 @@ #include <linux/skbuff.h> #include <net/sock.h> #include <linux/timer.h> -#include <asm/system.h> #include <asm/uaccess.h> #include <net/checksum.h> #include <asm/unaligned.h> diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index ba08341fb92..87526443841 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -64,7 +64,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <asm/system.h> #include <asm/uaccess.h> #include <linux/bitops.h> #include <linux/sched.h> @@ -84,6 +83,7 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/slab.h> +#include <linux/workqueue.h> #include "slip.h" #ifdef CONFIG_INET #include <linux/ip.h> @@ -391,10 +391,10 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len) #endif #ifdef CONFIG_SLIP_MODE_SLIP6 if (sl->mode & SL_MODE_SLIP6) - count = slip_esc6(p, (unsigned char *) sl->xbuff, len); + count = slip_esc6(p, sl->xbuff, len); else #endif - count = slip_esc(p, (unsigned char *) sl->xbuff, len); + count = slip_esc(p, sl->xbuff, len); /* Order of next two lines is *very* important. * When we are sending a little amount of data, @@ -417,31 +417,44 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len) #endif } -/* - * Called by the driver when there's room for more data. If we have - * more packets to send, we send them here. - */ -static void slip_write_wakeup(struct tty_struct *tty) +/* Write out any remaining transmit buffer. Scheduled when tty is writable */ +static void slip_transmit(struct work_struct *work) { + struct slip *sl = container_of(work, struct slip, tx_work); int actual; - struct slip *sl = tty->disc_data; + spin_lock_bh(&sl->lock); /* First make sure we're connected. */ - if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) + if (!sl->tty || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) { + spin_unlock_bh(&sl->lock); return; + } if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ sl->dev->stats.tx_packets++; - clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); + spin_unlock_bh(&sl->lock); sl_unlock(sl); return; } - actual = tty->ops->write(tty, sl->xhead, sl->xleft); + actual = sl->tty->ops->write(sl->tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; + spin_unlock_bh(&sl->lock); +} + +/* + * Called by the driver when there's room for more data. + * Schedule the transmit. + */ +static void slip_write_wakeup(struct tty_struct *tty) +{ + struct slip *sl = tty->disc_data; + + schedule_work(&sl->tx_work); } static void sl_tx_timeout(struct net_device *dev) @@ -747,6 +760,7 @@ static struct slip *sl_alloc(dev_t line) sl->magic = SLIP_MAGIC; sl->dev = dev; spin_lock_init(&sl->lock); + INIT_WORK(&sl->tx_work, slip_transmit); sl->mode = SL_MODE_DEFAULT; #ifdef CONFIG_SLIP_SMART /* initialize timer_list struct */ @@ -870,8 +884,12 @@ static void slip_close(struct tty_struct *tty) if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty) return; + spin_lock_bh(&sl->lock); tty->disc_data = NULL; sl->tty = NULL; + spin_unlock_bh(&sl->lock); + + flush_work(&sl->tx_work); /* VSV = very important to remove timers */ #ifdef CONFIG_SLIP_SMART @@ -1296,10 +1314,8 @@ static int __init slip_init(void) slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL); - if (!slip_devs) { - printk(KERN_ERR "SLIP: Can't allocate slip devices array.\n"); + if (!slip_devs) return -ENOMEM; - } /* Fill in our line protocol discipline, and register it */ status = tty_register_ldisc(N_SLIP, &sl_ldisc); diff --git a/drivers/net/slip/slip.h b/drivers/net/slip/slip.h index 67673cf1266..cf32aadf508 100644 --- a/drivers/net/slip/slip.h +++ b/drivers/net/slip/slip.h @@ -53,6 +53,7 @@ struct slip { struct tty_struct *tty; /* ptr to TTY structure */ struct net_device *dev; /* easy for intr handling */ spinlock_t lock; + struct work_struct tx_work; /* Flushes transmit buffer */ #ifdef SL_INCLUDE_CSLIP struct slcompress *slcomp; /* for header compression */ |
