diff options
Diffstat (limited to 'drivers/net/slip/slip.c')
-rw-r--r-- | drivers/net/slip/slip.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index ad4a94e9ff57..87526443841f 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c | |||
@@ -83,6 +83,7 @@ | |||
83 | #include <linux/delay.h> | 83 | #include <linux/delay.h> |
84 | #include <linux/init.h> | 84 | #include <linux/init.h> |
85 | #include <linux/slab.h> | 85 | #include <linux/slab.h> |
86 | #include <linux/workqueue.h> | ||
86 | #include "slip.h" | 87 | #include "slip.h" |
87 | #ifdef CONFIG_INET | 88 | #ifdef CONFIG_INET |
88 | #include <linux/ip.h> | 89 | #include <linux/ip.h> |
@@ -416,36 +417,46 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len) | |||
416 | #endif | 417 | #endif |
417 | } | 418 | } |
418 | 419 | ||
419 | /* | 420 | /* Write out any remaining transmit buffer. Scheduled when tty is writable */ |
420 | * Called by the driver when there's room for more data. If we have | 421 | static void slip_transmit(struct work_struct *work) |
421 | * more packets to send, we send them here. | ||
422 | */ | ||
423 | static void slip_write_wakeup(struct tty_struct *tty) | ||
424 | { | 422 | { |
423 | struct slip *sl = container_of(work, struct slip, tx_work); | ||
425 | int actual; | 424 | int actual; |
426 | struct slip *sl = tty->disc_data; | ||
427 | 425 | ||
426 | spin_lock_bh(&sl->lock); | ||
428 | /* First make sure we're connected. */ | 427 | /* First make sure we're connected. */ |
429 | if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) | 428 | if (!sl->tty || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) { |
429 | spin_unlock_bh(&sl->lock); | ||
430 | return; | 430 | return; |
431 | } | ||
431 | 432 | ||
432 | spin_lock_bh(&sl->lock); | ||
433 | if (sl->xleft <= 0) { | 433 | if (sl->xleft <= 0) { |
434 | /* Now serial buffer is almost free & we can start | 434 | /* Now serial buffer is almost free & we can start |
435 | * transmission of another packet */ | 435 | * transmission of another packet */ |
436 | sl->dev->stats.tx_packets++; | 436 | sl->dev->stats.tx_packets++; |
437 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | 437 | clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); |
438 | spin_unlock_bh(&sl->lock); | 438 | spin_unlock_bh(&sl->lock); |
439 | sl_unlock(sl); | 439 | sl_unlock(sl); |
440 | return; | 440 | return; |
441 | } | 441 | } |
442 | 442 | ||
443 | actual = tty->ops->write(tty, sl->xhead, sl->xleft); | 443 | actual = sl->tty->ops->write(sl->tty, sl->xhead, sl->xleft); |
444 | sl->xleft -= actual; | 444 | sl->xleft -= actual; |
445 | sl->xhead += actual; | 445 | sl->xhead += actual; |
446 | spin_unlock_bh(&sl->lock); | 446 | spin_unlock_bh(&sl->lock); |
447 | } | 447 | } |
448 | 448 | ||
449 | /* | ||
450 | * Called by the driver when there's room for more data. | ||
451 | * Schedule the transmit. | ||
452 | */ | ||
453 | static void slip_write_wakeup(struct tty_struct *tty) | ||
454 | { | ||
455 | struct slip *sl = tty->disc_data; | ||
456 | |||
457 | schedule_work(&sl->tx_work); | ||
458 | } | ||
459 | |||
449 | static void sl_tx_timeout(struct net_device *dev) | 460 | static void sl_tx_timeout(struct net_device *dev) |
450 | { | 461 | { |
451 | struct slip *sl = netdev_priv(dev); | 462 | struct slip *sl = netdev_priv(dev); |
@@ -749,6 +760,7 @@ static struct slip *sl_alloc(dev_t line) | |||
749 | sl->magic = SLIP_MAGIC; | 760 | sl->magic = SLIP_MAGIC; |
750 | sl->dev = dev; | 761 | sl->dev = dev; |
751 | spin_lock_init(&sl->lock); | 762 | spin_lock_init(&sl->lock); |
763 | INIT_WORK(&sl->tx_work, slip_transmit); | ||
752 | sl->mode = SL_MODE_DEFAULT; | 764 | sl->mode = SL_MODE_DEFAULT; |
753 | #ifdef CONFIG_SLIP_SMART | 765 | #ifdef CONFIG_SLIP_SMART |
754 | /* initialize timer_list struct */ | 766 | /* initialize timer_list struct */ |
@@ -872,8 +884,12 @@ static void slip_close(struct tty_struct *tty) | |||
872 | if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty) | 884 | if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty) |
873 | return; | 885 | return; |
874 | 886 | ||
887 | spin_lock_bh(&sl->lock); | ||
875 | tty->disc_data = NULL; | 888 | tty->disc_data = NULL; |
876 | sl->tty = NULL; | 889 | sl->tty = NULL; |
890 | spin_unlock_bh(&sl->lock); | ||
891 | |||
892 | flush_work(&sl->tx_work); | ||
877 | 893 | ||
878 | /* VSV = very important to remove timers */ | 894 | /* VSV = very important to remove timers */ |
879 | #ifdef CONFIG_SLIP_SMART | 895 | #ifdef CONFIG_SLIP_SMART |