.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Things to sort out: |
---|
3 | 4 | * |
---|
.. | .. |
---|
33 | 34 | #include <linux/lapb.h> |
---|
34 | 35 | #include <linux/init.h> |
---|
35 | 36 | #include <linux/rtnetlink.h> |
---|
36 | | -#include <linux/compat.h> |
---|
37 | 37 | #include <linux/slab.h> |
---|
38 | 38 | #include <net/x25device.h> |
---|
39 | 39 | #include "x25_asy.h" |
---|
.. | .. |
---|
202 | 202 | return; |
---|
203 | 203 | } |
---|
204 | 204 | skb_put_data(skb, sl->rbuff, count); |
---|
205 | | - skb->protocol = x25_type_trans(skb, sl->dev); |
---|
206 | | - err = lapb_data_received(skb->dev, skb); |
---|
| 205 | + err = lapb_data_received(sl->dev, skb); |
---|
207 | 206 | if (err != LAPB_OK) { |
---|
208 | 207 | kfree_skb(skb); |
---|
209 | 208 | printk(KERN_DEBUG "x25_asy: data received err - %d\n", err); |
---|
.. | .. |
---|
243 | 242 | actual = sl->tty->ops->write(sl->tty, sl->xbuff, count); |
---|
244 | 243 | sl->xleft = count - actual; |
---|
245 | 244 | sl->xhead = sl->xbuff + actual; |
---|
246 | | - /* VSV */ |
---|
247 | | - clear_bit(SLF_OUTWAIT, &sl->flags); /* reset outfill flag */ |
---|
248 | 245 | } |
---|
249 | 246 | |
---|
250 | 247 | /* |
---|
.. | .. |
---|
274 | 271 | sl->xhead += actual; |
---|
275 | 272 | } |
---|
276 | 273 | |
---|
277 | | -static void x25_asy_timeout(struct net_device *dev) |
---|
| 274 | +static void x25_asy_timeout(struct net_device *dev, unsigned int txqueue) |
---|
278 | 275 | { |
---|
279 | 276 | struct x25_asy *sl = netdev_priv(dev); |
---|
280 | 277 | |
---|
.. | .. |
---|
307 | 304 | return NETDEV_TX_OK; |
---|
308 | 305 | } |
---|
309 | 306 | |
---|
| 307 | + /* There should be a pseudo header of 1 byte added by upper layers. |
---|
| 308 | + * Check to make sure it is there before reading it. |
---|
| 309 | + */ |
---|
| 310 | + if (skb->len < 1) { |
---|
| 311 | + kfree_skb(skb); |
---|
| 312 | + return NETDEV_TX_OK; |
---|
| 313 | + } |
---|
| 314 | + |
---|
310 | 315 | switch (skb->data[0]) { |
---|
311 | 316 | case X25_IFACE_DATA: |
---|
312 | 317 | break; |
---|
.. | .. |
---|
322 | 327 | if (err != LAPB_OK) |
---|
323 | 328 | netdev_err(dev, "lapb_disconnect_request error: %d\n", |
---|
324 | 329 | err); |
---|
325 | | - /* fall through */ |
---|
| 330 | + fallthrough; |
---|
326 | 331 | default: |
---|
327 | 332 | kfree_skb(skb); |
---|
328 | 333 | return NETDEV_TX_OK; |
---|
.. | .. |
---|
456 | 461 | { |
---|
457 | 462 | struct x25_asy *sl = netdev_priv(dev); |
---|
458 | 463 | unsigned long len; |
---|
459 | | - int err; |
---|
460 | 464 | |
---|
461 | 465 | if (sl->tty == NULL) |
---|
462 | 466 | return -ENODEV; |
---|
.. | .. |
---|
482 | 486 | sl->xleft = 0; |
---|
483 | 487 | sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */ |
---|
484 | 488 | |
---|
485 | | - netif_start_queue(dev); |
---|
486 | | - |
---|
487 | | - /* |
---|
488 | | - * Now attach LAPB |
---|
489 | | - */ |
---|
490 | | - err = lapb_register(dev, &x25_asy_callbacks); |
---|
491 | | - if (err == LAPB_OK) |
---|
492 | | - return 0; |
---|
| 489 | + return 0; |
---|
493 | 490 | |
---|
494 | 491 | /* Cleanup */ |
---|
495 | 492 | kfree(sl->xbuff); |
---|
.. | .. |
---|
511 | 508 | if (sl->tty) |
---|
512 | 509 | clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); |
---|
513 | 510 | |
---|
514 | | - netif_stop_queue(dev); |
---|
515 | 511 | sl->rcount = 0; |
---|
516 | 512 | sl->xleft = 0; |
---|
517 | 513 | spin_unlock(&sl->lock); |
---|
.. | .. |
---|
596 | 592 | static void x25_asy_close_tty(struct tty_struct *tty) |
---|
597 | 593 | { |
---|
598 | 594 | struct x25_asy *sl = tty->disc_data; |
---|
599 | | - int err; |
---|
600 | 595 | |
---|
601 | 596 | /* First make sure we're connected. */ |
---|
602 | 597 | if (!sl || sl->magic != X25_ASY_MAGIC) |
---|
.. | .. |
---|
606 | 601 | if (sl->dev->flags & IFF_UP) |
---|
607 | 602 | dev_close(sl->dev); |
---|
608 | 603 | rtnl_unlock(); |
---|
609 | | - |
---|
610 | | - err = lapb_unregister(sl->dev); |
---|
611 | | - if (err != LAPB_OK) |
---|
612 | | - pr_err("x25_asy_close: lapb_unregister error: %d\n", |
---|
613 | | - err); |
---|
614 | 604 | |
---|
615 | 605 | tty->disc_data = NULL; |
---|
616 | 606 | sl->tty = NULL; |
---|
.. | .. |
---|
712 | 702 | } |
---|
713 | 703 | } |
---|
714 | 704 | |
---|
715 | | -#ifdef CONFIG_COMPAT |
---|
716 | | -static long x25_asy_compat_ioctl(struct tty_struct *tty, struct file *file, |
---|
717 | | - unsigned int cmd, unsigned long arg) |
---|
718 | | -{ |
---|
719 | | - switch (cmd) { |
---|
720 | | - case SIOCGIFNAME: |
---|
721 | | - case SIOCSIFHWADDR: |
---|
722 | | - return x25_asy_ioctl(tty, file, cmd, |
---|
723 | | - (unsigned long)compat_ptr(arg)); |
---|
724 | | - } |
---|
725 | | - |
---|
726 | | - return -ENOIOCTLCMD; |
---|
727 | | -} |
---|
728 | | -#endif |
---|
729 | | - |
---|
730 | 705 | static int x25_asy_open_dev(struct net_device *dev) |
---|
731 | 706 | { |
---|
| 707 | + int err; |
---|
732 | 708 | struct x25_asy *sl = netdev_priv(dev); |
---|
733 | 709 | if (sl->tty == NULL) |
---|
734 | 710 | return -ENODEV; |
---|
| 711 | + |
---|
| 712 | + err = lapb_register(dev, &x25_asy_callbacks); |
---|
| 713 | + if (err != LAPB_OK) |
---|
| 714 | + return -ENOMEM; |
---|
| 715 | + |
---|
| 716 | + netif_start_queue(dev); |
---|
| 717 | + |
---|
| 718 | + return 0; |
---|
| 719 | +} |
---|
| 720 | + |
---|
| 721 | +static int x25_asy_close_dev(struct net_device *dev) |
---|
| 722 | +{ |
---|
| 723 | + int err; |
---|
| 724 | + |
---|
| 725 | + netif_stop_queue(dev); |
---|
| 726 | + |
---|
| 727 | + err = lapb_unregister(dev); |
---|
| 728 | + if (err != LAPB_OK) |
---|
| 729 | + pr_err("%s: lapb_unregister error: %d\n", |
---|
| 730 | + __func__, err); |
---|
| 731 | + |
---|
| 732 | + x25_asy_close(dev); |
---|
| 733 | + |
---|
735 | 734 | return 0; |
---|
736 | 735 | } |
---|
737 | 736 | |
---|
738 | 737 | static const struct net_device_ops x25_asy_netdev_ops = { |
---|
739 | 738 | .ndo_open = x25_asy_open_dev, |
---|
740 | | - .ndo_stop = x25_asy_close, |
---|
| 739 | + .ndo_stop = x25_asy_close_dev, |
---|
741 | 740 | .ndo_start_xmit = x25_asy_xmit, |
---|
742 | 741 | .ndo_tx_timeout = x25_asy_timeout, |
---|
743 | 742 | .ndo_change_mtu = x25_asy_change_mtu, |
---|
.. | .. |
---|
767 | 766 | dev->type = ARPHRD_X25; |
---|
768 | 767 | dev->tx_queue_len = 10; |
---|
769 | 768 | |
---|
| 769 | + /* When transmitting data: |
---|
| 770 | + * first this driver removes a pseudo header of 1 byte, |
---|
| 771 | + * then the lapb module prepends an LAPB header of at most 3 bytes. |
---|
| 772 | + */ |
---|
| 773 | + dev->needed_headroom = 3 - 1; |
---|
| 774 | + |
---|
770 | 775 | /* New-style flags. */ |
---|
771 | 776 | dev->flags = IFF_NOARP; |
---|
772 | 777 | } |
---|
.. | .. |
---|
778 | 783 | .open = x25_asy_open_tty, |
---|
779 | 784 | .close = x25_asy_close_tty, |
---|
780 | 785 | .ioctl = x25_asy_ioctl, |
---|
781 | | -#ifdef CONFIG_COMPAT |
---|
782 | | - .compat_ioctl = x25_asy_compat_ioctl, |
---|
783 | | -#endif |
---|
784 | 786 | .receive_buf = x25_asy_receive_buf, |
---|
785 | 787 | .write_wakeup = x25_asy_write_wakeup, |
---|
786 | 788 | }; |
---|