1. Move the lapb_register/lapb_unregister calls into the ndo_open/ndo_stop functions in x25_asy_netdev_ops. This makes the LAPB protocol start/stop when the network interface starts/stops. When the network interface is down, the LAPB protocol shouldn't be running and the LAPB module shoudn't be generating control frames.
2. Move netif_start_queue/netif_stop_queue into the ndo_open/ndo_stop functions in x25_asy_netdev_ops. This makes the TX queue start/stop when the network interface starts/stops. 3. The x25_asy_close function was originally used as the ndo_stop function. However, I think when stopping the interface we shouldn't do the things that this function does (except netif_stop_queue). 1) We shouldn't clear TTY_DO_WRITE_WAKEUP and set sl->xleft to 0, because this may cause the transmission of the last frame before stopping to be incomplete. 2) We shouldn't set sl->rcount to 0, because if we stop the interface and quickly start it again, the first frame we receive could be incomplete. So I moved it to make it be called in x25_asy_close_tty (when closing the TTY line discipline) instead. (This also makes the code look better because x25_asy_open is called in x25_asy_open_tty.) Cc: Martin Schiller <m...@dev.tdt.de> Signed-off-by: Xie He <xie.he.0...@gmail.com> --- drivers/net/wan/x25_asy.c | 42 +++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 7ee980575208..88a73ce6d9f4 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -464,7 +464,6 @@ static int x25_asy_open(struct net_device *dev) { struct x25_asy *sl = netdev_priv(dev); unsigned long len; - int err; if (sl->tty == NULL) return -ENODEV; @@ -490,14 +489,7 @@ static int x25_asy_open(struct net_device *dev) sl->xleft = 0; sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */ - netif_start_queue(dev); - - /* - * Now attach LAPB - */ - err = lapb_register(dev, &x25_asy_callbacks); - if (err == LAPB_OK) - return 0; + return 0; /* Cleanup */ kfree(sl->xbuff); @@ -519,7 +511,6 @@ static int x25_asy_close(struct net_device *dev) if (sl->tty) clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); - netif_stop_queue(dev); sl->rcount = 0; sl->xleft = 0; spin_unlock(&sl->lock); @@ -604,7 +595,6 @@ static int x25_asy_open_tty(struct tty_struct *tty) static void x25_asy_close_tty(struct tty_struct *tty) { struct x25_asy *sl = tty->disc_data; - int err; /* First make sure we're connected. */ if (!sl || sl->magic != X25_ASY_MAGIC) @@ -615,11 +605,7 @@ static void x25_asy_close_tty(struct tty_struct *tty) dev_close(sl->dev); rtnl_unlock(); - err = lapb_unregister(sl->dev); - if (err != LAPB_OK) - pr_err("%s: lapb_unregister error: %d\n", - __func__, err); - + x25_asy_close(sl->dev); tty->disc_data = NULL; sl->tty = NULL; x25_asy_free(sl); @@ -722,15 +708,37 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, static int x25_asy_open_dev(struct net_device *dev) { + int err; struct x25_asy *sl = netdev_priv(dev); if (sl->tty == NULL) return -ENODEV; + + err = lapb_register(dev, &x25_asy_callbacks); + if (err != LAPB_OK) + return -ENOMEM; + + netif_start_queue(dev); + + return 0; +} + +static int x25_asy_close_dev(struct net_device *dev) +{ + int err; + + netif_stop_queue(dev); + + err = lapb_unregister(dev); + if (err != LAPB_OK) + pr_err("%s: lapb_unregister error: %d\n", + __func__, err); + return 0; } static const struct net_device_ops x25_asy_netdev_ops = { .ndo_open = x25_asy_open_dev, - .ndo_stop = x25_asy_close, + .ndo_stop = x25_asy_close_dev, .ndo_start_xmit = x25_asy_xmit, .ndo_tx_timeout = x25_asy_timeout, .ndo_change_mtu = x25_asy_change_mtu, -- 2.25.1