| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * 6pack.c This module implements the 6pack protocol for kernel-based |
|---|
| 3 | 4 | * devices like TTY. It interfaces between a raw TTY and the |
|---|
| .. | .. |
|---|
| 34 | 35 | #include <linux/ip.h> |
|---|
| 35 | 36 | #include <linux/tcp.h> |
|---|
| 36 | 37 | #include <linux/semaphore.h> |
|---|
| 37 | | -#include <linux/compat.h> |
|---|
| 38 | 38 | #include <linux/refcount.h> |
|---|
| 39 | 39 | |
|---|
| 40 | 40 | #define SIXPACK_VERSION "Revision: 0.3.0" |
|---|
| .. | .. |
|---|
| 121 | 121 | struct timer_list tx_t; |
|---|
| 122 | 122 | struct timer_list resync_t; |
|---|
| 123 | 123 | refcount_t refcnt; |
|---|
| 124 | | - struct semaphore dead_sem; |
|---|
| 124 | + struct completion dead; |
|---|
| 125 | 125 | spinlock_t lock; |
|---|
| 126 | 126 | }; |
|---|
| 127 | 127 | |
|---|
| .. | .. |
|---|
| 311 | 311 | { |
|---|
| 312 | 312 | /* Finish setting up the DEVICE info. */ |
|---|
| 313 | 313 | dev->netdev_ops = &sp_netdev_ops; |
|---|
| 314 | | - dev->needs_free_netdev = true; |
|---|
| 315 | 314 | dev->mtu = SIXP_MTU; |
|---|
| 316 | 315 | dev->hard_header_len = AX25_MAX_HEADER_LEN; |
|---|
| 317 | 316 | dev->header_ops = &ax25_header_ops; |
|---|
| .. | .. |
|---|
| 344 | 343 | |
|---|
| 345 | 344 | sp->dev->stats.rx_bytes += count; |
|---|
| 346 | 345 | |
|---|
| 347 | | - if ((skb = dev_alloc_skb(count)) == NULL) |
|---|
| 346 | + if ((skb = dev_alloc_skb(count + 1)) == NULL) |
|---|
| 348 | 347 | goto out_mem; |
|---|
| 349 | 348 | |
|---|
| 350 | | - ptr = skb_put(skb, count); |
|---|
| 349 | + ptr = skb_put(skb, count + 1); |
|---|
| 351 | 350 | *ptr++ = cmd; /* KISS command */ |
|---|
| 352 | 351 | |
|---|
| 353 | 352 | memcpy(ptr, sp->cooked_buf + 1, count); |
|---|
| .. | .. |
|---|
| 390 | 389 | static void sp_put(struct sixpack *sp) |
|---|
| 391 | 390 | { |
|---|
| 392 | 391 | if (refcount_dec_and_test(&sp->refcnt)) |
|---|
| 393 | | - up(&sp->dead_sem); |
|---|
| 392 | + complete(&sp->dead); |
|---|
| 394 | 393 | } |
|---|
| 395 | 394 | |
|---|
| 396 | 395 | /* |
|---|
| .. | .. |
|---|
| 572 | 571 | |
|---|
| 573 | 572 | spin_lock_init(&sp->lock); |
|---|
| 574 | 573 | refcount_set(&sp->refcnt, 1); |
|---|
| 575 | | - sema_init(&sp->dead_sem, 0); |
|---|
| 574 | + init_completion(&sp->dead); |
|---|
| 576 | 575 | |
|---|
| 577 | 576 | /* !!! length of the buffers. MTU is IP MTU, not PACLEN! */ |
|---|
| 578 | 577 | |
|---|
| .. | .. |
|---|
| 666 | 665 | * we have to wait for all existing users to finish. |
|---|
| 667 | 666 | */ |
|---|
| 668 | 667 | if (!refcount_dec_and_test(&sp->refcnt)) |
|---|
| 669 | | - down(&sp->dead_sem); |
|---|
| 668 | + wait_for_completion(&sp->dead); |
|---|
| 670 | 669 | |
|---|
| 671 | 670 | /* We must stop the queue to avoid potentially scribbling |
|---|
| 672 | | - * on the free buffers. The sp->dead_sem is not sufficient |
|---|
| 671 | + * on the free buffers. The sp->dead completion is not sufficient |
|---|
| 673 | 672 | * to protect us from sp->xbuff access. |
|---|
| 674 | 673 | */ |
|---|
| 675 | 674 | netif_stop_queue(sp->dev); |
|---|
| 676 | 675 | |
|---|
| 676 | + unregister_netdev(sp->dev); |
|---|
| 677 | + |
|---|
| 677 | 678 | del_timer_sync(&sp->tx_t); |
|---|
| 678 | 679 | del_timer_sync(&sp->resync_t); |
|---|
| 679 | 680 | |
|---|
| 680 | | - /* Free all 6pack frame buffers. */ |
|---|
| 681 | + /* Free all 6pack frame buffers after unreg. */ |
|---|
| 681 | 682 | kfree(sp->rbuff); |
|---|
| 682 | 683 | kfree(sp->xbuff); |
|---|
| 683 | 684 | |
|---|
| 684 | | - unregister_netdev(sp->dev); |
|---|
| 685 | + free_netdev(sp->dev); |
|---|
| 685 | 686 | } |
|---|
| 686 | 687 | |
|---|
| 687 | 688 | /* Perform I/O control on an active 6pack channel. */ |
|---|
| .. | .. |
|---|
| 747 | 748 | return err; |
|---|
| 748 | 749 | } |
|---|
| 749 | 750 | |
|---|
| 750 | | -#ifdef CONFIG_COMPAT |
|---|
| 751 | | -static long sixpack_compat_ioctl(struct tty_struct * tty, struct file * file, |
|---|
| 752 | | - unsigned int cmd, unsigned long arg) |
|---|
| 753 | | -{ |
|---|
| 754 | | - switch (cmd) { |
|---|
| 755 | | - case SIOCGIFNAME: |
|---|
| 756 | | - case SIOCGIFENCAP: |
|---|
| 757 | | - case SIOCSIFENCAP: |
|---|
| 758 | | - case SIOCSIFHWADDR: |
|---|
| 759 | | - return sixpack_ioctl(tty, file, cmd, |
|---|
| 760 | | - (unsigned long)compat_ptr(arg)); |
|---|
| 761 | | - } |
|---|
| 762 | | - |
|---|
| 763 | | - return -ENOIOCTLCMD; |
|---|
| 764 | | -} |
|---|
| 765 | | -#endif |
|---|
| 766 | | - |
|---|
| 767 | 751 | static struct tty_ldisc_ops sp_ldisc = { |
|---|
| 768 | 752 | .owner = THIS_MODULE, |
|---|
| 769 | 753 | .magic = TTY_LDISC_MAGIC, |
|---|
| .. | .. |
|---|
| 771 | 755 | .open = sixpack_open, |
|---|
| 772 | 756 | .close = sixpack_close, |
|---|
| 773 | 757 | .ioctl = sixpack_ioctl, |
|---|
| 774 | | -#ifdef CONFIG_COMPAT |
|---|
| 775 | | - .compat_ioctl = sixpack_compat_ioctl, |
|---|
| 776 | | -#endif |
|---|
| 777 | 758 | .receive_buf = sixpack_receive_buf, |
|---|
| 778 | 759 | .write_wakeup = sixpack_write_wakeup, |
|---|
| 779 | 760 | }; |
|---|