|
83 | 83 | #include <linux/delay.h>
|
84 | 84 | #include <linux/init.h>
|
85 | 85 | #include <linux/slab.h>
|
| 86 | +#include <linux/workqueue.h> |
86 | 87 | #include "slip.h"
|
87 | 88 | #ifdef CONFIG_INET
|
88 | 89 | #include <linux/ip.h>
|
@@ -416,36 +417,46 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
|
416 | 417 | #endif
|
417 | 418 | }
|
418 | 419 |
|
419 |
| -/* |
420 |
| - * Called by the driver when there's room for more data. If we have |
421 |
| - * more packets to send, we send them here. |
422 |
| - */ |
423 |
| -static void slip_write_wakeup(struct tty_struct *tty) |
| 420 | +/* Write out any remaining transmit buffer. Scheduled when tty is writable */ |
| 421 | +static void slip_transmit(struct work_struct *work) |
424 | 422 | {
|
| 423 | + struct slip *sl = container_of(work, struct slip, tx_work); |
425 | 424 | int actual;
|
426 |
| - struct slip *sl = tty->disc_data; |
427 | 425 |
|
| 426 | + spin_lock_bh(&sl->lock); |
428 | 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 | 430 | return;
|
| 431 | + } |
431 | 432 |
|
432 |
| - spin_lock_bh(&sl->lock); |
433 | 433 | if (sl->xleft <= 0) {
|
434 | 434 | /* Now serial buffer is almost free & we can start
|
435 | 435 | * transmission of another packet */
|
436 | 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 | 438 | spin_unlock_bh(&sl->lock);
|
439 | 439 | sl_unlock(sl);
|
440 | 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 | 444 | sl->xleft -= actual;
|
445 | 445 | sl->xhead += actual;
|
446 | 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 | 460 | static void sl_tx_timeout(struct net_device *dev)
|
450 | 461 | {
|
451 | 462 | struct slip *sl = netdev_priv(dev);
|
@@ -749,6 +760,7 @@ static struct slip *sl_alloc(dev_t line)
|
749 | 760 | sl->magic = SLIP_MAGIC;
|
750 | 761 | sl->dev = dev;
|
751 | 762 | spin_lock_init(&sl->lock);
|
| 763 | + INIT_WORK(&sl->tx_work, slip_transmit); |
752 | 764 | sl->mode = SL_MODE_DEFAULT;
|
753 | 765 | #ifdef CONFIG_SLIP_SMART
|
754 | 766 | /* initialize timer_list struct */
|
@@ -872,8 +884,12 @@ static void slip_close(struct tty_struct *tty)
|
872 | 884 | if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty)
|
873 | 885 | return;
|
874 | 886 |
|
| 887 | + spin_lock_bh(&sl->lock); |
875 | 888 | tty->disc_data = NULL;
|
876 | 889 | sl->tty = NULL;
|
| 890 | + spin_unlock_bh(&sl->lock); |
| 891 | + |
| 892 | + flush_work(&sl->tx_work); |
877 | 893 |
|
878 | 894 | /* VSV = very important to remove timers */
|
879 | 895 | #ifdef CONFIG_SLIP_SMART
|
|
0 commit comments