aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/slip/slip.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/slip/slip.c')
-rw-r--r--drivers/net/slip/slip.c36
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 421static void slip_transmit(struct work_struct *work)
421 * more packets to send, we send them here.
422 */
423static 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 */
453static 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
449static void sl_tx_timeout(struct net_device *dev) 460static 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