| .. | .. |
|---|
| 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 | }; |
|---|