[PATCH net-deletions] net: remove ax25 and amateur radio (hamradio) subsystem
#Partially appliedFrom:Jakub Kicinski <kuba@kernel.org>
Date:
Message-ID:<20260421021824.1293976-1-kuba@kernel.org>
Patch:v1 · 1/1
Language:Mixed
Patch-ID:ec38a888b1671bf6c62c363898b5b9a0b983e4c3
Files:
Documentation/.renames.txtDocumentation/admin-guide/kernel-parameters.txtDocumentation/networking/6pack.rstDocumentation/networking/ax25.rstDocumentation/networking/device_drivers/hamradio/baycom.rstDocumentation/networking/device_drivers/hamradio/index.rstDocumentation/networking/device_drivers/hamradio/z8530drv.rstDocumentation/networking/device_drivers/index.rstDocumentation/networking/index.rstDocumentation/staging/magic-number.rstDocumentation/translations/it_IT/staging/magic-number.rstDocumentation/translations/sp_SP/process/magic-number.rstDocumentation/translations/zh_CN/process/magic-number.rstDocumentation/translations/zh_TW/process/magic-number.rstMAINTAINERSarch/mips/configs/bcm47xx_defconfigarch/mips/configs/bigsur_defconfigarch/mips/configs/gpr_defconfigarch/mips/configs/mtx1_defconfigarch/mips/configs/rb532_defconfigarch/mips/configs/rm200_defconfigarch/mips/configs/rt305x_defconfigarch/mips/configs/xway_defconfigdrivers/net/Makefiledrivers/net/hamradio/6pack.cdrivers/net/hamradio/Kconfigdrivers/net/hamradio/Makefiledrivers/net/hamradio/baycom_epp.cdrivers/net/hamradio/baycom_par.cdrivers/net/hamradio/baycom_ser_fdx.cdrivers/net/hamradio/baycom_ser_hdx.cdrivers/net/hamradio/bpqether.cdrivers/net/hamradio/hdlcdrv.cdrivers/net/hamradio/mkiss.cdrivers/net/hamradio/scc.cdrivers/net/hamradio/yam.cdrivers/net/hamradio/z8530.hinclude/linux/hdlcdrv.hinclude/linux/netdevice.hinclude/linux/scc.hinclude/linux/yam.hinclude/net/ax25.hinclude/net/netrom.hinclude/net/rose.hinclude/uapi/linux/baycom.hinclude/uapi/linux/hdlcdrv.hinclude/uapi/linux/netrom.hinclude/uapi/linux/rose.hinclude/uapi/linux/scc.hnet/Kconfignet/Makefilenet/ax25/Kconfignet/ax25/Makefilenet/ax25/af_ax25.cnet/ax25/ax25_addr.cnet/ax25/ax25_dev.cnet/ax25/ax25_ds_in.cnet/ax25/ax25_ds_subr.cnet/ax25/ax25_ds_timer.cnet/ax25/ax25_iface.cnet/ax25/ax25_in.cnet/ax25/ax25_ip.cnet/ax25/ax25_out.cnet/ax25/ax25_route.cnet/ax25/ax25_std_in.cnet/ax25/ax25_std_subr.cnet/ax25/ax25_std_timer.cnet/ax25/ax25_subr.cnet/ax25/ax25_timer.cnet/ax25/ax25_uid.cnet/ax25/sysctl_net_ax25.cnet/ipv4/arp.cnet/netrom/Makefilenet/netrom/af_netrom.cnet/netrom/nr_dev.cnet/netrom/nr_in.cnet/netrom/nr_loopback.cnet/netrom/nr_out.cnet/netrom/nr_route.cnet/netrom/nr_subr.cnet/netrom/nr_timer.cnet/netrom/sysctl_net_netrom.cnet/rose/Makefilenet/rose/af_rose.cnet/rose/rose_dev.cnet/rose/rose_in.cnet/rose/rose_link.cnet/rose/rose_loopback.cnet/rose/rose_out.cnet/rose/rose_route.cnet/rose/rose_subr.cnet/rose/rose_timer.cnet/rose/sysctl_net_rose.cLinks:lore message ↗ · raw mail ↗
Patch content 93 changed files
Remove the amateur radio (AX.25, NET/ROM, ROSE) protocol implementationand all associated hamradio device drivers from the kernel tree.This set of protocols has long been a huge bug/syzbot magnet,and since nobody stepped up to help us deal with the influxof the AI-generated bug reports we need to move it out of treeto protect our sanity. The code is moved to an out-of-tree repo:https://github.com/linux-netdev/mod-orphanif it's cleaned up and reworked there we can accept it back. Minimal stub headers are kept for include/net/ax25.h (AX25_P_IP,AX25_ADDR_LEN, ax25_address) and include/net/rose.h (ROSE_ADDR_LEN)so that the conditional integration code in arp.c and tun.c continuesto compile and work when the out-of-tree modules are loaded. Signed-off-by: Jakub Kicinski <kuba@kernel.org>---CC: corbet@lwn.netCC: skhan@linuxfoundation.orgCC: federico.vaga@vaga.pv.itCC: carlos.bilbao@kernel.orgCC: avadhut.naik@amd.comCC: alexs@kernel.orgCC: si.yanteng@linux.devCC: dzm91@hust.edu.cnCC: 2023002089@link.tyut.edu.cnCC: tsbogend@alpha.franken.deCC: dsahern@kernel.orgCC: jani.nikula@intel.comCC: mchehab+huawei@kernel.orgCC: gregkh@linuxfoundation.orgCC: jirislaby@kernel.orgCC: tytso@mit.eduCC: herbert@gondor.apana.org.auCC: ebiggers@kernel.orgCC: johannes.berg@intel.comCC: geert@linux-m68k.orgCC: pablo@netfilter.orgCC: tglx@kernel.orgCC: mashiro.chen@mailbox.orgCC: mingo@kernel.orgCC: dqfext@gmail.comCC: jreuter@yaina.deCC: sdf@fomichev.meCC: pkshih@realtek.comCC: enelsonmoore@gmail.comCC: mkl@pengutronix.deCC: toke@toke.dkCC: kees@kernel.orgCC: crossd@gmail.comCC: jlayton@kernel.orgCC: wangliang74@huawei.comCC: aha310510@gmail.comCC: takamitz@amazon.co.jpCC: kuniyu@google.comCC: linux-doc@vger.kernel.orgCC: linux-mips@vger.kernel.org--- MAINTAINERS | 73 - Documentation/.renames.txt | 2 - .../admin-guide/kernel-parameters.txt | 18 - Documentation/networking/6pack.rst | 191 -- Documentation/networking/ax25.rst | 17 - .../device_drivers/hamradio/baycom.rst | 174 -- .../device_drivers/hamradio/index.rst | 12 - .../device_drivers/hamradio/z8530drv.rst | 686 ------ .../networking/device_drivers/index.rst | 1 - Documentation/networking/index.rst | 2 - Documentation/staging/magic-number.rst | 3 - .../it_IT/staging/magic-number.rst | 3 - .../sp_SP/process/magic-number.rst | 3 - .../zh_CN/process/magic-number.rst | 3 - .../zh_TW/process/magic-number.rst | 3 - drivers/net/hamradio/Kconfig | 162 -- net/Kconfig | 1 - net/ax25/Kconfig | 108 - drivers/net/Makefile | 1 - drivers/net/hamradio/Makefile | 22 - net/Makefile | 3 - net/ax25/Makefile | 12 - net/netrom/Makefile | 10 - net/rose/Makefile | 10 - drivers/net/hamradio/z8530.h | 246 -- include/linux/hdlcdrv.h | 276 --- include/linux/netdevice.h | 5 +- include/linux/scc.h | 86 - include/linux/yam.h | 67 - include/net/ax25.h | 476 +--- include/net/netrom.h | 273 --- include/net/rose.h | 263 +- include/uapi/linux/baycom.h | 40 - include/uapi/linux/hdlcdrv.h | 111 - include/uapi/linux/netrom.h | 37 - include/uapi/linux/rose.h | 91 - include/uapi/linux/scc.h | 174 -- drivers/net/hamradio/6pack.c | 912 ------- drivers/net/hamradio/baycom_epp.c | 1316 ---------- drivers/net/hamradio/baycom_par.c | 598 ----- drivers/net/hamradio/baycom_ser_fdx.c | 678 ----- drivers/net/hamradio/baycom_ser_hdx.c | 727 ------ drivers/net/hamradio/bpqether.c | 593 ----- drivers/net/hamradio/hdlcdrv.c | 747 ------ drivers/net/hamradio/mkiss.c | 980 -------- drivers/net/hamradio/scc.c | 2179 ----------------- drivers/net/hamradio/yam.c | 1191 --------- net/ax25/af_ax25.c | 2089 ---------------- net/ax25/ax25_addr.c | 303 --- net/ax25/ax25_dev.c | 200 -- net/ax25/ax25_ds_in.c | 298 --- net/ax25/ax25_ds_subr.c | 204 -- net/ax25/ax25_ds_timer.c | 235 -- net/ax25/ax25_iface.c | 214 -- net/ax25/ax25_in.c | 455 ---- net/ax25/ax25_ip.c | 247 -- net/ax25/ax25_out.c | 398 --- net/ax25/ax25_route.c | 416 ---- net/ax25/ax25_std_in.c | 443 ---- net/ax25/ax25_std_subr.c | 83 - net/ax25/ax25_std_timer.c | 175 -- net/ax25/ax25_subr.c | 296 --- net/ax25/ax25_timer.c | 224 -- net/ax25/ax25_uid.c | 204 -- net/ax25/sysctl_net_ax25.c | 181 -- net/ipv4/arp.c | 1 - net/netrom/af_netrom.c | 1536 ------------ net/netrom/nr_dev.c | 178 -- net/netrom/nr_in.c | 301 --- net/netrom/nr_loopback.c | 73 - net/netrom/nr_out.c | 272 -- net/netrom/nr_route.c | 989 -------- net/netrom/nr_subr.c | 280 --- net/netrom/nr_timer.c | 249 -- net/netrom/sysctl_net_netrom.c | 156 -- net/rose/af_rose.c | 1687 ------------- net/rose/rose_dev.c | 141 -- net/rose/rose_in.c | 301 --- net/rose/rose_link.c | 289 --- net/rose/rose_loopback.c | 133 - net/rose/rose_out.c | 122 - net/rose/rose_route.c | 1333 ---------- net/rose/rose_subr.c | 556 ----- net/rose/rose_timer.c | 227 -- net/rose/sysctl_net_rose.c | 125 - arch/mips/configs/bcm47xx_defconfig | 1 - arch/mips/configs/bigsur_defconfig | 10 - arch/mips/configs/gpr_defconfig | 11 - arch/mips/configs/mtx1_defconfig | 11 - arch/mips/configs/rb532_defconfig | 1 - arch/mips/configs/rm200_defconfig | 7 - arch/mips/configs/rt305x_defconfig | 1 - arch/mips/configs/xway_defconfig | 1 - 93 files changed, 6 insertions(+), 29237 deletions(-) delete mode 100644 Documentation/networking/6pack.rst delete mode 100644 Documentation/networking/ax25.rst delete mode 100644 Documentation/networking/device_drivers/hamradio/baycom.rst delete mode 100644 Documentation/networking/device_drivers/hamradio/index.rst delete mode 100644 Documentation/networking/device_drivers/hamradio/z8530drv.rst delete mode 100644 drivers/net/hamradio/Kconfig delete mode 100644 net/ax25/Kconfig delete mode 100644 drivers/net/hamradio/Makefile delete mode 100644 net/ax25/Makefile delete mode 100644 net/netrom/Makefile delete mode 100644 net/rose/Makefile delete mode 100644 drivers/net/hamradio/z8530.h delete mode 100644 include/linux/hdlcdrv.h delete mode 100644 include/linux/scc.h delete mode 100644 include/linux/yam.h delete mode 100644 include/net/netrom.h delete mode 100644 include/uapi/linux/baycom.h delete mode 100644 include/uapi/linux/hdlcdrv.h delete mode 100644 include/uapi/linux/netrom.h delete mode 100644 include/uapi/linux/rose.h delete mode 100644 include/uapi/linux/scc.h delete mode 100644 drivers/net/hamradio/6pack.c delete mode 100644 drivers/net/hamradio/baycom_epp.c delete mode 100644 drivers/net/hamradio/baycom_par.c delete mode 100644 drivers/net/hamradio/baycom_ser_fdx.c delete mode 100644 drivers/net/hamradio/baycom_ser_hdx.c delete mode 100644 drivers/net/hamradio/bpqether.c delete mode 100644 drivers/net/hamradio/hdlcdrv.c delete mode 100644 drivers/net/hamradio/mkiss.c delete mode 100644 drivers/net/hamradio/scc.c delete mode 100644 drivers/net/hamradio/yam.c delete mode 100644 net/ax25/af_ax25.c delete mode 100644 net/ax25/ax25_addr.c delete mode 100644 net/ax25/ax25_dev.c delete mode 100644 net/ax25/ax25_ds_in.c delete mode 100644 net/ax25/ax25_ds_subr.c delete mode 100644 net/ax25/ax25_ds_timer.c delete mode 100644 net/ax25/ax25_iface.c delete mode 100644 net/ax25/ax25_in.c delete mode 100644 net/ax25/ax25_ip.c delete mode 100644 net/ax25/ax25_out.c delete mode 100644 net/ax25/ax25_route.c delete mode 100644 net/ax25/ax25_std_in.c delete mode 100644 net/ax25/ax25_std_subr.c delete mode 100644 net/ax25/ax25_std_timer.c delete mode 100644 net/ax25/ax25_subr.c delete mode 100644 net/ax25/ax25_timer.c delete mode 100644 net/ax25/ax25_uid.c delete mode 100644 net/ax25/sysctl_net_ax25.c delete mode 100644 net/netrom/af_netrom.c delete mode 100644 net/netrom/nr_dev.c delete mode 100644 net/netrom/nr_in.c delete mode 100644 net/netrom/nr_loopback.c delete mode 100644 net/netrom/nr_out.c delete mode 100644 net/netrom/nr_route.c delete mode 100644 net/netrom/nr_subr.c delete mode 100644 net/netrom/nr_timer.c delete mode 100644 net/netrom/sysctl_net_netrom.c delete mode 100644 net/rose/af_rose.c delete mode 100644 net/rose/rose_dev.c delete mode 100644 net/rose/rose_in.c delete mode 100644 net/rose/rose_link.c delete mode 100644 net/rose/rose_loopback.c delete mode 100644 net/rose/rose_out.c delete mode 100644 net/rose/rose_route.c delete mode 100644 net/rose/rose_subr.c delete mode 100644 net/rose/rose_timer.c delete mode 100644 net/rose/sysctl_net_rose.c diff --git a/MAINTAINERS b/MAINTAINERSindex 66f29cde4985..cfcf422dd40a 100644--- a/MAINTAINERS+++ b/MAINTAINERS@@ -102,12 +102,6 @@ F: Documentation/networking/6lowpan.rst F: include/net/6lowpan.h F: net/6lowpan/ -6PACK NETWORK DRIVER FOR AX.25-M: Andreas Koensgen <ajk@comnets.uni-bremen.de>-L: linux-hams@vger.kernel.org-S: Maintained-F: drivers/net/hamradio/6pack.c- 802.11 (including CFG80211/NL80211) M: Johannes Berg <johannes@sipsolutions.net> L: linux-wireless@vger.kernel.org@@ -4281,14 +4275,6 @@ S: Maintained F: Documentation/devicetree/bindings/leds/backlight/awinic,aw99706.yaml F: drivers/video/backlight/aw99706.c -AX.25 NETWORK LAYER-L: linux-hams@vger.kernel.org-S: Orphan-W: https://linux-ax25.in-berlin.de-F: include/net/ax25.h-F: include/uapi/linux/ax25.h-F: net/ax25/- AXENTIA ARM DEVICES M: Peter Rosin <peda@axentia.se> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)@@ -4430,13 +4416,6 @@ F: include/uapi/linux/batadv_packet.h F: include/uapi/linux/batman_adv.h F: net/batman-adv/ -BAYCOM/HDLCDRV DRIVERS FOR AX.25-M: Thomas Sailer <t.sailer@alumni.ethz.ch>-L: linux-hams@vger.kernel.org-S: Maintained-W: http://www.baycom.org/~tom/ham/ham.html-F: drivers/net/hamradio/baycom*- BCACHE (BLOCK LAYER CACHE) M: Coly Li <colyli@fnnas.com> M: Kent Overstreet <kent.overstreet@linux.dev>@@ -7020,20 +6999,6 @@ S: Maintained F: drivers/rtc/rtc-ds1685.c F: include/linux/rtc/ds1685.h -DAMA SLAVE for AX.25-M: Joerg Reuter <jreuter@yaina.de>-L: linux-hams@vger.kernel.org-S: Maintained-W: http://yaina.de/jreuter/-W: http://www.qsl.net/dl1bke/-F: net/ax25/af_ax25.c-F: net/ax25/ax25_dev.c-F: net/ax25/ax25_ds_*-F: net/ax25/ax25_in.c-F: net/ax25/ax25_out.c-F: net/ax25/ax25_timer.c-F: net/ax25/sysctl_net_ax25.c- DASHARO ACPI PLATFORM DRIVER M: Michał Kopeć <michal.kopec@3mdeb.com> S: Maintained@@ -11444,11 +11409,6 @@ T: git https://github.com/Rust-for-Linux/linux.git timekeeping-next F: rust/kernel/time.rs F: rust/kernel/time/ -HIGH-SPEED SCC DRIVER FOR AX.25-L: linux-hams@vger.kernel.org-S: Orphan-F: drivers/net/hamradio/scc.c- HIGHPOINT ROCKETRAID 3xxx RAID DRIVER M: HighPoint Linux Team <linux@highpoint-tech.com> S: Supported@@ -18272,14 +18232,6 @@ F: net/bridge/br_netfilter*.c F: net/netfilter/ F: tools/testing/selftests/net/netfilter/ -NETROM NETWORK LAYER-L: linux-hams@vger.kernel.org-S: Orphan-W: https://linux-ax25.in-berlin.de-F: include/net/netrom.h-F: include/uapi/linux/netrom.h-F: net/netrom/- NETRONIX EMBEDDED CONTROLLER M: Jonathan Neuschäfer <j.neuschaefer@gmx.net> S: Maintained@@ -23072,14 +23024,6 @@ F: include/linux/mfd/rohm-bd96802.h F: include/linux/mfd/rohm-generic.h F: include/linux/mfd/rohm-shared.h -ROSE NETWORK LAYER-L: linux-hams@vger.kernel.org-S: Orphan-W: https://linux-ax25.in-berlin.de-F: include/net/rose.h-F: include/uapi/linux/rose.h-F: net/rose/- ROTATION DRIVER FOR ALLWINNER A83T M: Jernej Skrabec <jernej.skrabec@gmail.com> L: linux-media@vger.kernel.org@@ -29105,13 +29049,6 @@ F: lib/decompress_unxz.c F: lib/xz/ F: scripts/xz_wrap.sh -YAM DRIVER FOR AX.25-M: Jean-Paul Roubelat <jpr@f6fbb.org>-L: linux-hams@vger.kernel.org-S: Maintained-F: drivers/net/hamradio/yam*-F: include/linux/yam.h- YAMA SECURITY MODULE M: Kees Cook <kees@kernel.org> S: Supported@@ -29133,16 +29070,6 @@ S: Maintained F: Documentation/input/devices/yealink.rst F: drivers/input/misc/yealink.* -Z8530 DRIVER FOR AX.25-M: Joerg Reuter <jreuter@yaina.de>-L: linux-hams@vger.kernel.org-S: Maintained-W: http://yaina.de/jreuter/-W: http://www.qsl.net/dl1bke/-F: Documentation/networking/device_drivers/hamradio/z8530drv.rst-F: drivers/net/hamradio/*scc.c-F: drivers/net/hamradio/z8530.h- ZD1211RW WIRELESS DRIVER L: linux-wireless@vger.kernel.org S: Orphandiff --git a/Documentation/.renames.txt b/Documentation/.renames.txtindex c4de5200abdb..df4db1121995 100644--- a/Documentation/.renames.txt+++ b/Documentation/.renames.txt@@ -783,7 +783,6 @@ namespaces/compatibility-list admin-guide/namespaces/compatibility-list namespaces/index admin-guide/namespaces/index namespaces/resource-control admin-guide/namespaces/resource-control networking/altera_tse networking/device_drivers/ethernet/altera/altera_tse-networking/baycom networking/device_drivers/hamradio/baycom networking/bpf_flow_dissector bpf/prog_flow_dissector networking/cxacru networking/device_drivers/atm/cxacru networking/defza networking/device_drivers/fddi/defza@@ -846,7 +845,6 @@ networking/ixgbe networking/device_drivers/ethernet/intel/ixgbe networking/ixgbevf networking/device_drivers/ethernet/intel/ixgbevf networking/netdev-FAQ process/maintainer-netdev networking/skfp networking/device_drivers/fddi/skfp-networking/z8530drv networking/device_drivers/hamradio/z8530drv nfc/index driver-api/nfc/index nfc/nfc-hci driver-api/nfc/nfc-hci nfc/nfc-pn544 driver-api/nfc/nfc-pn544diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txtindex f2ce1f4975c1..09354ff7cff2 100644--- a/Documentation/admin-guide/kernel-parameters.txt+++ b/Documentation/admin-guide/kernel-parameters.txt@@ -6,7 +6,6 @@ APPARMOR AppArmor support is enabled. ARM ARM architecture is enabled. ARM64 ARM64 architecture is enabled.- AX25 Appropriate AX.25 support is enabled. CLK Common clock infrastructure is enabled. CMA Contiguous Memory Area support is enabled. DRM Direct Rendering Management support is enabled.@@ -633,23 +632,6 @@ Kernel parameters 1 - Enable the BAU. unset - Disable the BAU. - baycom_epp= [HW,AX25]- Format: <io>,<mode>-- baycom_par= [HW,AX25] BayCom Parallel Port AX.25 Modem- Format: <io>,<mode>- See header of drivers/net/hamradio/baycom_par.c.-- baycom_ser_fdx= [HW,AX25]- BayCom Serial Port AX.25 Modem (Full Duplex Mode)- Format: <io>,<irq>,<mode>[,<baud>]- See header of drivers/net/hamradio/baycom_ser_fdx.c.-- baycom_ser_hdx= [HW,AX25]- BayCom Serial Port AX.25 Modem (Half Duplex Mode)- Format: <io>,<irq>,<mode>- See header of drivers/net/hamradio/baycom_ser_hdx.c.- bdev_allow_write_mounted= Format: <bool> Control the ability to open a mounted block devicediff --git a/Documentation/networking/6pack.rst b/Documentation/networking/6pack.rstdeleted file mode 100644index 66d5fd4fc821..000000000000--- a/Documentation/networking/6pack.rst+++ /dev/null@@ -1,191 +0,0 @@-.. SPDX-License-Identifier: GPL-2.0--==============-6pack Protocol-==============--This is the 6pack-mini-HOWTO, written by--Andreas Könsgen DG3KQ--:Internet: ajk@comnets.uni-bremen.de-:AMPR-net: dg3kq@db0pra.ampr.org-:AX.25: dg3kq@db0ach.#nrw.deu.eu--Last update: April 7, 1998--1. What is 6pack, and what are the advantages to KISS?-======================================================--6pack is a transmission protocol for data exchange between the PC and-the TNC over a serial line. It can be used as an alternative to KISS.--6pack has two major advantages:--- The PC is given full control over the radio- channel. Special control data is exchanged between the PC and the TNC so- that the PC knows at any time if the TNC is receiving data, if a TNC- buffer underrun or overrun has occurred, if the PTT is- set and so on. This control data is processed at a higher priority than- normal data, so a data stream can be interrupted at any time to issue an- important event. This helps to improve the channel access and timing- algorithms as everything is computed in the PC. It would even be possible- to experiment with something completely different from the known CSMA and- DAMA channel access methods.- This kind of real-time control is especially important to supply several- TNCs that are connected between each other and the PC by a daisy chain- (however, this feature is not supported yet by the Linux 6pack driver).--- Each packet transferred over the serial line is supplied with a checksum,- so it is easy to detect errors due to problems on the serial line.- Received packets that are corrupt are not passed on to the AX.25 layer.- Damaged packets that the TNC has received from the PC are not transmitted.--More details about 6pack are described in the file 6pack.ps that is located-in the doc directory of the AX.25 utilities package.--2. Who has developed the 6pack protocol?-========================================--The 6pack protocol has been developed by Ekki Plicht DF4OR, Henning Rech-DF9IC and Gunter Jost DK7WJ. A driver for 6pack, written by Gunter Jost and-Matthias Welwarsky DG2FEF, comes along with the PC version of FlexNet.-They have also written a firmware for TNCs to perform the 6pack-protocol (see section 4 below).--3. Where can I get the latest version of 6pack for LinuX?-=========================================================--At the moment, the 6pack stuff can obtained via anonymous ftp from-db0bm.automation.fh-aachen.de. In the directory /incoming/dg3kq,-there is a file named 6pack.tgz.--4. Preparing the TNC for 6pack operation-========================================--To be able to use 6pack, a special firmware for the TNC is needed. The EPROM-of a newly bought TNC does not contain 6pack, so you will have to-program an EPROM yourself. The image file for 6pack EPROMs should be-available on any packet radio box where PC/FlexNet can be found. The name of-the file is 6pack.bin. This file is copyrighted and maintained by the FlexNet-team. It can be used under the terms of the license that comes along-with PC/FlexNet. Please do not ask me about the internals of this file as I-don't know anything about it. I used a textual description of the 6pack-protocol to program the Linux driver.--TNCs contain a 64kByte EPROM, the lower half of which is used for-the firmware/KISS. The upper half is either empty or is sometimes-programmed with software called TAPR. In the latter case, the TNC-is supplied with a DIP switch so you can easily change between the-two systems. When programming a new EPROM, one of the systems is replaced-by 6pack. It is useful to replace TAPR, as this software is rarely used-nowadays. If your TNC is not equipped with the switch mentioned above, you-can build in one yourself that switches over the highest address pin-of the EPROM between HIGH and LOW level. After having inserted the new EPROM-and switched to 6pack, apply power to the TNC for a first test. The connect-and the status LED are lit for about a second if the firmware initialises-the TNC correctly.--5. Building and installing the 6pack driver-===========================================--The driver has been tested with kernel version 2.1.90. Use with older-kernels may lead to a compilation error because the interface to a kernel-function has been changed in the 2.1.8x kernels.--How to turn on 6pack support:--------------------------------- In the linux kernel configuration program, select the code maturity level- options menu and turn on the prompting for development drivers.--- Select the amateur radio support menu and turn on the serial port 6pack- driver.--- Compile and install the kernel and the modules.--To use the driver, the kissattach program delivered with the AX.25 utilities-has to be modified.--- Do a cd to the directory that holds the kissattach sources. Edit the- kissattach.c file. At the top, insert the following lines::-- #ifndef N_6PACK- #define N_6PACK (N_AX25+1)- #endif-- Then find the line:-- int disc = N_AX25;-- and replace N_AX25 by N_6PACK.--- Recompile kissattach. Rename it to spattach to avoid confusions.--Installing the driver:-------------------------- Do an insmod 6pack. Look at your /var/log/messages file to check if the- module has printed its initialization message.--- Do a spattach as you would launch kissattach when starting a KISS port.- Check if the kernel prints the message '6pack: TNC found'.--- From here, everything should work as if you were setting up a KISS port.- The only difference is that the network device that represents- the 6pack port is called sp instead of sl or ax. So, sp0 would be the- first 6pack port.--Although the driver has been tested on various platforms, I still declare it-ALPHA. BE CAREFUL! Sync your disks before insmoding the 6pack module-and spattaching. Watch out if your computer behaves strangely. Read section-6 of this file about known problems.--Note that the connect and status LEDs of the TNC are controlled in a-different way than they are when the TNC is used with PC/FlexNet. When using-FlexNet, the connect LED is on if there is a connection; the status LED is-on if there is data in the buffer of the PC's AX.25 engine that has to be-transmitted. Under Linux, the 6pack layer is beyond the AX.25 layer,-so the 6pack driver doesn't know anything about connects or data that-has not yet been transmitted. Therefore the LEDs are controlled-as they are in KISS mode: The connect LED is turned on if data is transferred-from the PC to the TNC over the serial line, the status LED if data is-sent to the PC.--6. Known problems-=================--When testing the driver with 2.0.3x kernels and-operating with data rates on the radio channel of 9600 Baud or higher,-the driver may, on certain systems, sometimes print the message '6pack:-bad checksum', which is due to data loss if the other station sends two-or more subsequent packets. I have been told that this is due to a problem-with the serial driver of 2.0.3x kernels. I don't know yet if the problem-still exists with 2.1.x kernels, as I have heard that the serial driver-code has been changed with 2.1.x.--When shutting down the sp interface with ifconfig, the kernel crashes if-there is still an AX.25 connection left over which an IP connection was-running, even if that IP connection is already closed. The problem does not-occur when there is a bare AX.25 connection still running. I don't know if-this is a problem of the 6pack driver or something else in the kernel.--The driver has been tested as a module, not yet as a kernel-builtin driver.--The 6pack protocol supports daisy-chaining of TNCs in a token ring, which is-connected to one serial port of the PC. This feature is not implemented-and at least at the moment I won't be able to do it because I do not have-the opportunity to build a TNC daisy-chain and test it.--Some of the comments in the source code are inaccurate. They are left from-the SLIP/KISS driver, from which the 6pack driver has been derived.-I haven't modified or removed them yet -- sorry! The code itself needs-some cleaning and optimizing. This will be done in a later release.--If you encounter a bug or if you have a question or suggestion concerning the-driver, feel free to mail me, using the addresses given at the beginning of-this file.--Have fun!--Andreasdiff --git a/Documentation/networking/ax25.rst b/Documentation/networking/ax25.rstdeleted file mode 100644index 89c79dd6c6f9..000000000000--- a/Documentation/networking/ax25.rst+++ /dev/null@@ -1,17 +0,0 @@-.. SPDX-License-Identifier: GPL-2.0--=====-AX.25-=====--To use the amateur radio protocols within Linux you will need to get a-suitable copy of the AX.25 Utilities. More detailed information about-AX.25, NET/ROM and ROSE, associated programs and utilities can be-found on https://linux-ax25.in-berlin.de.--There is a mailing list for discussing Linux amateur radio matters-called linux-hams@vger.kernel.org. To subscribe to it, send a message to-linux-hams+subscribe@vger.kernel.org or use the web interface at-https://vger.kernel.org. The subject and body of the message are-ignored. You don't need to be subscribed to post but of course that-means you might miss an answer.diff --git a/Documentation/networking/device_drivers/hamradio/baycom.rst b/Documentation/networking/device_drivers/hamradio/baycom.rstdeleted file mode 100644index fe2d010f0e86..000000000000--- a/Documentation/networking/device_drivers/hamradio/baycom.rst+++ /dev/null@@ -1,174 +0,0 @@-.. SPDX-License-Identifier: GPL-2.0--===============================-Linux Drivers for Baycom Modems-===============================--Thomas M. Sailer, HB9JNX/AE4WA, <sailer@ife.ee.ethz.ch>--The drivers for the baycom modems have been split into-separate drivers as they did not share any code, and the driver-and device names have changed.--This document describes the Linux Kernel Drivers for simple Baycom style-amateur radio modems.--The following drivers are available:-====================================--baycom_ser_fdx:- This driver supports the SER12 modems either full or half duplex.- Its baud rate may be changed via the ``baud`` module parameter,- therefore it supports just about every bit bang modem on a- serial port. Its devices are called bcsf0 through bcsf3.- This is the recommended driver for SER12 type modems,- however if you have a broken UART clone that does not have working- delta status bits, you may try baycom_ser_hdx.--baycom_ser_hdx:- This is an alternative driver for SER12 type modems.- It only supports half duplex, and only 1200 baud. Its devices- are called bcsh0 through bcsh3. Use this driver only if baycom_ser_fdx- does not work with your UART.--baycom_par:- This driver supports the par96 and picpar modems.- Its devices are called bcp0 through bcp3.--baycom_epp:- This driver supports the EPP modem.- Its devices are called bce0 through bce3.- This driver is work-in-progress.--The following modems are supported:--======= ========================================================================-ser12 This is a very simple 1200 baud AFSK modem. The modem consists only- of a modulator/demodulator chip, usually a TI TCM3105. The computer- is responsible for regenerating the receiver bit clock, as well as- for handling the HDLC protocol. The modem connects to a serial port,- hence the name. Since the serial port is not used as an async serial- port, the kernel driver for serial ports cannot be used, and this- driver only supports standard serial hardware (8250, 16450, 16550)--par96 This is a modem for 9600 baud FSK compatible to the G3RUH standard.- The modem does all the filtering and regenerates the receiver clock.- Data is transferred from and to the PC via a shift register.- The shift register is filled with 16 bits and an interrupt is signalled.- The PC then empties the shift register in a burst. This modem connects- to the parallel port, hence the name. The modem leaves the- implementation of the HDLC protocol and the scrambler polynomial to- the PC.--picpar This is a redesign of the par96 modem by Henning Rech, DF9IC. The modem- is protocol compatible to par96, but uses only three low power ICs- and can therefore be fed from the parallel port and does not require- an additional power supply. Furthermore, it incorporates a carrier- detect circuitry.--EPP This is a high-speed modem adaptor that connects to an enhanced parallel- port.-- Its target audience is users working over a high speed hub (76.8kbit/s).--eppfpga This is a redesign of the EPP adaptor.-======= ========================================================================--All of the above modems only support half duplex communications. However,-the driver supports the KISS (see below) fullduplex command. It then simply-starts to send as soon as there's a packet to transmit and does not care-about DCD, i.e. it starts to send even if there's someone else on the channel.-This command is required by some implementations of the DAMA channel-access protocol.---The Interface of the drivers-============================--Unlike previous drivers, these drivers are no longer character devices,-but they are now true kernel network interfaces. Installation is therefore-simple. Once installed, four interfaces named bc{sf,sh,p,e}[0-3] are available.-sethdlc from the ax25 utilities may be used to set driver states etc.-Users of userland AX.25 stacks may use the net2kiss utility (also available-in the ax25 utilities package) to convert packets of a network interface-to a KISS stream on a pseudo tty. There's also a patch available from-me for WAMPES which allows attaching a kernel network interface directly.---Configuring the driver-======================--Every time a driver is inserted into the kernel, it has to know which-modems it should access at which ports. This can be done with the setbaycom-utility. If you are only using one modem, you can also configure the-driver from the insmod command line (or by means of an option line in-``/etc/modprobe.d/*.conf``).--Examples::-- modprobe baycom_ser_fdx mode="ser12*" iobase=0x3f8 irq=4- sethdlc -i bcsf0 -p mode "ser12*" io 0x3f8 irq 4--Both lines configure the first port to drive a ser12 modem at the first-serial port (COM1 under DOS). The * in the mode parameter instructs the driver-to use the software DCD algorithm (see below)::-- insmod baycom_par mode="picpar" iobase=0x378- sethdlc -i bcp0 -p mode "picpar" io 0x378--Both lines configure the first port to drive a picpar modem at the-first parallel port (LPT1 under DOS). (Note: picpar implies-hardware DCD, par96 implies software DCD).--The channel access parameters can be set with sethdlc -a or kissparms.-Note that both utilities interpret the values slightly differently.---Hardware DCD versus Software DCD-================================--To avoid collisions on the air, the driver must know when the channel is-busy. This is the task of the DCD circuitry/software. The driver may either-utilise a software DCD algorithm (options=1) or use a DCD signal from-the hardware (options=0).--======= =================================================================-ser12 if software DCD is utilised, the radio's squelch should always be- open. It is highly recommended to use the software DCD algorithm,- as it is much faster than most hardware squelch circuitry. The- disadvantage is a slightly higher load on the system.--par96 the software DCD algorithm for this type of modem is rather poor.- The modem simply does not provide enough information to implement- a reasonable DCD algorithm in software. Therefore, if your radio- feeds the DCD input of the PAR96 modem, the use of the hardware- DCD circuitry is recommended.--picpar the picpar modem features a builtin DCD hardware, which is highly- recommended.-======= =================================================================----Compatibility with the rest of the Linux kernel-===============================================--The serial driver and the baycom serial drivers compete-for the same hardware resources. Of course only one driver can access a given-interface at a time. The serial driver grabs all interfaces it can find at-startup time. Therefore the baycom drivers subsequently won't be able to-access a serial port. You might therefore find it necessary to release-a port owned by the serial driver with 'setserial /dev/ttyS# uart none', where-# is the number of the interface. The baycom drivers do not reserve any-ports at startup, unless one is specified on the 'insmod' command line. Another-method to solve the problem is to compile all drivers as modules and-leave it to kmod to load the correct driver depending on the application.--The parallel port drivers (baycom_par, baycom_epp) now use the parport subsystem-to arbitrate the ports between different client drivers.--vy 73s de--Tom Sailer, sailer@ife.ee.ethz.ch--hb9jnx @ hb9w.ampr.orgdiff --git a/Documentation/networking/device_drivers/hamradio/index.rst b/Documentation/networking/device_drivers/hamradio/index.rstdeleted file mode 100644index 6af481c5b020..000000000000--- a/Documentation/networking/device_drivers/hamradio/index.rst+++ /dev/null@@ -1,12 +0,0 @@-.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)--Amateur Radio Device Drivers-============================--Contents:--.. toctree::- :maxdepth: 2-- baycom- z8530drvdiff --git a/Documentation/networking/device_drivers/hamradio/z8530drv.rst b/Documentation/networking/device_drivers/hamradio/z8530drv.rstdeleted file mode 100644index d2942760f167..000000000000--- a/Documentation/networking/device_drivers/hamradio/z8530drv.rst+++ /dev/null@@ -1,686 +0,0 @@-.. SPDX-License-Identifier: GPL-2.0-.. include:: <isonum.txt>--=========================================================-SCC.C - Linux driver for Z8530 based HDLC cards for AX.25-=========================================================---This is a subset of the documentation. To use this driver you MUST have the-full package from:--Internet:-- 1. ftp://ftp.ccac.rwth-aachen.de/pub/jr/z8530drv-utils_3.0-3.tar.gz-- 2. ftp://ftp.pspt.fi/pub/ham/linux/ax25/z8530drv-utils_3.0-3.tar.gz--Please note that the information in this document may be hopelessly outdated.-A new version of the documentation, along with links to other important-Linux Kernel AX.25 documentation and programs, is available on-http://yaina.de/jreuter--Copyright |copy| 1993,2000 by Joerg Reuter DL1BKE <jreuter@yaina.de>--portions Copyright |copy| 1993 Guido ten Dolle PE1NNZ--for the complete copyright notice see >> Copying.Z8530DRV <<--1. Initialization of the driver-===============================--To use the driver, 3 steps must be performed:-- 1. if compiled as module: loading the module- 2. Setup of hardware, MODEM and KISS parameters with sccinit- 3. Attach each channel to the Linux kernel AX.25 with "ifconfig"--Unlike the versions below 2.4 this driver is a real network device-driver. If you want to run xNOS instead of our fine kernel AX.25-use a 2.x version (available from above sites) or read the-AX.25-HOWTO on how to emulate a KISS TNC on network device drivers.---1.1 Loading the module-======================--(If you're going to compile the driver as a part of the kernel image,- skip this chapter and continue with 1.2)--Before you can use a module, you'll have to load it with::-- insmod scc.o--please read 'man insmod' that comes with module-init-tools.--You should include the insmod in one of the /etc/rc.d/rc.* files,-and don't forget to insert a call of sccinit after that. It-will read your /etc/z8530drv.conf.--1.2. /etc/z8530drv.conf-=======================--To setup all parameters you must run /sbin/sccinit from one-of your rc.*-files. This has to be done BEFORE you can-"ifconfig" an interface. Sccinit reads the file /etc/z8530drv.conf-and sets the hardware, MODEM and KISS parameters. A sample file is-delivered with this package. Change it to your needs.--The file itself consists of two main sections.--1.2.1 configuration of hardware parameters-==========================================--The hardware setup section defines the following parameters for each-Z8530::-- chip 1- data_a 0x300 # data port A- ctrl_a 0x304 # control port A- data_b 0x301 # data port B- ctrl_b 0x305 # control port B- irq 5 # IRQ No. 5- pclock 4915200 # clock- board BAYCOM # hardware type- escc no # enhanced SCC chip? (8580/85180/85280)- vector 0 # latch for interrupt vector- special no # address of special function register- option 0 # option to set via sfr---chip- - this is just a delimiter to make sccinit a bit simpler to- program. A parameter has no effect.--data_a- - the address of the data port A of this Z8530 (needed)-ctrl_a- - the address of the control port A (needed)-data_b- - the address of the data port B (needed)-ctrl_b- - the address of the control port B (needed)--irq- - the used IRQ for this chip. Different chips can use different- IRQs or the same. If they share an interrupt, it needs to be- specified within one chip-definition only.--pclock - the clock at the PCLK pin of the Z8530 (option, 4915200 is- default), measured in Hertz--board- - the "type" of the board:-- ======================= ========- SCC type value- ======================= ========- PA0HZP SCC card PA0HZP- EAGLE card EAGLE- PC100 card PC100- PRIMUS-PC (DG9BL) card PRIMUS- BayCom (U)SCC card BAYCOM- ======================= ========--escc- - if you want support for ESCC chips (8580, 85180, 85280), set- this to "yes" (option, defaults to "no")--vector- - address of the vector latch (aka "intack port") for PA0HZP- cards. There can be only one vector latch for all chips!- (option, defaults to 0)--special- - address of the special function register on several cards.- (option, defaults to 0)--option - The value you write into that register (option, default is 0)--You can specify up to four chips (8 channels). If this is not enough,-just change::-- #define MAXSCC 4--to a higher value.--Example for the BAYCOM USCC:-------------------------------::-- chip 1- data_a 0x300 # data port A- ctrl_a 0x304 # control port A- data_b 0x301 # data port B- ctrl_b 0x305 # control port B- irq 5 # IRQ No. 5 (#)- board BAYCOM # hardware type (*)- #- # SCC chip 2- #- chip 2- data_a 0x302- ctrl_a 0x306- data_b 0x303- ctrl_b 0x307- board BAYCOM--An example for a PA0HZP card:--------------------------------::-- chip 1- data_a 0x153- data_b 0x151- ctrl_a 0x152- ctrl_b 0x150- irq 9- pclock 4915200- board PA0HZP- vector 0x168- escc no- #- #- #- chip 2- data_a 0x157- data_b 0x155- ctrl_a 0x156- ctrl_b 0x154- irq 9- pclock 4915200- board PA0HZP- vector 0x168- escc no--A DRSI would should probably work with this:----------------------------------------------(actually: two DRSI cards...)--::-- chip 1- data_a 0x303- data_b 0x301- ctrl_a 0x302- ctrl_b 0x300- irq 7- pclock 4915200- board DRSI- escc no- #- #- #- chip 2- data_a 0x313- data_b 0x311- ctrl_a 0x312- ctrl_b 0x310- irq 7- pclock 4915200- board DRSI- escc no--Note that you cannot use the on-board baudrate generator off DRSI-cards. Use "mode dpll" for clock source (see below).--This is based on information provided by Mike Bilow (and verified-by Paul Helay)--The utility "gencfg"-----------------------If you only know the parameters for the PE1CHL driver for DOS,-run gencfg. It will generate the correct port addresses (I hope).-Its parameters are exactly the same as the ones you use with-the "attach scc" command in net, except that the string "init" must-not appear. Example::-- gencfg 2 0x150 4 2 0 1 0x168 9 4915200--will print a skeleton z8530drv.conf for the OptoSCC to stdout.--::-- gencfg 2 0x300 2 4 5 -4 0 7 4915200 0x10--does the same for the BAYCOM USCC card. In my opinion it is much easier-to edit scc_config.h...---1.2.2 channel configuration-===========================--The channel definition is divided into three sub sections for each-channel:--An example for scc0::-- # DEVICE-- device scc0 # the device for the following params-- # MODEM / BUFFERS-- speed 1200 # the default baudrate- clock dpll # clock source:- # dpll = normal half duplex operation- # external = MODEM provides own Rx/Tx clock- # divider = use full duplex divider if- # installed (1)- mode nrzi # HDLC encoding mode- # nrzi = 1k2 MODEM, G3RUH 9k6 MODEM- # nrz = DF9IC 9k6 MODEM- #- bufsize 384 # size of buffers. Note that this must include- # the AX.25 header, not only the data field!- # (optional, defaults to 384)-- # KISS (Layer 1)-- txdelay 36 # (see chapter 1.4)- persist 64- slot 8- tail 8- fulldup 0- wait 12- min 3- maxkey 7- idle 3- maxdef 120- group 0- txoff off- softdcd on- slip off--The order WITHIN these sections is unimportant. The order OF these-sections IS important. The MODEM parameters are set with the first-recognized KISS parameter...--Please note that you can initialize the board only once after boot-(or insmod). You can change all parameters but "mode" and "clock"-later with the Sccparam program or through KISS. Just to avoid-security holes...--(1) this divider is usually mounted on the SCC-PBC (PA0HZP) or not- present at all (BayCom). It feeds back the output of the DPLL- (digital pll) as transmit clock. Using this mode without a divider- installed will normally result in keying the transceiver until- maxkey expires --- of course without sending anything (useful).--2. Attachment of a channel by your AX.25 software-=================================================--2.1 Kernel AX.25-================--To set up an AX.25 device you can simply type::-- ifconfig scc0 44.128.1.1 hw ax25 dl0tha-7--This will create a network interface with the IP number 44.128.20.107-and the callsign "dl0tha". If you do not have any IP number (yet) you-can use any of the 44.128.0.0 network. Note that you do not need-axattach. The purpose of axattach (like slattach) is to create a KISS-network device linked to a TTY. Please read the documentation of the-ax25-utils and the AX.25-HOWTO to learn how to set the parameters of-the kernel AX.25.--2.2 NOS, NET and TFKISS-=======================--Since the TTY driver (aka KISS TNC emulation) is gone you need-to emulate the old behaviour. The cost of using these programs is-that you probably need to compile the kernel AX.25, regardless of whether-you actually use it or not. First setup your /etc/ax25/axports,-for example::-- 9k6 dl0tha-9 9600 255 4 9600 baud port (scc3)- axlink dl0tha-15 38400 255 4 Link to NOS--Now "ifconfig" the scc device::-- ifconfig scc3 44.128.1.1 hw ax25 dl0tha-9--You can now axattach a pseudo-TTY::-- axattach /dev/ptys0 axlink--and start your NOS and attach /dev/ptys0 there. The problem is that-NOS is reachable only via digipeating through the kernel AX.25-(disastrous on a DAMA controlled channel). To solve this problem,-configure "rxecho" to echo the incoming frames from "9k6" to "axlink"-and outgoing frames from "axlink" to "9k6" and start::-- rxecho--Or simply use "kissbridge" coming with z8530drv-utils::-- ifconfig scc3 hw ax25 dl0tha-9- kissbridge scc3 /dev/ptys0---3. Adjustment and Display of parameters-=======================================--3.1 Displaying SCC Parameters:-==============================--Once a SCC channel has been attached, the parameter settings and-some statistic information can be shown using the param program::-- dl1bke-u:~$ sccstat scc0-- Parameters:-- speed : 1200 baud- txdelay : 36- persist : 255- slottime : 0- txtail : 8- fulldup : 1- waittime : 12- mintime : 3 sec- maxkeyup : 7 sec- idletime : 3 sec- maxdefer : 120 sec- group : 0x00- txoff : off- softdcd : on- SLIP : off-- Status:-- HDLC Z8530 Interrupts Buffers- ------------------------------------------------------------------------ Sent : 273 RxOver : 0 RxInts : 125074 Size : 384- Received : 1095 TxUnder: 0 TxInts : 4684 NoSpace : 0- RxErrors : 1591 ExInts : 11776- TxErrors : 0 SpInts : 1503- Tx State : idle---The status info shown is:--============== ==============================================================-Sent number of frames transmitted-Received number of frames received-RxErrors number of receive errors (CRC, ABORT)-TxErrors number of discarded Tx frames (due to various reasons)-Tx State status of the Tx interrupt handler: idle/busy/active/tail (2)-RxOver number of receiver overruns-TxUnder number of transmitter underruns-RxInts number of receiver interrupts-TxInts number of transmitter interrupts-EpInts number of receiver special condition interrupts-SpInts number of external/status interrupts-Size maximum size of an AX.25 frame (*with* AX.25 headers!)-NoSpace number of times a buffer could not get allocated-============== ==============================================================--An overrun is abnormal. If lots of these occur, the product of-baudrate and number of interfaces is too high for the processing-power of your computer. NoSpace errors are unlikely to be caused by the-driver or the kernel AX.25.---3.2 Setting Parameters-======================---The setting of parameters of the emulated KISS TNC is done in the-same way in the SCC driver. You can change parameters by using-the kissparms program from the ax25-utils package or use the program-"sccparam"::-- sccparam <device> <paramname> <decimal-|hexadecimal value>--You can change the following parameters:--=========== =====-param value-=========== =====-speed 1200-txdelay 36-persist 255-slottime 0-txtail 8-fulldup 1-waittime 12-mintime 3-maxkeyup 7-idletime 3-maxdefer 120-group 0x00-txoff off-softdcd on-SLIP off-=========== =====---The parameters have the following meaning:--speed:- The baudrate on this channel in bits/sec-- Example: sccparam /dev/scc3 speed 9600--txdelay:- The delay (in units of 10 ms) after keying of the- transmitter, until the first byte is sent. This is usually- called "TXDELAY" in a TNC. When 0 is specified, the driver- will just wait until the CTS signal is asserted. This- assumes the presence of a timer or other circuitry in the- MODEM and/or transmitter, that asserts CTS when the- transmitter is ready for data.- A normal value of this parameter is 30-36.-- Example: sccparam /dev/scc0 txd 20--persist:- This is the probability that the transmitter will be keyed- when the channel is found to be free. It is a value from 0- to 255, and the probability is (value+1)/256. The value- should be somewhere near 50-60, and should be lowered when- the channel is used more heavily.-- Example: sccparam /dev/scc2 persist 20--slottime:- This is the time between samples of the channel. It is- expressed in units of 10 ms. About 200-300 ms (value 20-30)- seems to be a good value.-- Example: sccparam /dev/scc0 slot 20--tail:- The time the transmitter will remain keyed after the last- byte of a packet has been transferred to the SCC. This is- necessary because the CRC and a flag still have to leave the- SCC before the transmitter is keyed down. The value depends- on the baudrate selected. A few character times should be- sufficient, e.g. 40ms at 1200 baud. (value 4)- The value of this parameter is in 10 ms units.-- Example: sccparam /dev/scc2 4--full:- The full-duplex mode switch. This can be one of the following- values:-- 0: The interface will operate in CSMA mode (the normal- half-duplex packet radio operation)- 1: Fullduplex mode, i.e. the transmitter will be keyed at- any time, without checking the received carrier. It- will be unkeyed when there are no packets to be sent.- 2: Like 1, but the transmitter will remain keyed, also- when there are no packets to be sent. Flags will be- sent in that case, until a timeout (parameter 10)- occurs.-- Example: sccparam /dev/scc0 fulldup off--wait:- The initial waittime before any transmit attempt, after the- frame has been queue for transmit. This is the length of- the first slot in CSMA mode. In full duplex modes it is- set to 0 for maximum performance.- The value of this parameter is in 10 ms units.-- Example: sccparam /dev/scc1 wait 4--maxkey:- The maximal time the transmitter will be keyed to send- packets, in seconds. This can be useful on busy CSMA- channels, to avoid "getting a bad reputation" when you are- generating a lot of traffic. After the specified time has- elapsed, no new frame will be started. Instead, the trans-- mitter will be switched off for a specified time (parameter- min), and then the selected algorithm for keyup will be- started again.- The value 0 as well as "off" will disable this feature,- and allow infinite transmission time.-- Example: sccparam /dev/scc0 maxk 20--min:- This is the time the transmitter will be switched off when- the maximum transmission time is exceeded.-- Example: sccparam /dev/scc3 min 10--idle:- This parameter specifies the maximum idle time in full duplex- 2 mode, in seconds. When no frames have been sent for this- time, the transmitter will be keyed down. A value of 0 is- has same result as the fullduplex mode 1. This parameter- can be disabled.-- Example: sccparam /dev/scc2 idle off # transmit forever--maxdefer- This is the maximum time (in seconds) to wait for a free channel- to send. When this timer expires the transmitter will be keyed- IMMEDIATELY. If you love to get trouble with other users you- should set this to a very low value ;-)-- Example: sccparam /dev/scc0 maxdefer 240 # 2 minutes---txoff:- When this parameter has the value 0, the transmission of packets- is enable. Otherwise it is disabled.-- Example: sccparam /dev/scc2 txoff on--group:- It is possible to build special radio equipment to use more than- one frequency on the same band, e.g. using several receivers and- only one transmitter that can be switched between frequencies.- Also, you can connect several radios that are active on the same- band. In these cases, it is not possible, or not a good idea, to- transmit on more than one frequency. The SCC driver provides a- method to lock transmitters on different interfaces, using the- "param <interface> group <x>" command. This will only work when- you are using CSMA mode (parameter full = 0).-- The number <x> must be 0 if you want no group restrictions, and- can be computed as follows to create restricted groups:- <x> is the sum of some OCTAL numbers:--- === =======================================================- 200 This transmitter will only be keyed when all other- transmitters in the group are off.- 100 This transmitter will only be keyed when the carrier- detect of all other interfaces in the group is off.- 0xx A byte that can be used to define different groups.- Interfaces are in the same group, when the logical AND- between their xx values is nonzero.- === =======================================================-- Examples:-- When 2 interfaces use group 201, their transmitters will never be- keyed at the same time.-- When 2 interfaces use group 101, the transmitters will only key- when both channels are clear at the same time. When group 301,- the transmitters will not be keyed at the same time.-- Don't forget to convert the octal numbers into decimal before- you set the parameter.-- Example: (to be written)--softdcd:- use a software dcd instead of the real one... Useful for a very- slow squelch.-- Example: sccparam /dev/scc0 soft on---4. Problems-===========--If you have tx-problems with your BayCom USCC card please check-the manufacturer of the 8530. SGS chips have a slightly-different timing. Try Zilog... A solution is to write to register 8-instead to the data port, but this won't work with the ESCC chips.-*SIGH!*--A very common problem is that the PTT locks until the maxkeyup timer-expires, although interrupts and clock source are correct. In most-cases compiling the driver with CONFIG_SCC_DELAY (set with-make config) solves the problems. For more hints read the (pseudo) FAQ-and the documentation coming with z8530drv-utils.--I got reports that the driver has problems on some 386-based systems.-(i.e. Amstrad) Those systems have a bogus AT bus timing which will-lead to delayed answers on interrupts. You can recognize these-problems by looking at the output of Sccstat for the suspected-port. If it shows under- and overruns you own such a system.--Delayed processing of received data: This depends on--- the kernel version--- kernel profiling compiled or not--- a high interrupt load--- a high load of the machine --- running X, Xmorph, XV and Povray,- while compiling the kernel... hmm ... even with 32 MB RAM ... ;-)- Or running a named for the whole .ampr.org domain on an 8 MB- box...--- using information from rxecho or kissbridge.--Kernel panics: please read /linux/README and find out if it-really occurred within the scc driver.--If you cannot solve a problem, send me--- a description of the problem,-- information on your hardware (computer system, scc board, modem)-- your kernel version-- the output of cat /proc/net/z8530--4. Thor RLC100-==============--Mysteriously this board seems not to work with the driver. Anyone-got it up-and-running?---Many thanks to Linus Torvalds and Alan Cox for including the driver-in the Linux standard distribution and their support.--::-- Joerg Reuter ampr-net: dl1bke@db0pra.ampr.org- AX-25 : DL1BKE @ DB0ABH.#BAY.DEU.EU- Internet: jreuter@yaina.de- WWW : http://yaina.de/jreuterdiff --git a/Documentation/networking/device_drivers/index.rst b/Documentation/networking/device_drivers/index.rstindex 1df51c9f7827..1f54f01d24be 100644--- a/Documentation/networking/device_drivers/index.rst+++ b/Documentation/networking/device_drivers/index.rst@@ -13,6 +13,5 @@ Hardware Device Drivers cellular/index ethernet/index fddi/index- hamradio/index wifi/index wwan/indexdiff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rstindex 2e946924ad3f..44a422ad3b05 100644--- a/Documentation/networking/index.rst+++ b/Documentation/networking/index.rst@@ -40,11 +40,9 @@ Refer to :ref:`netdev-FAQ` for a guide on netdev development process specifics. tls-handshake nfc 6lowpan- 6pack arcnet-hardware arcnet atm- ax25 bonding cdc_mbim dctcpdiff --git a/Documentation/staging/magic-number.rst b/Documentation/staging/magic-number.rstindex 79afddf0e692..670d3189a976 100644--- a/Documentation/staging/magic-number.rst+++ b/Documentation/staging/magic-number.rst@@ -72,11 +72,8 @@ PG_MAGIC 'P' pg_{read,write}_hdr ``include/uapi/l APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c`` FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h`` SLIP_MAGIC 0x5302 slip ``drivers/net/slip/slip.h``-BAYCOM_MAGIC 19730510 baycom_state ``drivers/net/hamradio/baycom_epp.c``-HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h`` KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h`` CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``-YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c`` CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c`` QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c`` QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``diff --git a/Documentation/translations/it_IT/staging/magic-number.rst b/Documentation/translations/it_IT/staging/magic-number.rstindex cd8f23571835..43dd6398300b 100644--- a/Documentation/translations/it_IT/staging/magic-number.rst+++ b/Documentation/translations/it_IT/staging/magic-number.rst@@ -78,11 +78,8 @@ PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/ APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c`` FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h`` SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``-BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``-HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h`` KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h`` CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``-YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c`` CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c`` QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c`` QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``diff --git a/Documentation/translations/sp_SP/process/magic-number.rst b/Documentation/translations/sp_SP/process/magic-number.rstindex beb4b4c1de11..f5b4c3f2849f 100644--- a/Documentation/translations/sp_SP/process/magic-number.rst+++ b/Documentation/translations/sp_SP/process/magic-number.rst@@ -77,11 +77,8 @@ PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/ APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c`` FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h`` SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``-BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``-HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h`` KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h`` CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``-YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c`` CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c`` QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c`` QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``diff --git a/Documentation/translations/zh_CN/process/magic-number.rst b/Documentation/translations/zh_CN/process/magic-number.rstindex 4ebc84cc0c54..05ee75cf4346 100644--- a/Documentation/translations/zh_CN/process/magic-number.rst+++ b/Documentation/translations/zh_CN/process/magic-number.rst@@ -70,11 +70,8 @@ PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/ APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c`` FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h`` SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``-BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``-HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h`` KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h`` CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``-YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c`` CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c`` QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c`` QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``diff --git a/Documentation/translations/zh_TW/process/magic-number.rst b/Documentation/translations/zh_TW/process/magic-number.rstindex 5582df6d7ca7..bc7eb025dd1e 100644--- a/Documentation/translations/zh_TW/process/magic-number.rst+++ b/Documentation/translations/zh_TW/process/magic-number.rst@@ -64,11 +64,8 @@ PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/ APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c`` FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h`` SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``-BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``-HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h`` KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h`` CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``-YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c`` CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c`` QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c`` QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfigdeleted file mode 100644index 36a9aade9f33..000000000000--- a/drivers/net/hamradio/Kconfig+++ /dev/null@@ -1,162 +0,0 @@-# SPDX-License-Identifier: GPL-2.0-only-config MKISS- tristate "Serial port KISS driver"- depends on AX25 && TTY- select CRC16- help- KISS is a protocol used for the exchange of data between a computer- and a Terminal Node Controller (a small embedded system commonly- used for networking over AX.25 amateur radio connections; it- connects the computer's serial port with the radio's microphone- input and speaker output).-- Although KISS is less advanced than the 6pack protocol, it has- the advantage that it is already supported by most modern TNCs- without the need for a firmware upgrade.-- To compile this driver as a module, choose M here: the module- will be called mkiss.--config 6PACK- tristate "Serial port 6PACK driver"- depends on AX25 && TTY- help- 6pack is a transmission protocol for the data exchange between your- PC and your TNC (the Terminal Node Controller acts as a kind of- modem connecting your computer's serial port to your radio's- microphone input and speaker output). This protocol can be used as- an alternative to KISS for networking over AX.25 amateur radio- connections, but it has some extended functionality.-- Note that this driver is still experimental and might cause- problems. For details about the features and the usage of the- driver, read <file:Documentation/networking/6pack.rst>.-- To compile this driver as a module, choose M here: the module- will be called 6pack.--config BPQETHER- tristate "BPQ Ethernet driver"- depends on AX25- help- AX.25 is the protocol used for computer communication over amateur- radio. If you say Y here, you will be able to send and receive AX.25- traffic over Ethernet (also called "BPQ AX.25"), which could be- useful if some other computer on your local network has a direct- amateur radio connection.--config SCC- tristate "Z8530 SCC driver"- depends on ISA && AX25- help- These cards are used to connect your Linux box to an amateur radio- in order to communicate with other computers. If you want to use- this, read- <file:Documentation/networking/device_drivers/hamradio/z8530drv.rst>- and the AX25-HOWTO, available from- <http://www.tldp.org/docs.html#howto>. Also make sure to say Y- to "Amateur Radio AX.25 Level 2" support.-- To compile this driver as a module, choose M here: the module- will be called scc.--config SCC_DELAY- bool "additional delay for PA0HZP OptoSCC compatible boards"- depends on SCC- help- Say Y here if you experience problems with the SCC driver not- working properly; please read- <file:Documentation/networking/device_drivers/hamradio/z8530drv.rst>- for details.-- If unsure, say N.--config SCC_TRXECHO- bool "support for TRX that feedback the tx signal to rx"- depends on SCC- help- Some transmitters feed the transmitted signal back to the receive- line. Say Y here to foil this by explicitly disabling the receiver- during data transmission.-- If in doubt, say Y.--config BAYCOM_SER_FDX- tristate "BAYCOM ser12 fullduplex driver for AX.25"- depends on AX25 && HAS_IOPORT- select CRC_CCITT- help- This is one of two drivers for Baycom style simple amateur radio- modems that connect to a serial interface. The driver supports the- ser12 design in full-duplex mode. In addition, it allows the- baudrate to be set between 300 and 4800 baud (however not all modems- support all baudrates). This is the preferred driver. The next- driver, "BAYCOM ser12 half-duplex driver for AX.25" is the old- driver and still provided in case this driver does not work with- your serial interface chip. To configure the driver, use the sethdlc- utility available in the standard ax25 utilities package.- For more information on the modems, see- <file:Documentation/networking/device_drivers/hamradio/baycom.rst>.-- To compile this driver as a module, choose M here: the module- will be called baycom_ser_fdx. This is recommended.--config BAYCOM_SER_HDX- tristate "BAYCOM ser12 halfduplex driver for AX.25"- depends on AX25 && HAS_IOPORT- select CRC_CCITT- help- This is one of two drivers for Baycom style simple amateur radio- modems that connect to a serial interface. The driver supports the- ser12 design in half-duplex mode. This is the old driver. It is- still provided in case your serial interface chip does not work with- the full-duplex driver. This driver is deprecated. To configure- the driver, use the sethdlc utility available in the standard ax25- utilities package. For more information on the modems, see- <file:Documentation/networking/device_drivers/hamradio/baycom.rst>.-- To compile this driver as a module, choose M here: the module- will be called baycom_ser_hdx. This is recommended.--config BAYCOM_PAR- tristate "BAYCOM picpar and par96 driver for AX.25"- depends on PARPORT && AX25- select CRC_CCITT- help- This is a driver for Baycom style simple amateur radio modems that- connect to a parallel interface. The driver supports the picpar and- par96 designs. To configure the driver, use the sethdlc utility- available in the standard ax25 utilities package.- For more information on the modems, see- <file:Documentation/networking/device_drivers/hamradio/baycom.rst>.-- To compile this driver as a module, choose M here: the module- will be called baycom_par. This is recommended.--config BAYCOM_EPP- tristate "BAYCOM epp driver for AX.25"- depends on PARPORT && AX25 && !64BIT- select CRC_CCITT- help- This is a driver for Baycom style simple amateur radio modems that- connect to a parallel interface. The driver supports the EPP- designs. To configure the driver, use the sethdlc utility available- in the standard ax25 utilities package.- For more information on the modems, see- <file:Documentation/networking/device_drivers/hamradio/baycom.rst>.-- To compile this driver as a module, choose M here: the module- will be called baycom_epp. This is recommended.--config YAM- tristate "YAM driver for AX.25"- depends on AX25 && HAS_IOPORT- help- The YAM is a modem for packet radio which connects to the serial- port and includes some of the functions of a Terminal Node- Controller. If you have one of those, say Y here.-- To compile this driver as a module, choose M here: the module- will be called yam.-- diff --git a/net/Kconfig b/net/Kconfigindex 5c588dbcbdbd..bdea8aef7983 100644--- a/net/Kconfig+++ b/net/Kconfig@@ -414,7 +414,6 @@ endmenu # Network testing endmenu # Networking options -source "net/ax25/Kconfig" source "net/can/Kconfig" source "net/bluetooth/Kconfig" source "net/rxrpc/Kconfig"diff --git a/net/ax25/Kconfig b/net/ax25/Kconfigdeleted file mode 100644index 310169ce1488..000000000000--- a/net/ax25/Kconfig+++ /dev/null@@ -1,108 +0,0 @@-# SPDX-License-Identifier: GPL-2.0-only-#-# Amateur Radio protocols and AX.25 device configuration-#--menuconfig HAMRADIO- depends on NET- bool "Amateur Radio support"- help- If you want to connect your Linux box to an amateur radio, answer Y- here. You want to read <https://www.tapr.org/>- and more specifically about AX.25 on Linux- <https://linux-ax25.in-berlin.de>.-- Note that the answer to this question won't directly affect the- kernel: saying N will just cause the configurator to skip all- the questions about amateur radio.--comment "Packet Radio protocols"- depends on HAMRADIO--config AX25- tristate "Amateur Radio AX.25 Level 2 protocol"- depends on HAMRADIO- help- This is the protocol used for computer communication over amateur- radio. It is either used by itself for point-to-point links, or to- carry other protocols such as tcp/ip. To use it, you need a device- that connects your Linux box to your amateur radio. You can either- use a low speed TNC (a Terminal Node Controller acts as a kind of- modem connecting your computer's serial port to your radio's- microphone input and speaker output) supporting the KISS protocol or- one of the various SCC cards that are supported by the generic Z8530- or the DMA SCC driver. Another option are the Baycom modem serial- and parallel port hacks or the sound card modem (supported by their- own drivers). If you say Y here, you also have to say Y to one of- those drivers.-- Information about where to get supporting software for Linux amateur- radio as well as information about how to configure an AX.25 port is- contained in the AX25-HOWTO, available from- <https://www.tldp.org/docs.html#howto>. You might also want to- check out the file <file:Documentation/networking/ax25.rst> in the- kernel source. More information about digital amateur radio in- general is on the WWW at- <https://www.tapr.org/>.-- To compile this driver as a module, choose M here: the- module will be called ax25.--config AX25_DAMA_SLAVE- bool "AX.25 DAMA Slave support"- default y- depends on AX25- help- DAMA is a mechanism to prevent collisions when doing AX.25- networking. A DAMA server (called "master") accepts incoming traffic- from clients (called "slaves") and redistributes it to other slaves.- If you say Y here, your Linux box will act as a DAMA slave; this is- transparent in that you don't have to do any special DAMA- configuration. Linux cannot yet act as a DAMA server. This option- only compiles DAMA slave support into the kernel. It still needs to- be enabled at runtime. For more about DAMA see- <https://linux-ax25.in-berlin.de>. If unsure, say Y.--config NETROM- tristate "Amateur Radio NET/ROM protocol"- depends on AX25- help- NET/ROM is a network layer protocol on top of AX.25 useful for- routing.-- A comprehensive listing of all the software for Linux amateur radio- users as well as information about how to configure an AX.25 port is- contained in the Linux Ham Wiki, available from- <https://linux-ax25.in-berlin.de>. You also might want to check out- the file <file:Documentation/networking/ax25.rst>. More information- about digital amateur radio in general is on the WWW at- <https://www.tapr.org/>.-- To compile this driver as a module, choose M here: the- module will be called netrom.--config ROSE- tristate "Amateur Radio X.25 PLP (Rose)"- depends on AX25- help- The Packet Layer Protocol (PLP) is a way to route packets over X.25- connections in general and amateur radio AX.25 connections in- particular, essentially an alternative to NET/ROM.-- A comprehensive listing of all the software for Linux amateur radio- users as well as information about how to configure an AX.25 port is- contained in the Linux Ham Wiki, available from- <https://linux-ax25.in-berlin.de>. You also might want to check out- the file <file:Documentation/networking/ax25.rst>. More information- about digital amateur radio in general is on the WWW at- <https://www.tapr.org/>.-- To compile this driver as a module, choose M here: the- module will be called rose.--menu "AX.25 network device drivers"- depends on HAMRADIO && AX25--source "drivers/net/hamradio/Kconfig"--endmenudiff --git a/drivers/net/Makefile b/drivers/net/Makefileindex 3b2d28127634..b87a741fc952 100644--- a/drivers/net/Makefile+++ b/drivers/net/Makefile@@ -54,7 +54,6 @@ obj-y += dsa/ endif obj-$(CONFIG_ETHERNET) += ethernet/ obj-$(CONFIG_FDDI) += fddi/-obj-$(CONFIG_HAMRADIO) += hamradio/ obj-$(CONFIG_QCOM_IPA) += ipa/ obj-$(CONFIG_PLIP) += plip/ obj-$(CONFIG_PPP) += ppp/diff --git a/drivers/net/hamradio/Makefile b/drivers/net/hamradio/Makefiledeleted file mode 100644index 25fc400369ba..000000000000--- a/drivers/net/hamradio/Makefile+++ /dev/null@@ -1,22 +0,0 @@-# SPDX-License-Identifier: GPL-2.0-#-# Makefile for the Linux AX.25 and HFMODEM device drivers.-#-#-# 19971130 Moved the amateur radio related network drivers from -# drivers/net/ to drivers/hamradio for easier maintenance.-# Joerg Reuter DL1BKE <jreuter@yaina.de>-#-# 20000806 Rewritten to use lists instead of if-statements.-# Christoph Hellwig <hch@infradead.org>-#--obj-$(CONFIG_SCC) += scc.o-obj-$(CONFIG_MKISS) += mkiss.o-obj-$(CONFIG_6PACK) += 6pack.o-obj-$(CONFIG_YAM) += yam.o-obj-$(CONFIG_BPQETHER) += bpqether.o-obj-$(CONFIG_BAYCOM_SER_FDX) += baycom_ser_fdx.o hdlcdrv.o-obj-$(CONFIG_BAYCOM_SER_HDX) += baycom_ser_hdx.o hdlcdrv.o-obj-$(CONFIG_BAYCOM_PAR) += baycom_par.o hdlcdrv.o-obj-$(CONFIG_BAYCOM_EPP) += baycom_epp.o hdlcdrv.odiff --git a/net/Makefile b/net/Makefileindex 98e182829eff..d2175fce0406 100644--- a/net/Makefile+++ b/net/Makefile@@ -28,9 +28,6 @@ obj-y += dsa/ obj-$(CONFIG_ATALK) += appletalk/ obj-$(CONFIG_X25) += x25/ obj-$(CONFIG_LAPB) += lapb/-obj-$(CONFIG_NETROM) += netrom/-obj-$(CONFIG_ROSE) += rose/-obj-$(CONFIG_AX25) += ax25/ obj-$(CONFIG_CAN) += can/ obj-$(CONFIG_BT) += bluetooth/ obj-$(CONFIG_SUNRPC) += sunrpc/diff --git a/net/ax25/Makefile b/net/ax25/Makefiledeleted file mode 100644index 2e53affc8568..000000000000--- a/net/ax25/Makefile+++ /dev/null@@ -1,12 +0,0 @@-# SPDX-License-Identifier: GPL-2.0-#-# Makefile for the Linux AX.25 layer.-#--obj-$(CONFIG_AX25) += ax25.o--ax25-y := ax25_addr.o ax25_dev.o ax25_iface.o ax25_in.o ax25_ip.o ax25_out.o \- ax25_route.o ax25_std_in.o ax25_std_subr.o ax25_std_timer.o \- ax25_subr.o ax25_timer.o ax25_uid.o af_ax25.o-ax25-$(CONFIG_AX25_DAMA_SLAVE) += ax25_ds_in.o ax25_ds_subr.o ax25_ds_timer.o-ax25-$(CONFIG_SYSCTL) += sysctl_net_ax25.odiff --git a/net/netrom/Makefile b/net/netrom/Makefiledeleted file mode 100644index 603e36c9af2e..000000000000--- a/net/netrom/Makefile+++ /dev/null@@ -1,10 +0,0 @@-# SPDX-License-Identifier: GPL-2.0-only-#-# Makefile for the Linux NET/ROM layer.-#--obj-$(CONFIG_NETROM) += netrom.o--netrom-y := af_netrom.o nr_dev.o nr_in.o nr_loopback.o \- nr_out.o nr_route.o nr_subr.o nr_timer.o-netrom-$(CONFIG_SYSCTL) += sysctl_net_netrom.odiff --git a/net/rose/Makefile b/net/rose/Makefiledeleted file mode 100644index 3e6638f5ba57..000000000000--- a/net/rose/Makefile+++ /dev/null@@ -1,10 +0,0 @@-# SPDX-License-Identifier: GPL-2.0-only-#-# Makefile for the Linux Rose (X.25 PLP) layer.-#--obj-$(CONFIG_ROSE) += rose.o--rose-y := af_rose.o rose_dev.o rose_in.o rose_link.o rose_loopback.o \- rose_out.o rose_route.o rose_subr.o rose_timer.o-rose-$(CONFIG_SYSCTL) += sysctl_net_rose.odiff --git a/drivers/net/hamradio/z8530.h b/drivers/net/hamradio/z8530.hdeleted file mode 100644index 1655901d713b..000000000000--- a/drivers/net/hamradio/z8530.h+++ /dev/null@@ -1,246 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 */--/* 8530 Serial Communications Controller Register definitions */-#define FLAG 0x7e--/* Write Register 0 */-#define R0 0 /* Register selects */-#define R1 1-#define R2 2-#define R3 3-#define R4 4-#define R5 5-#define R6 6-#define R7 7-#define R8 8-#define R9 9-#define R10 10-#define R11 11-#define R12 12-#define R13 13-#define R14 14-#define R15 15--#define NULLCODE 0 /* Null Code */-#define POINT_HIGH 0x8 /* Select upper half of registers */-#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */-#define SEND_ABORT 0x18 /* HDLC Abort */-#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */-#define RES_Tx_P 0x28 /* Reset TxINT Pending */-#define ERR_RES 0x30 /* Error Reset */-#define RES_H_IUS 0x38 /* Reset highest IUS */--#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */-#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */-#define RES_EOM_L 0xC0 /* Reset EOM latch */--/* Write Register 1 */--#define EXT_INT_ENAB 0x1 /* Ext Int Enable */-#define TxINT_ENAB 0x2 /* Tx Int Enable */-#define PAR_SPEC 0x4 /* Parity is special condition */--#define RxINT_DISAB 0 /* Rx Int Disable */-#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */-#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */-#define INT_ERR_Rx 0x18 /* Int on error only */--#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */-#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */-#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */--/* Write Register #2 (Interrupt Vector) */--/* Write Register 3 */--#define RxENABLE 0x1 /* Rx Enable */-#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */-#define ADD_SM 0x4 /* Address Search Mode (SDLC) */-#define RxCRC_ENAB 0x8 /* Rx CRC Enable */-#define ENT_HM 0x10 /* Enter Hunt Mode */-#define AUTO_ENAB 0x20 /* Auto Enables */-#define Rx5 0x0 /* Rx 5 Bits/Character */-#define Rx7 0x40 /* Rx 7 Bits/Character */-#define Rx6 0x80 /* Rx 6 Bits/Character */-#define Rx8 0xc0 /* Rx 8 Bits/Character */--/* Write Register 4 */--#define PAR_ENA 0x1 /* Parity Enable */-#define PAR_EVEN 0x2 /* Parity Even/Odd* */--#define SYNC_ENAB 0 /* Sync Modes Enable */-#define SB1 0x4 /* 1 stop bit/char */-#define SB15 0x8 /* 1.5 stop bits/char */-#define SB2 0xc /* 2 stop bits/char */--#define MONSYNC 0 /* 8 Bit Sync character */-#define BISYNC 0x10 /* 16 bit sync character */-#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */-#define EXTSYNC 0x30 /* External Sync Mode */--#define X1CLK 0x0 /* x1 clock mode */-#define X16CLK 0x40 /* x16 clock mode */-#define X32CLK 0x80 /* x32 clock mode */-#define X64CLK 0xC0 /* x64 clock mode */--/* Write Register 5 */--#define TxCRC_ENAB 0x1 /* Tx CRC Enable */-#define RTS 0x2 /* RTS */-#define SDLC_CRC 0x4 /* SDLC/CRC-16 */-#define TxENAB 0x8 /* Tx Enable */-#define SND_BRK 0x10 /* Send Break */-#define Tx5 0x0 /* Tx 5 bits (or less)/character */-#define Tx7 0x20 /* Tx 7 bits/character */-#define Tx6 0x40 /* Tx 6 bits/character */-#define Tx8 0x60 /* Tx 8 bits/character */-#define DTR 0x80 /* DTR */--/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */--/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */--/* Write Register 8 (transmit buffer) */--/* Write Register 9 (Master interrupt control) */-#define VIS 1 /* Vector Includes Status */-#define NV 2 /* No Vector */-#define DLC 4 /* Disable Lower Chain */-#define MIE 8 /* Master Interrupt Enable */-#define STATHI 0x10 /* Status high */-#define NORESET 0 /* No reset on write to R9 */-#define CHRB 0x40 /* Reset channel B */-#define CHRA 0x80 /* Reset channel A */-#define FHWRES 0xc0 /* Force hardware reset */--/* Write Register 10 (misc control bits) */-#define BIT6 1 /* 6 bit/8bit sync */-#define LOOPMODE 2 /* SDLC Loop mode */-#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */-#define MARKIDLE 8 /* Mark/flag on idle */-#define GAOP 0x10 /* Go active on poll */-#define NRZ 0 /* NRZ mode */-#define NRZI 0x20 /* NRZI mode */-#define FM1 0x40 /* FM1 (transition = 1) */-#define FM0 0x60 /* FM0 (transition = 0) */-#define CRCPS 0x80 /* CRC Preset I/O */--/* Write Register 11 (Clock Mode control) */-#define TRxCXT 0 /* TRxC = Xtal output */-#define TRxCTC 1 /* TRxC = Transmit clock */-#define TRxCBR 2 /* TRxC = BR Generator Output */-#define TRxCDP 3 /* TRxC = DPLL output */-#define TRxCOI 4 /* TRxC O/I */-#define TCRTxCP 0 /* Transmit clock = RTxC pin */-#define TCTRxCP 8 /* Transmit clock = TRxC pin */-#define TCBR 0x10 /* Transmit clock = BR Generator output */-#define TCDPLL 0x18 /* Transmit clock = DPLL output */-#define RCRTxCP 0 /* Receive clock = RTxC pin */-#define RCTRxCP 0x20 /* Receive clock = TRxC pin */-#define RCBR 0x40 /* Receive clock = BR Generator output */-#define RCDPLL 0x60 /* Receive clock = DPLL output */-#define RTxCX 0x80 /* RTxC Xtal/No Xtal */--/* Write Register 12 (lower byte of baud rate generator time constant) */--/* Write Register 13 (upper byte of baud rate generator time constant) */--/* Write Register 14 (Misc control bits) */-#define BRENABL 1 /* Baud rate generator enable */-#define BRSRC 2 /* Baud rate generator source */-#define DTRREQ 4 /* DTR/Request function */-#define AUTOECHO 8 /* Auto Echo */-#define LOOPBAK 0x10 /* Local loopback */-#define SEARCH 0x20 /* Enter search mode */-#define RMC 0x40 /* Reset missing clock */-#define DISDPLL 0x60 /* Disable DPLL */-#define SSBR 0x80 /* Set DPLL source = BR generator */-#define SSRTxC 0xa0 /* Set DPLL source = RTxC */-#define SFMM 0xc0 /* Set FM mode */-#define SNRZI 0xe0 /* Set NRZI mode */--/* Write Register 15 (external/status interrupt control) */-#define ZCIE 2 /* Zero count IE */-#define DCDIE 8 /* DCD IE */-#define SYNCIE 0x10 /* Sync/hunt IE */-#define CTSIE 0x20 /* CTS IE */-#define TxUIE 0x40 /* Tx Underrun/EOM IE */-#define BRKIE 0x80 /* Break/Abort IE */---/* Read Register 0 */-#define Rx_CH_AV 0x1 /* Rx Character Available */-#define ZCOUNT 0x2 /* Zero count */-#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */-#define DCD 0x8 /* DCD */-#define SYNC_HUNT 0x10 /* Sync/hunt */-#define CTS 0x20 /* CTS */-#define TxEOM 0x40 /* Tx underrun */-#define BRK_ABRT 0x80 /* Break/Abort */--/* Read Register 1 */-#define ALL_SNT 0x1 /* All sent */-/* Residue Data for 8 Rx bits/char programmed */-#define RES3 0x8 /* 0/3 */-#define RES4 0x4 /* 0/4 */-#define RES5 0xc /* 0/5 */-#define RES6 0x2 /* 0/6 */-#define RES7 0xa /* 0/7 */-#define RES8 0x6 /* 0/8 */-#define RES18 0xe /* 1/8 */-#define RES28 0x0 /* 2/8 */-/* Special Rx Condition Interrupts */-#define PAR_ERR 0x10 /* Parity error */-#define Rx_OVR 0x20 /* Rx Overrun Error */-#define CRC_ERR 0x40 /* CRC/Framing Error */-#define END_FR 0x80 /* End of Frame (SDLC) */--/* Read Register 2 (channel b only) - Interrupt vector */--/* Read Register 3 (interrupt pending register) ch a only */-#define CHBEXT 0x1 /* Channel B Ext/Stat IP */-#define CHBTxIP 0x2 /* Channel B Tx IP */-#define CHBRxIP 0x4 /* Channel B Rx IP */-#define CHAEXT 0x8 /* Channel A Ext/Stat IP */-#define CHATxIP 0x10 /* Channel A Tx IP */-#define CHARxIP 0x20 /* Channel A Rx IP */--/* Read Register 8 (receive data register) */--/* Read Register 10 (misc status bits) */-#define ONLOOP 2 /* On loop */-#define LOOPSEND 0x10 /* Loop sending */-#define CLK2MIS 0x40 /* Two clocks missing */-#define CLK1MIS 0x80 /* One clock missing */--/* Read Register 12 (lower byte of baud rate generator constant) */--/* Read Register 13 (upper byte of baud rate generator constant) */--/* Read Register 15 (value of WR 15) */--/* Z85C30/Z85230 Enhanced SCC register definitions */--/* Write Register 7' (SDLC/HDLC Programmable Enhancements) */-#define AUTOTXF 0x01 /* Auto Tx Flag */-#define AUTOEOM 0x02 /* Auto EOM Latch Reset */-#define AUTORTS 0x04 /* Auto RTS */-#define TXDNRZI 0x08 /* TxD Pulled High in SDLC NRZI mode */-#define RXFIFOH 0x08 /* Z85230: Int on RX FIFO half full */-#define FASTDTR 0x10 /* Fast DTR/REQ Mode */-#define CRCCBCR 0x20 /* CRC Check Bytes Completely Received */-#define TXFIFOE 0x20 /* Z85230: Int on TX FIFO completely empty */-#define EXTRDEN 0x40 /* Extended Read Enabled */--/* Write Register 15 (external/status interrupt control) */-#define SHDLCE 1 /* SDLC/HDLC Enhancements Enable */-#define FIFOE 4 /* FIFO Enable */--/* Read Register 6 (frame status FIFO) */-#define BCLSB 0xff /* LSB of 14 bits count */--/* Read Register 7 (frame status FIFO) */-#define BCMSB 0x3f /* MSB of 14 bits count */-#define FDA 0x40 /* FIFO Data Available Status */-#define FOS 0x80 /* FIFO Overflow Status */diff --git a/include/linux/hdlcdrv.h b/include/linux/hdlcdrv.hdeleted file mode 100644index 5d70c3f98f5b..000000000000--- a/include/linux/hdlcdrv.h+++ /dev/null@@ -1,276 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 */-/*- * hdlcdrv.h -- HDLC packet radio network driver.- * The Linux soundcard driver for 1200 baud and 9600 baud packet radio- * (C) 1996-1998 by Thomas Sailer, HB9JNX/AE4WA- */-#ifndef _HDLCDRV_H-#define _HDLCDRV_H---#include <linux/netdevice.h>-#include <linux/if.h>-#include <linux/spinlock.h>-#include <uapi/linux/hdlcdrv.h>--#define HDLCDRV_MAGIC 0x5ac6e778-#define HDLCDRV_HDLCBUFFER 32 /* should be a power of 2 for speed reasons */-#define HDLCDRV_BITBUFFER 256 /* should be a power of 2 for speed reasons */-#undef HDLCDRV_LOOPBACK /* define for HDLC debugging purposes */-#define HDLCDRV_DEBUG--/* maximum packet length, excluding CRC */-#define HDLCDRV_MAXFLEN 400 ---struct hdlcdrv_hdlcbuffer {- spinlock_t lock;- unsigned rd, wr;- unsigned short buf[HDLCDRV_HDLCBUFFER];-};--#ifdef HDLCDRV_DEBUG-struct hdlcdrv_bitbuffer {- unsigned int rd;- unsigned int wr;- unsigned int shreg;- unsigned char buffer[HDLCDRV_BITBUFFER];-};--static inline void hdlcdrv_add_bitbuffer(struct hdlcdrv_bitbuffer *buf, - unsigned int bit)-{- unsigned char new;-- new = buf->shreg & 1;- buf->shreg >>= 1;- buf->shreg |= (!!bit) << 7;- if (new) {- buf->buffer[buf->wr] = buf->shreg;- buf->wr = (buf->wr+1) % sizeof(buf->buffer);- buf->shreg = 0x80;- }-}--static inline void hdlcdrv_add_bitbuffer_word(struct hdlcdrv_bitbuffer *buf, - unsigned int bits)-{- buf->buffer[buf->wr] = bits & 0xff;- buf->wr = (buf->wr+1) % sizeof(buf->buffer);- buf->buffer[buf->wr] = (bits >> 8) & 0xff;- buf->wr = (buf->wr+1) % sizeof(buf->buffer);--}-#endif /* HDLCDRV_DEBUG */--/* -------------------------------------------------------------------- */-/*- * Information that need to be kept for each driver. - */--struct hdlcdrv_ops {- /*- * first some informations needed by the hdlcdrv routines- */- const char *drvname;- const char *drvinfo;- /*- * the routines called by the hdlcdrv routines- */- int (*open)(struct net_device *);- int (*close)(struct net_device *);- int (*ioctl)(struct net_device *, void __user *,- struct hdlcdrv_ioctl *, int);-};--struct hdlcdrv_state {- int magic;- int opened;-- const struct hdlcdrv_ops *ops;-- struct {- int bitrate;- } par;-- struct hdlcdrv_pttoutput {- int dma2;- int seriobase;- int pariobase;- int midiiobase;- unsigned int flags;- } ptt_out;-- struct hdlcdrv_channel_params ch_params;-- struct hdlcdrv_hdlcrx {- struct hdlcdrv_hdlcbuffer hbuf;- unsigned long in_hdlc_rx;- /* 0 = sync hunt, != 0 receiving */- int rx_state; - unsigned int bitstream;- unsigned int bitbuf;- int numbits;- unsigned char dcd;- - int len;- unsigned char *bp;- unsigned char buffer[HDLCDRV_MAXFLEN+2];- } hdlcrx;-- struct hdlcdrv_hdlctx {- struct hdlcdrv_hdlcbuffer hbuf;- unsigned long in_hdlc_tx;- /*- * 0 = send flags- * 1 = send txtail (flags)- * 2 = send packet- */- int tx_state; - int numflags;- unsigned int bitstream;- unsigned char ptt;- int calibrate;- int slotcnt;-- unsigned int bitbuf;- int numbits;- - int len;- unsigned char *bp;- unsigned char buffer[HDLCDRV_MAXFLEN+2];- } hdlctx;--#ifdef HDLCDRV_DEBUG- struct hdlcdrv_bitbuffer bitbuf_channel;- struct hdlcdrv_bitbuffer bitbuf_hdlc;-#endif /* HDLCDRV_DEBUG */-- int ptt_keyed;-- /* queued skb for transmission */- struct sk_buff *skb;-};---/* -------------------------------------------------------------------- */--static inline int hdlcdrv_hbuf_full(struct hdlcdrv_hdlcbuffer *hb) -{- unsigned long flags;- int ret;- - spin_lock_irqsave(&hb->lock, flags);- ret = !((HDLCDRV_HDLCBUFFER - 1 + hb->rd - hb->wr) % HDLCDRV_HDLCBUFFER);- spin_unlock_irqrestore(&hb->lock, flags);- return ret;-}--/* -------------------------------------------------------------------- */--static inline int hdlcdrv_hbuf_empty(struct hdlcdrv_hdlcbuffer *hb)-{- unsigned long flags;- int ret;- - spin_lock_irqsave(&hb->lock, flags);- ret = (hb->rd == hb->wr);- spin_unlock_irqrestore(&hb->lock, flags);- return ret;-}--/* -------------------------------------------------------------------- */--static inline unsigned short hdlcdrv_hbuf_get(struct hdlcdrv_hdlcbuffer *hb)-{- unsigned long flags;- unsigned short val;- unsigned newr;-- spin_lock_irqsave(&hb->lock, flags);- if (hb->rd == hb->wr)- val = 0;- else {- newr = (hb->rd+1) % HDLCDRV_HDLCBUFFER;- val = hb->buf[hb->rd];- hb->rd = newr;- }- spin_unlock_irqrestore(&hb->lock, flags);- return val;-}--/* -------------------------------------------------------------------- */--static inline void hdlcdrv_hbuf_put(struct hdlcdrv_hdlcbuffer *hb, - unsigned short val)-{- unsigned newp;- unsigned long flags;- - spin_lock_irqsave(&hb->lock, flags);- newp = (hb->wr+1) % HDLCDRV_HDLCBUFFER;- if (newp != hb->rd) { - hb->buf[hb->wr] = val & 0xffff;- hb->wr = newp;- }- spin_unlock_irqrestore(&hb->lock, flags);-}--/* -------------------------------------------------------------------- */--static inline void hdlcdrv_putbits(struct hdlcdrv_state *s, unsigned int bits)-{- hdlcdrv_hbuf_put(&s->hdlcrx.hbuf, bits);-}--static inline unsigned int hdlcdrv_getbits(struct hdlcdrv_state *s)-{- unsigned int ret;-- if (hdlcdrv_hbuf_empty(&s->hdlctx.hbuf)) {- if (s->hdlctx.calibrate > 0)- s->hdlctx.calibrate--;- else- s->hdlctx.ptt = 0;- ret = 0;- } else - ret = hdlcdrv_hbuf_get(&s->hdlctx.hbuf);-#ifdef HDLCDRV_LOOPBACK- hdlcdrv_hbuf_put(&s->hdlcrx.hbuf, ret);-#endif /* HDLCDRV_LOOPBACK */- return ret;-}--static inline void hdlcdrv_channelbit(struct hdlcdrv_state *s, unsigned int bit)-{-#ifdef HDLCDRV_DEBUG- hdlcdrv_add_bitbuffer(&s->bitbuf_channel, bit);-#endif /* HDLCDRV_DEBUG */-}--static inline void hdlcdrv_setdcd(struct hdlcdrv_state *s, int dcd)-{- s->hdlcrx.dcd = !!dcd;-}--static inline int hdlcdrv_ptt(struct hdlcdrv_state *s)-{- return s->hdlctx.ptt || (s->hdlctx.calibrate > 0);-}--/* -------------------------------------------------------------------- */--void hdlcdrv_receiver(struct net_device *, struct hdlcdrv_state *);-void hdlcdrv_transmitter(struct net_device *, struct hdlcdrv_state *);-void hdlcdrv_arbitrate(struct net_device *, struct hdlcdrv_state *);-struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,- unsigned int privsize, const char *ifname,- unsigned int baseaddr, unsigned int irq, - unsigned int dma);-void hdlcdrv_unregister(struct net_device *dev);--/* -------------------------------------------------------------------- */----#endif /* _HDLCDRV_H */diff --git a/include/linux/netdevice.h b/include/linux/netdevice.hindex 7969fcdd5ac4..e9e2ec8d4c19 100644--- a/include/linux/netdevice.h+++ b/include/linux/netdevice.h@@ -162,7 +162,7 @@ static inline bool dev_xmit_complete(int rc) #if defined(CONFIG_HYPERV_NET) # define LL_MAX_HEADER 128-#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25)+#elif defined(CONFIG_WLAN) # if defined(CONFIG_MAC80211_MESH) # define LL_MAX_HEADER 128 # else@@ -2316,9 +2316,6 @@ struct net_device { #if IS_ENABLED(CONFIG_ATALK) void *atalk_ptr; #endif-#if IS_ENABLED(CONFIG_AX25)- struct ax25_dev __rcu *ax25_ptr;-#endif #if IS_ENABLED(CONFIG_CFG80211) struct wireless_dev *ieee80211_ptr; #endifdiff --git a/include/linux/scc.h b/include/linux/scc.hdeleted file mode 100644index 745eabd17c10..000000000000--- a/include/linux/scc.h+++ /dev/null@@ -1,86 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 */-/* $Id: scc.h,v 1.29 1997/04/02 14:56:45 jreuter Exp jreuter $ */-#ifndef _SCC_H-#define _SCC_H--#include <uapi/linux/scc.h>---enum {TX_OFF, TX_ON}; /* command for scc_key_trx() */--/* Vector masks in RR2B */--#define VECTOR_MASK 0x06-#define TXINT 0x00-#define EXINT 0x02-#define RXINT 0x04-#define SPINT 0x06--#ifdef CONFIG_SCC_DELAY-#define Inb(port) inb_p(port)-#define Outb(port, val) outb_p(val, port)-#else-#define Inb(port) inb(port)-#define Outb(port, val) outb(val, port)-#endif--/* SCC channel control structure for KISS */--struct scc_kiss {- unsigned char txdelay; /* Transmit Delay 10 ms/cnt */- unsigned char persist; /* Persistence (0-255) as a % */- unsigned char slottime; /* Delay to wait on persistence hit */- unsigned char tailtime; /* Delay after last byte written */- unsigned char fulldup; /* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */- unsigned char waittime; /* Waittime before any transmit attempt */- unsigned int maxkeyup; /* Maximum time to transmit (seconds) */- unsigned int mintime; /* Minimal offtime after MAXKEYUP timeout (seconds) */- unsigned int idletime; /* Maximum idle time in ALWAYS KEYED mode (seconds) */- unsigned int maxdefer; /* Timer for CSMA channel busy limit */- unsigned char tx_inhibit; /* Transmit is not allowed when set */ - unsigned char group; /* Group ID for AX.25 TX interlocking */- unsigned char mode; /* 'normal' or 'hwctrl' mode (unused) */- unsigned char softdcd; /* Use DPLL instead of DCD pin for carrier detect */-};---/* SCC channel structure */--struct scc_channel {- int init; /* channel exists? */-- struct net_device *dev; /* link to device control structure */- struct net_device_stats dev_stat;/* device statistics */-- char brand; /* manufacturer of the board */- long clock; /* used clock */-- io_port ctrl; /* I/O address of CONTROL register */- io_port data; /* I/O address of DATA register */- io_port special; /* I/O address of special function port */- int irq; /* Number of Interrupt */-- char option;- char enhanced; /* Enhanced SCC support */-- unsigned char wreg[16]; /* Copy of last written value in WRx */- unsigned char status; /* Copy of R0 at last external interrupt */- unsigned char dcd; /* DCD status */-- struct scc_kiss kiss; /* control structure for KISS params */- struct scc_stat stat; /* statistical information */- struct scc_modem modem; /* modem information */-- struct sk_buff_head tx_queue; /* next tx buffer */- struct sk_buff *rx_buff; /* pointer to frame currently received */- struct sk_buff *tx_buff; /* pointer to frame currently transmitted */-- /* Timer */- struct timer_list tx_t; /* tx timer for this channel */- struct timer_list tx_wdog; /* tx watchdogs */- - /* Channel lock */- spinlock_t lock; /* Channel guard lock */-};--#endif /* defined(_SCC_H) */diff --git a/include/linux/yam.h b/include/linux/yam.hdeleted file mode 100644index a29b04fa1e66..000000000000--- a/include/linux/yam.h+++ /dev/null@@ -1,67 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0-or-later */-/*****************************************************************************/--/*- * yam.h -- YAM radio modem driver.- *- * Copyright (C) 1998 Frederic Rible F1OAT (frible@teaser.fr)- * Adapted from baycom.c driver written by Thomas Sailer (sailer@ife.ee.ethz.ch)- *- * Please note that the GPL allows you to use the driver, NOT the radio.- * In order to use the radio, you need a license from the communications- * authority of your country.- */--/*****************************************************************************/--#define SIOCYAMRESERVED (0)-#define SIOCYAMSCFG (1) /* Set configuration */-#define SIOCYAMGCFG (2) /* Get configuration */-#define SIOCYAMSMCS (3) /* Set mcs data */--#define YAM_IOBASE (1 << 0)-#define YAM_IRQ (1 << 1)-#define YAM_BITRATE (1 << 2) /* Bit rate of radio port ->57600 */-#define YAM_MODE (1 << 3) /* 0=simplex 1=duplex 2=duplex+tempo */-#define YAM_HOLDDLY (1 << 4) /* duplex tempo (sec) */-#define YAM_TXDELAY (1 << 5) /* Tx Delay (ms) */-#define YAM_TXTAIL (1 << 6) /* Tx Tail (ms) */-#define YAM_PERSIST (1 << 7) /* Persist (ms) */-#define YAM_SLOTTIME (1 << 8) /* Slottime (ms) */-#define YAM_BAUDRATE (1 << 9) /* Baud rate of rs232 port ->115200 */--#define YAM_MAXBITRATE 57600-#define YAM_MAXBAUDRATE 115200-#define YAM_MAXMODE 2-#define YAM_MAXHOLDDLY 99-#define YAM_MAXTXDELAY 999-#define YAM_MAXTXTAIL 999-#define YAM_MAXPERSIST 255-#define YAM_MAXSLOTTIME 999--#define YAM_FPGA_SIZE 5302--struct yamcfg {- unsigned int mask; /* Mask of commands */- unsigned int iobase; /* IO Base of COM port */- unsigned int irq; /* IRQ of COM port */- unsigned int bitrate; /* Bit rate of radio port */- unsigned int baudrate; /* Baud rate of the RS232 port */- unsigned int txdelay; /* TxDelay */- unsigned int txtail; /* TxTail */- unsigned int persist; /* Persistence */- unsigned int slottime; /* Slottime */- unsigned int mode; /* mode 0 (simp), 1(Dupl), 2(Dupl+delay) */- unsigned int holddly; /* PTT delay in FullDuplex 2 mode */-};--struct yamdrv_ioctl_cfg {- int cmd;- struct yamcfg cfg;-};--struct yamdrv_ioctl_mcs {- int cmd;- unsigned int bitrate;- unsigned char bits[YAM_FPGA_SIZE];-};diff --git a/include/net/ax25.h b/include/net/ax25.hindex 9fc6a6657266..6b2f518facdb 100644--- a/include/net/ax25.h+++ b/include/net/ax25.h@@ -1,480 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0 */-/*- * Declarations of AX.25 type objects.- *- * Alan Cox (GW4PTS) 10/11/93- */ #ifndef _AX25_H-#define _AX25_H +#define _AX25_H #include <linux/ax25.h>-#include <linux/spinlock.h>-#include <linux/timer.h>-#include <linux/list.h>-#include <linux/slab.h>-#include <linux/refcount.h>-#include <net/neighbour.h>-#include <net/sock.h>-#include <linux/seq_file.h> -#define AX25_T1CLAMPLO 1-#define AX25_T1CLAMPHI (30 * HZ)--#define AX25_BPQ_HEADER_LEN 16-#define AX25_KISS_HEADER_LEN 1--#define AX25_HEADER_LEN 17-#define AX25_ADDR_LEN 7-#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN)-#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN)--/* AX.25 Protocol IDs */-#define AX25_P_ROSE 0x01-#define AX25_P_VJCOMP 0x06 /* Compressed TCP/IP packet */- /* Van Jacobsen (RFC 1144) */-#define AX25_P_VJUNCOMP 0x07 /* Uncompressed TCP/IP packet */- /* Van Jacobsen (RFC 1144) */-#define AX25_P_SEGMENT 0x08 /* Segmentation fragment */-#define AX25_P_TEXNET 0xc3 /* TEXTNET datagram protocol */-#define AX25_P_LQ 0xc4 /* Link Quality Protocol */-#define AX25_P_ATALK 0xca /* Appletalk */-#define AX25_P_ATALK_ARP 0xcb /* Appletalk ARP */-#define AX25_P_IP 0xcc /* ARPA Internet Protocol */-#define AX25_P_ARP 0xcd /* ARPA Address Resolution */-#define AX25_P_FLEXNET 0xce /* FlexNet */-#define AX25_P_NETROM 0xcf /* NET/ROM */-#define AX25_P_TEXT 0xF0 /* No layer 3 protocol impl. */--/* AX.25 Segment control values */-#define AX25_SEG_REM 0x7F-#define AX25_SEG_FIRST 0x80--#define AX25_CBIT 0x80 /* Command/Response bit */-#define AX25_EBIT 0x01 /* HDLC Address Extension bit */-#define AX25_HBIT 0x80 /* Has been repeated bit */--#define AX25_SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */-#define AX25_ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */-#define AX25_DAMA_FLAG 0x20 /* Well, it is *NOT* unused! (dl1bke 951121 */--#define AX25_COND_ACK_PENDING 0x01-#define AX25_COND_REJECT 0x02-#define AX25_COND_PEER_RX_BUSY 0x04-#define AX25_COND_OWN_RX_BUSY 0x08-#define AX25_COND_DAMA_MODE 0x10--#ifndef _LINUX_NETDEVICE_H-#include <linux/netdevice.h>-#endif--/* Upper sub-layer (LAPB) definitions */--/* Control field templates */-#define AX25_I 0x00 /* Information frames */-#define AX25_S 0x01 /* Supervisory frames */-#define AX25_RR 0x01 /* Receiver ready */-#define AX25_RNR 0x05 /* Receiver not ready */-#define AX25_REJ 0x09 /* Reject */-#define AX25_U 0x03 /* Unnumbered frames */-#define AX25_SABM 0x2f /* Set Asynchronous Balanced Mode */-#define AX25_SABME 0x6f /* Set Asynchronous Balanced Mode Extended */-#define AX25_DISC 0x43 /* Disconnect */-#define AX25_DM 0x0f /* Disconnected mode */-#define AX25_UA 0x63 /* Unnumbered acknowledge */-#define AX25_FRMR 0x87 /* Frame reject */-#define AX25_UI 0x03 /* Unnumbered information */-#define AX25_XID 0xaf /* Exchange information */-#define AX25_TEST 0xe3 /* Test */--#define AX25_PF 0x10 /* Poll/final bit for standard AX.25 */-#define AX25_EPF 0x01 /* Poll/final bit for extended AX.25 */--#define AX25_ILLEGAL 0x100 /* Impossible to be a real frame type */--#define AX25_POLLOFF 0-#define AX25_POLLON 1--/* AX25 L2 C-bit */-#define AX25_COMMAND 1-#define AX25_RESPONSE 2--/* Define Link State constants. */--enum { - AX25_STATE_0, /* Listening */- AX25_STATE_1, /* SABM sent */- AX25_STATE_2, /* DISC sent */- AX25_STATE_3, /* Established */- AX25_STATE_4 /* Recovery */-};--#define AX25_MODULUS 8 /* Standard AX.25 modulus */-#define AX25_EMODULUS 128 /* Extended AX.25 modulus */--enum {- AX25_PROTO_STD_SIMPLEX,- AX25_PROTO_STD_DUPLEX,-#ifdef CONFIG_AX25_DAMA_SLAVE- AX25_PROTO_DAMA_SLAVE,-#endif- __AX25_PROTO_MAX,- AX25_PROTO_MAX = __AX25_PROTO_MAX -1-};--enum {- AX25_VALUES_IPDEFMODE, /* 0=DG 1=VC */- AX25_VALUES_AXDEFMODE, /* 0=Normal 1=Extended Seq Nos */- AX25_VALUES_BACKOFF, /* 0=None 1=Linear 2=Exponential */- AX25_VALUES_CONMODE, /* Allow connected modes - 0=No 1=no "PID text" 2=all PIDs */- AX25_VALUES_WINDOW, /* Default window size for standard AX.25 */- AX25_VALUES_EWINDOW, /* Default window size for extended AX.25 */- AX25_VALUES_T1, /* Default T1 timeout value */- AX25_VALUES_T2, /* Default T2 timeout value */- AX25_VALUES_T3, /* Default T3 timeout value */- AX25_VALUES_IDLE, /* Connected mode idle timer */- AX25_VALUES_N2, /* Default N2 value */- AX25_VALUES_PACLEN, /* AX.25 MTU */- AX25_VALUES_PROTOCOL, /* Std AX.25, DAMA Slave */-#ifdef CONFIG_AX25_DAMA_SLAVE- AX25_VALUES_DS_TIMEOUT, /* DAMA Slave timeout */-#endif- AX25_MAX_VALUES /* THIS MUST REMAIN THE LAST ENTRY OF THIS LIST */-};--#define AX25_DEF_IPDEFMODE 0 /* Datagram */-#define AX25_DEF_AXDEFMODE 0 /* Normal */-#define AX25_DEF_BACKOFF 1 /* Linear backoff */-#define AX25_DEF_CONMODE 2 /* Connected mode allowed */-#define AX25_DEF_WINDOW 2 /* Window=2 */-#define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */-#define AX25_DEF_T1 10000 /* T1=10s */-#define AX25_DEF_T2 3000 /* T2=3s */-#define AX25_DEF_T3 300000 /* T3=300s */-#define AX25_DEF_N2 10 /* N2=10 */-#define AX25_DEF_IDLE 0 /* Idle=None */-#define AX25_DEF_PACLEN 256 /* Paclen=256 */-#define AX25_DEF_PROTOCOL AX25_PROTO_STD_SIMPLEX /* Standard AX.25 */-#define AX25_DEF_DS_TIMEOUT 180000 /* DAMA timeout 3 minutes */--typedef struct ax25_uid_assoc {- struct hlist_node uid_node;- refcount_t refcount;- kuid_t uid;- ax25_address call;-} ax25_uid_assoc;--#define ax25_uid_for_each(__ax25, list) \- hlist_for_each_entry(__ax25, list, uid_node)--#define ax25_uid_hold(ax25) \- refcount_inc(&((ax25)->refcount))--static inline void ax25_uid_put(ax25_uid_assoc *assoc)-{- if (refcount_dec_and_test(&assoc->refcount)) {- kfree(assoc);- }-}--typedef struct {- ax25_address calls[AX25_MAX_DIGIS];- unsigned char repeated[AX25_MAX_DIGIS];- unsigned char ndigi;- signed char lastrepeat;-} ax25_digi;--typedef struct ax25_route {- struct ax25_route *next;- ax25_address callsign;- struct net_device *dev;- ax25_digi *digipeat;- char ip_mode;-} ax25_route;--void __ax25_put_route(ax25_route *ax25_rt);--extern rwlock_t ax25_route_lock;--static inline void ax25_route_lock_use(void)-{- read_lock(&ax25_route_lock);-}--static inline void ax25_route_lock_unuse(void)-{- read_unlock(&ax25_route_lock);-}--typedef struct {- char slave; /* slave_mode? */- struct timer_list slave_timer; /* timeout timer */- unsigned short slave_timeout; /* when? */-} ax25_dama_info;--typedef struct ax25_dev {- struct list_head list;-- struct net_device *dev;- netdevice_tracker dev_tracker;-- struct net_device *forward;- struct ctl_table_header *sysheader;- int values[AX25_MAX_VALUES];-#ifdef CONFIG_AX25_DAMA_SLAVE- ax25_dama_info dama;-#endif- refcount_t refcount;- bool device_up;- struct rcu_head rcu;-} ax25_dev;--typedef struct ax25_cb {- struct hlist_node ax25_node;- ax25_address source_addr, dest_addr;- ax25_digi *digipeat;- ax25_dev *ax25_dev;- netdevice_tracker dev_tracker;- unsigned char iamdigi;- unsigned char state, modulus, pidincl;- unsigned short vs, vr, va;- unsigned char condition, backoff;- unsigned char n2, n2count;- struct timer_list t1timer, t2timer, t3timer, idletimer;- unsigned long t1, t2, t3, idle, rtt;- unsigned short paclen, fragno, fraglen;- struct sk_buff_head write_queue;- struct sk_buff_head reseq_queue;- struct sk_buff_head ack_queue;- struct sk_buff_head frag_queue;- unsigned char window;- struct timer_list timer, dtimer;- struct sock *sk; /* Backlink to socket */- refcount_t refcount;-} ax25_cb;--struct ax25_sock {- struct sock sk;- struct ax25_cb *cb;-};--#define ax25_sk(ptr) container_of_const(ptr, struct ax25_sock, sk)--static inline struct ax25_cb *sk_to_ax25(const struct sock *sk)-{- return ax25_sk(sk)->cb;-}--#define ax25_for_each(__ax25, list) \- hlist_for_each_entry(__ax25, list, ax25_node)--#define ax25_cb_hold(__ax25) \- refcount_inc(&((__ax25)->refcount))--static __inline__ void ax25_cb_put(ax25_cb *ax25)-{- if (refcount_dec_and_test(&ax25->refcount)) {- kfree(ax25->digipeat);- kfree(ax25);- }-}--static inline void ax25_dev_hold(ax25_dev *ax25_dev)-{- refcount_inc(&ax25_dev->refcount);-}--static inline void ax25_dev_put(ax25_dev *ax25_dev)-{- if (refcount_dec_and_test(&ax25_dev->refcount))- kfree_rcu(ax25_dev, rcu);-}-static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)-{- skb->dev = dev;- skb_reset_mac_header(skb);- skb->pkt_type = PACKET_HOST;- return htons(ETH_P_AX25);-}--/* af_ax25.c */-extern struct hlist_head ax25_list;-extern spinlock_t ax25_list_lock;-void ax25_cb_add(ax25_cb *);-struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);-struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);-ax25_cb *ax25_find_cb(const ax25_address *, ax25_address *, ax25_digi *,- struct net_device *);-void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);-void ax25_destroy_socket(ax25_cb *);-ax25_cb * __must_check ax25_create_cb(void);-void ax25_fillin_cb(ax25_cb *, ax25_dev *);-struct sock *ax25_make_new(struct sock *, struct ax25_dev *);--/* ax25_addr.c */-extern const ax25_address ax25_bcast;-extern const ax25_address ax25_defaddr;-extern const ax25_address null_ax25_address;-char *ax2asc(char *buf, const ax25_address *);-void asc2ax(ax25_address *addr, const char *callsign);-int ax25cmp(const ax25_address *, const ax25_address *);-int ax25digicmp(const ax25_digi *, const ax25_digi *);-const unsigned char *ax25_addr_parse(const unsigned char *, int,- ax25_address *, ax25_address *, ax25_digi *, int *, int *);-int ax25_addr_build(unsigned char *, const ax25_address *,- const ax25_address *, const ax25_digi *, int, int);-int ax25_addr_size(const ax25_digi *);-void ax25_digi_invert(const ax25_digi *, ax25_digi *);--/* ax25_dev.c */-extern spinlock_t ax25_dev_lock;--#if IS_ENABLED(CONFIG_AX25)-static inline ax25_dev *ax25_dev_ax25dev(const struct net_device *dev)-{- return rcu_dereference_rtnl(dev->ax25_ptr);-}-#endif--ax25_dev *ax25_addr_ax25dev(ax25_address *);-void ax25_dev_device_up(struct net_device *);-void ax25_dev_device_down(struct net_device *);-int ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);-struct net_device *ax25_fwd_dev(struct net_device *);-void ax25_dev_free(void);--/* ax25_ds_in.c */-int ax25_ds_frame_in(ax25_cb *, struct sk_buff *, int);--/* ax25_ds_subr.c */-void ax25_ds_nr_error_recovery(ax25_cb *);-void ax25_ds_enquiry_response(ax25_cb *);-void ax25_ds_establish_data_link(ax25_cb *);-void ax25_dev_dama_off(ax25_dev *);-void ax25_dama_on(ax25_cb *);-void ax25_dama_off(ax25_cb *);--/* ax25_ds_timer.c */-void ax25_ds_setup_timer(ax25_dev *);-void ax25_ds_set_timer(ax25_dev *);-void ax25_ds_del_timer(ax25_dev *);-void ax25_ds_timer(ax25_cb *);-void ax25_ds_t1_timeout(ax25_cb *);-void ax25_ds_heartbeat_expiry(ax25_cb *);-void ax25_ds_t3timer_expiry(ax25_cb *);-void ax25_ds_idletimer_expiry(ax25_cb *);--/* ax25_iface.c */--struct ax25_protocol {- struct ax25_protocol *next;- unsigned int pid;- int (*func)(struct sk_buff *, ax25_cb *);-};--void ax25_register_pid(struct ax25_protocol *ap);-void ax25_protocol_release(unsigned int);--struct ax25_linkfail {- struct hlist_node lf_node;- void (*func)(ax25_cb *, int);-};--void ax25_linkfail_register(struct ax25_linkfail *lf);-void ax25_linkfail_release(struct ax25_linkfail *lf);-int __must_check ax25_listen_register(const ax25_address *,- struct net_device *);-void ax25_listen_release(const ax25_address *, struct net_device *);-int(*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);-int ax25_listen_mine(const ax25_address *, struct net_device *);-void ax25_link_failed(ax25_cb *, int);-int ax25_protocol_is_registered(unsigned int);--/* ax25_in.c */-int ax25_rx_iframe(ax25_cb *, struct sk_buff *);-int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *,- struct net_device *);--/* ax25_ip.c */-netdev_tx_t ax25_ip_xmit(struct sk_buff *skb);-extern const struct header_ops ax25_header_ops;--/* ax25_out.c */-ax25_cb *ax25_send_frame(struct sk_buff *, int, const ax25_address *,- ax25_address *, ax25_digi *, struct net_device *);-void ax25_output(ax25_cb *, int, struct sk_buff *);-void ax25_kick(ax25_cb *);-void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);-void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev);-int ax25_check_iframes_acked(ax25_cb *, unsigned short);--/* ax25_route.c */-void ax25_rt_device_down(struct net_device *);-int ax25_rt_ioctl(unsigned int, void __user *);-extern const struct seq_operations ax25_rt_seqops;-ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);-struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *,- ax25_address *, ax25_digi *);-void ax25_rt_free(void);--/* ax25_std_in.c */-int ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);--/* ax25_std_subr.c */-void ax25_std_nr_error_recovery(ax25_cb *);-void ax25_std_establish_data_link(ax25_cb *);-void ax25_std_transmit_enquiry(ax25_cb *);-void ax25_std_enquiry_response(ax25_cb *);-void ax25_std_timeout_response(ax25_cb *);--/* ax25_std_timer.c */-void ax25_std_heartbeat_expiry(ax25_cb *);-void ax25_std_t1timer_expiry(ax25_cb *);-void ax25_std_t2timer_expiry(ax25_cb *);-void ax25_std_t3timer_expiry(ax25_cb *);-void ax25_std_idletimer_expiry(ax25_cb *);--/* ax25_subr.c */-void ax25_clear_queues(ax25_cb *);-void ax25_frames_acked(ax25_cb *, unsigned short);-void ax25_requeue_frames(ax25_cb *);-int ax25_validate_nr(ax25_cb *, unsigned short);-int ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);-void ax25_send_control(ax25_cb *, int, int, int);-void ax25_return_dm(struct net_device *, ax25_address *, ax25_address *,- ax25_digi *);-void ax25_calculate_t1(ax25_cb *);-void ax25_calculate_rtt(ax25_cb *);-void ax25_disconnect(ax25_cb *, int);--/* ax25_timer.c */-void ax25_setup_timers(ax25_cb *);-void ax25_start_heartbeat(ax25_cb *);-void ax25_start_t1timer(ax25_cb *);-void ax25_start_t2timer(ax25_cb *);-void ax25_start_t3timer(ax25_cb *);-void ax25_start_idletimer(ax25_cb *);-void ax25_stop_heartbeat(ax25_cb *);-void ax25_stop_t1timer(ax25_cb *);-void ax25_stop_t2timer(ax25_cb *);-void ax25_stop_t3timer(ax25_cb *);-void ax25_stop_idletimer(ax25_cb *);-int ax25_t1timer_running(ax25_cb *);-unsigned long ax25_display_timer(struct timer_list *);--/* ax25_uid.c */-extern int ax25_uid_policy;-ax25_uid_assoc *ax25_findbyuid(kuid_t);-int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);-extern const struct seq_operations ax25_uid_seqops;-void ax25_uid_free(void);--/* sysctl_net_ax25.c */-#ifdef CONFIG_SYSCTL-int ax25_register_dev_sysctl(ax25_dev *ax25_dev);-void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev);-#else-static inline int ax25_register_dev_sysctl(ax25_dev *ax25_dev) { return 0; }-static inline void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) {}-#endif /* CONFIG_SYSCTL */+#define AX25_ADDR_LEN 7+#define AX25_P_IP 0xCC #endifdiff --git a/include/net/netrom.h b/include/net/netrom.hdeleted file mode 100644index f0565a5987d1..000000000000--- a/include/net/netrom.h+++ /dev/null@@ -1,273 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 */-/*- * Declarations of NET/ROM type objects.- *- * Jonathan Naylor G4KLX 9/4/95- */--#ifndef _NETROM_H-#define _NETROM_H --#include <linux/netrom.h>-#include <linux/list.h>-#include <linux/slab.h>-#include <net/sock.h>-#include <linux/refcount.h>-#include <linux/seq_file.h>-#include <net/ax25.h>--#define NR_NETWORK_LEN 15-#define NR_TRANSPORT_LEN 5--#define NR_PROTO_IP 0x0C--#define NR_PROTOEXT 0x00-#define NR_CONNREQ 0x01-#define NR_CONNACK 0x02-#define NR_DISCREQ 0x03-#define NR_DISCACK 0x04-#define NR_INFO 0x05-#define NR_INFOACK 0x06-#define NR_RESET 0x07--#define NR_CHOKE_FLAG 0x80-#define NR_NAK_FLAG 0x40-#define NR_MORE_FLAG 0x20--/* Define Link State constants. */-enum {- NR_STATE_0,- NR_STATE_1,- NR_STATE_2,- NR_STATE_3-};--#define NR_COND_ACK_PENDING 0x01-#define NR_COND_REJECT 0x02-#define NR_COND_PEER_RX_BUSY 0x04-#define NR_COND_OWN_RX_BUSY 0x08--#define NR_DEFAULT_T1 120000 /* Outstanding frames - 120 seconds */-#define NR_DEFAULT_T2 5000 /* Response delay - 5 seconds */-#define NR_DEFAULT_N2 3 /* Number of Retries - 3 */-#define NR_DEFAULT_T4 180000 /* Busy Delay - 180 seconds */-#define NR_DEFAULT_IDLE 0 /* No Activity Timeout - none */-#define NR_DEFAULT_WINDOW 4 /* Default Window Size - 4 */-#define NR_DEFAULT_OBS 6 /* Default Obsolescence Count - 6 */-#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality - 10 */-#define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */-#define NR_DEFAULT_ROUTING 1 /* Is routing enabled ? */-#define NR_DEFAULT_FAILS 2 /* Link fails until route fails */-#define NR_DEFAULT_RESET 0 /* Sent / accept reset cmds? */--#define NR_MODULUS 256-#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */-#define NR_MAX_PACKET_SIZE 236 /* Maximum Packet Length - 236 */--struct nr_sock {- struct sock sock;- ax25_address user_addr, source_addr, dest_addr;- struct net_device *device;- unsigned char my_index, my_id;- unsigned char your_index, your_id;- unsigned char state, condition, bpqext, window;- unsigned short vs, vr, va, vl;- unsigned char n2, n2count;- unsigned long t1, t2, t4, idle;- unsigned short fraglen;- struct timer_list t1timer;- struct timer_list t2timer;- struct timer_list t4timer;- struct timer_list idletimer;- struct sk_buff_head ack_queue;- struct sk_buff_head reseq_queue;- struct sk_buff_head frag_queue;-};--#define nr_sk(sk) ((struct nr_sock *)(sk))--struct nr_neigh {- struct hlist_node neigh_node;- ax25_address callsign;- ax25_digi *digipeat;- ax25_cb *ax25;- struct net_device *dev;- unsigned char quality;- unsigned char locked;- unsigned short count;- unsigned int number;- unsigned char failed;- refcount_t refcount;-};--struct nr_route {- unsigned char quality;- unsigned char obs_count;- struct nr_neigh *neighbour;-};--struct nr_node {- struct hlist_node node_node;- ax25_address callsign;- char mnemonic[7];- unsigned char which;- unsigned char count;- struct nr_route routes[3];- refcount_t refcount;- spinlock_t node_lock;-};--/*********************************************************************- * nr_node & nr_neigh lists, refcounting and locking- *********************************************************************/--#define nr_node_hold(__nr_node) \- refcount_inc(&((__nr_node)->refcount))--static __inline__ void nr_node_put(struct nr_node *nr_node)-{- if (refcount_dec_and_test(&nr_node->refcount)) {- kfree(nr_node);- }-}--#define nr_neigh_hold(__nr_neigh) \- refcount_inc(&((__nr_neigh)->refcount))--static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)-{- if (refcount_dec_and_test(&nr_neigh->refcount)) {- if (nr_neigh->ax25)- ax25_cb_put(nr_neigh->ax25);- kfree(nr_neigh->digipeat);- kfree(nr_neigh);- }-}--/* nr_node_lock and nr_node_unlock also hold/put the node's refcounter.- */-static __inline__ void nr_node_lock(struct nr_node *nr_node)-{- nr_node_hold(nr_node);- spin_lock_bh(&nr_node->node_lock);-}--static __inline__ void nr_node_unlock(struct nr_node *nr_node)-{- spin_unlock_bh(&nr_node->node_lock);- nr_node_put(nr_node);-}--#define nr_neigh_for_each(__nr_neigh, list) \- hlist_for_each_entry(__nr_neigh, list, neigh_node)--#define nr_neigh_for_each_safe(__nr_neigh, node2, list) \- hlist_for_each_entry_safe(__nr_neigh, node2, list, neigh_node)--#define nr_node_for_each(__nr_node, list) \- hlist_for_each_entry(__nr_node, list, node_node)--#define nr_node_for_each_safe(__nr_node, node2, list) \- hlist_for_each_entry_safe(__nr_node, node2, list, node_node)---/*********************************************************************/--/* af_netrom.c */-extern int sysctl_netrom_default_path_quality;-extern int sysctl_netrom_obsolescence_count_initialiser;-extern int sysctl_netrom_network_ttl_initialiser;-extern int sysctl_netrom_transport_timeout;-extern int sysctl_netrom_transport_maximum_tries;-extern int sysctl_netrom_transport_acknowledge_delay;-extern int sysctl_netrom_transport_busy_delay;-extern int sysctl_netrom_transport_requested_window_size;-extern int sysctl_netrom_transport_no_activity_timeout;-extern int sysctl_netrom_routing_control;-extern int sysctl_netrom_link_fails_count;-extern int sysctl_netrom_reset_circuit;--int nr_rx_frame(struct sk_buff *, struct net_device *);-void nr_destroy_socket(struct sock *);--/* nr_dev.c */-int nr_rx_ip(struct sk_buff *, struct net_device *);-void nr_setup(struct net_device *);--/* nr_in.c */-int nr_process_rx_frame(struct sock *, struct sk_buff *);--/* nr_loopback.c */-void nr_loopback_init(void);-void nr_loopback_clear(void);-int nr_loopback_queue(struct sk_buff *);--/* nr_out.c */-void nr_output(struct sock *, struct sk_buff *);-void nr_send_nak_frame(struct sock *);-void nr_kick(struct sock *);-void nr_transmit_buffer(struct sock *, struct sk_buff *);-void nr_establish_data_link(struct sock *);-void nr_enquiry_response(struct sock *);-void nr_check_iframes_acked(struct sock *, unsigned short);--/* nr_route.c */-void nr_rt_device_down(struct net_device *);-struct net_device *nr_dev_first(void);-struct net_device *nr_dev_get(ax25_address *);-int nr_rt_ioctl(unsigned int, void __user *);-void nr_link_failed(ax25_cb *, int);-int nr_route_frame(struct sk_buff *, ax25_cb *);-extern const struct seq_operations nr_node_seqops;-extern const struct seq_operations nr_neigh_seqops;-void nr_rt_free(void);--/* nr_subr.c */-void nr_clear_queues(struct sock *);-void nr_frames_acked(struct sock *, unsigned short);-void nr_requeue_frames(struct sock *);-int nr_validate_nr(struct sock *, unsigned short);-int nr_in_rx_window(struct sock *, unsigned short);-void nr_write_internal(struct sock *, int);--void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags);--/*- * This routine is called when a Connect Acknowledge with the Choke Flag- * set is needed to refuse a connection.- */-#define nr_transmit_refusal(skb, mine) \-do { \- __nr_transmit_reply((skb), (mine), NR_CONNACK | NR_CHOKE_FLAG); \-} while (0)--/*- * This routine is called when we don't have a circuit matching an incoming- * NET/ROM packet. This is an G8PZT Xrouter extension.- */-#define nr_transmit_reset(skb, mine) \-do { \- __nr_transmit_reply((skb), (mine), NR_RESET); \-} while (0)--void nr_disconnect(struct sock *, int);--/* nr_timer.c */-void nr_init_timers(struct sock *sk);-void nr_start_heartbeat(struct sock *);-void nr_start_t1timer(struct sock *);-void nr_start_t2timer(struct sock *);-void nr_start_t4timer(struct sock *);-void nr_start_idletimer(struct sock *);-void nr_stop_heartbeat(struct sock *);-void nr_stop_t1timer(struct sock *);-void nr_stop_t2timer(struct sock *);-void nr_stop_t4timer(struct sock *);-void nr_stop_idletimer(struct sock *);-int nr_t1timer_running(struct sock *);--/* sysctl_net_netrom.c */-int nr_register_sysctl(void);-void nr_unregister_sysctl(void);--#endifdiff --git a/include/net/rose.h b/include/net/rose.hindex 2b5491bbf39a..41bfcb224f0b 100644--- a/include/net/rose.h+++ b/include/net/rose.h@@ -1,266 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */-/*- * Declarations of Rose type objects.- *- * Jonathan Naylor G4KLX 25/8/96- */- #ifndef _ROSE_H-#define _ROSE_H +#define _ROSE_H -#include <linux/refcount.h>-#include <linux/rose.h>-#include <net/ax25.h>-#include <net/sock.h>--#define ROSE_ADDR_LEN 5--#define ROSE_MIN_LEN 3--#define ROSE_CALL_REQ_ADDR_LEN_OFF 3-#define ROSE_CALL_REQ_ADDR_LEN_VAL 0xAA /* each address is 10 digits */-#define ROSE_CALL_REQ_DEST_ADDR_OFF 4-#define ROSE_CALL_REQ_SRC_ADDR_OFF 9-#define ROSE_CALL_REQ_FACILITIES_OFF 14--#define ROSE_GFI 0x10-#define ROSE_Q_BIT 0x80-#define ROSE_D_BIT 0x40-#define ROSE_M_BIT 0x10--#define ROSE_CALL_REQUEST 0x0B-#define ROSE_CALL_ACCEPTED 0x0F-#define ROSE_CLEAR_REQUEST 0x13-#define ROSE_CLEAR_CONFIRMATION 0x17-#define ROSE_DATA 0x00-#define ROSE_INTERRUPT 0x23-#define ROSE_INTERRUPT_CONFIRMATION 0x27-#define ROSE_RR 0x01-#define ROSE_RNR 0x05-#define ROSE_REJ 0x09-#define ROSE_RESET_REQUEST 0x1B-#define ROSE_RESET_CONFIRMATION 0x1F-#define ROSE_REGISTRATION_REQUEST 0xF3-#define ROSE_REGISTRATION_CONFIRMATION 0xF7-#define ROSE_RESTART_REQUEST 0xFB-#define ROSE_RESTART_CONFIRMATION 0xFF-#define ROSE_DIAGNOSTIC 0xF1-#define ROSE_ILLEGAL 0xFD--/* Define Link State constants. */--enum {- ROSE_STATE_0, /* Ready */- ROSE_STATE_1, /* Awaiting Call Accepted */- ROSE_STATE_2, /* Awaiting Clear Confirmation */- ROSE_STATE_3, /* Data Transfer */- ROSE_STATE_4, /* Awaiting Reset Confirmation */- ROSE_STATE_5 /* Deferred Call Acceptance */-};--#define ROSE_DEFAULT_T0 180000 /* Default T10 T20 value */-#define ROSE_DEFAULT_T1 200000 /* Default T11 T21 value */-#define ROSE_DEFAULT_T2 180000 /* Default T12 T22 value */-#define ROSE_DEFAULT_T3 180000 /* Default T13 T23 value */-#define ROSE_DEFAULT_HB 5000 /* Default Holdback value */-#define ROSE_DEFAULT_IDLE 0 /* No Activity Timeout - none */-#define ROSE_DEFAULT_ROUTING 1 /* Default routing flag */-#define ROSE_DEFAULT_FAIL_TIMEOUT 120000 /* Time until link considered usable */-#define ROSE_DEFAULT_MAXVC 50 /* Maximum number of VCs per neighbour */-#define ROSE_DEFAULT_WINDOW_SIZE 7 /* Default window size */--#define ROSE_MODULUS 8-#define ROSE_MAX_PACKET_SIZE 251 /* Maximum packet size */--#define ROSE_COND_ACK_PENDING 0x01-#define ROSE_COND_PEER_RX_BUSY 0x02-#define ROSE_COND_OWN_RX_BUSY 0x04--#define FAC_NATIONAL 0x00-#define FAC_CCITT 0x0F--#define FAC_NATIONAL_RAND 0x7F-#define FAC_NATIONAL_FLAGS 0x3F-#define FAC_NATIONAL_DEST_DIGI 0xE9-#define FAC_NATIONAL_SRC_DIGI 0xEB-#define FAC_NATIONAL_FAIL_CALL 0xED-#define FAC_NATIONAL_FAIL_ADD 0xEE-#define FAC_NATIONAL_DIGIS 0xEF--#define FAC_CCITT_DEST_NSAP 0xC9-#define FAC_CCITT_SRC_NSAP 0xCB--struct rose_neigh {- struct rose_neigh *next;- ax25_address callsign;- ax25_digi *digipeat;- ax25_cb *ax25;- struct net_device *dev;- unsigned short count;- refcount_t use;- unsigned int number;- char restarted;- char dce_mode;- char loopback;- struct sk_buff_head queue;- struct timer_list t0timer;- struct timer_list ftimer;-};--struct rose_node {- struct rose_node *next;- rose_address address;- unsigned short mask;- unsigned char count;- char loopback;- struct rose_neigh *neighbour[3];-};--struct rose_route {- struct rose_route *next;- unsigned int lci1, lci2;- rose_address src_addr, dest_addr;- ax25_address src_call, dest_call;- struct rose_neigh *neigh1, *neigh2;- unsigned int rand;-};--struct rose_sock {- struct sock sock;- rose_address source_addr, dest_addr;- ax25_address source_call, dest_call;- unsigned char source_ndigis, dest_ndigis;- ax25_address source_digis[ROSE_MAX_DIGIS];- ax25_address dest_digis[ROSE_MAX_DIGIS];- struct rose_neigh *neighbour;- struct net_device *device;- netdevice_tracker dev_tracker;- unsigned int lci, rand;- unsigned char state, condition, qbitincl, defer;- unsigned char cause, diagnostic;- unsigned short vs, vr, va, vl;- unsigned long t1, t2, t3, hb, idle;-#ifdef M_BIT- unsigned short fraglen;- struct sk_buff_head frag_queue;-#endif- struct sk_buff_head ack_queue;- struct rose_facilities_struct facilities;- struct timer_list timer;- struct timer_list idletimer;-};--#define rose_sk(sk) ((struct rose_sock *)(sk))--static inline void rose_neigh_hold(struct rose_neigh *rose_neigh)-{- refcount_inc(&rose_neigh->use);-}--static inline void rose_neigh_put(struct rose_neigh *rose_neigh)-{- if (refcount_dec_and_test(&rose_neigh->use)) {- if (rose_neigh->ax25)- ax25_cb_put(rose_neigh->ax25);- kfree(rose_neigh->digipeat);- kfree(rose_neigh);- }-}--/* af_rose.c */-extern ax25_address rose_callsign;-extern int sysctl_rose_restart_request_timeout;-extern int sysctl_rose_call_request_timeout;-extern int sysctl_rose_reset_request_timeout;-extern int sysctl_rose_clear_request_timeout;-extern int sysctl_rose_no_activity_timeout;-extern int sysctl_rose_ack_hold_back_timeout;-extern int sysctl_rose_routing_control;-extern int sysctl_rose_link_fail_timeout;-extern int sysctl_rose_maximum_vcs;-extern int sysctl_rose_window_size;--int rosecmp(const rose_address *, const rose_address *);-int rosecmpm(const rose_address *, const rose_address *, unsigned short);-char *rose2asc(char *buf, const rose_address *);-struct sock *rose_find_socket(unsigned int, struct rose_neigh *);-void rose_kill_by_neigh(struct rose_neigh *);-unsigned int rose_new_lci(struct rose_neigh *);-int rose_rx_call_request(struct sk_buff *, struct net_device *,- struct rose_neigh *, unsigned int);-void rose_destroy_socket(struct sock *);--/* rose_dev.c */-void rose_setup(struct net_device *);--/* rose_in.c */-int rose_process_rx_frame(struct sock *, struct sk_buff *);--/* rose_link.c */-void rose_start_ftimer(struct rose_neigh *);-void rose_stop_ftimer(struct rose_neigh *);-void rose_stop_t0timer(struct rose_neigh *);-int rose_ftimer_running(struct rose_neigh *);-void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *,- unsigned short);-void rose_transmit_clear_request(struct rose_neigh *, unsigned int,- unsigned char, unsigned char);-void rose_transmit_link(struct sk_buff *, struct rose_neigh *);--/* rose_loopback.c */-void rose_loopback_init(void);-void rose_loopback_clear(void);-int rose_loopback_queue(struct sk_buff *, struct rose_neigh *);--/* rose_out.c */-void rose_kick(struct sock *);-void rose_enquiry_response(struct sock *);--/* rose_route.c */-extern struct rose_neigh *rose_loopback_neigh;-extern const struct seq_operations rose_neigh_seqops;-extern const struct seq_operations rose_node_seqops;-extern struct seq_operations rose_route_seqops;--void rose_add_loopback_neigh(void);-int __must_check rose_add_loopback_node(const rose_address *);-void rose_del_loopback_node(const rose_address *);-void rose_rt_device_down(struct net_device *);-void rose_link_device_down(struct net_device *);-struct net_device *rose_dev_first(void);-struct net_device *rose_dev_get(rose_address *);-struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *);-struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *,- unsigned char *, int);-int rose_rt_ioctl(unsigned int, void __user *);-void rose_link_failed(ax25_cb *, int);-int rose_route_frame(struct sk_buff *, ax25_cb *);-void rose_rt_free(void);--/* rose_subr.c */-void rose_clear_queues(struct sock *);-void rose_frames_acked(struct sock *, unsigned short);-void rose_requeue_frames(struct sock *);-int rose_validate_nr(struct sock *, unsigned short);-void rose_write_internal(struct sock *, int);-int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);-int rose_parse_facilities(unsigned char *, unsigned int,- struct rose_facilities_struct *);-void rose_disconnect(struct sock *, int, int, int);--/* rose_timer.c */-void rose_start_heartbeat(struct sock *);-void rose_start_t1timer(struct sock *);-void rose_start_t2timer(struct sock *);-void rose_start_t3timer(struct sock *);-void rose_start_hbtimer(struct sock *);-void rose_start_idletimer(struct sock *);-void rose_stop_heartbeat(struct sock *);-void rose_stop_timer(struct sock *);-void rose_stop_idletimer(struct sock *);--/* sysctl_net_rose.c */-void rose_register_sysctl(void);-void rose_unregister_sysctl(void);+#define ROSE_ADDR_LEN 5 #endifdiff --git a/include/uapi/linux/baycom.h b/include/uapi/linux/baycom.hdeleted file mode 100644index 478cb565ae52..000000000000--- a/include/uapi/linux/baycom.h+++ /dev/null@@ -1,40 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */-/*- * The Linux BAYCOM driver for the Baycom serial 1200 baud modem- * and the parallel 9600 baud modem- * (C) 1997-1998 by Thomas Sailer, HB9JNX/AE4WA- */--#ifndef _BAYCOM_H-#define _BAYCOM_H--/* -------------------------------------------------------------------- */-/*- * structs for the IOCTL commands- */--struct baycom_debug_data {- unsigned long debug1;- unsigned long debug2;- long debug3;-};--struct baycom_ioctl {- int cmd;- union {- struct baycom_debug_data dbg;- } data;-};--/* -------------------------------------------------------------------- */--/*- * ioctl values change for baycom- */-#define BAYCOMCTL_GETDEBUG 0x92--/* -------------------------------------------------------------------- */--#endif /* _BAYCOM_H */--/* --------------------------------------------------------------------- */diff --git a/include/uapi/linux/hdlcdrv.h b/include/uapi/linux/hdlcdrv.hdeleted file mode 100644index 9fe9499403a6..000000000000--- a/include/uapi/linux/hdlcdrv.h+++ /dev/null@@ -1,111 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */-/*- * hdlcdrv.h -- HDLC packet radio network driver.- * The Linux soundcard driver for 1200 baud and 9600 baud packet radio- * (C) 1996-1998 by Thomas Sailer, HB9JNX/AE4WA- */--#ifndef _UAPI_HDLCDRV_H-#define _UAPI_HDLCDRV_H--/* -------------------------------------------------------------------- */-/*- * structs for the IOCTL commands- */--struct hdlcdrv_params {- int iobase;- int irq;- int dma;- int dma2;- int seriobase;- int pariobase;- int midiiobase;-}; --struct hdlcdrv_channel_params {- int tx_delay; /* the transmitter keyup delay in 10ms units */- int tx_tail; /* the transmitter keyoff delay in 10ms units */- int slottime; /* the slottime in 10ms; usually 10 = 100ms */- int ppersist; /* the p-persistence 0..255 */- int fulldup; /* some driver do not support full duplex, setting */- /* this just makes them send even if DCD is on */-}; --struct hdlcdrv_old_channel_state {- int ptt;- int dcd;- int ptt_keyed;-};--struct hdlcdrv_channel_state {- int ptt;- int dcd;- int ptt_keyed;- unsigned long tx_packets;- unsigned long tx_errors;- unsigned long rx_packets;- unsigned long rx_errors;-};--struct hdlcdrv_ioctl {- int cmd;- union {- struct hdlcdrv_params mp;- struct hdlcdrv_channel_params cp;- struct hdlcdrv_channel_state cs;- struct hdlcdrv_old_channel_state ocs;- unsigned int calibrate;- unsigned char bits;- char modename[128];- char drivername[32];- } data;-};--/* -------------------------------------------------------------------- */--/*- * ioctl values- */-#define HDLCDRVCTL_GETMODEMPAR 0-#define HDLCDRVCTL_SETMODEMPAR 1-#define HDLCDRVCTL_MODEMPARMASK 2 /* not handled by hdlcdrv */-#define HDLCDRVCTL_GETCHANNELPAR 10-#define HDLCDRVCTL_SETCHANNELPAR 11-#define HDLCDRVCTL_OLDGETSTAT 20-#define HDLCDRVCTL_CALIBRATE 21-#define HDLCDRVCTL_GETSTAT 22--/*- * these are mainly for debugging purposes- */-#define HDLCDRVCTL_GETSAMPLES 30-#define HDLCDRVCTL_GETBITS 31--/*- * not handled by hdlcdrv, but by its depending drivers- */-#define HDLCDRVCTL_GETMODE 40-#define HDLCDRVCTL_SETMODE 41-#define HDLCDRVCTL_MODELIST 42-#define HDLCDRVCTL_DRIVERNAME 43--/*- * mask of needed modem parameters, returned by HDLCDRVCTL_MODEMPARMASK- */-#define HDLCDRV_PARMASK_IOBASE (1<<0)-#define HDLCDRV_PARMASK_IRQ (1<<1)-#define HDLCDRV_PARMASK_DMA (1<<2)-#define HDLCDRV_PARMASK_DMA2 (1<<3)-#define HDLCDRV_PARMASK_SERIOBASE (1<<4)-#define HDLCDRV_PARMASK_PARIOBASE (1<<5)-#define HDLCDRV_PARMASK_MIDIIOBASE (1<<6)--/* -------------------------------------------------------------------- */---/* -------------------------------------------------------------------- */--#endif /* _UAPI_HDLCDRV_H */--/* -------------------------------------------------------------------- */diff --git a/include/uapi/linux/netrom.h b/include/uapi/linux/netrom.hdeleted file mode 100644index 7498ea3c3940..000000000000--- a/include/uapi/linux/netrom.h+++ /dev/null@@ -1,37 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */-/*- * These are the public elements of the Linux kernel NET/ROM implementation.- * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the- * definition of the ax25_address structure.- */--#ifndef NETROM_KERNEL_H-#define NETROM_KERNEL_H--#include <linux/ax25.h>--#define NETROM_MTU 236--#define NETROM_T1 1-#define NETROM_T2 2-#define NETROM_N2 3-#define NETROM_T4 6-#define NETROM_IDLE 7--#define SIOCNRDECOBS (SIOCPROTOPRIVATE+2)--struct nr_route_struct {-#define NETROM_NEIGH 0-#define NETROM_NODE 1- int type;- ax25_address callsign;- char device[16];- unsigned int quality;- char mnemonic[7];- ax25_address neighbour;- unsigned int obs_count;- unsigned int ndigis;- ax25_address digipeaters[AX25_MAX_DIGIS];-};--#endifdiff --git a/include/uapi/linux/rose.h b/include/uapi/linux/rose.hdeleted file mode 100644index 19aa4693c8fc..000000000000--- a/include/uapi/linux/rose.h+++ /dev/null@@ -1,91 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */-/*- * These are the public elements of the Linux kernel Rose implementation.- * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the- * definition of the ax25_address structure.- */--#ifndef ROSE_KERNEL_H-#define ROSE_KERNEL_H--#include <linux/socket.h>-#include <linux/ax25.h>--#define ROSE_MTU 251--#define ROSE_MAX_DIGIS 6--#define ROSE_DEFER 1-#define ROSE_T1 2-#define ROSE_T2 3-#define ROSE_T3 4-#define ROSE_IDLE 5-#define ROSE_QBITINCL 6-#define ROSE_HOLDBACK 7--#define SIOCRSGCAUSE (SIOCPROTOPRIVATE+0)-#define SIOCRSSCAUSE (SIOCPROTOPRIVATE+1)-#define SIOCRSL2CALL (SIOCPROTOPRIVATE+2)-#define SIOCRSSL2CALL (SIOCPROTOPRIVATE+2)-#define SIOCRSACCEPT (SIOCPROTOPRIVATE+3)-#define SIOCRSCLRRT (SIOCPROTOPRIVATE+4)-#define SIOCRSGL2CALL (SIOCPROTOPRIVATE+5)-#define SIOCRSGFACILITIES (SIOCPROTOPRIVATE+6)--#define ROSE_DTE_ORIGINATED 0x00-#define ROSE_NUMBER_BUSY 0x01-#define ROSE_INVALID_FACILITY 0x03-#define ROSE_NETWORK_CONGESTION 0x05-#define ROSE_OUT_OF_ORDER 0x09-#define ROSE_ACCESS_BARRED 0x0B-#define ROSE_NOT_OBTAINABLE 0x0D-#define ROSE_REMOTE_PROCEDURE 0x11-#define ROSE_LOCAL_PROCEDURE 0x13-#define ROSE_SHIP_ABSENT 0x39--typedef struct {- char rose_addr[5];-} rose_address;--struct sockaddr_rose {- __kernel_sa_family_t srose_family;- rose_address srose_addr;- ax25_address srose_call;- int srose_ndigis;- ax25_address srose_digi;-};--struct full_sockaddr_rose {- __kernel_sa_family_t srose_family;- rose_address srose_addr;- ax25_address srose_call;- unsigned int srose_ndigis;- ax25_address srose_digis[ROSE_MAX_DIGIS];-};--struct rose_route_struct {- rose_address address;- unsigned short mask;- ax25_address neighbour;- char device[16];- unsigned char ndigis;- ax25_address digipeaters[AX25_MAX_DIGIS];-};--struct rose_cause_struct {- unsigned char cause;- unsigned char diagnostic;-};--struct rose_facilities_struct {- rose_address source_addr, dest_addr;- ax25_address source_call, dest_call;- unsigned char source_ndigis, dest_ndigis;- ax25_address source_digis[ROSE_MAX_DIGIS];- ax25_address dest_digis[ROSE_MAX_DIGIS];- unsigned int rand;- rose_address fail_addr;- ax25_address fail_call;-};--#endifdiff --git a/include/uapi/linux/scc.h b/include/uapi/linux/scc.hdeleted file mode 100644index 947edb17ce9d..000000000000--- a/include/uapi/linux/scc.h+++ /dev/null@@ -1,174 +0,0 @@-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */-/* $Id: scc.h,v 1.29 1997/04/02 14:56:45 jreuter Exp jreuter $ */--#ifndef _UAPI_SCC_H-#define _UAPI_SCC_H--#include <linux/sockios.h>--/* selection of hardware types */--#define PA0HZP 0x00 /* hardware type for PA0HZP SCC card and compatible */-#define EAGLE 0x01 /* hardware type for EAGLE card */-#define PC100 0x02 /* hardware type for PC100 card */-#define PRIMUS 0x04 /* hardware type for PRIMUS-PC (DG9BL) card */-#define DRSI 0x08 /* hardware type for DRSI PC*Packet card */-#define BAYCOM 0x10 /* hardware type for BayCom (U)SCC */--/* DEV ioctl() commands */--enum SCC_ioctl_cmds {- SIOCSCCRESERVED = SIOCDEVPRIVATE,- SIOCSCCCFG,- SIOCSCCINI,- SIOCSCCCHANINI,- SIOCSCCSMEM,- SIOCSCCGKISS,- SIOCSCCSKISS,- SIOCSCCGSTAT,- SIOCSCCCAL-};--/* Device parameter control (from WAMPES) */--enum L1_params {- PARAM_DATA,- PARAM_TXDELAY,- PARAM_PERSIST,- PARAM_SLOTTIME,- PARAM_TXTAIL,- PARAM_FULLDUP,- PARAM_SOFTDCD, /* was: PARAM_HW */- PARAM_MUTE, /* ??? */- PARAM_DTR,- PARAM_RTS,- PARAM_SPEED,- PARAM_ENDDELAY, /* ??? */- PARAM_GROUP,- PARAM_IDLE,- PARAM_MIN,- PARAM_MAXKEY,- PARAM_WAIT,- PARAM_MAXDEFER,- PARAM_TX,- PARAM_HWEVENT = 31,- PARAM_RETURN = 255 /* reset kiss mode */-};--/* fulldup parameter */--enum FULLDUP_modes {- KISS_DUPLEX_HALF, /* normal CSMA operation */- KISS_DUPLEX_FULL, /* fullduplex, key down trx after transmission */- KISS_DUPLEX_LINK, /* fullduplex, key down trx after 'idletime' sec */- KISS_DUPLEX_OPTIMA /* fullduplex, let the protocol layer control the hw */-};--/* misc. parameters */--#define TIMER_OFF 65535U /* to switch off timers */-#define NO_SUCH_PARAM 65534U /* param not implemented */--/* HWEVENT parameter */--enum HWEVENT_opts {- HWEV_DCD_ON,- HWEV_DCD_OFF,- HWEV_ALL_SENT-};--/* channel grouping */--#define RXGROUP 0100 /* if set, only tx when all channels clear */-#define TXGROUP 0200 /* if set, don't transmit simultaneously */--/* Tx/Rx clock sources */--enum CLOCK_sources {- CLK_DPLL, /* normal halfduplex operation */- CLK_EXTERNAL, /* external clocking (G3RUH/DF9IC modems) */- CLK_DIVIDER, /* Rx = DPLL, Tx = divider (fullduplex with */- /* modems without clock regeneration */- CLK_BRG /* experimental fullduplex mode with DPLL/BRG for */- /* MODEMs without clock recovery */-};--/* Tx state */--enum TX_state {- TXS_IDLE, /* Transmitter off, no data pending */- TXS_BUSY, /* waiting for permission to send / tailtime */- TXS_ACTIVE, /* Transmitter on, sending data */- TXS_NEWFRAME, /* reset CRC and send (next) frame */- TXS_IDLE2, /* Transmitter on, no data pending */- TXS_WAIT, /* Waiting for Mintime to expire */- TXS_TIMEOUT /* We had a transmission timeout */-};--typedef unsigned long io_port; /* type definition for an 'io port address' */--/* SCC statistical information */--struct scc_stat {- long rxints; /* Receiver interrupts */- long txints; /* Transmitter interrupts */- long exints; /* External/status interrupts */- long spints; /* Special receiver interrupts */-- long txframes; /* Packets sent */- long rxframes; /* Number of Frames Actually Received */- long rxerrs; /* CRC Errors */- long txerrs; /* KISS errors */- - unsigned int nospace; /* "Out of buffers" */- unsigned int rx_over; /* Receiver Overruns */- unsigned int tx_under; /* Transmitter Underruns */-- unsigned int tx_state; /* Transmitter state */- int tx_queued; /* tx frames enqueued */-- unsigned int maxqueue; /* allocated tx_buffers */- unsigned int bufsize; /* used buffersize */-};--struct scc_modem {- long speed; /* Line speed, bps */- char clocksrc; /* 0 = DPLL, 1 = external, 2 = divider */- char nrz; /* NRZ instead of NRZI */ -};--struct scc_kiss_cmd {- int command; /* one of the KISS-Commands defined above */- unsigned param; /* KISS-Param */-};--struct scc_hw_config {- io_port data_a; /* data port channel A */- io_port ctrl_a; /* control port channel A */- io_port data_b; /* data port channel B */- io_port ctrl_b; /* control port channel B */- io_port vector_latch; /* INTACK-Latch (#) */- io_port special; /* special function port */-- int irq; /* irq */- long clock; /* clock */- char option; /* command for function port */-- char brand; /* hardware type */- char escc; /* use ext. features of a 8580/85180/85280 */-};--/* (#) only one INTACK latch allowed. */---struct scc_mem_config {- unsigned int dummy;- unsigned int bufsize;-};--struct scc_calibrate {- unsigned int time;- unsigned char pattern;-};--#endif /* _UAPI_SCC_H */diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.cdeleted file mode 100644index c8b2dc5c1bec..000000000000--- a/drivers/net/hamradio/6pack.c+++ /dev/null@@ -1,912 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-only-/*- * 6pack.c This module implements the 6pack protocol for kernel-based- * devices like TTY. It interfaces between a raw TTY and the- * kernel's AX.25 protocol layers.- *- * Authors: Andreas Könsgen <ajk@comnets.uni-bremen.de>- * Ralf Baechle DL5RB <ralf@linux-mips.org>- *- * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by- *- * Laurence Culhane, <loz@holmes.demon.co.uk>- * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>- */--#include <linux/module.h>-#include <linux/uaccess.h>-#include <linux/bitops.h>-#include <linux/string.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/in.h>-#include <linux/tty.h>-#include <linux/errno.h>-#include <linux/netdevice.h>-#include <linux/timer.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/etherdevice.h>-#include <linux/skbuff.h>-#include <linux/rtnetlink.h>-#include <linux/spinlock.h>-#include <linux/if_arp.h>-#include <linux/init.h>-#include <linux/ip.h>-#include <linux/tcp.h>-#include <linux/semaphore.h>-#include <linux/refcount.h>--/* sixpack priority commands */-#define SIXP_SEOF 0x40 /* start and end of a 6pack frame */-#define SIXP_TX_URUN 0x48 /* transmit overrun */-#define SIXP_RX_ORUN 0x50 /* receive overrun */-#define SIXP_RX_BUF_OVL 0x58 /* receive buffer overflow */--#define SIXP_CHKSUM 0xFF /* valid checksum of a 6pack frame */--/* masks to get certain bits out of the status bytes sent by the TNC */--#define SIXP_CMD_MASK 0xC0-#define SIXP_CHN_MASK 0x07-#define SIXP_PRIO_CMD_MASK 0x80-#define SIXP_STD_CMD_MASK 0x40-#define SIXP_PRIO_DATA_MASK 0x38-#define SIXP_TX_MASK 0x20-#define SIXP_RX_MASK 0x10-#define SIXP_RX_DCD_MASK 0x18-#define SIXP_LEDS_ON 0x78-#define SIXP_LEDS_OFF 0x60-#define SIXP_CON 0x08-#define SIXP_STA 0x10--#define SIXP_FOUND_TNC 0xe9-#define SIXP_CON_ON 0x68-#define SIXP_DCD_MASK 0x08-#define SIXP_DAMA_OFF 0--/* default level 2 parameters */-#define SIXP_TXDELAY 25 /* 250 ms */-#define SIXP_PERSIST 50 /* in 256ths */-#define SIXP_SLOTTIME 10 /* 100 ms */-#define SIXP_INIT_RESYNC_TIMEOUT (3*HZ/2) /* in 1 s */-#define SIXP_RESYNC_TIMEOUT 5*HZ /* in 1 s */--/* 6pack configuration. */-#define SIXP_NRUNIT 31 /* MAX number of 6pack channels */-#define SIXP_MTU 256 /* Default MTU */--enum sixpack_flags {- SIXPF_ERROR, /* Parity, etc. error */-};--struct sixpack {- /* Various fields. */- struct tty_struct *tty; /* ptr to TTY structure */- struct net_device *dev; /* easy for intr handling */-- /* These are pointers to the malloc()ed frame buffers. */- int rcount; /* received chars counter */- unsigned char *xbuff; /* transmitter buffer */- unsigned char *xhead; /* next byte to XMIT */- int xleft; /* bytes left in XMIT queue */-- u8 raw_buf[4];- u8 cooked_buf[400];-- unsigned int rx_count;- unsigned int rx_count_cooked;- spinlock_t rxlock;-- unsigned long flags; /* Flag values/ mode etc */- unsigned char mode; /* 6pack mode */-- /* 6pack stuff */- unsigned char tx_delay;- unsigned char persistence;- unsigned char slottime;- unsigned char duplex;- unsigned char led_state;- u8 status;- u8 status1;- unsigned char status2;- unsigned char tx_enable;- unsigned char tnc_state;-- struct timer_list tx_t;- struct timer_list resync_t;- spinlock_t lock;-};--#define AX25_6PACK_HEADER_LEN 0--static void sixpack_decode(struct sixpack *, const u8 *, size_t);-static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);--/*- * Perform the persistence/slottime algorithm for CSMA access. If the- * persistence check was successful, write the data to the serial driver.- * Note that in case of DAMA operation, the data is not sent here.- */--static void sp_xmit_on_air(struct timer_list *t)-{- struct sixpack *sp = timer_container_of(sp, t, tx_t);- int actual, when = sp->slottime;- static unsigned char random;-- random = random * 17 + 41;-- if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {- sp->led_state = 0x70;- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- sp->tx_enable = 1;- actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);- sp->xleft -= actual;- sp->xhead += actual;- sp->led_state = 0x60;- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- sp->status2 = 0;- } else- mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);-}--/* ----> 6pack timer interrupt handler and friends. <---- */--/* Encapsulate one AX.25 frame and stuff into a TTY queue. */-static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)-{- unsigned char *msg, *p = icp;- int actual, count;-- if (len > AX25_MTU + 73) {- msg = "oversized transmit packet!";- goto out_drop;- }-- if (p[0] > 5) {- msg = "invalid KISS command";- goto out_drop;- }-- if ((p[0] != 0) && (len > 2)) {- msg = "KISS control packet too long";- goto out_drop;- }-- if ((p[0] == 0) && (len < 15)) {- msg = "bad AX.25 packet to transmit";- goto out_drop;- }-- count = encode_sixpack(p, sp->xbuff, len, sp->tx_delay);- set_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);-- switch (p[0]) {- case 1: sp->tx_delay = p[1];- return;- case 2: sp->persistence = p[1];- return;- case 3: sp->slottime = p[1];- return;- case 4: /* ignored */- return;- case 5: sp->duplex = p[1];- return;- }-- if (p[0] != 0)- return;-- /*- * In case of fullduplex or DAMA operation, we don't take care about the- * state of the DCD or of any timers, as the determination of the- * correct time to send is the job of the AX.25 layer. We send- * immediately after data has arrived.- */- if (sp->duplex == 1) {- sp->led_state = 0x70;- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- sp->tx_enable = 1;- actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);- sp->xleft = count - actual;- sp->xhead = sp->xbuff + actual;- sp->led_state = 0x60;- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- } else {- sp->xleft = count;- sp->xhead = sp->xbuff;- sp->status2 = count;- sp_xmit_on_air(&sp->tx_t);- }-- return;--out_drop:- sp->dev->stats.tx_dropped++;- netif_start_queue(sp->dev);- if (net_ratelimit())- printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg);-}--/* Encapsulate an IP datagram and kick it into a TTY queue. */--static netdev_tx_t sp_xmit(struct sk_buff *skb, struct net_device *dev)-{- struct sixpack *sp = netdev_priv(dev);-- if (skb->protocol == htons(ETH_P_IP))- return ax25_ip_xmit(skb);-- spin_lock_bh(&sp->lock);- /* We were not busy, so we are now... :-) */- netif_stop_queue(dev);- dev->stats.tx_bytes += skb->len;- sp_encaps(sp, skb->data, skb->len);- spin_unlock_bh(&sp->lock);-- dev_kfree_skb(skb);-- return NETDEV_TX_OK;-}--static int sp_open_dev(struct net_device *dev)-{- struct sixpack *sp = netdev_priv(dev);-- if (sp->tty == NULL)- return -ENODEV;- return 0;-}--/* Close the low-level part of the 6pack channel. */-static int sp_close(struct net_device *dev)-{- struct sixpack *sp = netdev_priv(dev);-- spin_lock_bh(&sp->lock);- if (sp->tty) {- /* TTY discipline is running. */- clear_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);- }- netif_stop_queue(dev);- spin_unlock_bh(&sp->lock);-- return 0;-}--static int sp_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr_ax25 *sa = addr;-- netif_tx_lock_bh(dev);- netif_addr_lock(dev);- __dev_addr_set(dev, &sa->sax25_call, AX25_ADDR_LEN);- netif_addr_unlock(dev);- netif_tx_unlock_bh(dev);-- return 0;-}--static const struct net_device_ops sp_netdev_ops = {- .ndo_open = sp_open_dev,- .ndo_stop = sp_close,- .ndo_start_xmit = sp_xmit,- .ndo_set_mac_address = sp_set_mac_address,-};--static void sp_setup(struct net_device *dev)-{- /* Finish setting up the DEVICE info. */- dev->netdev_ops = &sp_netdev_ops;- dev->mtu = SIXP_MTU;- dev->hard_header_len = AX25_MAX_HEADER_LEN;- dev->header_ops = &ax25_header_ops;-- dev->addr_len = AX25_ADDR_LEN;- dev->type = ARPHRD_AX25;- dev->tx_queue_len = 10;-- /* Only activated in AX.25 mode */- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);- dev_addr_set(dev, (u8 *)&ax25_defaddr);-- dev->flags = 0;-}--/* Send one completely decapsulated IP datagram to the IP layer. */--/*- * This is the routine that sends the received data to the kernel AX.25.- * 'cmd' is the KISS command. For AX.25 data, it is zero.- */--static void sp_bump(struct sixpack *sp, char cmd)-{- struct sk_buff *skb;- int count;- u8 *ptr;-- count = sp->rcount + 1;-- sp->dev->stats.rx_bytes += count;-- if ((skb = dev_alloc_skb(count + 1)) == NULL)- goto out_mem;-- ptr = skb_put(skb, count + 1);- *ptr++ = cmd; /* KISS command */-- memcpy(ptr, sp->cooked_buf + 1, count);- skb->protocol = ax25_type_trans(skb, sp->dev);- netif_rx(skb);- sp->dev->stats.rx_packets++;-- return;--out_mem:- sp->dev->stats.rx_dropped++;-}---/* ----------------------------------------------------------------------- */--/*- * Called by the TTY driver when there's room for more data. If we have- * more packets to send, we send them here.- */-static void sixpack_write_wakeup(struct tty_struct *tty)-{- struct sixpack *sp = tty->disc_data;- int actual;-- if (!sp)- return;- if (sp->xleft <= 0) {- /* Now serial buffer is almost free & we can start- * transmission of another packet */- sp->dev->stats.tx_packets++;- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);- sp->tx_enable = 0;- netif_wake_queue(sp->dev);- return;- }-- if (sp->tx_enable) {- actual = tty->ops->write(tty, sp->xhead, sp->xleft);- sp->xleft -= actual;- sp->xhead += actual;- }-}--/* ----------------------------------------------------------------------- */--/*- * Handle the 'receiver data ready' interrupt.- * This function is called by the tty module in the kernel when- * a block of 6pack data has been received, which can now be decapsulated- * and sent on to some IP layer for further processing.- */-static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,- const u8 *fp, size_t count)-{- struct sixpack *sp;-- if (!count)- return;-- sp = tty->disc_data;- if (!sp)- return;-- /* Read the characters out of the buffer */- while (count--) {- if (fp && *fp++) {- if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))- sp->dev->stats.rx_errors++;- cp++;- continue;- }- sixpack_decode(sp, cp, 1);- cp++;- }-- tty_unthrottle(tty);-}--/*- * Try to resync the TNC. Called by the resync timer defined in- * decode_prio_command- */--#define TNC_UNINITIALIZED 0-#define TNC_UNSYNC_STARTUP 1-#define TNC_UNSYNCED 2-#define TNC_IN_SYNC 3--static void __tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)-{- char *msg;-- switch (new_tnc_state) {- default: /* gcc oh piece-o-crap ... */- case TNC_UNSYNC_STARTUP:- msg = "Synchronizing with TNC";- break;- case TNC_UNSYNCED:- msg = "Lost synchronization with TNC\n";- break;- case TNC_IN_SYNC:- msg = "Found TNC";- break;- }-- sp->tnc_state = new_tnc_state;- printk(KERN_INFO "%s: %s\n", sp->dev->name, msg);-}--static inline void tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)-{- int old_tnc_state = sp->tnc_state;-- if (old_tnc_state != new_tnc_state)- __tnc_set_sync_state(sp, new_tnc_state);-}--static void resync_tnc(struct timer_list *t)-{- struct sixpack *sp = timer_container_of(sp, t, resync_t);- static char resync_cmd = 0xe8;-- /* clear any data that might have been received */-- sp->rx_count = 0;- sp->rx_count_cooked = 0;-- /* reset state machine */-- sp->status = 1;- sp->status1 = 1;- sp->status2 = 0;-- /* resync the TNC */-- sp->led_state = 0x60;- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- sp->tty->ops->write(sp->tty, &resync_cmd, 1);--- /* Start resync timer again -- the TNC might be still absent */- mod_timer(&sp->resync_t, jiffies + SIXP_RESYNC_TIMEOUT);-}--static inline int tnc_init(struct sixpack *sp)-{- unsigned char inbyte = 0xe8;-- tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);-- sp->tty->ops->write(sp->tty, &inbyte, 1);-- mod_timer(&sp->resync_t, jiffies + SIXP_RESYNC_TIMEOUT);-- return 0;-}--/*- * Open the high-level part of the 6pack channel.- * This function is called by the TTY module when the- * 6pack line discipline is called for. Because we are- * sure the tty line exists, we only have to link it to- * a free 6pcack channel...- */-static int sixpack_open(struct tty_struct *tty)-{- char *xbuff = NULL;- struct net_device *dev;- struct sixpack *sp;- unsigned long len;- int err = 0;-- if (!capable(CAP_NET_ADMIN))- return -EPERM;- if (tty->ops->write == NULL)- return -EOPNOTSUPP;-- dev = alloc_netdev(sizeof(struct sixpack), "sp%d", NET_NAME_UNKNOWN,- sp_setup);- if (!dev) {- err = -ENOMEM;- goto out;- }-- sp = netdev_priv(dev);- sp->dev = dev;-- spin_lock_init(&sp->lock);- spin_lock_init(&sp->rxlock);-- /* !!! length of the buffers. MTU is IP MTU, not PACLEN! */-- len = dev->mtu * 2;-- xbuff = kmalloc(len + 4, GFP_KERNEL);- if (xbuff == NULL) {- err = -ENOBUFS;- goto out_free;- }-- spin_lock_bh(&sp->lock);-- sp->tty = tty;-- sp->xbuff = xbuff;-- sp->rcount = 0;- sp->rx_count = 0;- sp->rx_count_cooked = 0;- sp->xleft = 0;-- sp->flags = 0; /* Clear ESCAPE & ERROR flags */-- sp->duplex = 0;- sp->tx_delay = SIXP_TXDELAY;- sp->persistence = SIXP_PERSIST;- sp->slottime = SIXP_SLOTTIME;- sp->led_state = 0x60;- sp->status = 1;- sp->status1 = 1;- sp->status2 = 0;- sp->tx_enable = 0;-- netif_start_queue(dev);-- timer_setup(&sp->tx_t, sp_xmit_on_air, 0);-- timer_setup(&sp->resync_t, resync_tnc, 0);-- spin_unlock_bh(&sp->lock);-- /* Done. We have linked the TTY line to a channel. */- tty->disc_data = sp;- tty->receive_room = 65536;-- /* Now we're ready to register. */- err = register_netdev(dev);- if (err)- goto out_free;-- tnc_init(sp);-- return 0;--out_free:- kfree(xbuff);-- free_netdev(dev);--out:- return err;-}---/*- * Close down a 6pack channel.- * This means flushing out any pending queues, and then restoring the- * TTY line discipline to what it was before it got hooked to 6pack- * (which usually is TTY again).- */-static void sixpack_close(struct tty_struct *tty)-{- struct sixpack *sp;-- sp = tty->disc_data;- if (!sp)- return;-- tty->disc_data = NULL;-- /* We must stop the queue to avoid potentially scribbling- * on the free buffers. The sp->dead completion is not sufficient- * to protect us from sp->xbuff access.- */- netif_stop_queue(sp->dev);-- unregister_netdev(sp->dev);-- timer_delete_sync(&sp->tx_t);- timer_delete_sync(&sp->resync_t);-- /* Free all 6pack frame buffers after unreg. */- kfree(sp->xbuff);-- free_netdev(sp->dev);-}--/* Perform I/O control on an active 6pack channel. */-static int sixpack_ioctl(struct tty_struct *tty, unsigned int cmd,- unsigned long arg)-{- struct sixpack *sp = tty->disc_data;- struct net_device *dev;- unsigned int tmp, err;-- if (!sp)- return -ENXIO;- dev = sp->dev;-- switch(cmd) {- case SIOCGIFNAME:- err = copy_to_user((void __user *) arg, dev->name,- strlen(dev->name) + 1) ? -EFAULT : 0;- break;-- case SIOCGIFENCAP:- err = put_user(0, (int __user *) arg);- break;-- case SIOCSIFENCAP:- if (get_user(tmp, (int __user *) arg)) {- err = -EFAULT;- break;- }-- sp->mode = tmp;- dev->addr_len = AX25_ADDR_LEN;- dev->hard_header_len = AX25_KISS_HEADER_LEN +- AX25_MAX_HEADER_LEN + 3;- dev->type = ARPHRD_AX25;-- err = 0;- break;-- case SIOCSIFHWADDR: {- char addr[AX25_ADDR_LEN];-- if (copy_from_user(&addr,- (void __user *)arg, AX25_ADDR_LEN)) {- err = -EFAULT;- break;- }-- netif_tx_lock_bh(dev);- __dev_addr_set(dev, &addr, AX25_ADDR_LEN);- netif_tx_unlock_bh(dev);- err = 0;- break;- }- default:- err = tty_mode_ioctl(tty, cmd, arg);- }-- return err;-}--static struct tty_ldisc_ops sp_ldisc = {- .owner = THIS_MODULE,- .num = N_6PACK,- .name = "6pack",- .open = sixpack_open,- .close = sixpack_close,- .ioctl = sixpack_ioctl,- .receive_buf = sixpack_receive_buf,- .write_wakeup = sixpack_write_wakeup,-};--/* Initialize 6pack control device -- register 6pack line discipline */--static int __init sixpack_init_driver(void)-{- int status;-- /* Register the provided line protocol discipline */- status = tty_register_ldisc(&sp_ldisc);- if (status)- pr_err("6pack: can't register line discipline (err = %d)\n", status);-- return status;-}--static void __exit sixpack_exit_driver(void)-{- tty_unregister_ldisc(&sp_ldisc);-}--/* encode an AX.25 packet into 6pack */--static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,- int length, unsigned char tx_delay)-{- int count = 0;- unsigned char checksum = 0, buf[400];- int raw_count = 0;-- tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;- tx_buf_raw[raw_count++] = SIXP_SEOF;-- buf[0] = tx_delay;- for (count = 1; count < length; count++)- buf[count] = tx_buf[count];-- for (count = 0; count < length; count++)- checksum += buf[count];- buf[length] = (unsigned char) 0xff - checksum;-- for (count = 0; count <= length; count++) {- if ((count % 3) == 0) {- tx_buf_raw[raw_count++] = (buf[count] & 0x3f);- tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);- } else if ((count % 3) == 1) {- tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);- tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x3c);- } else {- tx_buf_raw[raw_count++] |= (buf[count] & 0x03);- tx_buf_raw[raw_count++] = (buf[count] >> 2);- }- }- if ((length % 3) != 2)- raw_count++;- tx_buf_raw[raw_count++] = SIXP_SEOF;- return raw_count;-}--/* decode 4 sixpack-encoded bytes into 3 data bytes */--static void decode_data(struct sixpack *sp, u8 inbyte)-{- u8 *buf;-- if (sp->rx_count != 3) {- sp->raw_buf[sp->rx_count++] = inbyte;-- return;- }-- if (sp->rx_count_cooked + 2 >= sizeof(sp->cooked_buf)) {- pr_err("6pack: cooked buffer overrun, data loss\n");- sp->rx_count = 0;- return;- }-- buf = sp->raw_buf;- sp->cooked_buf[sp->rx_count_cooked++] =- buf[0] | ((buf[1] << 2) & 0xc0);- sp->cooked_buf[sp->rx_count_cooked++] =- (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);- sp->cooked_buf[sp->rx_count_cooked++] =- (buf[2] & 0x03) | (inbyte << 2);- sp->rx_count = 0;-}--/* identify and execute a 6pack priority command byte */--static void decode_prio_command(struct sixpack *sp, u8 cmd)-{- ssize_t actual;-- if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */-- /* RX and DCD flags can only be set in the same prio command,- if the DCD flag has been set without the RX flag in the previous- prio command. If DCD has not been set before, something in the- transmission has gone wrong. In this case, RX and DCD are- cleared in order to prevent the decode_data routine from- reading further data that might be corrupt. */-- if (((sp->status & SIXP_DCD_MASK) == 0) &&- ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {- if (sp->status != 1)- printk(KERN_DEBUG "6pack: protocol violation\n");- else- sp->status = 0;- cmd &= ~SIXP_RX_DCD_MASK;- }- sp->status = cmd & SIXP_PRIO_DATA_MASK;- } else { /* output watchdog char if idle */- if ((sp->status2 != 0) && (sp->duplex == 1)) {- sp->led_state = 0x70;- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- sp->tx_enable = 1;- actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);- sp->xleft -= actual;- sp->xhead += actual;- sp->led_state = 0x60;- sp->status2 = 0;-- }- }-- /* needed to trigger the TNC watchdog */- sp->tty->ops->write(sp->tty, &sp->led_state, 1);-- /* if the state byte has been received, the TNC is present,- so the resync timer can be reset. */-- if (sp->tnc_state == TNC_IN_SYNC)- mod_timer(&sp->resync_t, jiffies + SIXP_INIT_RESYNC_TIMEOUT);-- sp->status1 = cmd & SIXP_PRIO_DATA_MASK;-}--/* identify and execute a standard 6pack command byte */--static void decode_std_command(struct sixpack *sp, u8 cmd)-{- u8 checksum = 0, rest = 0;- short i;-- switch (cmd & SIXP_CMD_MASK) { /* normal command */- case SIXP_SEOF:- if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {- if ((sp->status & SIXP_RX_DCD_MASK) ==- SIXP_RX_DCD_MASK) {- sp->led_state = 0x68;- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- }- } else {- sp->led_state = 0x60;- /* fill trailing bytes with zeroes */- sp->tty->ops->write(sp->tty, &sp->led_state, 1);- spin_lock_bh(&sp->rxlock);- rest = sp->rx_count;- if (rest != 0)- for (i = rest; i <= 3; i++)- decode_data(sp, 0);- if (rest == 2)- sp->rx_count_cooked -= 2;- else if (rest == 3)- sp->rx_count_cooked -= 1;- for (i = 0; i < sp->rx_count_cooked; i++)- checksum += sp->cooked_buf[i];- if (checksum != SIXP_CHKSUM) {- printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);- } else {- sp->rcount = sp->rx_count_cooked-2;- sp_bump(sp, 0);- }- sp->rx_count_cooked = 0;- spin_unlock_bh(&sp->rxlock);- }- break;- case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");- break;- case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");- break;- case SIXP_RX_BUF_OVL:- printk(KERN_DEBUG "6pack: RX buffer overflow\n");- }-}--/* decode a 6pack packet */--static void-sixpack_decode(struct sixpack *sp, const u8 *pre_rbuff, size_t count)-{- size_t count1;- u8 inbyte;-- for (count1 = 0; count1 < count; count1++) {- inbyte = pre_rbuff[count1];- if (inbyte == SIXP_FOUND_TNC) {- tnc_set_sync_state(sp, TNC_IN_SYNC);- timer_delete(&sp->resync_t);- }- if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)- decode_prio_command(sp, inbyte);- else if ((inbyte & SIXP_STD_CMD_MASK) != 0)- decode_std_command(sp, inbyte);- else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) {- spin_lock_bh(&sp->rxlock);- decode_data(sp, inbyte);- spin_unlock_bh(&sp->rxlock);- }- }-}--MODULE_AUTHOR("Ralf Baechle DO1GRB <ralf@linux-mips.org>");-MODULE_DESCRIPTION("6pack driver for AX.25");-MODULE_LICENSE("GPL");-MODULE_ALIAS_LDISC(N_6PACK);--module_init(sixpack_init_driver);-module_exit(sixpack_exit_driver);diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.cdeleted file mode 100644index 5fda7a0fcce0..000000000000--- a/drivers/net/hamradio/baycom_epp.c+++ /dev/null@@ -1,1316 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*****************************************************************************/--/*- * baycom_epp.c -- baycom epp radio modem driver.- *- * Copyright (C) 1998-2000- * Thomas Sailer (sailer@ife.ee.ethz.ch)- *- * Please note that the GPL allows you to use the driver, NOT the radio.- * In order to use the radio, you need a license from the communications- * authority of your country.- *- * History:- * 0.1 xx.xx.1998 Initial version by Matthias Welwarsky (dg2fef)- * 0.2 21.04.1998 Massive rework by Thomas Sailer- * Integrated FPGA EPP modem configuration routines- * 0.3 11.05.1998 Took FPGA config out and moved it into a separate program- * 0.4 26.07.1999 Adapted to new lowlevel parport driver interface- * 0.5 03.08.1999 adapt to Linus' new __setup/__initcall- * removed some pre-2.2 kernel compatibility cruft- * 0.6 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts- * 0.7 12.02.2000 adapted to softnet driver interface- */--/*****************************************************************************/--#include <linux/crc-ccitt.h>-#include <linux/module.h>-#include <linux/kernel.h>-#include <linux/init.h>-#include <linux/sched.h>-#include <linux/string.h>-#include <linux/workqueue.h>-#include <linux/fs.h>-#include <linux/parport.h>-#include <linux/if_arp.h>-#include <linux/hdlcdrv.h>-#include <linux/baycom.h>-#include <linux/jiffies.h>-#include <linux/random.h>-#include <net/ax25.h> -#include <linux/uaccess.h>--/* --------------------------------------------------------------------- */--#define BAYCOM_DEBUG-#define BAYCOM_MAGIC 19730510--/* --------------------------------------------------------------------- */--static const char paranoia_str[] = KERN_ERR - "baycom_epp: bad magic number for hdlcdrv_state struct in routine %s\n";--static const char bc_drvname[] = "baycom_epp";-static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"-"baycom_epp: version 0.7\n";--/* --------------------------------------------------------------------- */--#define NR_PORTS 4--static struct net_device *baycom_device[NR_PORTS];--/* --------------------------------------------------------------------- */--/* EPP status register */-#define EPP_DCDBIT 0x80-#define EPP_PTTBIT 0x08-#define EPP_NREF 0x01-#define EPP_NRAEF 0x02-#define EPP_NRHF 0x04-#define EPP_NTHF 0x20-#define EPP_NTAEF 0x10-#define EPP_NTEF EPP_PTTBIT--/* EPP control register */-#define EPP_TX_FIFO_ENABLE 0x10-#define EPP_RX_FIFO_ENABLE 0x08-#define EPP_MODEM_ENABLE 0x20-#define EPP_LEDS 0xC0-#define EPP_IRQ_ENABLE 0x10--/* LPT registers */-#define LPTREG_ECONTROL 0x402-#define LPTREG_CONFIGB 0x401-#define LPTREG_CONFIGA 0x400-#define LPTREG_EPPDATA 0x004-#define LPTREG_EPPADDR 0x003-#define LPTREG_CONTROL 0x002-#define LPTREG_STATUS 0x001-#define LPTREG_DATA 0x000--/* LPT control register */-#define LPTCTRL_PROGRAM 0x04 /* 0 to reprogram */-#define LPTCTRL_WRITE 0x01-#define LPTCTRL_ADDRSTB 0x08-#define LPTCTRL_DATASTB 0x02-#define LPTCTRL_INTEN 0x10--/* LPT status register */-#define LPTSTAT_SHIFT_NINTR 6-#define LPTSTAT_WAIT 0x80-#define LPTSTAT_NINTR (1<<LPTSTAT_SHIFT_NINTR)-#define LPTSTAT_PE 0x20-#define LPTSTAT_DONE 0x10-#define LPTSTAT_NERROR 0x08-#define LPTSTAT_EPPTIMEOUT 0x01--/* LPT data register */-#define LPTDATA_SHIFT_TDI 0-#define LPTDATA_SHIFT_TMS 2-#define LPTDATA_TDI (1<<LPTDATA_SHIFT_TDI)-#define LPTDATA_TCK 0x02-#define LPTDATA_TMS (1<<LPTDATA_SHIFT_TMS)-#define LPTDATA_INITBIAS 0x80---/* EPP modem config/status bits */-#define EPP_DCDBIT 0x80-#define EPP_PTTBIT 0x08-#define EPP_RXEBIT 0x01-#define EPP_RXAEBIT 0x02-#define EPP_RXHFULL 0x04--#define EPP_NTHF 0x20-#define EPP_NTAEF 0x10-#define EPP_NTEF EPP_PTTBIT--#define EPP_TX_FIFO_ENABLE 0x10-#define EPP_RX_FIFO_ENABLE 0x08-#define EPP_MODEM_ENABLE 0x20-#define EPP_LEDS 0xC0-#define EPP_IRQ_ENABLE 0x10--/* Xilinx 4k JTAG instructions */-#define XC4K_IRLENGTH 3-#define XC4K_EXTEST 0-#define XC4K_PRELOAD 1-#define XC4K_CONFIGURE 5-#define XC4K_BYPASS 7--#define EPP_CONVENTIONAL 0-#define EPP_FPGA 1-#define EPP_FPGAEXTSTATUS 2--#define TXBUFFER_SIZE ((HDLCDRV_MAXFLEN*6/5)+8)--/* ---------------------------------------------------------------------- */-/*- * Information that need to be kept for each board.- */--struct baycom_state {- int magic;-- struct pardevice *pdev;- struct net_device *dev;- unsigned int work_running;- struct delayed_work run_work;- unsigned int modem;- unsigned int bitrate;- unsigned char stat;-- struct {- unsigned int intclk;- unsigned int fclk;- unsigned int bps;- unsigned int extmodem;- unsigned int loopback;- } cfg;-- struct hdlcdrv_channel_params ch_params;-- struct {- unsigned int bitbuf, bitstream, numbits, state;- unsigned char *bufptr;- int bufcnt;- unsigned char buf[TXBUFFER_SIZE];- } hdlcrx;-- struct {- int calibrate;- int slotcnt;- int flags;- enum { tx_idle = 0, tx_keyup, tx_data, tx_tail } state;- unsigned char *bufptr;- int bufcnt;- unsigned char buf[TXBUFFER_SIZE];- } hdlctx;-- unsigned int ptt_keyed;- struct sk_buff *skb; /* next transmit packet */--#ifdef BAYCOM_DEBUG- struct debug_vals {- unsigned long last_jiffies;- unsigned cur_intcnt;- unsigned last_intcnt;- int cur_pllcorr;- int last_pllcorr;- unsigned int mod_cycles;- unsigned int demod_cycles;- } debug_vals;-#endif /* BAYCOM_DEBUG */-};--/* --------------------------------------------------------------------- */--#define KISS_VERBOSE--/* --------------------------------------------------------------------- */--#define PARAM_TXDELAY 1-#define PARAM_PERSIST 2-#define PARAM_SLOTTIME 3-#define PARAM_TXTAIL 4-#define PARAM_FULLDUP 5-#define PARAM_HARDWARE 6-#define PARAM_RETURN 255--/* --------------------------------------------------------------------- */-/*- * the CRC routines are stolen from WAMPES- * by Dieter Deyke- */---/*---------------------------------------------------------------------------*/--#if 0-static inline void append_crc_ccitt(unsigned char *buffer, int len)-{- unsigned int crc = 0xffff;-- for (;len>0;len--)- crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buffer++) & 0xff];- crc ^= 0xffff;- *buffer++ = crc;- *buffer++ = crc >> 8;-}-#endif--/*---------------------------------------------------------------------------*/--static inline int check_crc_ccitt(const unsigned char *buf, int cnt)-{- return (crc_ccitt(0xffff, buf, cnt) & 0xffff) == 0xf0b8;-}--/*---------------------------------------------------------------------------*/--static inline int calc_crc_ccitt(const unsigned char *buf, int cnt)-{- return (crc_ccitt(0xffff, buf, cnt) ^ 0xffff) & 0xffff;-}--/* ---------------------------------------------------------------------- */--#define tenms_to_flags(bc,tenms) ((tenms * bc->bitrate) / 800)--/* --------------------------------------------------------------------- */--static inline void baycom_int_freq(struct baycom_state *bc)-{-#ifdef BAYCOM_DEBUG- unsigned long cur_jiffies = jiffies;- /*- * measure the interrupt frequency- */- bc->debug_vals.cur_intcnt++;- if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {- bc->debug_vals.last_jiffies = cur_jiffies;- bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;- bc->debug_vals.cur_intcnt = 0;- bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;- bc->debug_vals.cur_pllcorr = 0;- }-#endif /* BAYCOM_DEBUG */-}--/* ---------------------------------------------------------------------- */-/*- * eppconfig_path should be setable via /proc/sys.- */--static char const eppconfig_path[] = "/usr/sbin/eppfpga";--static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };--/* eppconfig: called during ifconfig up to configure the modem */-static int eppconfig(struct baycom_state *bc)-{- char modearg[256];- char portarg[16];- char *argv[] = {- (char *)eppconfig_path,- "-s",- "-p", portarg,- "-m", modearg,- NULL };-- /* set up arguments */- sprintf(modearg, "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat",- bc->cfg.intclk ? "int" : "ext",- bc->cfg.extmodem ? "ext" : "int", bc->cfg.fclk, bc->cfg.bps,- (bc->cfg.fclk + 8 * bc->cfg.bps) / (16 * bc->cfg.bps),- bc->cfg.loopback ? ",loopback" : "");- sprintf(portarg, "%ld", bc->pdev->port->base);- printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);-- return call_usermodehelper(eppconfig_path, argv, envp, UMH_WAIT_PROC);-}--/* ---------------------------------------------------------------------- */--static inline void do_kiss_params(struct baycom_state *bc,- unsigned char *data, unsigned long len)-{--#ifdef KISS_VERBOSE-#define PKP(a,b) printk(KERN_INFO "baycomm_epp: channel params: " a "\n", b)-#else /* KISS_VERBOSE */ -#define PKP(a,b) -#endif /* KISS_VERBOSE */ -- if (len < 2)- return;- switch(data[0]) {- case PARAM_TXDELAY:- bc->ch_params.tx_delay = data[1];- PKP("TX delay = %ums", 10 * bc->ch_params.tx_delay);- break;- case PARAM_PERSIST: - bc->ch_params.ppersist = data[1];- PKP("p persistence = %u", bc->ch_params.ppersist);- break;- case PARAM_SLOTTIME: - bc->ch_params.slottime = data[1];- PKP("slot time = %ums", bc->ch_params.slottime);- break;- case PARAM_TXTAIL: - bc->ch_params.tx_tail = data[1];- PKP("TX tail = %ums", bc->ch_params.tx_tail);- break;- case PARAM_FULLDUP: - bc->ch_params.fulldup = !!data[1];- PKP("%s duplex", bc->ch_params.fulldup ? "full" : "half");- break;- default:- break;- }-#undef PKP-}--/* --------------------------------------------------------------------- */--static void encode_hdlc(struct baycom_state *bc)-{- struct sk_buff *skb;- unsigned char *wp, *bp;- int pkt_len;- unsigned bitstream, notbitstream, bitbuf, numbit, crc;- unsigned char crcarr[2];- int j;- - if (bc->hdlctx.bufcnt > 0)- return;- skb = bc->skb;- if (!skb)- return;- bc->skb = NULL;- pkt_len = skb->len-1; /* strip KISS byte */- wp = bc->hdlctx.buf;- bp = skb->data+1;- crc = calc_crc_ccitt(bp, pkt_len);- crcarr[0] = crc;- crcarr[1] = crc >> 8;- *wp++ = 0x7e;- bitstream = bitbuf = numbit = 0;- while (pkt_len > -2) {- bitstream >>= 8;- bitstream |= ((unsigned int)*bp) << 8;- bitbuf |= ((unsigned int)*bp) << numbit;- notbitstream = ~bitstream;- bp++;- pkt_len--;- if (!pkt_len)- bp = crcarr;- for (j = 0; j < 8; j++)- if (unlikely(!(notbitstream & (0x1f0 << j)))) {- bitstream &= ~(0x100 << j);- bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |- ((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);- numbit++;- notbitstream = ~bitstream;- }- numbit += 8;- while (numbit >= 8) {- *wp++ = bitbuf;- bitbuf >>= 8;- numbit -= 8;- }- }- bitbuf |= 0x7e7e << numbit;- numbit += 16;- while (numbit >= 8) {- *wp++ = bitbuf;- bitbuf >>= 8;- numbit -= 8;- }- bc->hdlctx.bufptr = bc->hdlctx.buf;- bc->hdlctx.bufcnt = wp - bc->hdlctx.buf;- dev_kfree_skb(skb);- bc->dev->stats.tx_packets++;-}--/* ---------------------------------------------------------------------- */--static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)-{- struct parport *pp = bc->pdev->port;- unsigned char tmp[128];- int i, j;-- if (bc->hdlctx.state == tx_tail && !(stat & EPP_PTTBIT))- bc->hdlctx.state = tx_idle;- if (bc->hdlctx.state == tx_idle && bc->hdlctx.calibrate <= 0) {- if (bc->hdlctx.bufcnt <= 0)- encode_hdlc(bc);- if (bc->hdlctx.bufcnt <= 0)- return 0;- if (!bc->ch_params.fulldup) {- if (!(stat & EPP_DCDBIT)) {- bc->hdlctx.slotcnt = bc->ch_params.slottime;- return 0;- }- if ((--bc->hdlctx.slotcnt) > 0)- return 0;- bc->hdlctx.slotcnt = bc->ch_params.slottime;- if (get_random_u8() > bc->ch_params.ppersist)- return 0;- }- }- if (bc->hdlctx.state == tx_idle && bc->hdlctx.bufcnt > 0) {- bc->hdlctx.state = tx_keyup;- bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_delay);- bc->ptt_keyed++;- }- while (cnt > 0) {- switch (bc->hdlctx.state) {- case tx_keyup:- i = min_t(int, cnt, bc->hdlctx.flags);- cnt -= i;- bc->hdlctx.flags -= i;- if (bc->hdlctx.flags <= 0)- bc->hdlctx.state = tx_data;- memset(tmp, 0x7e, sizeof(tmp));- while (i > 0) {- j = (i > sizeof(tmp)) ? sizeof(tmp) : i;- if (j != pp->ops->epp_write_data(pp, tmp, j, 0))- return -1;- i -= j;- }- break;-- case tx_data:- if (bc->hdlctx.bufcnt <= 0) {- encode_hdlc(bc);- if (bc->hdlctx.bufcnt <= 0) {- bc->hdlctx.state = tx_tail;- bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_tail);- break;- }- }- i = min_t(int, cnt, bc->hdlctx.bufcnt);- bc->hdlctx.bufcnt -= i;- cnt -= i;- if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i, 0))- return -1;- bc->hdlctx.bufptr += i;- break;- - case tx_tail:- encode_hdlc(bc);- if (bc->hdlctx.bufcnt > 0) {- bc->hdlctx.state = tx_data;- break;- }- i = min_t(int, cnt, bc->hdlctx.flags);- if (i) {- cnt -= i;- bc->hdlctx.flags -= i;- memset(tmp, 0x7e, sizeof(tmp));- while (i > 0) {- j = (i > sizeof(tmp)) ? sizeof(tmp) : i;- if (j != pp->ops->epp_write_data(pp, tmp, j, 0))- return -1;- i -= j;- }- break;- }- fallthrough;-- default:- if (bc->hdlctx.calibrate <= 0)- return 0;- i = min_t(int, cnt, bc->hdlctx.calibrate);- cnt -= i;- bc->hdlctx.calibrate -= i;- memset(tmp, 0, sizeof(tmp));- while (i > 0) {- j = (i > sizeof(tmp)) ? sizeof(tmp) : i;- if (j != pp->ops->epp_write_data(pp, tmp, j, 0))- return -1;- i -= j;- }- break;- }- }- return 0;-}--/* ---------------------------------------------------------------------- */--static void do_rxpacket(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);- struct sk_buff *skb;- unsigned char *cp;- unsigned pktlen;-- if (bc->hdlcrx.bufcnt < 4) - return;- if (!check_crc_ccitt(bc->hdlcrx.buf, bc->hdlcrx.bufcnt)) - return;- pktlen = bc->hdlcrx.bufcnt-2+1; /* KISS kludge */- if (!(skb = dev_alloc_skb(pktlen))) {- printk("%s: memory squeeze, dropping packet\n", dev->name);- dev->stats.rx_dropped++;- return;- }- cp = skb_put(skb, pktlen);- *cp++ = 0; /* KISS kludge */- memcpy(cp, bc->hdlcrx.buf, pktlen - 1);- skb->protocol = ax25_type_trans(skb, dev);- netif_rx(skb);- dev->stats.rx_packets++;-}--static int receive(struct net_device *dev, int cnt)-{- struct baycom_state *bc = netdev_priv(dev);- struct parport *pp = bc->pdev->port;- unsigned int bitbuf, notbitstream, bitstream, numbits, state;- unsigned char tmp[128];- unsigned char *cp;- int cnt2, ret = 0;- int j;- - numbits = bc->hdlcrx.numbits;- state = bc->hdlcrx.state;- bitstream = bc->hdlcrx.bitstream;- bitbuf = bc->hdlcrx.bitbuf;- while (cnt > 0) {- cnt2 = (cnt > sizeof(tmp)) ? sizeof(tmp) : cnt;- cnt -= cnt2;- if (cnt2 != pp->ops->epp_read_data(pp, tmp, cnt2, 0)) {- ret = -1;- break;- }- cp = tmp;- for (; cnt2 > 0; cnt2--, cp++) {- bitstream >>= 8;- bitstream |= (*cp) << 8;- bitbuf >>= 8;- bitbuf |= (*cp) << 8;- numbits += 8;- notbitstream = ~bitstream;- for (j = 0; j < 8; j++) {-- /* flag or abort */- if (unlikely(!(notbitstream & (0x0fc << j)))) {-- /* abort received */- if (!(notbitstream & (0x1fc << j)))- state = 0;-- /* flag received */- else if ((bitstream & (0x1fe << j)) == (0x0fc << j)) {- if (state)- do_rxpacket(dev);- bc->hdlcrx.bufcnt = 0;- bc->hdlcrx.bufptr = bc->hdlcrx.buf;- state = 1;- numbits = 7-j;- }- }-- /* stuffed bit */- else if (unlikely((bitstream & (0x1f8 << j)) == (0xf8 << j))) {- numbits--;- bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);- }- }- while (state && numbits >= 8) {- if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) {- state = 0;- } else {- *(bc->hdlcrx.bufptr)++ = bitbuf >> (16-numbits);- bc->hdlcrx.bufcnt++;- numbits -= 8;- }- }- }- }- bc->hdlcrx.numbits = numbits;- bc->hdlcrx.state = state;- bc->hdlcrx.bitstream = bitstream;- bc->hdlcrx.bitbuf = bitbuf;- return ret;-}--/* --------------------------------------------------------------------- */--#define GETTICK(x) \-({ \- x = (unsigned int)get_cycles(); \-})--static void epp_bh(struct work_struct *work)-{- struct net_device *dev;- struct baycom_state *bc;- struct parport *pp;- unsigned char stat;- unsigned char tmp[2];- unsigned int time1 = 0, time2 = 0, time3 = 0;- int cnt, cnt2;-- bc = container_of(work, struct baycom_state, run_work.work);- dev = bc->dev;- if (!bc->work_running)- return;- baycom_int_freq(bc);- pp = bc->pdev->port;- /* update status */- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)- goto epptimeout;- bc->stat = stat;- bc->debug_vals.last_pllcorr = stat;- GETTICK(time1);- if (bc->modem == EPP_FPGAEXTSTATUS) {- /* get input count */- tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1;- if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)- goto epptimeout;- if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2)- goto epptimeout;- cnt = tmp[0] | (tmp[1] << 8);- cnt &= 0x7fff;- /* get output count */- tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2;- if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)- goto epptimeout;- if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2)- goto epptimeout;- cnt2 = tmp[0] | (tmp[1] << 8);- cnt2 = 16384 - (cnt2 & 0x7fff);- /* return to normal */- tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE;- if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)- goto epptimeout;- if (transmit(bc, cnt2, stat))- goto epptimeout;- GETTICK(time2);- if (receive(dev, cnt))- goto epptimeout;- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)- goto epptimeout;- bc->stat = stat;- } else {- /* try to tx */- switch (stat & (EPP_NTAEF|EPP_NTHF)) {- case EPP_NTHF:- cnt = 2048 - 256;- break;- - case EPP_NTAEF:- cnt = 2048 - 1793;- break;- - case 0:- cnt = 0;- break;- - default:- cnt = 2048 - 1025;- break;- }- if (transmit(bc, cnt, stat))- goto epptimeout;- GETTICK(time2);- /* do receiver */- while ((stat & (EPP_NRAEF|EPP_NRHF)) != EPP_NRHF) {- switch (stat & (EPP_NRAEF|EPP_NRHF)) {- case EPP_NRAEF:- cnt = 1025;- break;-- case 0:- cnt = 1793;- break;-- default:- cnt = 256;- break;- }- if (receive(dev, cnt))- goto epptimeout;- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)- goto epptimeout;- }- cnt = 0;- if (bc->bitrate < 50000)- cnt = 256;- else if (bc->bitrate < 100000)- cnt = 128;- while (cnt > 0 && stat & EPP_NREF) {- if (receive(dev, 1))- goto epptimeout;- cnt--;- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)- goto epptimeout;- }- }- GETTICK(time3);-#ifdef BAYCOM_DEBUG- bc->debug_vals.mod_cycles = time2 - time1;- bc->debug_vals.demod_cycles = time3 - time2;-#endif /* BAYCOM_DEBUG */- schedule_delayed_work(&bc->run_work, 1);- if (!bc->skb)- netif_wake_queue(dev);- return;- epptimeout:- printk(KERN_ERR "%s: EPP timeout!\n", bc_drvname);-}--/* ---------------------------------------------------------------------- */-/*- * ===================== network driver interface =========================- */--static netdev_tx_t baycom_send_packet(struct sk_buff *skb, struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);-- if (skb->protocol == htons(ETH_P_IP))- return ax25_ip_xmit(skb);-- if (skb->data[0] != 0) {- do_kiss_params(bc, skb->data, skb->len);- dev_kfree_skb(skb);- return NETDEV_TX_OK;- }- if (bc->skb) {- dev_kfree_skb(skb);- return NETDEV_TX_OK;- }- /* strip KISS byte */- if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) {- dev_kfree_skb(skb);- return NETDEV_TX_OK;- }- netif_stop_queue(dev);- bc->skb = skb;- return NETDEV_TX_OK;-}--/* --------------------------------------------------------------------- */--static int baycom_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr *sa = (struct sockaddr *)addr;-- /* addr is an AX.25 shifted ASCII mac address */- dev_addr_set(dev, sa->sa_data);- return 0; -}--/* --------------------------------------------------------------------- */--static void epp_wakeup(void *handle)-{- struct net_device *dev = (struct net_device *)handle;- struct baycom_state *bc = netdev_priv(dev);-- printk(KERN_DEBUG "baycom_epp: %s: why am I being woken up?\n", dev->name);- if (!parport_claim(bc->pdev))- printk(KERN_DEBUG "baycom_epp: %s: I'm broken.\n", dev->name);-}--/* --------------------------------------------------------------------- */--/*- * Open/initialize the board. This is called (in the current kernel)- * sometime after booting when the 'ifconfig' program is run.- *- * This routine should set everything up anew at each open, even- * registers that "should" only need to be set once at boot, so that- * there is non-reboot way to recover if something goes wrong.- */--static int epp_open(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);- struct parport *pp = parport_find_base(dev->base_addr);- unsigned int i, j;- unsigned char tmp[128];- unsigned char stat;- unsigned long tstart;- struct pardev_cb par_cb;- - if (!pp) {- printk(KERN_ERR "%s: parport at 0x%lx unknown\n", bc_drvname, dev->base_addr);- return -ENXIO;- }-#if 0- if (pp->irq < 0) {- printk(KERN_ERR "%s: parport at 0x%lx has no irq\n", bc_drvname, pp->base);- parport_put_port(pp);- return -ENXIO;- }-#endif- if ((~pp->modes) & (PARPORT_MODE_TRISTATE | PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) {- printk(KERN_ERR "%s: parport at 0x%lx cannot be used\n",- bc_drvname, pp->base);- parport_put_port(pp);- return -EIO;- }- memset(&bc->modem, 0, sizeof(bc->modem));- memset(&par_cb, 0, sizeof(par_cb));- par_cb.wakeup = epp_wakeup;- par_cb.private = (void *)dev;- par_cb.flags = PARPORT_DEV_EXCL;- for (i = 0; i < NR_PORTS; i++)- if (baycom_device[i] == dev)- break;-- if (i == NR_PORTS) {- pr_err("%s: no device found\n", bc_drvname);- parport_put_port(pp);- return -ENODEV;- }-- bc->pdev = parport_register_dev_model(pp, dev->name, &par_cb, i);- parport_put_port(pp);- if (!bc->pdev) {- printk(KERN_ERR "%s: cannot register parport at 0x%lx\n", bc_drvname, pp->base);- return -ENXIO;- }- if (parport_claim(bc->pdev)) {- printk(KERN_ERR "%s: parport at 0x%lx busy\n", bc_drvname, pp->base);- parport_unregister_device(bc->pdev);- return -EBUSY;- }- dev->irq = /*pp->irq*/ 0;- INIT_DELAYED_WORK(&bc->run_work, epp_bh);- bc->work_running = 1;- bc->modem = EPP_CONVENTIONAL;- if (eppconfig(bc))- printk(KERN_INFO "%s: no FPGA detected, assuming conventional EPP modem\n", bc_drvname);- else- bc->modem = /*EPP_FPGA*/ EPP_FPGAEXTSTATUS;- parport_write_control(pp, LPTCTRL_PROGRAM); /* prepare EPP mode; we aren't using interrupts */- /* reset the modem */- tmp[0] = 0;- tmp[1] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE;- if (pp->ops->epp_write_addr(pp, tmp, 2, 0) != 2)- goto epptimeout;- /* autoprobe baud rate */- tstart = jiffies;- i = 0;- while (time_before(jiffies, tstart + HZ/3)) {- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)- goto epptimeout;- if ((stat & (EPP_NRAEF|EPP_NRHF)) == EPP_NRHF) {- schedule();- continue;- }- if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128)- goto epptimeout;- if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128)- goto epptimeout;- i += 256;- }- for (j = 0; j < 256; j++) {- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)- goto epptimeout;- if (!(stat & EPP_NREF))- break;- if (pp->ops->epp_read_data(pp, tmp, 1, 0) != 1)- goto epptimeout;- i++;- }- tstart = jiffies - tstart;- bc->bitrate = i * (8 * HZ) / tstart;- j = 1;- i = bc->bitrate >> 3;- while (j < 7 && i > 150) {- j++;- i >>= 1;- }- printk(KERN_INFO "%s: autoprobed bitrate: %d int divider: %d int rate: %d\n", - bc_drvname, bc->bitrate, j, bc->bitrate >> (j+2));- tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE/*|j*/;- if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)- goto epptimeout;- /*- * initialise hdlc variables- */- bc->hdlcrx.state = 0;- bc->hdlcrx.numbits = 0;- bc->hdlctx.state = tx_idle;- bc->hdlctx.bufcnt = 0;- bc->hdlctx.slotcnt = bc->ch_params.slottime;- bc->hdlctx.calibrate = 0;- /* start the bottom half stuff */- schedule_delayed_work(&bc->run_work, 1);- netif_start_queue(dev);- return 0;-- epptimeout:- printk(KERN_ERR "%s: epp timeout during bitrate probe\n", bc_drvname);- parport_write_control(pp, 0); /* reset the adapter */- parport_release(bc->pdev);- parport_unregister_device(bc->pdev);- return -EIO;-}--/* --------------------------------------------------------------------- */--static int epp_close(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);- struct parport *pp = bc->pdev->port;- unsigned char tmp[1];-- bc->work_running = 0;- cancel_delayed_work_sync(&bc->run_work);- bc->stat = EPP_DCDBIT;- tmp[0] = 0;- pp->ops->epp_write_addr(pp, tmp, 1, 0);- parport_write_control(pp, 0); /* reset the adapter */- parport_release(bc->pdev);- parport_unregister_device(bc->pdev);- dev_kfree_skb(bc->skb);- bc->skb = NULL;- printk(KERN_INFO "%s: close epp at iobase 0x%lx irq %u\n",- bc_drvname, dev->base_addr, dev->irq);- return 0;-}--/* --------------------------------------------------------------------- */--static int baycom_setmode(struct baycom_state *bc, const char *modestr)-{- const char *cp;-- if (strstr(modestr,"intclk"))- bc->cfg.intclk = 1;- if (strstr(modestr,"extclk"))- bc->cfg.intclk = 0;- if (strstr(modestr,"intmodem"))- bc->cfg.extmodem = 0;- if (strstr(modestr,"extmodem"))- bc->cfg.extmodem = 1;- if (strstr(modestr,"loopback"))- bc->cfg.loopback = 1;- if (strstr(modestr, "noloopback"))- bc->cfg.loopback = 0;- if ((cp = strstr(modestr,"fclk="))) {- bc->cfg.fclk = simple_strtoul(cp+5, NULL, 0);- if (bc->cfg.fclk < 1000000)- bc->cfg.fclk = 1000000;- if (bc->cfg.fclk > 25000000)- bc->cfg.fclk = 25000000;- }- if ((cp = strstr(modestr,"bps="))) {- bc->cfg.bps = simple_strtoul(cp+4, NULL, 0);- if (bc->cfg.bps < 1000)- bc->cfg.bps = 1000;- if (bc->cfg.bps > 1500000)- bc->cfg.bps = 1500000;- }- return 0;-}--/* --------------------------------------------------------------------- */--static int baycom_siocdevprivate(struct net_device *dev, struct ifreq *ifr,- void __user *data, int cmd)-{- struct baycom_state *bc = netdev_priv(dev);- struct hdlcdrv_ioctl hi;-- if (cmd != SIOCDEVPRIVATE)- return -ENOIOCTLCMD;-- if (copy_from_user(&hi, data, sizeof(hi)))- return -EFAULT;- switch (hi.cmd) {- default:- return -ENOIOCTLCMD;-- case HDLCDRVCTL_GETCHANNELPAR:- hi.data.cp.tx_delay = bc->ch_params.tx_delay;- hi.data.cp.tx_tail = bc->ch_params.tx_tail;- hi.data.cp.slottime = bc->ch_params.slottime;- hi.data.cp.ppersist = bc->ch_params.ppersist;- hi.data.cp.fulldup = bc->ch_params.fulldup;- break;-- case HDLCDRVCTL_SETCHANNELPAR:- if (!capable(CAP_NET_ADMIN))- return -EACCES;- bc->ch_params.tx_delay = hi.data.cp.tx_delay;- bc->ch_params.tx_tail = hi.data.cp.tx_tail;- bc->ch_params.slottime = hi.data.cp.slottime;- bc->ch_params.ppersist = hi.data.cp.ppersist;- bc->ch_params.fulldup = hi.data.cp.fulldup;- bc->hdlctx.slotcnt = 1;- return 0;- - case HDLCDRVCTL_GETMODEMPAR:- hi.data.mp.iobase = dev->base_addr;- hi.data.mp.irq = dev->irq;- hi.data.mp.dma = dev->dma;- hi.data.mp.dma2 = 0;- hi.data.mp.seriobase = 0;- hi.data.mp.pariobase = 0;- hi.data.mp.midiiobase = 0;- break;-- case HDLCDRVCTL_SETMODEMPAR:- if ((!capable(CAP_SYS_RAWIO)) || netif_running(dev))- return -EACCES;- dev->base_addr = hi.data.mp.iobase;- dev->irq = /*hi.data.mp.irq*/0;- dev->dma = /*hi.data.mp.dma*/0;- return 0; - - case HDLCDRVCTL_GETSTAT:- hi.data.cs.ptt = !!(bc->stat & EPP_PTTBIT);- hi.data.cs.dcd = !(bc->stat & EPP_DCDBIT);- hi.data.cs.ptt_keyed = bc->ptt_keyed;- hi.data.cs.tx_packets = dev->stats.tx_packets;- hi.data.cs.tx_errors = dev->stats.tx_errors;- hi.data.cs.rx_packets = dev->stats.rx_packets;- hi.data.cs.rx_errors = dev->stats.rx_errors;- break; -- case HDLCDRVCTL_OLDGETSTAT:- hi.data.ocs.ptt = !!(bc->stat & EPP_PTTBIT);- hi.data.ocs.dcd = !(bc->stat & EPP_DCDBIT);- hi.data.ocs.ptt_keyed = bc->ptt_keyed;- break; -- case HDLCDRVCTL_CALIBRATE:- if (!capable(CAP_SYS_RAWIO))- return -EACCES;- bc->hdlctx.calibrate = hi.data.calibrate * bc->bitrate / 8;- return 0;-- case HDLCDRVCTL_DRIVERNAME:- strscpy_pad(hi.data.drivername, "baycom_epp");- break;- - case HDLCDRVCTL_GETMODE:- sprintf(hi.data.modename, "%sclk,%smodem,fclk=%d,bps=%d%s", - bc->cfg.intclk ? "int" : "ext",- bc->cfg.extmodem ? "ext" : "int", bc->cfg.fclk, bc->cfg.bps,- bc->cfg.loopback ? ",loopback" : "");- break;-- case HDLCDRVCTL_SETMODE:- if (!capable(CAP_NET_ADMIN) || netif_running(dev))- return -EACCES;- hi.data.modename[sizeof(hi.data.modename)-1] = '\0';- return baycom_setmode(bc, hi.data.modename);-- case HDLCDRVCTL_MODELIST:- strscpy_pad(hi.data.modename, "intclk,extclk,intmodem,extmodem,divider=x");- break;-- case HDLCDRVCTL_MODEMPARMASK:- return HDLCDRV_PARMASK_IOBASE;-- }- if (copy_to_user(data, &hi, sizeof(hi)))- return -EFAULT;- return 0;-}--/* --------------------------------------------------------------------- */--static const struct net_device_ops baycom_netdev_ops = {- .ndo_open = epp_open,- .ndo_stop = epp_close,- .ndo_siocdevprivate = baycom_siocdevprivate,- .ndo_start_xmit = baycom_send_packet,- .ndo_set_mac_address = baycom_set_mac_address,-};--/*- * Check for a network adaptor of this type, and return '0' if one exists.- * If dev->base_addr == 0, probe all likely locations.- * If dev->base_addr == 1, always return failure.- * If dev->base_addr == 2, allocate space for the device and return success- * (detachable devices only).- */-static void baycom_probe(struct net_device *dev)-{- const struct hdlcdrv_channel_params dflt_ch_params = { - 20, 2, 10, 40, 0 - };- struct baycom_state *bc;-- /*- * not a real probe! only initialize data structures- */- bc = netdev_priv(dev);- /*- * initialize the baycom_state struct- */- bc->ch_params = dflt_ch_params;- bc->ptt_keyed = 0;-- /*- * initialize the device struct- */-- /* Fill in the fields of the device structure */- bc->skb = NULL;- - dev->netdev_ops = &baycom_netdev_ops;- dev->header_ops = &ax25_header_ops;- - dev->type = ARPHRD_AX25; /* AF_AX25 device */- dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;- dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */- dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);- dev_addr_set(dev, (u8 *)&null_ax25_address);- dev->tx_queue_len = 16;-- /* New style flags */- dev->flags = 0;-}--/* --------------------------------------------------------------------- */--/*- * command line settable parameters- */-static char *mode[NR_PORTS] = { "", };-static int iobase[NR_PORTS] = { 0x378, };--module_param_array(mode, charp, NULL, 0);-MODULE_PARM_DESC(mode, "baycom operating mode");-module_param_hw_array(iobase, int, ioport, NULL, 0);-MODULE_PARM_DESC(iobase, "baycom io base address");--MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");-MODULE_DESCRIPTION("Baycom epp amateur radio modem driver");-MODULE_LICENSE("GPL");--/* --------------------------------------------------------------------- */--static int baycom_epp_par_probe(struct pardevice *par_dev)-{- struct device_driver *drv = par_dev->dev.driver;- int len = strlen(drv->name);-- if (strncmp(par_dev->name, drv->name, len))- return -ENODEV;-- return 0;-}--static struct parport_driver baycom_epp_par_driver = {- .name = "bce",- .probe = baycom_epp_par_probe,-};--static void __init baycom_epp_dev_setup(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);-- /*- * initialize part of the baycom_state struct- */- bc->dev = dev;- bc->magic = BAYCOM_MAGIC;- bc->cfg.fclk = 19666600;- bc->cfg.bps = 9600;- /*- * initialize part of the device struct- */- baycom_probe(dev);-}--static int __init init_baycomepp(void)-{- int i, found = 0, ret;- char set_hw = 1;-- printk(bc_drvinfo);-- ret = parport_register_driver(&baycom_epp_par_driver);- if (ret)- return ret;-- /*- * register net devices- */- for (i = 0; i < NR_PORTS; i++) {- struct net_device *dev;- - dev = alloc_netdev(sizeof(struct baycom_state), "bce%d",- NET_NAME_UNKNOWN, baycom_epp_dev_setup);-- if (!dev) {- printk(KERN_WARNING "bce%d : out of memory\n", i);- return found ? 0 : -ENOMEM;- }- - sprintf(dev->name, "bce%d", i);- dev->base_addr = iobase[i];-- if (!mode[i])- set_hw = 0;- if (!set_hw)- iobase[i] = 0;-- if (register_netdev(dev)) {- printk(KERN_WARNING "%s: cannot register net device %s\n", bc_drvname, dev->name);- free_netdev(dev);- break;- }- if (set_hw && baycom_setmode(netdev_priv(dev), mode[i]))- set_hw = 0;- baycom_device[i] = dev;- found++;- }-- if (found == 0) {- parport_unregister_driver(&baycom_epp_par_driver);- return -ENXIO;- }-- return 0;-}--static void __exit cleanup_baycomepp(void)-{- int i;-- for(i = 0; i < NR_PORTS; i++) {- struct net_device *dev = baycom_device[i];-- if (dev) {- struct baycom_state *bc = netdev_priv(dev);- if (bc->magic == BAYCOM_MAGIC) {- unregister_netdev(dev);- free_netdev(dev);- } else- printk(paranoia_str, "cleanup_module");- }- }- parport_unregister_driver(&baycom_epp_par_driver);-}--module_init(init_baycomepp);-module_exit(cleanup_baycomepp);--/* --------------------------------------------------------------------- */--#ifndef MODULE--/*- * format: baycom_epp=io,mode- * mode: fpga config options- */--static int __init baycom_epp_setup(char *str)-{- static unsigned __initdata nr_dev = 0;- int ints[2];-- if (nr_dev >= NR_PORTS)- return 0;- str = get_options(str, 2, ints);- if (ints[0] < 1)- return 0;- mode[nr_dev] = str;- iobase[nr_dev] = ints[1];- nr_dev++;- return 1;-}--__setup("baycom_epp=", baycom_epp_setup);--#endif /* MODULE */-/* --------------------------------------------------------------------- */diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.cdeleted file mode 100644index f03797103c6a..000000000000--- a/drivers/net/hamradio/baycom_par.c+++ /dev/null@@ -1,598 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*****************************************************************************/--/*- * baycom_par.c -- baycom par96 and picpar radio modem driver.- *- * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)- *- * Please note that the GPL allows you to use the driver, NOT the radio.- * In order to use the radio, you need a license from the communications- * authority of your country.- *- * Supported modems- *- * par96: This is a modem for 9600 baud FSK compatible to the G3RUH standard.- * The modem does all the filtering and regenerates the receiver clock.- * Data is transferred from and to the PC via a shift register.- * The shift register is filled with 16 bits and an interrupt is- * signalled. The PC then empties the shift register in a burst. This- * modem connects to the parallel port, hence the name. The modem- * leaves the implementation of the HDLC protocol and the scrambler- * polynomial to the PC. This modem is no longer available (at least- * from Baycom) and has been replaced by the PICPAR modem (see below).- * You may however still build one from the schematics published in- * cq-DL :-).- *- * picpar: This is a redesign of the par96 modem by Henning Rech, DF9IC. The- * modem is protocol compatible to par96, but uses only three low- * power ICs and can therefore be fed from the parallel port and- * does not require an additional power supply. It features- * built in DCD circuitry. The driver should therefore be configured- * for hardware DCD.- *- * Command line options (insmod command line)- *- * mode driver mode string. Valid choices are par96 and picpar.- * iobase base address of the port; common values are 0x378, 0x278, 0x3bc- *- * History:- * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface- * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)- * 0.3 26.04.1997 init code/data tagged- * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints)- * 0.5 11.11.1997 split into separate files for ser12/par96- * 0.6 03.08.1999 adapt to Linus' new __setup/__initcall- * removed some pre-2.2 kernel compatibility cruft- * 0.7 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts- * 0.8 12.02.2000 adapted to softnet driver interface- * removed direct parport access, uses parport driver methods- * 0.9 03.07.2000 fix interface name handling- */--/*****************************************************************************/--#include <linux/module.h>-#include <linux/kernel.h>-#include <linux/types.h>-#include <linux/fcntl.h>-#include <linux/interrupt.h>-#include <linux/ioport.h>-#include <linux/in.h>-#include <linux/string.h>-#include <linux/init.h>-#include <linux/delay.h>-#include <linux/errno.h>-#include <linux/netdevice.h>-#include <linux/hdlcdrv.h>-#include <linux/baycom.h>-#include <linux/parport.h>-#include <linux/bitops.h>-#include <linux/jiffies.h>--#include <linux/uaccess.h>--/* --------------------------------------------------------------------- */--#define BAYCOM_DEBUG--/*- * modem options; bit mask- */-#define BAYCOM_OPTIONS_SOFTDCD 1--/* --------------------------------------------------------------------- */--static const char bc_drvname[] = "baycom_par";-static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"-"baycom_par: version 0.9\n";--/* --------------------------------------------------------------------- */--#define NR_PORTS 4--static struct net_device *baycom_device[NR_PORTS];--/* --------------------------------------------------------------------- */--#define PAR96_BURSTBITS 16-#define PAR96_BURST 4-#define PAR96_PTT 2-#define PAR96_TXBIT 1-#define PAR96_ACK 0x40-#define PAR96_RXBIT 0x20-#define PAR96_DCD 0x10-#define PAR97_POWER 0xf8--/* ---------------------------------------------------------------------- */-/*- * Information that need to be kept for each board.- */--struct baycom_state {- struct hdlcdrv_state hdrv;-- struct pardevice *pdev;- unsigned int options;-- struct modem_state {- short arb_divider;- unsigned char flags;- unsigned int shreg;- struct modem_state_par96 {- int dcd_count;- unsigned int dcd_shreg;- unsigned long descram;- unsigned long scram;- } par96;- } modem;--#ifdef BAYCOM_DEBUG- struct debug_vals {- unsigned long last_jiffies;- unsigned cur_intcnt;- unsigned last_intcnt;- int cur_pllcorr;- int last_pllcorr;- } debug_vals;-#endif /* BAYCOM_DEBUG */-};--/* --------------------------------------------------------------------- */--static inline void baycom_int_freq(struct baycom_state *bc)-{-#ifdef BAYCOM_DEBUG- unsigned long cur_jiffies = jiffies;- /*- * measure the interrupt frequency- */- bc->debug_vals.cur_intcnt++;- if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {- bc->debug_vals.last_jiffies = cur_jiffies;- bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;- bc->debug_vals.cur_intcnt = 0;- bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;- bc->debug_vals.cur_pllcorr = 0;- }-#endif /* BAYCOM_DEBUG */-}--/* --------------------------------------------------------------------- */-/*- * ===================== PAR96 specific routines =========================- */--#define PAR96_DESCRAM_TAP1 0x20000-#define PAR96_DESCRAM_TAP2 0x01000-#define PAR96_DESCRAM_TAP3 0x00001--#define PAR96_DESCRAM_TAPSH1 17-#define PAR96_DESCRAM_TAPSH2 12-#define PAR96_DESCRAM_TAPSH3 0--#define PAR96_SCRAM_TAP1 0x20000 /* X^17 */-#define PAR96_SCRAM_TAPN 0x00021 /* X^0+X^5 */--/* --------------------------------------------------------------------- */--static inline void par96_tx(struct net_device *dev, struct baycom_state *bc)-{- int i;- unsigned int data = hdlcdrv_getbits(&bc->hdrv);- struct parport *pp = bc->pdev->port;-- for(i = 0; i < PAR96_BURSTBITS; i++, data >>= 1) {- unsigned char val = PAR97_POWER;- bc->modem.par96.scram = ((bc->modem.par96.scram << 1) |- (bc->modem.par96.scram & 1));- if (!(data & 1))- bc->modem.par96.scram ^= 1;- if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 1))- bc->modem.par96.scram ^=- (PAR96_SCRAM_TAPN << 1);- if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 2))- val |= PAR96_TXBIT;- pp->ops->write_data(pp, val);- pp->ops->write_data(pp, val | PAR96_BURST);- }-}--/* --------------------------------------------------------------------- */--static inline void par96_rx(struct net_device *dev, struct baycom_state *bc)-{- int i;- unsigned int data, mask, mask2, descx;- struct parport *pp = bc->pdev->port;-- /*- * do receiver; differential decode and descramble on the fly- */- for(data = i = 0; i < PAR96_BURSTBITS; i++) {- bc->modem.par96.descram = (bc->modem.par96.descram << 1);- if (pp->ops->read_status(pp) & PAR96_RXBIT)- bc->modem.par96.descram |= 1;- descx = bc->modem.par96.descram ^- (bc->modem.par96.descram >> 1);- /* now the diff decoded data is inverted in descram */- pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT);- descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^- (descx >> PAR96_DESCRAM_TAPSH2));- data >>= 1;- if (!(descx & 1))- data |= 0x8000;- pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT | PAR96_BURST);- }- hdlcdrv_putbits(&bc->hdrv, data);- /*- * do DCD algorithm- */- if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {- bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg >> 16)- | (data << 16);- /* search for flags and set the dcd counter appropriately */- for(mask = 0x1fe00, mask2 = 0xfc00, i = 0;- i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)- if ((bc->modem.par96.dcd_shreg & mask) == mask2)- bc->modem.par96.dcd_count = HDLCDRV_MAXFLEN+4;- /* check for abort/noise sequences */- for(mask = 0x1fe00, mask2 = 0x1fe00, i = 0;- i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)- if (((bc->modem.par96.dcd_shreg & mask) == mask2) &&- (bc->modem.par96.dcd_count >= 0))- bc->modem.par96.dcd_count -= HDLCDRV_MAXFLEN-10;- /* decrement and set the dcd variable */- if (bc->modem.par96.dcd_count >= 0)- bc->modem.par96.dcd_count -= 2;- hdlcdrv_setdcd(&bc->hdrv, bc->modem.par96.dcd_count > 0);- } else {- hdlcdrv_setdcd(&bc->hdrv, !!(pp->ops->read_status(pp) & PAR96_DCD));- }-}--/* --------------------------------------------------------------------- */--static void par96_interrupt(void *dev_id)-{- struct net_device *dev = dev_id;- struct baycom_state *bc = netdev_priv(dev);-- baycom_int_freq(bc);- /*- * check if transmitter active- */- if (hdlcdrv_ptt(&bc->hdrv))- par96_tx(dev, bc);- else {- par96_rx(dev, bc);- if (--bc->modem.arb_divider <= 0) {- bc->modem.arb_divider = 6;- local_irq_enable();- hdlcdrv_arbitrate(dev, &bc->hdrv);- }- }- local_irq_enable();- hdlcdrv_transmitter(dev, &bc->hdrv);- hdlcdrv_receiver(dev, &bc->hdrv);- local_irq_disable();-}--/* --------------------------------------------------------------------- */--static void par96_wakeup(void *handle)-{- struct net_device *dev = (struct net_device *)handle;- struct baycom_state *bc = netdev_priv(dev);-- printk(KERN_DEBUG "baycom_par: %s: why am I being woken up?\n", dev->name);- if (!parport_claim(bc->pdev))- printk(KERN_DEBUG "baycom_par: %s: I'm broken.\n", dev->name);-}--/* --------------------------------------------------------------------- */--static int par96_open(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);- struct pardev_cb par_cb;- struct parport *pp;- int i;-- if (!dev || !bc)- return -ENXIO;- pp = parport_find_base(dev->base_addr);- if (!pp) {- printk(KERN_ERR "baycom_par: parport at 0x%lx unknown\n", dev->base_addr);- return -ENXIO;- }- if (pp->irq < 0) {- printk(KERN_ERR "baycom_par: parport at 0x%lx has no irq\n", pp->base);- parport_put_port(pp);- return -ENXIO;- }- if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) {- printk(KERN_ERR "baycom_par: parport at 0x%lx cannot be used\n", pp->base);- parport_put_port(pp);- return -ENXIO;- }- memset(&bc->modem, 0, sizeof(bc->modem));- bc->hdrv.par.bitrate = 9600;- memset(&par_cb, 0, sizeof(par_cb));- par_cb.wakeup = par96_wakeup;- par_cb.irq_func = par96_interrupt;- par_cb.private = (void *)dev;- par_cb.flags = PARPORT_DEV_EXCL;- for (i = 0; i < NR_PORTS; i++)- if (baycom_device[i] == dev)- break;-- if (i == NR_PORTS) {- pr_err("%s: no device found\n", bc_drvname);- parport_put_port(pp);- return -ENODEV;- }- bc->pdev = parport_register_dev_model(pp, dev->name, &par_cb, i);- parport_put_port(pp);- if (!bc->pdev) {- printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", dev->base_addr);- return -ENXIO;- }- if (parport_claim(bc->pdev)) {- printk(KERN_ERR "baycom_par: parport at 0x%lx busy\n", pp->base);- parport_unregister_device(bc->pdev);- return -EBUSY;- }- pp = bc->pdev->port;- dev->irq = pp->irq;- pp->ops->data_forward(pp);- bc->hdrv.par.bitrate = 9600;- pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER); /* switch off PTT */- pp->ops->enable_irq(pp);- printk(KERN_INFO "%s: par96 at iobase 0x%lx irq %u options 0x%x\n",- bc_drvname, dev->base_addr, dev->irq, bc->options);- return 0;-}--/* --------------------------------------------------------------------- */--static int par96_close(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);- struct parport *pp;-- if (!dev || !bc)- return -EINVAL;- pp = bc->pdev->port;- /* disable interrupt */- pp->ops->disable_irq(pp);- /* switch off PTT */- pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER);- parport_release(bc->pdev);- parport_unregister_device(bc->pdev);- printk(KERN_INFO "%s: close par96 at iobase 0x%lx irq %u\n",- bc_drvname, dev->base_addr, dev->irq);- return 0;-}--/* --------------------------------------------------------------------- */-/*- * ===================== hdlcdrv driver interface =========================- */--static int baycom_ioctl(struct net_device *dev, void __user *data,- struct hdlcdrv_ioctl *hi, int cmd);--/* --------------------------------------------------------------------- */--static const struct hdlcdrv_ops par96_ops = {- .drvname = bc_drvname,- .drvinfo = bc_drvinfo,- .open = par96_open,- .close = par96_close,- .ioctl = baycom_ioctl-};--/* --------------------------------------------------------------------- */--static int baycom_setmode(struct baycom_state *bc, const char *modestr)-{- if (!strncmp(modestr, "picpar", 6))- bc->options = 0;- else if (!strncmp(modestr, "par96", 5))- bc->options = BAYCOM_OPTIONS_SOFTDCD;- else- bc->options = !!strchr(modestr, '*');- return 0;-}--/* --------------------------------------------------------------------- */--static int baycom_ioctl(struct net_device *dev, void __user *data,- struct hdlcdrv_ioctl *hi, int cmd)-{- struct baycom_state *bc;- struct baycom_ioctl bi;-- if (!dev)- return -EINVAL;-- bc = netdev_priv(dev);- BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);-- if (cmd != SIOCDEVPRIVATE)- return -ENOIOCTLCMD;- switch (hi->cmd) {- default:- break;-- case HDLCDRVCTL_GETMODE:- strscpy(hi->data.modename, bc->options ? "par96" : "picpar");- if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))- return -EFAULT;- return 0;-- case HDLCDRVCTL_SETMODE:- if (netif_running(dev) || !capable(CAP_NET_ADMIN))- return -EACCES;- hi->data.modename[sizeof(hi->data.modename)-1] = '\0';- return baycom_setmode(bc, hi->data.modename);-- case HDLCDRVCTL_MODELIST:- strscpy(hi->data.modename, "par96,picpar");- if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))- return -EFAULT;- return 0;-- case HDLCDRVCTL_MODEMPARMASK:- return HDLCDRV_PARMASK_IOBASE;-- }-- if (copy_from_user(&bi, data, sizeof(bi)))- return -EFAULT;- switch (bi.cmd) {- default:- return -ENOIOCTLCMD;--#ifdef BAYCOM_DEBUG- case BAYCOMCTL_GETDEBUG:- bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;- bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;- bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;- break;-#endif /* BAYCOM_DEBUG */-- }- if (copy_to_user(data, &bi, sizeof(bi)))- return -EFAULT;- return 0;--}--/* --------------------------------------------------------------------- */--/*- * command line settable parameters- */-static char *mode[NR_PORTS] = { "picpar", };-static int iobase[NR_PORTS] = { 0x378, };--module_param_array(mode, charp, NULL, 0);-MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar");-module_param_hw_array(iobase, int, ioport, NULL, 0);-MODULE_PARM_DESC(iobase, "baycom io base address");--MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");-MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver");-MODULE_LICENSE("GPL");--/* --------------------------------------------------------------------- */--static int baycom_par_probe(struct pardevice *par_dev)-{- struct device_driver *drv = par_dev->dev.driver;- int len = strlen(drv->name);-- if (strncmp(par_dev->name, drv->name, len))- return -ENODEV;-- return 0;-}--static struct parport_driver baycom_par_driver = {- .name = "bcp",- .probe = baycom_par_probe,-};--static int __init init_baycompar(void)-{- int i, found = 0, ret;- char set_hw = 1;-- printk(bc_drvinfo);-- ret = parport_register_driver(&baycom_par_driver);- if (ret)- return ret;-- /*- * register net devices- */- for (i = 0; i < NR_PORTS; i++) {- struct net_device *dev;- struct baycom_state *bc;- char ifname[IFNAMSIZ];-- sprintf(ifname, "bcp%d", i);-- if (!mode[i])- set_hw = 0;- if (!set_hw)- iobase[i] = 0;-- dev = hdlcdrv_register(&par96_ops,- sizeof(struct baycom_state),- ifname, iobase[i], 0, 0);- if (IS_ERR(dev)) - break;-- bc = netdev_priv(dev);- if (set_hw && baycom_setmode(bc, mode[i]))- set_hw = 0;- found++;- baycom_device[i] = dev;- }-- if (!found) {- parport_unregister_driver(&baycom_par_driver);- return -ENXIO;- }- return 0;-}--static void __exit cleanup_baycompar(void)-{- int i;-- for(i = 0; i < NR_PORTS; i++) {- struct net_device *dev = baycom_device[i];-- if (dev)- hdlcdrv_unregister(dev);- }- parport_unregister_driver(&baycom_par_driver);-}--module_init(init_baycompar);-module_exit(cleanup_baycompar);--/* --------------------------------------------------------------------- */--#ifndef MODULE--/*- * format: baycom_par=io,mode- * mode: par96,picpar- */--static int __init baycom_par_setup(char *str)-{- static unsigned nr_dev;- int ints[2];-- if (nr_dev >= NR_PORTS)- return 0;- str = get_options(str, 2, ints);- if (ints[0] < 1)- return 0;- mode[nr_dev] = str;- iobase[nr_dev] = ints[1];- nr_dev++;- return 1;-}--__setup("baycom_par=", baycom_par_setup);--#endif /* MODULE */-/* --------------------------------------------------------------------- */diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.cdeleted file mode 100644index ee5bd3c12040..000000000000--- a/drivers/net/hamradio/baycom_ser_fdx.c+++ /dev/null@@ -1,678 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*****************************************************************************/--/*- * baycom_ser_fdx.c -- baycom ser12 fullduplex radio modem driver.- *- * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)- *- * Please note that the GPL allows you to use the driver, NOT the radio.- * In order to use the radio, you need a license from the communications- * authority of your country.- *- * Supported modems- *- * ser12: This is a very simple 1200 baud AFSK modem. The modem consists only- * of a modulator/demodulator chip, usually a TI TCM3105. The computer- * is responsible for regenerating the receiver bit clock, as well as- * for handling the HDLC protocol. The modem connects to a serial port,- * hence the name. Since the serial port is not used as an async serial- * port, the kernel driver for serial ports cannot be used, and this- * driver only supports standard serial hardware (8250, 16450, 16550A)- *- * This modem usually draws its supply current out of the otherwise unused- * TXD pin of the serial port. Thus a contiguous stream of 0x00-bytes- * is transmitted to achieve a positive supply voltage.- *- * hsk: This is a 4800 baud FSK modem, designed for TNC use. It works fine- * in 'baycom-mode' :-) In contrast to the TCM3105 modem, power is- * externally supplied. So there's no need to provide the 0x00-byte-stream- * when receiving or idle, which drastically reduces interrupt load.- *- * Command line options (insmod command line)- *- * mode ser# hardware DCD- * ser#* software DCD- * ser#+ hardware DCD, inverted signal at DCD pin- * '#' denotes the baud rate / 100, eg. ser12* is '1200 baud, soft DCD'- * iobase base address of the port; common values are 0x3f8, 0x2f8, 0x3e8, 0x2e8- * baud baud rate (between 300 and 4800)- * irq interrupt line of the port; common values are 4,3- *- * History:- * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface- * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)- * 0.3 26.04.1997 init code/data tagged- * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints)- * 0.5 11.11.1997 ser12/par96 split into separate files- * 0.6 24.01.1998 Thorsten Kranzkowski, dl8bcu and Thomas Sailer:- * reduced interrupt load in transmit case- * reworked receiver- * 0.7 03.08.1999 adapt to Linus' new __setup/__initcall- * 0.8 10.08.1999 use module_init/module_exit- * 0.9 12.02.2000 adapted to softnet driver interface- * 0.10 03.07.2000 fix interface name handling- */--/*****************************************************************************/--#include <linux/capability.h>-#include <linux/module.h>-#include <linux/ioport.h>-#include <linux/string.h>-#include <linux/init.h>-#include <linux/interrupt.h>-#include <linux/hdlcdrv.h>-#include <linux/baycom.h>-#include <linux/jiffies.h>-#include <linux/time64.h>--#include <linux/uaccess.h>-#include <asm/io.h>-#include <asm/irq.h>--/* --------------------------------------------------------------------- */--#define BAYCOM_DEBUG--/* --------------------------------------------------------------------- */--static const char bc_drvname[] = "baycom_ser_fdx";-static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"-"baycom_ser_fdx: version 0.10\n";--/* --------------------------------------------------------------------- */--#define NR_PORTS 4--static struct net_device *baycom_device[NR_PORTS];--/* --------------------------------------------------------------------- */--#define RBR(iobase) (iobase+0)-#define THR(iobase) (iobase+0)-#define IER(iobase) (iobase+1)-#define IIR(iobase) (iobase+2)-#define FCR(iobase) (iobase+2)-#define LCR(iobase) (iobase+3)-#define MCR(iobase) (iobase+4)-#define LSR(iobase) (iobase+5)-#define MSR(iobase) (iobase+6)-#define SCR(iobase) (iobase+7)-#define DLL(iobase) (iobase+0)-#define DLM(iobase) (iobase+1)--#define SER12_EXTENT 8--/* ---------------------------------------------------------------------- */-/*- * Information that need to be kept for each board.- */--struct baycom_state {- struct hdlcdrv_state hdrv;-- unsigned int baud, baud_us, baud_arbdiv, baud_uartdiv, baud_dcdtimeout;- int opt_dcd;-- struct modem_state {- unsigned char flags;- unsigned char ptt;- unsigned int shreg;- struct modem_state_ser12 {- unsigned char tx_bit;- unsigned char last_rxbit;- int dcd_sum0, dcd_sum1, dcd_sum2;- int dcd_time;- unsigned int pll_time;- unsigned int txshreg;- } ser12;- } modem;--#ifdef BAYCOM_DEBUG- struct debug_vals {- unsigned long last_jiffies;- unsigned cur_intcnt;- unsigned last_intcnt;- int cur_pllcorr;- int last_pllcorr;- } debug_vals;-#endif /* BAYCOM_DEBUG */-};--/* --------------------------------------------------------------------- */--static inline void baycom_int_freq(struct baycom_state *bc)-{-#ifdef BAYCOM_DEBUG- unsigned long cur_jiffies = jiffies;- /*- * measure the interrupt frequency- */- bc->debug_vals.cur_intcnt++;- if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {- bc->debug_vals.last_jiffies = cur_jiffies;- bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;- bc->debug_vals.cur_intcnt = 0;- bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;- bc->debug_vals.cur_pllcorr = 0;- }-#endif /* BAYCOM_DEBUG */-}--/* --------------------------------------------------------------------- */-/*- * ===================== SER12 specific routines =========================- */--/* --------------------------------------------------------------------- */--static inline void ser12_set_divisor(struct net_device *dev,- unsigned int divisor)-{- outb(0x81, LCR(dev->base_addr)); /* DLAB = 1 */- outb(divisor, DLL(dev->base_addr));- outb(divisor >> 8, DLM(dev->base_addr));- outb(0x01, LCR(dev->base_addr)); /* word length = 6 */- /*- * make sure the next interrupt is generated;- * 0 must be used to power the modem; the modem draws its- * power from the TxD line- */- outb(0x00, THR(dev->base_addr));- /*- * it is important not to set the divider while transmitting;- * this reportedly makes some UARTs generating interrupts- * in the hundredthousands per second region- * Reported by: Ignacio.Arenaza@studi.epfl.ch (Ignacio Arenaza Nuno)- */-}--static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timespec64 *ts, unsigned char curs)-{- int timediff;- int bdus8 = bc->baud_us >> 3;- int bdus4 = bc->baud_us >> 2;- int bdus2 = bc->baud_us >> 1;-- timediff = 1000000 + ts->tv_nsec / NSEC_PER_USEC -- bc->modem.ser12.pll_time;- while (timediff >= 500000)- timediff -= 1000000;- while (timediff >= bdus2) {- timediff -= bc->baud_us;- bc->modem.ser12.pll_time += bc->baud_us;- bc->modem.ser12.dcd_time--;- /* first check if there is room to add a bit */- if (bc->modem.shreg & 1) {- hdlcdrv_putbits(&bc->hdrv, (bc->modem.shreg >> 1) ^ 0xffff);- bc->modem.shreg = 0x10000;- }- /* add a one bit */- bc->modem.shreg >>= 1;- }- if (bc->modem.ser12.dcd_time <= 0) {- if (!bc->opt_dcd)- hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 + - bc->modem.ser12.dcd_sum1 + - bc->modem.ser12.dcd_sum2) < 0);- bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;- bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;- bc->modem.ser12.dcd_sum0 = 2; /* slight bias */- bc->modem.ser12.dcd_time += 120;- }- if (bc->modem.ser12.last_rxbit != curs) {- bc->modem.ser12.last_rxbit = curs;- bc->modem.shreg |= 0x10000;- /* adjust the PLL */- if (timediff > 0)- bc->modem.ser12.pll_time += bdus8;- else- bc->modem.ser12.pll_time += 1000000 - bdus8;- /* update DCD */- if (abs(timediff) > bdus4)- bc->modem.ser12.dcd_sum0 += 4;- else- bc->modem.ser12.dcd_sum0--;-#ifdef BAYCOM_DEBUG- bc->debug_vals.cur_pllcorr = timediff;-#endif /* BAYCOM_DEBUG */- }- while (bc->modem.ser12.pll_time >= 1000000)- bc->modem.ser12.pll_time -= 1000000;-}--/* --------------------------------------------------------------------- */--static irqreturn_t ser12_interrupt(int irq, void *dev_id)-{- struct net_device *dev = (struct net_device *)dev_id;- struct baycom_state *bc = netdev_priv(dev);- struct timespec64 ts;- unsigned char iir, msr;- unsigned int txcount = 0;-- if (!bc || bc->hdrv.magic != HDLCDRV_MAGIC)- return IRQ_NONE;- /* fast way out for shared irq */- if ((iir = inb(IIR(dev->base_addr))) & 1) - return IRQ_NONE;- /* get current time */- ktime_get_ts64(&ts);- msr = inb(MSR(dev->base_addr));- /* delta DCD */- if ((msr & 8) && bc->opt_dcd)- hdlcdrv_setdcd(&bc->hdrv, !((msr ^ bc->opt_dcd) & 0x80));- do {- switch (iir & 6) {- case 6:- inb(LSR(dev->base_addr));- break;- - case 4:- inb(RBR(dev->base_addr));- break;- - case 2:- /*- * make sure the next interrupt is generated;- * 0 must be used to power the modem; the modem draws its- * power from the TxD line- */- outb(0x00, THR(dev->base_addr));- baycom_int_freq(bc);- txcount++;- /*- * first output the last bit (!) then call HDLC transmitter,- * since this may take quite long- */- if (bc->modem.ptt)- outb(0x0e | (!!bc->modem.ser12.tx_bit), MCR(dev->base_addr));- else- outb(0x0d, MCR(dev->base_addr)); /* transmitter off */- break;- - default:- msr = inb(MSR(dev->base_addr));- /* delta DCD */- if ((msr & 8) && bc->opt_dcd) - hdlcdrv_setdcd(&bc->hdrv, !((msr ^ bc->opt_dcd) & 0x80));- break;- }- iir = inb(IIR(dev->base_addr));- } while (!(iir & 1));- ser12_rx(dev, bc, &ts, msr & 0x10); /* CTS */- if (bc->modem.ptt && txcount) {- if (bc->modem.ser12.txshreg <= 1) {- bc->modem.ser12.txshreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv);- if (!hdlcdrv_ptt(&bc->hdrv)) {- ser12_set_divisor(dev, 115200/100/8);- bc->modem.ptt = 0;- goto end_transmit;- }- }- bc->modem.ser12.tx_bit = !(bc->modem.ser12.tx_bit ^ (bc->modem.ser12.txshreg & 1));- bc->modem.ser12.txshreg >>= 1;- }- end_transmit:- local_irq_enable();- if (!bc->modem.ptt && txcount) {- hdlcdrv_arbitrate(dev, &bc->hdrv);- if (hdlcdrv_ptt(&bc->hdrv)) {- ser12_set_divisor(dev, bc->baud_uartdiv);- bc->modem.ser12.txshreg = 1;- bc->modem.ptt = 1;- }- }- hdlcdrv_transmitter(dev, &bc->hdrv);- hdlcdrv_receiver(dev, &bc->hdrv);- local_irq_disable();- return IRQ_HANDLED;-}--/* --------------------------------------------------------------------- */--enum uart { c_uart_unknown, c_uart_8250,- c_uart_16450, c_uart_16550, c_uart_16550A};-static const char *uart_str[] = { - "unknown", "8250", "16450", "16550", "16550A" -};--static enum uart ser12_check_uart(unsigned int iobase)-{- unsigned char b1,b2,b3;- enum uart u;- enum uart uart_tab[] =- { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };-- b1 = inb(MCR(iobase));- outb(b1 | 0x10, MCR(iobase)); /* loopback mode */- b2 = inb(MSR(iobase));- outb(0x1a, MCR(iobase));- b3 = inb(MSR(iobase)) & 0xf0;- outb(b1, MCR(iobase)); /* restore old values */- outb(b2, MSR(iobase));- if (b3 != 0x90)- return c_uart_unknown;- inb(RBR(iobase));- inb(RBR(iobase));- outb(0x01, FCR(iobase)); /* enable FIFOs */- u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];- if (u == c_uart_16450) {- outb(0x5a, SCR(iobase));- b1 = inb(SCR(iobase));- outb(0xa5, SCR(iobase));- b2 = inb(SCR(iobase));- if ((b1 != 0x5a) || (b2 != 0xa5))- u = c_uart_8250;- }- return u;-}--/* --------------------------------------------------------------------- */--static int ser12_open(struct net_device *dev)-{- const unsigned int nr_irqs = irq_get_nr_irqs();- struct baycom_state *bc = netdev_priv(dev);- enum uart u;-- if (!dev || !bc)- return -ENXIO;- if (!dev->base_addr || dev->base_addr > 0xffff-SER12_EXTENT ||- dev->irq < 2 || dev->irq > nr_irqs) {- printk(KERN_INFO "baycom_ser_fdx: invalid portnumber (max %u) "- "or irq (2 <= irq <= %d)\n",- 0xffff-SER12_EXTENT, nr_irqs);- return -ENXIO;- }- if (bc->baud < 300 || bc->baud > 4800) {- printk(KERN_INFO "baycom_ser_fdx: invalid baudrate "- "(300...4800)\n");- return -EINVAL;- }- if (!request_region(dev->base_addr, SER12_EXTENT, "baycom_ser_fdx")) {- printk(KERN_WARNING "BAYCOM_SER_FSX: I/O port 0x%04lx busy\n",- dev->base_addr);- return -EACCES;- }- memset(&bc->modem, 0, sizeof(bc->modem));- bc->hdrv.par.bitrate = bc->baud;- bc->baud_us = 1000000/bc->baud;- bc->baud_uartdiv = (115200/8)/bc->baud;- if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown){- release_region(dev->base_addr, SER12_EXTENT);- return -EIO;- }- outb(0, FCR(dev->base_addr)); /* disable FIFOs */- outb(0x0d, MCR(dev->base_addr));- outb(0, IER(dev->base_addr));- if (request_irq(dev->irq, ser12_interrupt, IRQF_SHARED,- "baycom_ser_fdx", dev)) {- release_region(dev->base_addr, SER12_EXTENT);- return -EBUSY;- }- /*- * set the SIO to 6 Bits/character; during receive,- * the baud rate is set to produce 100 ints/sec- * to feed the channel arbitration process,- * during transmit to baud ints/sec to run- * the transmitter- */- ser12_set_divisor(dev, 115200/100/8);- /*- * enable transmitter empty interrupt and modem status interrupt- */- outb(0x0a, IER(dev->base_addr));- /*- * make sure the next interrupt is generated;- * 0 must be used to power the modem; the modem draws its- * power from the TxD line- */- outb(0x00, THR(dev->base_addr));- hdlcdrv_setdcd(&bc->hdrv, 0);- printk(KERN_INFO "%s: ser_fdx at iobase 0x%lx irq %u baud %u uart %s\n",- bc_drvname, dev->base_addr, dev->irq, bc->baud, uart_str[u]);- return 0;-}--/* --------------------------------------------------------------------- */--static int ser12_close(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);-- if (!dev || !bc)- return -EINVAL;- /*- * disable interrupts- */- outb(0, IER(dev->base_addr));- outb(1, MCR(dev->base_addr));- free_irq(dev->irq, dev);- release_region(dev->base_addr, SER12_EXTENT);- printk(KERN_INFO "%s: close ser_fdx at iobase 0x%lx irq %u\n",- bc_drvname, dev->base_addr, dev->irq);- return 0;-}--/* --------------------------------------------------------------------- */-/*- * ===================== hdlcdrv driver interface =========================- */--/* --------------------------------------------------------------------- */--static int baycom_ioctl(struct net_device *dev, void __user *data,- struct hdlcdrv_ioctl *hi, int cmd);--/* --------------------------------------------------------------------- */--static const struct hdlcdrv_ops ser12_ops = {- .drvname = bc_drvname,- .drvinfo = bc_drvinfo,- .open = ser12_open,- .close = ser12_close,- .ioctl = baycom_ioctl,-};--/* --------------------------------------------------------------------- */--static int baycom_setmode(struct baycom_state *bc, const char *modestr)-{- unsigned int baud;-- if (!strncmp(modestr, "ser", 3)) {- baud = simple_strtoul(modestr+3, NULL, 10);- if (baud >= 3 && baud <= 48)- bc->baud = baud*100;- }- if (strchr(modestr, '*'))- bc->opt_dcd = 0;- else if (strchr(modestr, '+'))- bc->opt_dcd = -1;- else- bc->opt_dcd = 1;- return 0;-}--/* --------------------------------------------------------------------- */--static int baycom_ioctl(struct net_device *dev, void __user *data,- struct hdlcdrv_ioctl *hi, int cmd)-{- struct baycom_state *bc;- struct baycom_ioctl bi;-- if (!dev)- return -EINVAL;-- bc = netdev_priv(dev);- BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);-- if (cmd != SIOCDEVPRIVATE)- return -ENOIOCTLCMD;- switch (hi->cmd) {- default:- break;-- case HDLCDRVCTL_GETMODE:- sprintf(hi->data.modename, "ser%u", bc->baud / 100);- if (bc->opt_dcd <= 0)- strcat(hi->data.modename, (!bc->opt_dcd) ? "*" : "+");- if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))- return -EFAULT;- return 0;-- case HDLCDRVCTL_SETMODE:- if (netif_running(dev) || !capable(CAP_NET_ADMIN))- return -EACCES;- hi->data.modename[sizeof(hi->data.modename)-1] = '\0';- return baycom_setmode(bc, hi->data.modename);-- case HDLCDRVCTL_MODELIST:- strscpy(hi->data.modename, "ser12,ser3,ser24");- if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))- return -EFAULT;- return 0;-- case HDLCDRVCTL_MODEMPARMASK:- return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ;-- }-- if (copy_from_user(&bi, data, sizeof(bi)))- return -EFAULT;- switch (bi.cmd) {- default:- return -ENOIOCTLCMD;--#ifdef BAYCOM_DEBUG- case BAYCOMCTL_GETDEBUG:- bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;- bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;- bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;- break;-#endif /* BAYCOM_DEBUG */-- }- if (copy_to_user(data, &bi, sizeof(bi)))- return -EFAULT;- return 0;--}--/* --------------------------------------------------------------------- */--/*- * command line settable parameters- */-static char *mode[NR_PORTS] = { "ser12*", };-static int iobase[NR_PORTS] = { 0x3f8, };-static int irq[NR_PORTS] = { 4, };-static int baud[NR_PORTS] = { [0 ... NR_PORTS-1] = 1200 };--module_param_array(mode, charp, NULL, 0);-MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD");-module_param_hw_array(iobase, int, ioport, NULL, 0);-MODULE_PARM_DESC(iobase, "baycom io base address");-module_param_hw_array(irq, int, irq, NULL, 0);-MODULE_PARM_DESC(irq, "baycom irq number");-module_param_array(baud, int, NULL, 0);-MODULE_PARM_DESC(baud, "baycom baud rate (300 to 4800)");--MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");-MODULE_DESCRIPTION("Baycom ser12 full duplex amateur radio modem driver");-MODULE_LICENSE("GPL");--/* --------------------------------------------------------------------- */--static int __init init_baycomserfdx(void)-{- int i, found = 0;- char set_hw = 1;-- printk(bc_drvinfo);- /*- * register net devices- */- for (i = 0; i < NR_PORTS; i++) {- struct net_device *dev;- struct baycom_state *bc;- char ifname[IFNAMSIZ];-- sprintf(ifname, "bcsf%d", i);-- if (!mode[i])- set_hw = 0;- if (!set_hw)- iobase[i] = irq[i] = 0;-- dev = hdlcdrv_register(&ser12_ops, - sizeof(struct baycom_state),- ifname, iobase[i], irq[i], 0);- if (IS_ERR(dev)) - break;-- bc = netdev_priv(dev);- if (set_hw && baycom_setmode(bc, mode[i]))- set_hw = 0;- bc->baud = baud[i];- found++;- baycom_device[i] = dev;- }-- if (!found)- return -ENXIO;- return 0;-}--static void __exit cleanup_baycomserfdx(void)-{- int i;-- for(i = 0; i < NR_PORTS; i++) {- struct net_device *dev = baycom_device[i];- if (dev) - hdlcdrv_unregister(dev);- }-}--module_init(init_baycomserfdx);-module_exit(cleanup_baycomserfdx);--/* --------------------------------------------------------------------- */--#ifndef MODULE--/*- * format: baycom_ser_fdx=io,irq,mode- * mode: ser# hardware DCD- * ser#* software DCD- * ser#+ hardware DCD, inverted signal at DCD pin- * '#' denotes the baud rate / 100, eg. ser12* is '1200 baud, soft DCD'- */--static int __init baycom_ser_fdx_setup(char *str)-{- static unsigned nr_dev;- int ints[4];-- if (nr_dev >= NR_PORTS)- return 0;- str = get_options(str, 4, ints);- if (ints[0] < 2)- return 0;- mode[nr_dev] = str;- iobase[nr_dev] = ints[1];- irq[nr_dev] = ints[2];- if (ints[0] >= 3)- baud[nr_dev] = ints[3];- nr_dev++;- return 1;-}--__setup("baycom_ser_fdx=", baycom_ser_fdx_setup);--#endif /* MODULE */-/* --------------------------------------------------------------------- */diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.cdeleted file mode 100644index 05bdad214799..000000000000--- a/drivers/net/hamradio/baycom_ser_hdx.c+++ /dev/null@@ -1,727 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*****************************************************************************/--/*- * baycom_ser_hdx.c -- baycom ser12 halfduplex radio modem driver.- *- * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)- *- * Please note that the GPL allows you to use the driver, NOT the radio.- * In order to use the radio, you need a license from the communications- * authority of your country.- *- * Supported modems- *- * ser12: This is a very simple 1200 baud AFSK modem. The modem consists only- * of a modulator/demodulator chip, usually a TI TCM3105. The computer- * is responsible for regenerating the receiver bit clock, as well as- * for handling the HDLC protocol. The modem connects to a serial port,- * hence the name. Since the serial port is not used as an async serial- * port, the kernel driver for serial ports cannot be used, and this- * driver only supports standard serial hardware (8250, 16450, 16550A)- *- * Command line options (insmod command line)- *- * mode ser12 hardware DCD- * ser12* software DCD- * ser12@ hardware/software DCD, i.e. no explicit DCD signal but hardware- * mutes audio input to the modem- * ser12+ hardware DCD, inverted signal at DCD pin- * iobase base address of the port; common values are 0x3f8, 0x2f8, 0x3e8, 0x2e8- * irq interrupt line of the port; common values are 4,3- *- * History:- * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface- * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)- * 0.3 26.04.1997 init code/data tagged- * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints)- * 0.5 11.11.1997 ser12/par96 split into separate files- * 0.6 14.04.1998 cleanups- * 0.7 03.08.1999 adapt to Linus' new __setup/__initcall- * 0.8 10.08.1999 use module_init/module_exit- * 0.9 12.02.2000 adapted to softnet driver interface- * 0.10 03.07.2000 fix interface name handling- */--/*****************************************************************************/--#include <linux/capability.h>-#include <linux/module.h>-#include <linux/ioport.h>-#include <linux/string.h>-#include <linux/init.h>-#include <linux/interrupt.h>-#include <linux/uaccess.h>-#include <asm/io.h>-#include <linux/hdlcdrv.h>-#include <linux/baycom.h>-#include <linux/jiffies.h>--/* --------------------------------------------------------------------- */--#define BAYCOM_DEBUG--/* --------------------------------------------------------------------- */--static const char bc_drvname[] = "baycom_ser_hdx";-static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"-"baycom_ser_hdx: version 0.10\n";--/* --------------------------------------------------------------------- */--#define NR_PORTS 4--static struct net_device *baycom_device[NR_PORTS];--/* --------------------------------------------------------------------- */--#define RBR(iobase) (iobase+0)-#define THR(iobase) (iobase+0)-#define IER(iobase) (iobase+1)-#define IIR(iobase) (iobase+2)-#define FCR(iobase) (iobase+2)-#define LCR(iobase) (iobase+3)-#define MCR(iobase) (iobase+4)-#define LSR(iobase) (iobase+5)-#define MSR(iobase) (iobase+6)-#define SCR(iobase) (iobase+7)-#define DLL(iobase) (iobase+0)-#define DLM(iobase) (iobase+1)--#define SER12_EXTENT 8--/* ---------------------------------------------------------------------- */-/*- * Information that need to be kept for each board.- */--struct baycom_state {- struct hdlcdrv_state hdrv;-- int opt_dcd;-- struct modem_state {- short arb_divider;- unsigned char flags;- unsigned int shreg;- struct modem_state_ser12 {- unsigned char tx_bit;- int dcd_sum0, dcd_sum1, dcd_sum2;- unsigned char last_sample;- unsigned char last_rxbit;- unsigned int dcd_shreg;- unsigned int dcd_time;- unsigned int bit_pll;- unsigned char interm_sample;- } ser12;- } modem;--#ifdef BAYCOM_DEBUG- struct debug_vals {- unsigned long last_jiffies;- unsigned cur_intcnt;- unsigned last_intcnt;- int cur_pllcorr;- int last_pllcorr;- } debug_vals;-#endif /* BAYCOM_DEBUG */-};--/* --------------------------------------------------------------------- */--static inline void baycom_int_freq(struct baycom_state *bc)-{-#ifdef BAYCOM_DEBUG- unsigned long cur_jiffies = jiffies;- /*- * measure the interrupt frequency- */- bc->debug_vals.cur_intcnt++;- if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {- bc->debug_vals.last_jiffies = cur_jiffies;- bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;- bc->debug_vals.cur_intcnt = 0;- bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;- bc->debug_vals.cur_pllcorr = 0;- }-#endif /* BAYCOM_DEBUG */-}--/* --------------------------------------------------------------------- */-/*- * ===================== SER12 specific routines =========================- */--static inline void ser12_set_divisor(struct net_device *dev,- unsigned char divisor)-{- outb(0x81, LCR(dev->base_addr)); /* DLAB = 1 */- outb(divisor, DLL(dev->base_addr));- outb(0, DLM(dev->base_addr));- outb(0x01, LCR(dev->base_addr)); /* word length = 6 */- /*- * make sure the next interrupt is generated;- * 0 must be used to power the modem; the modem draws its- * power from the TxD line- */- outb(0x00, THR(dev->base_addr));- /*- * it is important not to set the divider while transmitting;- * this reportedly makes some UARTs generating interrupts- * in the hundredthousands per second region- * Reported by: Ignacio.Arenaza@studi.epfl.ch (Ignacio Arenaza Nuno)- */-}--/* --------------------------------------------------------------------- */--/*- * must call the TX arbitrator every 10ms- */-#define SER12_ARB_DIVIDER(bc) (bc->opt_dcd ? 24 : 36)- -#define SER12_DCD_INTERVAL(bc) (bc->opt_dcd ? 12 : 240)--static inline void ser12_tx(struct net_device *dev, struct baycom_state *bc)-{- /* one interrupt per channel bit */- ser12_set_divisor(dev, 12);- /*- * first output the last bit (!) then call HDLC transmitter,- * since this may take quite long- */- outb(0x0e | (!!bc->modem.ser12.tx_bit), MCR(dev->base_addr));- if (bc->modem.shreg <= 1)- bc->modem.shreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv);- bc->modem.ser12.tx_bit = !(bc->modem.ser12.tx_bit ^- (bc->modem.shreg & 1));- bc->modem.shreg >>= 1;-}--/* --------------------------------------------------------------------- */--static inline void ser12_rx(struct net_device *dev, struct baycom_state *bc)-{- unsigned char cur_s;- /*- * do demodulator- */- cur_s = inb(MSR(dev->base_addr)) & 0x10; /* the CTS line */- hdlcdrv_channelbit(&bc->hdrv, cur_s);- bc->modem.ser12.dcd_shreg = (bc->modem.ser12.dcd_shreg << 1) |- (cur_s != bc->modem.ser12.last_sample);- bc->modem.ser12.last_sample = cur_s;- if(bc->modem.ser12.dcd_shreg & 1) {- if (!bc->opt_dcd) {- unsigned int dcdspos, dcdsneg;-- dcdspos = dcdsneg = 0;- dcdspos += ((bc->modem.ser12.dcd_shreg >> 1) & 1);- if (!(bc->modem.ser12.dcd_shreg & 0x7ffffffe))- dcdspos += 2;- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 2) & 1);- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 3) & 1);- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 4) & 1);-- bc->modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;- } else- bc->modem.ser12.dcd_sum0--;- }- if(!bc->modem.ser12.dcd_time) {- hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +- bc->modem.ser12.dcd_sum1 +- bc->modem.ser12.dcd_sum2) < 0);- bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;- bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;- /* offset to ensure DCD off on silent input */- bc->modem.ser12.dcd_sum0 = 2;- bc->modem.ser12.dcd_time = SER12_DCD_INTERVAL(bc);- }- bc->modem.ser12.dcd_time--;- if (!bc->opt_dcd) {- /*- * PLL code for the improved software DCD algorithm- */- if (bc->modem.ser12.interm_sample) {- /*- * intermediate sample; set timing correction to normal- */- ser12_set_divisor(dev, 4);- } else {- /*- * do PLL correction and call HDLC receiver- */- switch (bc->modem.ser12.dcd_shreg & 7) {- case 1: /* transition too late */- ser12_set_divisor(dev, 5);-#ifdef BAYCOM_DEBUG- bc->debug_vals.cur_pllcorr++;-#endif /* BAYCOM_DEBUG */- break;- case 4: /* transition too early */- ser12_set_divisor(dev, 3);-#ifdef BAYCOM_DEBUG- bc->debug_vals.cur_pllcorr--;-#endif /* BAYCOM_DEBUG */- break;- default:- ser12_set_divisor(dev, 4);- break;- }- bc->modem.shreg >>= 1;- if (bc->modem.ser12.last_sample ==- bc->modem.ser12.last_rxbit)- bc->modem.shreg |= 0x10000;- bc->modem.ser12.last_rxbit =- bc->modem.ser12.last_sample;- }- if (++bc->modem.ser12.interm_sample >= 3)- bc->modem.ser12.interm_sample = 0;- /*- * DCD stuff- */- if (bc->modem.ser12.dcd_shreg & 1) {- unsigned int dcdspos, dcdsneg;-- dcdspos = dcdsneg = 0;- dcdspos += ((bc->modem.ser12.dcd_shreg >> 1) & 1);- dcdspos += (!(bc->modem.ser12.dcd_shreg & 0x7ffffffe))- << 1;- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 2) & 1);- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 3) & 1);- dcdsneg += ((bc->modem.ser12.dcd_shreg >> 4) & 1);-- bc->modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;- }- } else {- /*- * PLL algorithm for the hardware squelch DCD algorithm- */- if (bc->modem.ser12.interm_sample) {- /*- * intermediate sample; set timing correction to normal- */- ser12_set_divisor(dev, 6);- } else {- /*- * do PLL correction and call HDLC receiver- */- switch (bc->modem.ser12.dcd_shreg & 3) {- case 1: /* transition too late */- ser12_set_divisor(dev, 7);-#ifdef BAYCOM_DEBUG- bc->debug_vals.cur_pllcorr++;-#endif /* BAYCOM_DEBUG */- break;- case 2: /* transition too early */- ser12_set_divisor(dev, 5);-#ifdef BAYCOM_DEBUG- bc->debug_vals.cur_pllcorr--;-#endif /* BAYCOM_DEBUG */- break;- default:- ser12_set_divisor(dev, 6);- break;- }- bc->modem.shreg >>= 1;- if (bc->modem.ser12.last_sample ==- bc->modem.ser12.last_rxbit)- bc->modem.shreg |= 0x10000;- bc->modem.ser12.last_rxbit =- bc->modem.ser12.last_sample;- }- bc->modem.ser12.interm_sample = !bc->modem.ser12.interm_sample;- /*- * DCD stuff- */- bc->modem.ser12.dcd_sum0 -= (bc->modem.ser12.dcd_shreg & 1);- }- outb(0x0d, MCR(dev->base_addr)); /* transmitter off */- if (bc->modem.shreg & 1) {- hdlcdrv_putbits(&bc->hdrv, bc->modem.shreg >> 1);- bc->modem.shreg = 0x10000;- }- if(!bc->modem.ser12.dcd_time) {- if (bc->opt_dcd & 1) - hdlcdrv_setdcd(&bc->hdrv, !((inb(MSR(dev->base_addr)) ^ bc->opt_dcd) & 0x80));- else- hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +- bc->modem.ser12.dcd_sum1 +- bc->modem.ser12.dcd_sum2) < 0);- bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;- bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;- /* offset to ensure DCD off on silent input */- bc->modem.ser12.dcd_sum0 = 2;- bc->modem.ser12.dcd_time = SER12_DCD_INTERVAL(bc);- }- bc->modem.ser12.dcd_time--;-}--/* --------------------------------------------------------------------- */--static irqreturn_t ser12_interrupt(int irq, void *dev_id)-{- struct net_device *dev = (struct net_device *)dev_id;- struct baycom_state *bc = netdev_priv(dev);- unsigned char iir;-- if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)- return IRQ_NONE;- /* fast way out */- if ((iir = inb(IIR(dev->base_addr))) & 1)- return IRQ_NONE;- baycom_int_freq(bc);- do {- switch (iir & 6) {- case 6:- inb(LSR(dev->base_addr));- break;- - case 4:- inb(RBR(dev->base_addr));- break;- - case 2:- /*- * check if transmitter active- */- if (hdlcdrv_ptt(&bc->hdrv))- ser12_tx(dev, bc);- else {- ser12_rx(dev, bc);- bc->modem.arb_divider--;- }- outb(0x00, THR(dev->base_addr));- break;- - default:- inb(MSR(dev->base_addr));- break;- }- iir = inb(IIR(dev->base_addr));- } while (!(iir & 1));- if (bc->modem.arb_divider <= 0) {- bc->modem.arb_divider = SER12_ARB_DIVIDER(bc);- local_irq_enable();- hdlcdrv_arbitrate(dev, &bc->hdrv);- }- local_irq_enable();- hdlcdrv_transmitter(dev, &bc->hdrv);- hdlcdrv_receiver(dev, &bc->hdrv);- local_irq_disable();- return IRQ_HANDLED;-}--/* --------------------------------------------------------------------- */--enum uart { c_uart_unknown, c_uart_8250,- c_uart_16450, c_uart_16550, c_uart_16550A};-static const char *uart_str[] = { - "unknown", "8250", "16450", "16550", "16550A" -};--static enum uart ser12_check_uart(unsigned int iobase)-{- unsigned char b1,b2,b3;- enum uart u;- enum uart uart_tab[] =- { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };-- b1 = inb(MCR(iobase));- outb(b1 | 0x10, MCR(iobase)); /* loopback mode */- b2 = inb(MSR(iobase));- outb(0x1a, MCR(iobase));- b3 = inb(MSR(iobase)) & 0xf0;- outb(b1, MCR(iobase)); /* restore old values */- outb(b2, MSR(iobase));- if (b3 != 0x90)- return c_uart_unknown;- inb(RBR(iobase));- inb(RBR(iobase));- outb(0x01, FCR(iobase)); /* enable FIFOs */- u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];- if (u == c_uart_16450) {- outb(0x5a, SCR(iobase));- b1 = inb(SCR(iobase));- outb(0xa5, SCR(iobase));- b2 = inb(SCR(iobase));- if ((b1 != 0x5a) || (b2 != 0xa5))- u = c_uart_8250;- }- return u;-}--/* --------------------------------------------------------------------- */--static int ser12_open(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);- enum uart u;-- if (!dev || !bc)- return -ENXIO;- if (!dev->base_addr || dev->base_addr > 0x1000-SER12_EXTENT ||- dev->irq < 2 || dev->irq > 15)- return -ENXIO;- if (!request_region(dev->base_addr, SER12_EXTENT, "baycom_ser12"))- return -EACCES;- memset(&bc->modem, 0, sizeof(bc->modem));- bc->hdrv.par.bitrate = 1200;- if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown) {- release_region(dev->base_addr, SER12_EXTENT); - return -EIO;- }- outb(0, FCR(dev->base_addr)); /* disable FIFOs */- outb(0x0d, MCR(dev->base_addr));- outb(0, IER(dev->base_addr));- if (request_irq(dev->irq, ser12_interrupt, IRQF_SHARED,- "baycom_ser12", dev)) {- release_region(dev->base_addr, SER12_EXTENT); - return -EBUSY;- }- /*- * enable transmitter empty interrupt- */- outb(2, IER(dev->base_addr));- /*- * set the SIO to 6 Bits/character and 19200 or 28800 baud, so that- * we get exactly (hopefully) 2 or 3 interrupts per radio symbol,- * depending on the usage of the software DCD routine- */- ser12_set_divisor(dev, bc->opt_dcd ? 6 : 4);- printk(KERN_INFO "%s: ser12 at iobase 0x%lx irq %u uart %s\n", - bc_drvname, dev->base_addr, dev->irq, uart_str[u]);- return 0;-}--/* --------------------------------------------------------------------- */--static int ser12_close(struct net_device *dev)-{- struct baycom_state *bc = netdev_priv(dev);-- if (!dev || !bc)- return -EINVAL;- /*- * disable interrupts- */- outb(0, IER(dev->base_addr));- outb(1, MCR(dev->base_addr));- free_irq(dev->irq, dev);- release_region(dev->base_addr, SER12_EXTENT);- printk(KERN_INFO "%s: close ser12 at iobase 0x%lx irq %u\n",- bc_drvname, dev->base_addr, dev->irq);- return 0;-}--/* --------------------------------------------------------------------- */-/*- * ===================== hdlcdrv driver interface =========================- */--/* --------------------------------------------------------------------- */--static int baycom_ioctl(struct net_device *dev, void __user *data,- struct hdlcdrv_ioctl *hi, int cmd);--/* --------------------------------------------------------------------- */--static const struct hdlcdrv_ops ser12_ops = {- .drvname = bc_drvname,- .drvinfo = bc_drvinfo,- .open = ser12_open,- .close = ser12_close,- .ioctl = baycom_ioctl,-};--/* --------------------------------------------------------------------- */--static int baycom_setmode(struct baycom_state *bc, const char *modestr)-{- if (strchr(modestr, '*'))- bc->opt_dcd = 0;- else if (strchr(modestr, '+'))- bc->opt_dcd = -1;- else if (strchr(modestr, '@'))- bc->opt_dcd = -2;- else- bc->opt_dcd = 1;- return 0;-}--/* --------------------------------------------------------------------- */--static int baycom_ioctl(struct net_device *dev, void __user *data,- struct hdlcdrv_ioctl *hi, int cmd)-{- struct baycom_state *bc;- struct baycom_ioctl bi;-- if (!dev)- return -EINVAL;-- bc = netdev_priv(dev);- BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);-- if (cmd != SIOCDEVPRIVATE)- return -ENOIOCTLCMD;- switch (hi->cmd) {- default:- break;-- case HDLCDRVCTL_GETMODE:- strscpy(hi->data.modename, "ser12");- if (bc->opt_dcd <= 0)- strcat(hi->data.modename, (!bc->opt_dcd) ? "*" : (bc->opt_dcd == -2) ? "@" : "+");- if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))- return -EFAULT;- return 0;-- case HDLCDRVCTL_SETMODE:- if (netif_running(dev) || !capable(CAP_NET_ADMIN))- return -EACCES;- hi->data.modename[sizeof(hi->data.modename)-1] = '\0';- return baycom_setmode(bc, hi->data.modename);-- case HDLCDRVCTL_MODELIST:- strscpy(hi->data.modename, "ser12");- if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))- return -EFAULT;- return 0;-- case HDLCDRVCTL_MODEMPARMASK:- return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ;-- }-- if (copy_from_user(&bi, data, sizeof(bi)))- return -EFAULT;- switch (bi.cmd) {- default:- return -ENOIOCTLCMD;--#ifdef BAYCOM_DEBUG- case BAYCOMCTL_GETDEBUG:- bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;- bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;- bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;- break;-#endif /* BAYCOM_DEBUG */-- }- if (copy_to_user(data, &bi, sizeof(bi)))- return -EFAULT;- return 0;--}--/* --------------------------------------------------------------------- */--/*- * command line settable parameters- */-static char *mode[NR_PORTS] = { "ser12*", };-static int iobase[NR_PORTS] = { 0x3f8, };-static int irq[NR_PORTS] = { 4, };--module_param_array(mode, charp, NULL, 0);-MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD");-module_param_hw_array(iobase, int, ioport, NULL, 0);-MODULE_PARM_DESC(iobase, "baycom io base address");-module_param_hw_array(irq, int, irq, NULL, 0);-MODULE_PARM_DESC(irq, "baycom irq number");--MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");-MODULE_DESCRIPTION("Baycom ser12 half duplex amateur radio modem driver");-MODULE_LICENSE("GPL");--/* --------------------------------------------------------------------- */--static int __init init_baycomserhdx(void)-{- int i, found = 0;- char set_hw = 1;-- printk(bc_drvinfo);- /*- * register net devices- */- for (i = 0; i < NR_PORTS; i++) {- struct net_device *dev;- struct baycom_state *bc;- char ifname[IFNAMSIZ];-- sprintf(ifname, "bcsh%d", i);-- if (!mode[i])- set_hw = 0;- if (!set_hw)- iobase[i] = irq[i] = 0;-- dev = hdlcdrv_register(&ser12_ops, - sizeof(struct baycom_state),- ifname, iobase[i], irq[i], 0);- if (IS_ERR(dev)) - break;-- bc = netdev_priv(dev);- if (set_hw && baycom_setmode(bc, mode[i]))- set_hw = 0;- found++;- baycom_device[i] = dev;- }-- if (!found)- return -ENXIO;- return 0;-}--static void __exit cleanup_baycomserhdx(void)-{- int i;-- for(i = 0; i < NR_PORTS; i++) {- struct net_device *dev = baycom_device[i];-- if (dev)- hdlcdrv_unregister(dev);- }-}--module_init(init_baycomserhdx);-module_exit(cleanup_baycomserhdx);--/* --------------------------------------------------------------------- */--#ifndef MODULE--/*- * format: baycom_ser_hdx=io,irq,mode- * mode: ser12 hardware DCD- * ser12* software DCD- * ser12@ hardware/software DCD, i.e. no explicit DCD signal but hardware- * mutes audio input to the modem- * ser12+ hardware DCD, inverted signal at DCD pin- */--static int __init baycom_ser_hdx_setup(char *str)-{- static unsigned nr_dev;- int ints[3];-- if (nr_dev >= NR_PORTS)- return 0;- str = get_options(str, 3, ints);- if (ints[0] < 2)- return 0;- mode[nr_dev] = str;- iobase[nr_dev] = ints[1];- irq[nr_dev] = ints[2];- nr_dev++;- return 1;-}--__setup("baycom_ser_hdx=", baycom_ser_hdx_setup);--#endif /* MODULE */-/* --------------------------------------------------------------------- */diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.cdeleted file mode 100644index 214fd1f819a1..000000000000--- a/drivers/net/hamradio/bpqether.c+++ /dev/null@@ -1,593 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- * G8BPQ compatible "AX.25 via ethernet" driver release 004- *- * This code REQUIRES 2.0.0 or higher/ NET3.029- *- * This is a "pseudo" network driver to allow AX.25 over Ethernet- * using G8BPQ encapsulation. It has been extracted from the protocol- * implementation because- *- * - things got unreadable within the protocol stack- * - to cure the protocol stack from "feature-ism"- * - a protocol implementation shouldn't need to know on- * which hardware it is running- * - user-level programs like the AX.25 utilities shouldn't- * need to know about the hardware.- * - IP over ethernet encapsulated AX.25 was impossible- * - rxecho.c did not work- * - to have room for extensions- * - it just deserves to "live" as an own driver- *- * This driver can use any ethernet destination address, and can be- * limited to accept frames from one dedicated ethernet card only.- *- * Note that the driver sets up the BPQ devices automagically on- * startup or (if started before the "insmod" of an ethernet device)- * on "ifconfig up". It hopefully will remove the BPQ on "rmmod"ing- * the ethernet device (in fact: as soon as another ethernet or bpq- * device gets "ifconfig"ured).- *- * I have heard that several people are thinking of experiments- * with highspeed packet radio using existing ethernet cards.- * Well, this driver is prepared for this purpose, just add- * your tx key control and a txdelay / tailtime algorithm,- * probably some buffering, and /voila/...- *- * History- * BPQ 001 Joerg(DL1BKE) Extracted BPQ code from AX.25- * protocol stack and added my own- * yet existing patches- * BPQ 002 Joerg(DL1BKE) Scan network device list on- * startup.- * BPQ 003 Joerg(DL1BKE) Ethernet destination address- * and accepted source address- * can be configured by an ioctl()- * call.- * Fixed to match Linux networking- * changes - 2.1.15.- * BPQ 004 Joerg(DL1BKE) Fixed to not lock up on ifconfig.- */--#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/string.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/etherdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/notifier.h>-#include <linux/proc_fs.h>-#include <linux/seq_file.h>-#include <linux/stat.h>-#include <linux/module.h>-#include <linux/init.h>-#include <linux/rtnetlink.h>--#include <net/ip.h>-#include <net/arp.h>-#include <net/netdev_lock.h>-#include <net/net_namespace.h>--#include <linux/bpqether.h>--static const char banner[] __initconst = KERN_INFO \- "AX.25: bpqether driver version 004\n";--static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);-static int bpq_device_event(struct notifier_block *, unsigned long, void *);--static struct packet_type bpq_packet_type __read_mostly = {- .type = cpu_to_be16(ETH_P_BPQ),- .func = bpq_rcv,-};--static struct notifier_block bpq_dev_notifier = {- .notifier_call = bpq_device_event,-};---struct bpqdev {- struct list_head bpq_list; /* list of bpq devices chain */- struct net_device *ethdev; /* link to ethernet device */- struct net_device *axdev; /* bpq device (bpq#) */- char dest_addr[6]; /* ether destination address */- char acpt_addr[6]; /* accept ether frames from this address only */-};--static LIST_HEAD(bpq_devices);--/* ------------------------------------------------------------------------ */---/*- * Get the ethernet device for a BPQ device- */-static inline struct net_device *bpq_get_ether_dev(struct net_device *dev)-{- struct bpqdev *bpq = netdev_priv(dev);-- return bpq ? bpq->ethdev : NULL;-}--/*- * Get the BPQ device for the ethernet device- */-static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)-{- struct bpqdev *bpq;-- list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list,- lockdep_rtnl_is_held()) {- if (bpq->ethdev == dev)- return bpq->axdev;- }- return NULL;-}--static inline int dev_is_ethdev(struct net_device *dev)-{- return dev->type == ARPHRD_ETHER && !netdev_need_ops_lock(dev);-}--/* ------------------------------------------------------------------------ */---/*- * Receive an AX.25 frame via an ethernet interface.- */-static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev)-{- int len;- char * ptr;- struct ethhdr *eth;- struct bpqdev *bpq;-- if (!net_eq(dev_net(dev), &init_net))- goto drop;-- if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)- return NET_RX_DROP;-- if (!pskb_may_pull(skb, sizeof(struct ethhdr)))- goto drop;-- rcu_read_lock();- dev = bpq_get_ax25_dev(dev);-- if (dev == NULL || !netif_running(dev)) - goto drop_unlock;-- /*- * if we want to accept frames from just one ethernet device- * we check the source address of the sender.- */-- bpq = netdev_priv(dev);-- eth = eth_hdr(skb);-- if (!(bpq->acpt_addr[0] & 0x01) &&- !ether_addr_equal(eth->h_source, bpq->acpt_addr))- goto drop_unlock;-- if (skb_cow(skb, sizeof(struct ethhdr)))- goto drop_unlock;-- len = skb->data[0] + skb->data[1] * 256 - 5;-- if (len < 0 || len > skb->len - 2)- goto drop_unlock;-- skb_pull(skb, 2); /* Remove the length bytes */- skb_trim(skb, len); /* Set the length of the data */-- dev->stats.rx_packets++;- dev->stats.rx_bytes += len;-- ptr = skb_push(skb, 1);- *ptr = 0;-- skb->protocol = ax25_type_trans(skb, dev);- netif_rx(skb);-unlock:-- rcu_read_unlock();-- return 0;-drop_unlock:- kfree_skb(skb);- goto unlock;--drop:- kfree_skb(skb);- return 0;-}--/*- * Send an AX.25 frame via an ethernet interface- */-static netdev_tx_t bpq_xmit(struct sk_buff *skb, struct net_device *dev)-{- unsigned char *ptr;- struct bpqdev *bpq;- struct net_device *orig_dev;- int size;-- if (skb->protocol == htons(ETH_P_IP))- return ax25_ip_xmit(skb);-- /*- * Just to be *really* sure not to send anything if the interface- * is down, the ethernet device may have gone.- */- if (!netif_running(dev)) {- kfree_skb(skb);- return NETDEV_TX_OK;- }-- skb_pull(skb, 1); /* Drop KISS byte */- size = skb->len;-- /*- * We're about to mess with the skb which may still shared with the- * generic networking code so unshare and ensure it's got enough- * space for the BPQ headers.- */- if (skb_cow(skb, AX25_BPQ_HEADER_LEN)) {- if (net_ratelimit())- pr_err("bpqether: out of memory\n");- kfree_skb(skb);-- return NETDEV_TX_OK;- }-- ptr = skb_push(skb, 2); /* Make space for length */-- *ptr++ = (size + 5) % 256;- *ptr++ = (size + 5) / 256;-- bpq = netdev_priv(dev);-- orig_dev = dev;- if ((dev = bpq_get_ether_dev(dev)) == NULL) {- orig_dev->stats.tx_dropped++;- kfree_skb(skb);- return NETDEV_TX_OK;- }-- skb->protocol = ax25_type_trans(skb, dev);- skb_reset_network_header(skb);- dev_hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);- dev->stats.tx_packets++;- dev->stats.tx_bytes+=skb->len;- - dev_queue_xmit(skb);- netif_wake_queue(dev);- return NETDEV_TX_OK;-}--/*- * Set AX.25 callsign- */-static int bpq_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr *sa = (struct sockaddr *)addr;-- dev_addr_set(dev, sa->sa_data);-- return 0;-}--/* Ioctl commands- *- * SIOCSBPQETHOPT reserved for enhancements- * SIOCSBPQETHADDR set the destination and accepted- * source ethernet address (broadcast- * or multicast: accept all)- */-static int bpq_siocdevprivate(struct net_device *dev, struct ifreq *ifr,- void __user *data, int cmd)-{- struct bpq_ethaddr __user *ethaddr = data;- struct bpqdev *bpq = netdev_priv(dev);- struct bpq_req req;-- if (!capable(CAP_NET_ADMIN))- return -EPERM;-- switch (cmd) {- case SIOCSBPQETHOPT:- if (copy_from_user(&req, data, sizeof(struct bpq_req)))- return -EFAULT;- switch (req.cmd) {- case SIOCGBPQETHPARAM:- case SIOCSBPQETHPARAM:- default:- return -EINVAL;- }-- break;-- case SIOCSBPQETHADDR:- if (copy_from_user(bpq->dest_addr, ethaddr->destination, ETH_ALEN))- return -EFAULT;- if (copy_from_user(bpq->acpt_addr, ethaddr->accept, ETH_ALEN))- return -EFAULT;- break;-- default:- return -EINVAL;- }-- return 0;-}--/*- * open/close a device- */-static int bpq_open(struct net_device *dev)-{- netif_start_queue(dev);- return 0;-}--static int bpq_close(struct net_device *dev)-{- netif_stop_queue(dev);- return 0;-}---/* ------------------------------------------------------------------------ */--#ifdef CONFIG_PROC_FS-/*- * Proc filesystem- */-static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)- __acquires(RCU)-{- int i = 1;- struct bpqdev *bpqdev;-- rcu_read_lock();-- if (*pos == 0)- return SEQ_START_TOKEN;- - list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) {- if (i == *pos)- return bpqdev;- }- return NULL;-}--static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)-{- struct list_head *p;- struct bpqdev *bpqdev = v;-- ++*pos;-- if (v == SEQ_START_TOKEN)- p = rcu_dereference(list_next_rcu(&bpq_devices));- else- p = rcu_dereference(list_next_rcu(&bpqdev->bpq_list));-- return (p == &bpq_devices) ? NULL - : list_entry(p, struct bpqdev, bpq_list);-}--static void bpq_seq_stop(struct seq_file *seq, void *v)- __releases(RCU)-{- rcu_read_unlock();-}---static int bpq_seq_show(struct seq_file *seq, void *v)-{- if (v == SEQ_START_TOKEN)- seq_puts(seq, - "dev ether destination accept from\n");- else {- const struct bpqdev *bpqdev = v;-- seq_printf(seq, "%-5s %-10s %pM ",- bpqdev->axdev->name, bpqdev->ethdev->name,- bpqdev->dest_addr);-- if (is_multicast_ether_addr(bpqdev->acpt_addr))- seq_printf(seq, "*\n");- else- seq_printf(seq, "%pM\n", bpqdev->acpt_addr);-- }- return 0;-}--static const struct seq_operations bpq_seqops = {- .start = bpq_seq_start,- .next = bpq_seq_next,- .stop = bpq_seq_stop,- .show = bpq_seq_show,-};-#endif-/* ------------------------------------------------------------------------ */--static const struct net_device_ops bpq_netdev_ops = {- .ndo_open = bpq_open,- .ndo_stop = bpq_close,- .ndo_start_xmit = bpq_xmit,- .ndo_set_mac_address = bpq_set_mac_address,- .ndo_siocdevprivate = bpq_siocdevprivate,-};--static void bpq_setup(struct net_device *dev)-{- netdev_lockdep_set_classes(dev);-- dev->netdev_ops = &bpq_netdev_ops;- dev->needs_free_netdev = true;-- dev->flags = 0;- dev->lltx = true; /* Allow recursion */--#if IS_ENABLED(CONFIG_AX25)- dev->header_ops = &ax25_header_ops;-#endif-- dev->type = ARPHRD_AX25;- dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;- dev->mtu = AX25_DEF_PACLEN;- dev->addr_len = AX25_ADDR_LEN;-- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);- dev_addr_set(dev, (u8 *)&ax25_defaddr);-}--/*- * Setup a new device.- */-static int bpq_new_device(struct net_device *edev)-{- int err;- struct net_device *ndev;- struct bpqdev *bpq;-- ndev = alloc_netdev(sizeof(struct bpqdev), "bpq%d", NET_NAME_UNKNOWN,- bpq_setup);- if (!ndev)- return -ENOMEM;-- - bpq = netdev_priv(ndev);- dev_hold(edev);- bpq->ethdev = edev;- bpq->axdev = ndev;-- eth_broadcast_addr(bpq->dest_addr);- eth_broadcast_addr(bpq->acpt_addr);-- err = register_netdevice(ndev);- if (err)- goto error;-- /* List protected by RTNL */- list_add_rcu(&bpq->bpq_list, &bpq_devices);- return 0;-- error:- dev_put(edev);- free_netdev(ndev);- return err;- -}--static void bpq_free_device(struct net_device *ndev)-{- struct bpqdev *bpq = netdev_priv(ndev);-- dev_put(bpq->ethdev);- list_del_rcu(&bpq->bpq_list);-- unregister_netdevice(ndev);-}--/*- * Handle device status changes.- */-static int bpq_device_event(struct notifier_block *this,- unsigned long event, void *ptr)-{- struct net_device *dev = netdev_notifier_info_to_dev(ptr);-- if (!net_eq(dev_net(dev), &init_net))- return NOTIFY_DONE;-- if (!dev_is_ethdev(dev) && !bpq_get_ax25_dev(dev))- return NOTIFY_DONE;-- switch (event) {- case NETDEV_UP: /* new ethernet device -> new BPQ interface */- if (bpq_get_ax25_dev(dev) == NULL)- bpq_new_device(dev);- break;-- case NETDEV_DOWN: /* ethernet device closed -> close BPQ interface */- if ((dev = bpq_get_ax25_dev(dev)) != NULL)- dev_close(dev);- break;-- case NETDEV_UNREGISTER: /* ethernet device removed -> free BPQ interface */- if ((dev = bpq_get_ax25_dev(dev)) != NULL)- bpq_free_device(dev);- break;- default:- break;- }-- return NOTIFY_DONE;-}---/* ------------------------------------------------------------------------ */--/*- * Initialize driver. To be called from af_ax25 if not compiled as a- * module- */-static int __init bpq_init_driver(void)-{-#ifdef CONFIG_PROC_FS- if (!proc_create_seq("bpqether", 0444, init_net.proc_net, &bpq_seqops)) {- printk(KERN_ERR- "bpq: cannot create /proc/net/bpqether entry.\n");- return -ENOENT;- }-#endif /* CONFIG_PROC_FS */-- dev_add_pack(&bpq_packet_type);-- register_netdevice_notifier(&bpq_dev_notifier);-- printk(banner);-- return 0;-}--static void __exit bpq_cleanup_driver(void)-{- struct bpqdev *bpq;-- dev_remove_pack(&bpq_packet_type);-- unregister_netdevice_notifier(&bpq_dev_notifier);-- remove_proc_entry("bpqether", init_net.proc_net);-- rtnl_lock();- while (!list_empty(&bpq_devices)) {- bpq = list_entry(bpq_devices.next, struct bpqdev, bpq_list);- bpq_free_device(bpq->axdev);- }- rtnl_unlock();-}--MODULE_AUTHOR("Joerg Reuter DL1BKE <jreuter@yaina.de>");-MODULE_DESCRIPTION("Transmit and receive AX.25 packets over Ethernet");-MODULE_LICENSE("GPL");-module_init(bpq_init_driver);-module_exit(bpq_cleanup_driver);diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.cdeleted file mode 100644index 3b88e465d08f..000000000000--- a/drivers/net/hamradio/hdlcdrv.c+++ /dev/null@@ -1,747 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*****************************************************************************/--/*- * hdlcdrv.c -- HDLC packet radio network driver.- *- * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)- *- * Please note that the GPL allows you to use the driver, NOT the radio.- * In order to use the radio, you need a license from the communications- * authority of your country.- *- * The driver was derived from Donald Beckers skeleton.c- * Written 1993-94 by Donald Becker.- *- * History:- * 0.1 21.09.1996 Started- * 18.10.1996 Changed to new user space access routines - * (copy_{to,from}_user)- * 0.2 21.11.1996 various small changes- * 0.3 03.03.1997 fixed (hopefully) IP not working with ax.25 as a module- * 0.4 16.04.1997 init code/data tagged- * 0.5 30.07.1997 made HDLC buffers bigger (solves a problem with the- * soundmodem driver)- * 0.6 05.04.1998 add spinlocks- * 0.7 03.08.1999 removed some old compatibility cruft- * 0.8 12.02.2000 adapted to softnet driver interface- */--/*****************************************************************************/--#include <linux/capability.h>-#include <linux/compat.h>-#include <linux/module.h>-#include <linux/types.h>-#include <linux/net.h>-#include <linux/in.h>-#include <linux/if.h>-#include <linux/errno.h>-#include <linux/init.h>-#include <linux/bitops.h>--#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <linux/hdlcdrv.h>-#include <linux/random.h>-#include <net/ax25.h> -#include <linux/uaccess.h>--#include <linux/crc-ccitt.h>--/* --------------------------------------------------------------------- */--#define KISS_VERBOSE--/* --------------------------------------------------------------------- */--#define PARAM_TXDELAY 1-#define PARAM_PERSIST 2-#define PARAM_SLOTTIME 3-#define PARAM_TXTAIL 4-#define PARAM_FULLDUP 5-#define PARAM_HARDWARE 6-#define PARAM_RETURN 255--/* --------------------------------------------------------------------- */-/*- * the CRC routines are stolen from WAMPES- * by Dieter Deyke- */---/*---------------------------------------------------------------------------*/--static inline void append_crc_ccitt(unsigned char *buffer, int len)-{- unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff;- buffer += len;- *buffer++ = crc;- *buffer++ = crc >> 8;-}--/*---------------------------------------------------------------------------*/--static inline int check_crc_ccitt(const unsigned char *buf, int cnt)-{- return (crc_ccitt(0xffff, buf, cnt) & 0xffff) == 0xf0b8;-}--/*---------------------------------------------------------------------------*/--#if 0-static int calc_crc_ccitt(const unsigned char *buf, int cnt)-{- unsigned int crc = 0xffff;-- for (; cnt > 0; cnt--)- crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];- crc ^= 0xffff;- return crc & 0xffff;-}-#endif--/* ---------------------------------------------------------------------- */--#define tenms_to_2flags(s,tenms) ((tenms * s->par.bitrate) / 100 / 16)--/* ---------------------------------------------------------------------- */-/*- * The HDLC routines- */--static int hdlc_rx_add_bytes(struct hdlcdrv_state *s, unsigned int bits, - int num)-{- int added = 0;- - while (s->hdlcrx.rx_state && num >= 8) {- if (s->hdlcrx.len >= sizeof(s->hdlcrx.buffer)) {- s->hdlcrx.rx_state = 0;- return 0;- }- *s->hdlcrx.bp++ = bits >> (32-num);- s->hdlcrx.len++;- num -= 8;- added += 8;- }- return added;-}--static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s)-{- struct sk_buff *skb;- int pkt_len;- unsigned char *cp;-- if (s->hdlcrx.len < 4) - return;- if (!check_crc_ccitt(s->hdlcrx.buffer, s->hdlcrx.len)) - return;- pkt_len = s->hdlcrx.len - 2 + 1; /* KISS kludge */- if (!(skb = dev_alloc_skb(pkt_len))) {- printk("%s: memory squeeze, dropping packet\n", dev->name);- dev->stats.rx_dropped++;- return;- }- cp = skb_put(skb, pkt_len);- *cp++ = 0; /* KISS kludge */- memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);- skb->protocol = ax25_type_trans(skb, dev);- netif_rx(skb);- dev->stats.rx_packets++;-}--void hdlcdrv_receiver(struct net_device *dev, struct hdlcdrv_state *s)-{- int i;- unsigned int mask1, mask2, mask3, mask4, mask5, mask6, word;- - if (!s || s->magic != HDLCDRV_MAGIC) - return;- if (test_and_set_bit(0, &s->hdlcrx.in_hdlc_rx))- return;-- while (!hdlcdrv_hbuf_empty(&s->hdlcrx.hbuf)) {- word = hdlcdrv_hbuf_get(&s->hdlcrx.hbuf); --#ifdef HDLCDRV_DEBUG- hdlcdrv_add_bitbuffer_word(&s->bitbuf_hdlc, word);-#endif /* HDLCDRV_DEBUG */- s->hdlcrx.bitstream >>= 16;- s->hdlcrx.bitstream |= word << 16;- s->hdlcrx.bitbuf >>= 16;- s->hdlcrx.bitbuf |= word << 16;- s->hdlcrx.numbits += 16;- for(i = 15, mask1 = 0x1fc00, mask2 = 0x1fe00, mask3 = 0x0fc00,- mask4 = 0x1f800, mask5 = 0xf800, mask6 = 0xffff; - i >= 0; - i--, mask1 <<= 1, mask2 <<= 1, mask3 <<= 1, mask4 <<= 1, - mask5 <<= 1, mask6 = (mask6 << 1) | 1) {- if ((s->hdlcrx.bitstream & mask1) == mask1)- s->hdlcrx.rx_state = 0; /* abort received */- else if ((s->hdlcrx.bitstream & mask2) == mask3) {- /* flag received */- if (s->hdlcrx.rx_state) {- hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf - << (8+i),- s->hdlcrx.numbits- -8-i);- hdlc_rx_flag(dev, s);- }- s->hdlcrx.len = 0;- s->hdlcrx.bp = s->hdlcrx.buffer;- s->hdlcrx.rx_state = 1;- s->hdlcrx.numbits = i;- } else if ((s->hdlcrx.bitstream & mask4) == mask5) {- /* stuffed bit */- s->hdlcrx.numbits--;- s->hdlcrx.bitbuf = (s->hdlcrx.bitbuf & (~mask6)) |- ((s->hdlcrx.bitbuf & mask6) << 1);- }- }- s->hdlcrx.numbits -= hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf,- s->hdlcrx.numbits);- }- clear_bit(0, &s->hdlcrx.in_hdlc_rx);-}--/* ---------------------------------------------------------------------- */--static inline void do_kiss_params(struct hdlcdrv_state *s,- unsigned char *data, unsigned long len)-{--#ifdef KISS_VERBOSE-#define PKP(a,b) printk(KERN_INFO "hdlcdrv.c: channel params: " a "\n", b)-#else /* KISS_VERBOSE */ -#define PKP(a,b) -#endif /* KISS_VERBOSE */ -- if (len < 2)- return;- switch(data[0]) {- case PARAM_TXDELAY:- s->ch_params.tx_delay = data[1];- PKP("TX delay = %ums", 10 * s->ch_params.tx_delay);- break;- case PARAM_PERSIST: - s->ch_params.ppersist = data[1];- PKP("p persistence = %u", s->ch_params.ppersist);- break;- case PARAM_SLOTTIME: - s->ch_params.slottime = data[1];- PKP("slot time = %ums", s->ch_params.slottime);- break;- case PARAM_TXTAIL: - s->ch_params.tx_tail = data[1];- PKP("TX tail = %ums", s->ch_params.tx_tail);- break;- case PARAM_FULLDUP: - s->ch_params.fulldup = !!data[1];- PKP("%s duplex", s->ch_params.fulldup ? "full" : "half");- break;- default:- break;- }-#undef PKP-}--/* ---------------------------------------------------------------------- */--void hdlcdrv_transmitter(struct net_device *dev, struct hdlcdrv_state *s)-{- unsigned int mask1, mask2, mask3;- int i;- struct sk_buff *skb;- int pkt_len;-- if (!s || s->magic != HDLCDRV_MAGIC) - return;- if (test_and_set_bit(0, &s->hdlctx.in_hdlc_tx))- return;- for (;;) {- if (s->hdlctx.numbits >= 16) {- if (hdlcdrv_hbuf_full(&s->hdlctx.hbuf)) {- clear_bit(0, &s->hdlctx.in_hdlc_tx);- return;- }- hdlcdrv_hbuf_put(&s->hdlctx.hbuf, s->hdlctx.bitbuf);- s->hdlctx.bitbuf >>= 16;- s->hdlctx.numbits -= 16;- }- switch (s->hdlctx.tx_state) {- default:- clear_bit(0, &s->hdlctx.in_hdlc_tx);- return;- case 0:- case 1:- if (s->hdlctx.numflags) {- s->hdlctx.numflags--;- s->hdlctx.bitbuf |= - 0x7e7e << s->hdlctx.numbits;- s->hdlctx.numbits += 16;- break;- }- if (s->hdlctx.tx_state == 1) {- clear_bit(0, &s->hdlctx.in_hdlc_tx);- return;- }- if (!(skb = s->skb)) {- int flgs = tenms_to_2flags(s, s->ch_params.tx_tail);- if (flgs < 2)- flgs = 2;- s->hdlctx.tx_state = 1;- s->hdlctx.numflags = flgs;- break;- }- s->skb = NULL;- netif_wake_queue(dev);- pkt_len = skb->len-1; /* strip KISS byte */- if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {- s->hdlctx.tx_state = 0;- s->hdlctx.numflags = 1;- dev_kfree_skb_irq(skb);- break;- }- skb_copy_from_linear_data_offset(skb, 1,- s->hdlctx.buffer,- pkt_len);- dev_kfree_skb_irq(skb);- s->hdlctx.bp = s->hdlctx.buffer;- append_crc_ccitt(s->hdlctx.buffer, pkt_len);- s->hdlctx.len = pkt_len+2; /* the appended CRC */- s->hdlctx.tx_state = 2;- s->hdlctx.bitstream = 0;- dev->stats.tx_packets++;- break;- case 2:- if (!s->hdlctx.len) {- s->hdlctx.tx_state = 0;- s->hdlctx.numflags = 1;- break;- }- s->hdlctx.len--;- s->hdlctx.bitbuf |= *s->hdlctx.bp <<- s->hdlctx.numbits;- s->hdlctx.bitstream >>= 8;- s->hdlctx.bitstream |= (*s->hdlctx.bp++) << 16;- mask1 = 0x1f000;- mask2 = 0x10000;- mask3 = 0xffffffff >> (31-s->hdlctx.numbits);- s->hdlctx.numbits += 8;- for(i = 0; i < 8; i++, mask1 <<= 1, mask2 <<= 1, - mask3 = (mask3 << 1) | 1) {- if ((s->hdlctx.bitstream & mask1) != mask1) - continue;- s->hdlctx.bitstream &= ~mask2;- s->hdlctx.bitbuf = - (s->hdlctx.bitbuf & mask3) |- ((s->hdlctx.bitbuf & - (~mask3)) << 1);- s->hdlctx.numbits++;- mask3 = (mask3 << 1) | 1;- }- break;- }- }-}--/* ---------------------------------------------------------------------- */--static void start_tx(struct net_device *dev, struct hdlcdrv_state *s)-{- s->hdlctx.tx_state = 0;- s->hdlctx.numflags = tenms_to_2flags(s, s->ch_params.tx_delay);- s->hdlctx.bitbuf = s->hdlctx.bitstream = s->hdlctx.numbits = 0;- hdlcdrv_transmitter(dev, s);- s->hdlctx.ptt = 1;- s->ptt_keyed++;-}--/* ---------------------------------------------------------------------- */--void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)-{- if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || !s->skb) - return;- if (s->ch_params.fulldup) {- start_tx(dev, s);- return;- }- if (s->hdlcrx.dcd) {- s->hdlctx.slotcnt = s->ch_params.slottime;- return;- }- if ((--s->hdlctx.slotcnt) > 0)- return;- s->hdlctx.slotcnt = s->ch_params.slottime;- if (get_random_u8() > s->ch_params.ppersist)- return;- start_tx(dev, s);-}--/* --------------------------------------------------------------------- */-/*- * ===================== network driver interface =========================- */--static netdev_tx_t hdlcdrv_send_packet(struct sk_buff *skb,- struct net_device *dev)-{- struct hdlcdrv_state *sm = netdev_priv(dev);-- if (skb->protocol == htons(ETH_P_IP))- return ax25_ip_xmit(skb);-- if (skb->data[0] != 0) {- do_kiss_params(sm, skb->data, skb->len);- dev_kfree_skb(skb);- return NETDEV_TX_OK;- }- if (sm->skb) {- dev_kfree_skb(skb);- return NETDEV_TX_OK;- }- netif_stop_queue(dev);- sm->skb = skb;- return NETDEV_TX_OK;-}--/* --------------------------------------------------------------------- */--static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr *sa = (struct sockaddr *)addr;-- /* addr is an AX.25 shifted ASCII mac address */- dev_addr_set(dev, sa->sa_data);- return 0; -}--/* --------------------------------------------------------------------- */-/*- * Open/initialize the board. This is called (in the current kernel)- * sometime after booting when the 'ifconfig' program is run.- *- * This routine should set everything up anew at each open, even- * registers that "should" only need to be set once at boot, so that- * there is non-reboot way to recover if something goes wrong.- */--static int hdlcdrv_open(struct net_device *dev)-{- struct hdlcdrv_state *s = netdev_priv(dev);- int i;-- if (!s->ops || !s->ops->open)- return -ENODEV;-- /*- * initialise some variables- */- s->opened = 1;- s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;- s->hdlcrx.in_hdlc_rx = 0;- s->hdlcrx.rx_state = 0;- - s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;- s->hdlctx.in_hdlc_tx = 0;- s->hdlctx.tx_state = 1;- s->hdlctx.numflags = 0;- s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;- s->hdlctx.ptt = 0;- s->hdlctx.slotcnt = s->ch_params.slottime;- s->hdlctx.calibrate = 0;-- i = s->ops->open(dev);- if (i)- return i;- netif_start_queue(dev);- return 0;-}--/* --------------------------------------------------------------------- */-/* - * The inverse routine to hdlcdrv_open(). - */--static int hdlcdrv_close(struct net_device *dev)-{- struct hdlcdrv_state *s = netdev_priv(dev);- int i = 0;-- netif_stop_queue(dev);-- if (s->ops && s->ops->close)- i = s->ops->close(dev);- dev_kfree_skb(s->skb);- s->skb = NULL;- s->opened = 0;- return i;-}--/* --------------------------------------------------------------------- */--static int hdlcdrv_siocdevprivate(struct net_device *dev, struct ifreq *ifr,- void __user *data, int cmd)-{- struct hdlcdrv_state *s = netdev_priv(dev);- struct hdlcdrv_ioctl bi;-- if (cmd != SIOCDEVPRIVATE)- return -ENOIOCTLCMD;-- if (in_compat_syscall()) /* to be implemented */- return -ENOIOCTLCMD;-- if (copy_from_user(&bi, data, sizeof(bi)))- return -EFAULT;-- switch (bi.cmd) {- default:- if (s->ops && s->ops->ioctl)- return s->ops->ioctl(dev, data, &bi, cmd);- return -ENOIOCTLCMD;-- case HDLCDRVCTL_GETCHANNELPAR:- bi.data.cp.tx_delay = s->ch_params.tx_delay;- bi.data.cp.tx_tail = s->ch_params.tx_tail;- bi.data.cp.slottime = s->ch_params.slottime;- bi.data.cp.ppersist = s->ch_params.ppersist;- bi.data.cp.fulldup = s->ch_params.fulldup;- break;-- case HDLCDRVCTL_SETCHANNELPAR:- if (!capable(CAP_NET_ADMIN))- return -EACCES;- s->ch_params.tx_delay = bi.data.cp.tx_delay;- s->ch_params.tx_tail = bi.data.cp.tx_tail;- s->ch_params.slottime = bi.data.cp.slottime;- s->ch_params.ppersist = bi.data.cp.ppersist;- s->ch_params.fulldup = bi.data.cp.fulldup;- s->hdlctx.slotcnt = 1;- return 0;- - case HDLCDRVCTL_GETMODEMPAR:- bi.data.mp.iobase = dev->base_addr;- bi.data.mp.irq = dev->irq;- bi.data.mp.dma = dev->dma;- bi.data.mp.dma2 = s->ptt_out.dma2;- bi.data.mp.seriobase = s->ptt_out.seriobase;- bi.data.mp.pariobase = s->ptt_out.pariobase;- bi.data.mp.midiiobase = s->ptt_out.midiiobase;- break;-- case HDLCDRVCTL_SETMODEMPAR:- if ((!capable(CAP_SYS_RAWIO)) || netif_running(dev))- return -EACCES;- dev->base_addr = bi.data.mp.iobase;- dev->irq = bi.data.mp.irq;- dev->dma = bi.data.mp.dma;- s->ptt_out.dma2 = bi.data.mp.dma2;- s->ptt_out.seriobase = bi.data.mp.seriobase;- s->ptt_out.pariobase = bi.data.mp.pariobase;- s->ptt_out.midiiobase = bi.data.mp.midiiobase;- return 0; - - case HDLCDRVCTL_GETSTAT:- bi.data.cs.ptt = hdlcdrv_ptt(s);- bi.data.cs.dcd = s->hdlcrx.dcd;- bi.data.cs.ptt_keyed = s->ptt_keyed;- bi.data.cs.tx_packets = dev->stats.tx_packets;- bi.data.cs.tx_errors = dev->stats.tx_errors;- bi.data.cs.rx_packets = dev->stats.rx_packets;- bi.data.cs.rx_errors = dev->stats.rx_errors;- break; -- case HDLCDRVCTL_OLDGETSTAT:- bi.data.ocs.ptt = hdlcdrv_ptt(s);- bi.data.ocs.dcd = s->hdlcrx.dcd;- bi.data.ocs.ptt_keyed = s->ptt_keyed;- break; -- case HDLCDRVCTL_CALIBRATE:- if(!capable(CAP_SYS_RAWIO))- return -EPERM;- if (s->par.bitrate <= 0)- return -EINVAL;- if (bi.data.calibrate > INT_MAX / s->par.bitrate)- return -EINVAL;- s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;- return 0;-- case HDLCDRVCTL_GETSAMPLES:-#ifndef HDLCDRV_DEBUG- return -EPERM;-#else /* HDLCDRV_DEBUG */- if (s->bitbuf_channel.rd == s->bitbuf_channel.wr) - return -EAGAIN;- bi.data.bits = - s->bitbuf_channel.buffer[s->bitbuf_channel.rd];- s->bitbuf_channel.rd = (s->bitbuf_channel.rd+1) %- sizeof(s->bitbuf_channel.buffer);- break;-#endif /* HDLCDRV_DEBUG */- - case HDLCDRVCTL_GETBITS:-#ifndef HDLCDRV_DEBUG- return -EPERM;-#else /* HDLCDRV_DEBUG */- if (s->bitbuf_hdlc.rd == s->bitbuf_hdlc.wr) - return -EAGAIN;- bi.data.bits = - s->bitbuf_hdlc.buffer[s->bitbuf_hdlc.rd];- s->bitbuf_hdlc.rd = (s->bitbuf_hdlc.rd+1) %- sizeof(s->bitbuf_hdlc.buffer);- break; -#endif /* HDLCDRV_DEBUG */-- case HDLCDRVCTL_DRIVERNAME:- if (s->ops && s->ops->drvname) {- strscpy(bi.data.drivername, s->ops->drvname,- sizeof(bi.data.drivername));- break;- }- bi.data.drivername[0] = '\0';- break;- - }- if (copy_to_user(data, &bi, sizeof(bi)))- return -EFAULT;- return 0;--}--/* --------------------------------------------------------------------- */--static const struct net_device_ops hdlcdrv_netdev = {- .ndo_open = hdlcdrv_open,- .ndo_stop = hdlcdrv_close,- .ndo_start_xmit = hdlcdrv_send_packet,- .ndo_siocdevprivate = hdlcdrv_siocdevprivate,- .ndo_set_mac_address = hdlcdrv_set_mac_address,-};--/*- * Initialize fields in hdlcdrv- */-static void hdlcdrv_setup(struct net_device *dev)-{- static const struct hdlcdrv_channel_params dflt_ch_params = { - 20, 2, 10, 40, 0 - };- struct hdlcdrv_state *s = netdev_priv(dev);-- /*- * initialize the hdlcdrv_state struct- */- s->ch_params = dflt_ch_params;- s->ptt_keyed = 0;-- spin_lock_init(&s->hdlcrx.hbuf.lock);- s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;- s->hdlcrx.in_hdlc_rx = 0;- s->hdlcrx.rx_state = 0;- - spin_lock_init(&s->hdlctx.hbuf.lock);- s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;- s->hdlctx.in_hdlc_tx = 0;- s->hdlctx.tx_state = 1;- s->hdlctx.numflags = 0;- s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;- s->hdlctx.ptt = 0;- s->hdlctx.slotcnt = s->ch_params.slottime;- s->hdlctx.calibrate = 0;--#ifdef HDLCDRV_DEBUG- s->bitbuf_channel.rd = s->bitbuf_channel.wr = 0;- s->bitbuf_channel.shreg = 0x80;-- s->bitbuf_hdlc.rd = s->bitbuf_hdlc.wr = 0;- s->bitbuf_hdlc.shreg = 0x80;-#endif /* HDLCDRV_DEBUG */--- /* Fill in the fields of the device structure */-- s->skb = NULL;- - dev->netdev_ops = &hdlcdrv_netdev;- dev->header_ops = &ax25_header_ops;- - dev->type = ARPHRD_AX25; /* AF_AX25 device */- dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;- dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */- dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);- dev_addr_set(dev, (u8 *)&ax25_defaddr);- dev->tx_queue_len = 16;-}--/* --------------------------------------------------------------------- */-struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,- unsigned int privsize, const char *ifname,- unsigned int baseaddr, unsigned int irq, - unsigned int dma) -{- struct net_device *dev;- struct hdlcdrv_state *s;- int err;-- if (privsize < sizeof(struct hdlcdrv_state))- privsize = sizeof(struct hdlcdrv_state);-- dev = alloc_netdev(privsize, ifname, NET_NAME_UNKNOWN, hdlcdrv_setup);- if (!dev)- return ERR_PTR(-ENOMEM);-- /*- * initialize part of the hdlcdrv_state struct- */- s = netdev_priv(dev);- s->magic = HDLCDRV_MAGIC;- s->ops = ops;- dev->base_addr = baseaddr;- dev->irq = irq;- dev->dma = dma;-- err = register_netdev(dev);- if (err < 0) {- printk(KERN_WARNING "hdlcdrv: cannot register net "- "device %s\n", dev->name);- free_netdev(dev);- dev = ERR_PTR(err);- }- return dev;-}--/* --------------------------------------------------------------------- */--void hdlcdrv_unregister(struct net_device *dev) -{- struct hdlcdrv_state *s = netdev_priv(dev);-- BUG_ON(s->magic != HDLCDRV_MAGIC);-- if (s->opened && s->ops->close)- s->ops->close(dev);- unregister_netdev(dev);- - free_netdev(dev);-}--/* --------------------------------------------------------------------- */--EXPORT_SYMBOL(hdlcdrv_receiver);-EXPORT_SYMBOL(hdlcdrv_transmitter);-EXPORT_SYMBOL(hdlcdrv_arbitrate);-EXPORT_SYMBOL(hdlcdrv_register);-EXPORT_SYMBOL(hdlcdrv_unregister);--/* --------------------------------------------------------------------- */--MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");-MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");-MODULE_LICENSE("GPL");diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.cdeleted file mode 100644index 5f38a002bd9e..000000000000--- a/drivers/net/hamradio/mkiss.c+++ /dev/null@@ -1,980 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-only-/*- *- * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>- * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>- * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>- */-#include <linux/module.h>-#include <linux/bitops.h>-#include <linux/uaccess.h>-#include <linux/crc16.h>-#include <linux/string.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/in.h>-#include <linux/inet.h>-#include <linux/slab.h>-#include <linux/tty.h>-#include <linux/errno.h>-#include <linux/netdevice.h>-#include <linux/major.h>-#include <linux/init.h>-#include <linux/rtnetlink.h>-#include <linux/etherdevice.h>-#include <linux/skbuff.h>-#include <linux/if_arp.h>-#include <linux/jiffies.h>-#include <linux/refcount.h>--#include <net/ax25.h>--#define AX_MTU 236--/* some arch define END as assembly function ending, just undef it */-#undef END-/* SLIP/KISS protocol characters. */-#define END 0300 /* indicates end of frame */-#define ESC 0333 /* indicates byte stuffing */-#define ESC_END 0334 /* ESC ESC_END means END 'data' */-#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */--struct mkiss {- struct tty_struct *tty; /* ptr to TTY structure */- struct net_device *dev; /* easy for intr handling */-- /* These are pointers to the malloc()ed frame buffers. */- spinlock_t buflock;/* lock for rbuf and xbuf */- unsigned char *rbuff; /* receiver buffer */- int rcount; /* received chars counter */- unsigned char *xbuff; /* transmitter buffer */- unsigned char *xhead; /* pointer to next byte to XMIT */- int xleft; /* bytes left in XMIT queue */-- /* Detailed SLIP statistics. */- int mtu; /* Our mtu (to spot changes!) */- int buffsize; /* Max buffers sizes */-- unsigned long flags; /* Flag values/ mode etc */- /* long req'd: used by set_bit --RR */-#define AXF_INUSE 0 /* Channel in use */-#define AXF_ESCAPE 1 /* ESC received */-#define AXF_ERROR 2 /* Parity, etc. error */-#define AXF_KEEPTEST 3 /* Keepalive test flag */-#define AXF_OUTWAIT 4 /* is outpacket was flag */-- int mode;- int crcmode; /* MW: for FlexNet, SMACK etc. */- int crcauto; /* CRC auto mode */--#define CRC_MODE_NONE 0-#define CRC_MODE_FLEX 1-#define CRC_MODE_SMACK 2-#define CRC_MODE_FLEX_TEST 3-#define CRC_MODE_SMACK_TEST 4-- refcount_t refcnt;- struct completion dead;-};--/*---------------------------------------------------------------------------*/--static const unsigned short crc_flex_table[] = {- 0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,- 0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,- 0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,- 0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,- 0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,- 0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,- 0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,- 0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,- 0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,- 0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,- 0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,- 0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,- 0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,- 0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,- 0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,- 0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,- 0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,- 0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,- 0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,- 0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,- 0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,- 0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,- 0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,- 0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,- 0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,- 0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,- 0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,- 0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,- 0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,- 0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,- 0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,- 0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff-};--static unsigned short calc_crc_flex(unsigned char *cp, int size)-{- unsigned short crc = 0xffff;-- while (size--)- crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];-- return crc;-}--static int check_crc_flex(unsigned char *cp, int size)-{- unsigned short crc = 0xffff;-- if (size < 3)- return -1;-- while (size--)- crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];-- if ((crc & 0xffff) != 0x7070)- return -1;-- return 0;-}--static int check_crc_16(unsigned char *cp, int size)-{- unsigned short crc = 0x0000;-- if (size < 3)- return -1;-- crc = crc16(0, cp, size);-- if (crc != 0x0000)- return -1;-- return 0;-}--/*- * Standard encapsulation- */--static int kiss_esc(unsigned char *s, unsigned char *d, int len)-{- unsigned char *ptr = d;- unsigned char c;-- /*- * Send an initial END character to flush out any data that may have- * accumulated in the receiver due to line noise.- */-- *ptr++ = END;-- while (len-- > 0) {- switch (c = *s++) {- case END:- *ptr++ = ESC;- *ptr++ = ESC_END;- break;- case ESC:- *ptr++ = ESC;- *ptr++ = ESC_ESC;- break;- default:- *ptr++ = c;- break;- }- }-- *ptr++ = END;-- return ptr - d;-}--/*- * MW:- * OK its ugly, but tell me a better solution without copying the- * packet to a temporary buffer :-)- */-static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc,- int len)-{- unsigned char *ptr = d;- unsigned char c=0;-- *ptr++ = END;- while (len > 0) {- if (len > 2)- c = *s++;- else if (len > 1)- c = crc >> 8;- else- c = crc & 0xff;-- len--;-- switch (c) {- case END:- *ptr++ = ESC;- *ptr++ = ESC_END;- break;- case ESC:- *ptr++ = ESC;- *ptr++ = ESC_ESC;- break;- default:- *ptr++ = c;- break;- }- }- *ptr++ = END;-- return ptr - d;-}--/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */-static void ax_bump(struct mkiss *ax)-{- struct sk_buff *skb;- int count;-- spin_lock_bh(&ax->buflock);- if (ax->rbuff[0] > 0x0f) {- if (ax->rbuff[0] & 0x80) {- if (check_crc_16(ax->rbuff, ax->rcount) < 0) {- ax->dev->stats.rx_errors++;- spin_unlock_bh(&ax->buflock);-- return;- }- if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {- printk(KERN_INFO- "mkiss: %s: Switching to crc-smack\n",- ax->dev->name);- ax->crcmode = CRC_MODE_SMACK;- }- ax->rcount -= 2;- *ax->rbuff &= ~0x80;- } else if (ax->rbuff[0] & 0x20) {- if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {- ax->dev->stats.rx_errors++;- spin_unlock_bh(&ax->buflock);- return;- }- if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {- printk(KERN_INFO- "mkiss: %s: Switching to crc-flexnet\n",- ax->dev->name);- ax->crcmode = CRC_MODE_FLEX;- }- ax->rcount -= 2;-- /*- * dl9sau bugfix: the trailling two bytes flexnet crc- * will not be passed to the kernel. thus we have to- * correct the kissparm signature, because it indicates- * a crc but there's none- */- *ax->rbuff &= ~0x20;- }- }-- count = ax->rcount;-- if ((skb = dev_alloc_skb(count)) == NULL) {- printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",- ax->dev->name);- ax->dev->stats.rx_dropped++;- spin_unlock_bh(&ax->buflock);- return;- }-- skb_put_data(skb, ax->rbuff, count);- skb->protocol = ax25_type_trans(skb, ax->dev);- netif_rx(skb);- ax->dev->stats.rx_packets++;- ax->dev->stats.rx_bytes += count;- spin_unlock_bh(&ax->buflock);-}--static void kiss_unesc(struct mkiss *ax, unsigned char s)-{- switch (s) {- case END:- /* drop keeptest bit = VSV */- if (test_bit(AXF_KEEPTEST, &ax->flags))- clear_bit(AXF_KEEPTEST, &ax->flags);-- if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))- ax_bump(ax);-- clear_bit(AXF_ESCAPE, &ax->flags);- ax->rcount = 0;- return;-- case ESC:- set_bit(AXF_ESCAPE, &ax->flags);- return;- case ESC_ESC:- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))- s = ESC;- break;- case ESC_END:- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))- s = END;- break;- }-- spin_lock_bh(&ax->buflock);- if (!test_bit(AXF_ERROR, &ax->flags)) {- if (ax->rcount < ax->buffsize) {- ax->rbuff[ax->rcount++] = s;- spin_unlock_bh(&ax->buflock);- return;- }-- ax->dev->stats.rx_over_errors++;- set_bit(AXF_ERROR, &ax->flags);- }- spin_unlock_bh(&ax->buflock);-}--static int ax_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr_ax25 *sa = addr;-- netif_tx_lock_bh(dev);- netif_addr_lock(dev);- __dev_addr_set(dev, &sa->sax25_call, AX25_ADDR_LEN);- netif_addr_unlock(dev);- netif_tx_unlock_bh(dev);-- return 0;-}--/*---------------------------------------------------------------------------*/--static void ax_changedmtu(struct mkiss *ax)-{- struct net_device *dev = ax->dev;- unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;- int len;-- len = dev->mtu * 2;-- /*- * allow for arrival of larger UDP packets, even if we say not to- * also fixes a bug in which SunOS sends 512-byte packets even with- * an MSS of 128- */- if (len < 576 * 2)- len = 576 * 2;-- xbuff = kmalloc(len + 4, GFP_ATOMIC);- rbuff = kmalloc(len + 4, GFP_ATOMIC);-- if (xbuff == NULL || rbuff == NULL) {- printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, "- "MTU change cancelled.\n",- ax->dev->name);- dev->mtu = ax->mtu;- kfree(xbuff);- kfree(rbuff);- return;- }-- spin_lock_bh(&ax->buflock);-- oxbuff = ax->xbuff;- ax->xbuff = xbuff;- orbuff = ax->rbuff;- ax->rbuff = rbuff;-- if (ax->xleft) {- if (ax->xleft <= len) {- memcpy(ax->xbuff, ax->xhead, ax->xleft);- } else {- ax->xleft = 0;- dev->stats.tx_dropped++;- }- }-- ax->xhead = ax->xbuff;-- if (ax->rcount) {- if (ax->rcount <= len) {- memcpy(ax->rbuff, orbuff, ax->rcount);- } else {- ax->rcount = 0;- dev->stats.rx_over_errors++;- set_bit(AXF_ERROR, &ax->flags);- }- }-- ax->mtu = dev->mtu + 73;- ax->buffsize = len;-- spin_unlock_bh(&ax->buflock);-- kfree(oxbuff);- kfree(orbuff);-}--/* Encapsulate one AX.25 packet and stuff into a TTY queue. */-static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)-{- struct mkiss *ax = netdev_priv(dev);- unsigned char *p;- int actual, count;-- if (ax->mtu != ax->dev->mtu + 73) /* Someone has been ifconfigging */- ax_changedmtu(ax);-- if (len > ax->mtu) { /* Sigh, shouldn't occur BUT ... */- printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);- dev->stats.tx_dropped++;- netif_start_queue(dev);- return;- }-- p = icp;-- spin_lock_bh(&ax->buflock);- if ((*p & 0x0f) != 0) {- /* Configuration Command (kissparms(1).- * Protocol spec says: never append CRC.- * This fixes a very old bug in the linux- * kiss driver. -- dl9sau */- switch (*p & 0xff) {- case 0x85:- /* command from userspace especially for us,- * not for delivery to the tnc */- if (len > 1) {- int cmd = (p[1] & 0xff);- switch(cmd) {- case 3:- ax->crcmode = CRC_MODE_SMACK;- break;- case 2:- ax->crcmode = CRC_MODE_FLEX;- break;- case 1:- ax->crcmode = CRC_MODE_NONE;- break;- case 0:- default:- ax->crcmode = CRC_MODE_SMACK_TEST;- cmd = 0;- }- ax->crcauto = (cmd ? 0 : 1);- printk(KERN_INFO "mkiss: %s: crc mode set to %d\n",- ax->dev->name, cmd);- }- spin_unlock_bh(&ax->buflock);- netif_start_queue(dev);-- return;- default:- count = kiss_esc(p, ax->xbuff, len);- }- } else {- unsigned short crc;- switch (ax->crcmode) {- case CRC_MODE_SMACK_TEST:- ax->crcmode = CRC_MODE_FLEX_TEST;- printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);- fallthrough;- case CRC_MODE_SMACK:- *p |= 0x80;- crc = swab16(crc16(0, p, len));- count = kiss_esc_crc(p, ax->xbuff, crc, len+2);- break;- case CRC_MODE_FLEX_TEST:- ax->crcmode = CRC_MODE_NONE;- printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);- fallthrough;- case CRC_MODE_FLEX:- *p |= 0x20;- crc = calc_crc_flex(p, len);- count = kiss_esc_crc(p, ax->xbuff, crc, len+2);- break;-- default:- count = kiss_esc(p, ax->xbuff, len);- }- }- spin_unlock_bh(&ax->buflock);-- set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);- actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);- dev->stats.tx_packets++;- dev->stats.tx_bytes += actual;-- netif_trans_update(ax->dev);- ax->xleft = count - actual;- ax->xhead = ax->xbuff + actual;-}--/* Encapsulate an AX.25 packet and kick it into a TTY queue. */-static netdev_tx_t ax_xmit(struct sk_buff *skb, struct net_device *dev)-{- struct mkiss *ax = netdev_priv(dev);-- if (skb->protocol == htons(ETH_P_IP))- return ax25_ip_xmit(skb);-- if (!netif_running(dev)) {- printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);- return NETDEV_TX_BUSY;- }-- if (netif_queue_stopped(dev)) {- /*- * May be we must check transmitter timeout here ?- * 14 Oct 1994 Dmitry Gorodchanin.- */- if (time_before(jiffies, dev_trans_start(dev) + 20 * HZ)) {- /* 20 sec timeout not reached */- return NETDEV_TX_BUSY;- }-- printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,- (tty_chars_in_buffer(ax->tty) || ax->xleft) ?- "bad line quality" : "driver error");-- ax->xleft = 0;- clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);- netif_start_queue(dev);- }-- /* We were not busy, so we are now... :-) */- netif_stop_queue(dev);- ax_encaps(dev, skb->data, skb->len);- kfree_skb(skb);-- return NETDEV_TX_OK;-}--static int ax_open_dev(struct net_device *dev)-{- struct mkiss *ax = netdev_priv(dev);-- if (ax->tty == NULL)- return -ENODEV;-- return 0;-}--/* Open the low-level part of the AX25 channel. Easy! */-static int ax_open(struct net_device *dev)-{- struct mkiss *ax = netdev_priv(dev);- unsigned long len;-- if (ax->tty == NULL)- return -ENODEV;-- /*- * Allocate the frame buffers:- *- * rbuff Receive buffer.- * xbuff Transmit buffer.- */- len = dev->mtu * 2;-- /*- * allow for arrival of larger UDP packets, even if we say not to- * also fixes a bug in which SunOS sends 512-byte packets even with- * an MSS of 128- */- if (len < 576 * 2)- len = 576 * 2;-- if ((ax->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)- goto norbuff;-- if ((ax->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)- goto noxbuff;-- ax->mtu = dev->mtu + 73;- ax->buffsize = len;- ax->rcount = 0;- ax->xleft = 0;-- ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */-- spin_lock_init(&ax->buflock);-- return 0;--noxbuff:- kfree(ax->rbuff);--norbuff:- return -ENOMEM;-}---/* Close the low-level part of the AX25 channel. Easy! */-static int ax_close(struct net_device *dev)-{- struct mkiss *ax = netdev_priv(dev);-- if (ax->tty)- clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);-- netif_stop_queue(dev);-- return 0;-}--static const struct net_device_ops ax_netdev_ops = {- .ndo_open = ax_open_dev,- .ndo_stop = ax_close,- .ndo_start_xmit = ax_xmit,- .ndo_set_mac_address = ax_set_mac_address,-};--static void ax_setup(struct net_device *dev)-{- /* Finish setting up the DEVICE info. */- dev->mtu = AX_MTU;- dev->hard_header_len = AX25_MAX_HEADER_LEN;- dev->addr_len = AX25_ADDR_LEN;- dev->type = ARPHRD_AX25;- dev->tx_queue_len = 10;- dev->header_ops = &ax25_header_ops;- dev->netdev_ops = &ax_netdev_ops;--- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);- dev_addr_set(dev, (u8 *)&ax25_defaddr);-- dev->flags = IFF_BROADCAST | IFF_MULTICAST;-}--/*- * We have a potential race on dereferencing tty->disc_data, because the tty- * layer provides no locking at all - thus one cpu could be running- * sixpack_receive_buf while another calls sixpack_close, which zeroes- * tty->disc_data and frees the memory that sixpack_receive_buf is using. The- * best way to fix this is to use a rwlock in the tty struct, but for now we- * use a single global rwlock for all ttys in ppp line discipline.- */-static DEFINE_RWLOCK(disc_data_lock);--static struct mkiss *mkiss_get(struct tty_struct *tty)-{- struct mkiss *ax;-- read_lock(&disc_data_lock);- ax = tty->disc_data;- if (ax)- refcount_inc(&ax->refcnt);- read_unlock(&disc_data_lock);-- return ax;-}--static void mkiss_put(struct mkiss *ax)-{- if (refcount_dec_and_test(&ax->refcnt))- complete(&ax->dead);-}--static int crc_force = 0; /* Can be overridden with insmod */--static int mkiss_open(struct tty_struct *tty)-{- struct net_device *dev;- struct mkiss *ax;- int err;-- if (!capable(CAP_NET_ADMIN))- return -EPERM;- if (tty->ops->write == NULL)- return -EOPNOTSUPP;-- dev = alloc_netdev(sizeof(struct mkiss), "ax%d", NET_NAME_UNKNOWN,- ax_setup);- if (!dev) {- err = -ENOMEM;- goto out;- }-- ax = netdev_priv(dev);- ax->dev = dev;-- spin_lock_init(&ax->buflock);- refcount_set(&ax->refcnt, 1);- init_completion(&ax->dead);-- ax->tty = tty;- tty->disc_data = ax;- tty->receive_room = 65535;-- tty_driver_flush_buffer(tty);-- /* Restore default settings */- dev->type = ARPHRD_AX25;-- /* Perform the low-level AX25 initialization. */- err = ax_open(ax->dev);- if (err)- goto out_free_netdev;-- err = register_netdev(dev);- if (err)- goto out_free_buffers;-- /* after register_netdev() - because else printk smashes the kernel */- switch (crc_force) {- case 3:- ax->crcmode = CRC_MODE_SMACK;- printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",- ax->dev->name);- break;- case 2:- ax->crcmode = CRC_MODE_FLEX;- printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",- ax->dev->name);- break;- case 1:- ax->crcmode = CRC_MODE_NONE;- printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",- ax->dev->name);- break;- case 0:- default:- crc_force = 0;- printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",- ax->dev->name);- ax->crcmode = CRC_MODE_SMACK_TEST;- }- ax->crcauto = (crc_force ? 0 : 1);-- netif_start_queue(dev);-- /* Done. We have linked the TTY line to a channel. */- return 0;--out_free_buffers:- kfree(ax->rbuff);- kfree(ax->xbuff);--out_free_netdev:- free_netdev(dev);--out:- return err;-}--static void mkiss_close(struct tty_struct *tty)-{- struct mkiss *ax;-- write_lock_irq(&disc_data_lock);- ax = tty->disc_data;- tty->disc_data = NULL;- write_unlock_irq(&disc_data_lock);-- if (!ax)- return;-- /*- * We have now ensured that nobody can start using ap from now on, but- * we have to wait for all existing users to finish.- */- if (!refcount_dec_and_test(&ax->refcnt))- wait_for_completion(&ax->dead);- /*- * Halt the transmit queue so that a new transmit cannot scribble- * on our buffers- */- netif_stop_queue(ax->dev);-- unregister_netdev(ax->dev);-- /* Free all AX25 frame buffers after unreg. */- kfree(ax->rbuff);- kfree(ax->xbuff);-- ax->tty = NULL;-- free_netdev(ax->dev);-}--/* Perform I/O control on an active ax25 channel. */-static int mkiss_ioctl(struct tty_struct *tty, unsigned int cmd,- unsigned long arg)-{- struct mkiss *ax = mkiss_get(tty);- struct net_device *dev;- unsigned int tmp, err;-- /* First make sure we're connected. */- if (ax == NULL)- return -ENXIO;- dev = ax->dev;-- switch (cmd) {- case SIOCGIFNAME:- err = copy_to_user((void __user *) arg, ax->dev->name,- strlen(ax->dev->name) + 1) ? -EFAULT : 0;- break;-- case SIOCGIFENCAP:- err = put_user(4, (int __user *) arg);- break;-- case SIOCSIFENCAP:- if (get_user(tmp, (int __user *) arg)) {- err = -EFAULT;- break;- }-- ax->mode = tmp;- dev->addr_len = AX25_ADDR_LEN;- dev->hard_header_len = AX25_KISS_HEADER_LEN +- AX25_MAX_HEADER_LEN + 3;- dev->type = ARPHRD_AX25;-- err = 0;- break;-- case SIOCSIFHWADDR: {- char addr[AX25_ADDR_LEN];-- if (copy_from_user(&addr,- (void __user *) arg, AX25_ADDR_LEN)) {- err = -EFAULT;- break;- }-- netif_tx_lock_bh(dev);- __dev_addr_set(dev, addr, AX25_ADDR_LEN);- netif_tx_unlock_bh(dev);-- err = 0;- break;- }- default:- err = -ENOIOCTLCMD;- }-- mkiss_put(ax);-- return err;-}--/*- * Handle the 'receiver data ready' interrupt.- * This function is called by the 'tty_io' module in the kernel when- * a block of data has been received, which can now be decapsulated- * and sent on to the AX.25 layer for further processing.- */-static void mkiss_receive_buf(struct tty_struct *tty, const u8 *cp,- const u8 *fp, size_t count)-{- struct mkiss *ax = mkiss_get(tty);-- if (!ax)- return;-- /*- * Argh! mtu change time! - costs us the packet part received- * at the change- */- if (ax->mtu != ax->dev->mtu + 73)- ax_changedmtu(ax);-- /* Read the characters out of the buffer */- while (count--) {- if (fp != NULL && *fp++) {- if (!test_and_set_bit(AXF_ERROR, &ax->flags))- ax->dev->stats.rx_errors++;- cp++;- continue;- }-- kiss_unesc(ax, *cp++);- }-- mkiss_put(ax);- tty_unthrottle(tty);-}--/*- * Called by the driver when there's room for more data. If we have- * more packets to send, we send them here.- */-static void mkiss_write_wakeup(struct tty_struct *tty)-{- struct mkiss *ax = mkiss_get(tty);- int actual;-- if (!ax)- return;-- if (ax->xleft <= 0) {- /* Now serial buffer is almost free & we can start- * transmission of another packet- */- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);-- netif_wake_queue(ax->dev);- goto out;- }-- actual = tty->ops->write(tty, ax->xhead, ax->xleft);- ax->xleft -= actual;- ax->xhead += actual;--out:- mkiss_put(ax);-}--static struct tty_ldisc_ops ax_ldisc = {- .owner = THIS_MODULE,- .num = N_AX25,- .name = "mkiss",- .open = mkiss_open,- .close = mkiss_close,- .ioctl = mkiss_ioctl,- .receive_buf = mkiss_receive_buf,- .write_wakeup = mkiss_write_wakeup-};--static const char banner[] __initconst = KERN_INFO \- "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";-static const char msg_regfail[] __initconst = KERN_ERR \- "mkiss: can't register line discipline (err = %d)\n";--static int __init mkiss_init_driver(void)-{- int status;-- printk(banner);-- status = tty_register_ldisc(&ax_ldisc);- if (status != 0)- printk(msg_regfail, status);-- return status;-}--static void __exit mkiss_exit_driver(void)-{- tty_unregister_ldisc(&ax_ldisc);-}--MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");-MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");-module_param(crc_force, int, 0);-MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");-MODULE_LICENSE("GPL");-MODULE_ALIAS_LDISC(N_AX25);--module_init(mkiss_init_driver);-module_exit(mkiss_exit_driver);diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.cdeleted file mode 100644index 8569db4a7140..000000000000--- a/drivers/net/hamradio/scc.c+++ /dev/null@@ -1,2179 +0,0 @@-#define RCS_ID "$Id: scc.c,v 1.75 1998/11/04 15:15:01 jreuter Exp jreuter $"--#define VERSION "3.0"--/*- * Please use z8530drv-utils-3.0 with this version.- * ------------------- *- * You can find a subset of the documentation in - * Documentation/networking/device_drivers/hamradio/z8530drv.rst.- */--/*- ********************************************************************- * SCC.C - Linux driver for Z8530 based HDLC cards for AX.25 *- ********************************************************************--- ********************************************************************-- Copyright (c) 1993, 2000 Joerg Reuter DL1BKE-- portions (c) 1993 Guido ten Dolle PE1NNZ-- ********************************************************************- - The driver and the programs in the archive are UNDER CONSTRUCTION.- The code is likely to fail, and so your kernel could --- even - a whole network. -- This driver is intended for Amateur Radio use. If you are running it- for commercial purposes, please drop me a note. I am nosy...-- ...BUT:- - ! You m u s t recognize the appropriate legislations of your country !- ! before you connect a radio to the SCC board and start to transmit or !- ! receive. The GPL allows you to use the d r i v e r, NOT the RADIO! !-- For non-Amateur-Radio use please note that you might need a special- allowance/licence from the designer of the SCC Board and/or the- MODEM. -- This program is free software; you can redistribute it and/or modify - it under the terms of the (modified) GNU General Public License - delivered with the Linux kernel source.- - This program is distributed in the hope that it will be useful,- but WITHOUT ANY WARRANTY; without even the implied warranty of- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the- GNU General Public License for more details.-- You should find a copy of the GNU General Public License in - /usr/src/linux/COPYING; - - ******************************************************************** -- - Incomplete history of z8530drv:- --------------------------------- 1994-09-13 started to write the driver, rescued most of my own- code (and Hans Alblas' memory buffer pool concept) from - an earlier project "sccdrv" which was initiated by - Guido ten Dolle. Not much of the old driver survived, - though. The first version I put my hands on was sccdrv1.3- from August 1993. The memory buffer pool concept- appeared in an unauthorized sccdrv version (1.5) from- August 1994.-- 1995-01-31 changed copyright notice to GPL without limitations.- - .- . <SNIP>- .- - 1996-10-05 New semester, new driver... -- * KISS TNC emulator removed (TTY driver)- * Source moved to drivers/net/- * Includes Z8530 defines from drivers/net/z8530.h- * Uses sk_buffer memory management- * Reduced overhead of /proc/net/z8530drv output- * Streamlined quite a lot things- * Invents brand new bugs... ;-)-- The move to version number 3.0 reflects theses changes.- You can use 'kissbridge' if you need a KISS TNC emulator.-- 1996-12-13 Fixed for Linux networking changes. (G4KLX)- 1997-01-08 Fixed the remaining problems.- 1997-04-02 Hopefully fixed the problems with the new *_timer()- routines, added calibration code.- 1997-10-12 Made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO- 1998-01-29 Small fix to avoid lock-up on initialization- 1998-09-29 Fixed the "grouping" bugs, tx_inhibit works again,- using dev->tx_queue_len now instead of MAXQUEUE now.- 1998-10-21 Postponed the spinlock changes, would need a lot of- testing I currently don't have the time to. Softdcd doesn't- work.- 1998-11-04 Softdcd does not work correctly in DPLL mode, in fact it - never did. The DPLL locks on noise, the SYNC unit sees- flags that aren't... Restarting the DPLL does not help- either, it resynchronizes too slow and the first received- frame gets lost.- 2000-02-13 Fixed for new network driver interface changes, still- does TX timeouts itself since it uses its own queue- scheme.-- Thanks to all who contributed to this driver with ideas and bug- reports!- - NB -- if you find errors, change something, please let me know- first before you distribute it... And please don't touch- the version number. Just replace my callsign in- "v3.0.dl1bke" with your own. Just to avoid confusion...-- If you want to add your modification to the linux distribution- please (!) contact me first.- - New versions of the driver will be announced on the linux-hams- mailing list on vger.kernel.org. To subscribe send an e-mail- to majordomo@vger.kernel.org with the following line in- the body of the mail:- - subscribe linux-hams- - The content of the "Subject" field will be ignored.-- vy 73,- Joerg Reuter ampr-net: dl1bke@db0pra.ampr.org- AX-25 : DL1BKE @ DB0ABH.#BAY.DEU.EU- Internet: jreuter@yaina.de- www : http://yaina.de/jreuter-*/--/* ----------------------------------------------------------------------- */--#undef SCC_LDELAY /* slow it even a bit more down */-#undef SCC_DONT_CHECK /* don't look if the SCCs you specified are available */--#define SCC_MAXCHIPS 4 /* number of max. supported chips */-#define SCC_BUFSIZE 384 /* must not exceed 4096 */-#undef SCC_DEBUG--#define SCC_DEFAULT_CLOCK 4915200 - /* default pclock if nothing is specified */--/* ----------------------------------------------------------------------- */--#include <linux/compat.h>-#include <linux/module.h>-#include <linux/errno.h>-#include <linux/signal.h>-#include <linux/timer.h>-#include <linux/interrupt.h>-#include <linux/ioport.h>-#include <linux/string.h>-#include <linux/in.h>-#include <linux/fcntl.h>-#include <linux/ptrace.h>-#include <linux/delay.h>-#include <linux/skbuff.h>-#include <linux/netdevice.h>-#include <linux/rtnetlink.h>-#include <linux/if_ether.h>-#include <linux/if_arp.h>-#include <linux/socket.h>-#include <linux/init.h>-#include <linux/scc.h>-#include <linux/ctype.h>-#include <linux/kernel.h>-#include <linux/proc_fs.h>-#include <linux/seq_file.h>-#include <linux/bitops.h>--#include <net/net_namespace.h>-#include <net/ax25.h>--#include <asm/irq.h>-#include <asm/io.h>-#include <linux/uaccess.h>--#include "z8530.h"--static const char banner[] __initconst = KERN_INFO \- "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n";--static void t_dwait(struct timer_list *t);-static void t_txdelay(struct timer_list *t);-static void t_tail(struct timer_list *t);-static void t_busy(struct timer_list *);-static void t_maxkeyup(struct timer_list *);-static void t_idle(struct timer_list *t);-static void scc_tx_done(struct scc_channel *);-static void scc_start_tx_timer(struct scc_channel *,- void (*)(struct timer_list *), unsigned long);-static void scc_start_maxkeyup(struct scc_channel *);-static void scc_start_defer(struct scc_channel *);--static void z8530_init(void);--static void init_channel(struct scc_channel *scc);-static void scc_key_trx (struct scc_channel *scc, char tx);-static void scc_init_timer(struct scc_channel *scc);--static int scc_net_alloc(const char *name, struct scc_channel *scc);-static void scc_net_setup(struct net_device *dev);-static int scc_net_open(struct net_device *dev);-static int scc_net_close(struct net_device *dev);-static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);-static netdev_tx_t scc_net_tx(struct sk_buff *skb,- struct net_device *dev);-static int scc_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr,- void __user *data, int cmd);-static int scc_net_set_mac_address(struct net_device *dev, void *addr);-static struct net_device_stats * scc_net_get_stats(struct net_device *dev);--static unsigned char SCC_DriverName[] = "scc";--static struct irqflags { unsigned char used : 1; } Ivec[NR_IRQS];- -static struct scc_channel SCC_Info[2 * SCC_MAXCHIPS]; /* information per channel */--static struct scc_ctrl {- io_port chan_A;- io_port chan_B;- int irq;-} SCC_ctrl[SCC_MAXCHIPS+1];--static unsigned char Driver_Initialized;-static int Nchips;-static io_port Vector_Latch;---/* ******************************************************************** */-/* * Port Access Functions * */-/* ******************************************************************** */--/* These provide interrupt save 2-step access to the Z8530 registers */--static DEFINE_SPINLOCK(iolock); /* Guards paired accesses */--static inline unsigned char InReg(io_port port, unsigned char reg)-{- unsigned long flags;- unsigned char r;-- spin_lock_irqsave(&iolock, flags); -#ifdef SCC_LDELAY- Outb(port, reg);- udelay(SCC_LDELAY);- r=Inb(port);- udelay(SCC_LDELAY);-#else- Outb(port, reg);- r=Inb(port);-#endif- spin_unlock_irqrestore(&iolock, flags);- return r;-}--static inline void OutReg(io_port port, unsigned char reg, unsigned char val)-{- unsigned long flags;-- spin_lock_irqsave(&iolock, flags);-#ifdef SCC_LDELAY- Outb(port, reg); udelay(SCC_LDELAY);- Outb(port, val); udelay(SCC_LDELAY);-#else- Outb(port, reg);- Outb(port, val);-#endif- spin_unlock_irqrestore(&iolock, flags);-}--static inline void wr(struct scc_channel *scc, unsigned char reg,- unsigned char val)-{- OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));-}--static inline void or(struct scc_channel *scc, unsigned char reg, unsigned char val)-{- OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));-}--static inline void cl(struct scc_channel *scc, unsigned char reg, unsigned char val)-{- OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));-}--/* ******************************************************************** */-/* * Some useful macros * */-/* ******************************************************************** */--static inline void scc_discard_buffers(struct scc_channel *scc)-{- unsigned long flags;- - spin_lock_irqsave(&scc->lock, flags); - if (scc->tx_buff != NULL)- {- dev_kfree_skb_irq(scc->tx_buff);- scc->tx_buff = NULL;- }- - while (!skb_queue_empty(&scc->tx_queue))- dev_kfree_skb_irq(skb_dequeue(&scc->tx_queue));-- spin_unlock_irqrestore(&scc->lock, flags);-}----/* ******************************************************************** */-/* * Interrupt Service Routines * */-/* ******************************************************************** */---/* ----> subroutines for the interrupt handlers <---- */--static inline void scc_notify(struct scc_channel *scc, int event)-{- struct sk_buff *skb;- char *bp;- - if (scc->kiss.fulldup != KISS_DUPLEX_OPTIMA)- return;-- skb = dev_alloc_skb(2);- if (skb != NULL)- {- bp = skb_put(skb, 2);- *bp++ = PARAM_HWEVENT;- *bp++ = event;- scc_net_rx(scc, skb);- } else- scc->stat.nospace++;-}--static inline void flush_rx_FIFO(struct scc_channel *scc)-{- int k;- - for (k=0; k<3; k++)- Inb(scc->data);- - if(scc->rx_buff != NULL) /* did we receive something? */- {- scc->stat.rxerrs++; /* then count it as an error */- dev_kfree_skb_irq(scc->rx_buff);- scc->rx_buff = NULL;- }-}--static void start_hunt(struct scc_channel *scc)-{- if ((scc->modem.clocksrc != CLK_EXTERNAL))- OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */- or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */-}--/* ----> four different interrupt handlers for Tx, Rx, changing of */-/* DCD/CTS and Rx/Tx errors */--/* Transmitter interrupt handler */-static inline void scc_txint(struct scc_channel *scc)-{- struct sk_buff *skb;-- scc->stat.txints++;- skb = scc->tx_buff;- - /* send first octet */- - if (skb == NULL)- {- skb = skb_dequeue(&scc->tx_queue);- scc->tx_buff = skb;- netif_wake_queue(scc->dev);-- if (skb == NULL)- {- scc_tx_done(scc);- Outb(scc->ctrl, RES_Tx_P);- return;- }- - if (skb->len == 0) /* Paranoia... */- {- dev_kfree_skb_irq(skb);- scc->tx_buff = NULL;- scc_tx_done(scc);- Outb(scc->ctrl, RES_Tx_P);- return;- }-- scc->stat.tx_state = TXS_ACTIVE;-- OutReg(scc->ctrl, R0, RES_Tx_CRC);- /* reset CRC generator */- or(scc,R10,ABUNDER); /* re-install underrun protection */- Outb(scc->data,*skb->data); /* send byte */- skb_pull(skb, 1);-- if (!scc->enhanced) /* reset EOM latch */- Outb(scc->ctrl,RES_EOM_L);- return;- }- - /* End Of Frame... */- - if (skb->len == 0)- {- Outb(scc->ctrl, RES_Tx_P); /* reset pending int */- cl(scc, R10, ABUNDER); /* send CRC */- dev_kfree_skb_irq(skb);- scc->tx_buff = NULL;- scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */- return;- } - - /* send octet */- - Outb(scc->data,*skb->data); - skb_pull(skb, 1);-}---/* External/Status interrupt handler */-static inline void scc_exint(struct scc_channel *scc)-{- unsigned char status,changes,chg_and_stat;-- scc->stat.exints++;-- status = InReg(scc->ctrl,R0);- changes = status ^ scc->status;- chg_and_stat = changes & status;- - /* ABORT: generated whenever DCD drops while receiving */-- if (chg_and_stat & BRK_ABRT) /* Received an ABORT */- flush_rx_FIFO(scc);-- /* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */-- if ((changes & SYNC_HUNT) && scc->kiss.softdcd)- {- if (status & SYNC_HUNT)- {- scc->dcd = 0;- flush_rx_FIFO(scc);- if ((scc->modem.clocksrc != CLK_EXTERNAL))- OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */- } else {- scc->dcd = 1;- }-- scc_notify(scc, scc->dcd? HWEV_DCD_OFF:HWEV_DCD_ON);- }-- /* DCD: on = start to receive packet, off = ABORT condition */- /* (a successfully received packet generates a special condition int) */- - if((changes & DCD) && !scc->kiss.softdcd) /* DCD input changed state */- {- if(status & DCD) /* DCD is now ON */- {- start_hunt(scc);- scc->dcd = 1;- } else { /* DCD is now OFF */- cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */- flush_rx_FIFO(scc);- scc->dcd = 0;- }- - scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);- }--#ifdef notdef- /* CTS: use external TxDelay (what's that good for?!)- * Anyway: If we _could_ use it (BayCom USCC uses CTS for- * own purposes) we _should_ use the "autoenable" feature- * of the Z8530 and not this interrupt...- */- - if (chg_and_stat & CTS) /* CTS is now ON */- {- if (scc->kiss.txdelay == 0) /* zero TXDELAY = wait for CTS */- scc_start_tx_timer(scc, t_txdelay, 0);- }-#endif- - if (scc->stat.tx_state == TXS_ACTIVE && (status & TxEOM))- {- scc->stat.tx_under++; /* oops, an underrun! count 'em */- Outb(scc->ctrl, RES_EXT_INT); /* reset ext/status interrupts */-- if (scc->tx_buff != NULL)- {- dev_kfree_skb_irq(scc->tx_buff);- scc->tx_buff = NULL;- }- - or(scc,R10,ABUNDER);- scc_start_tx_timer(scc, t_txdelay, 0); /* restart transmission */- }- - scc->status = status;- Outb(scc->ctrl,RES_EXT_INT);-}---/* Receiver interrupt handler */-static inline void scc_rxint(struct scc_channel *scc)-{- struct sk_buff *skb;-- scc->stat.rxints++;-- if((scc->wreg[5] & RTS) && scc->kiss.fulldup == KISS_DUPLEX_HALF)- {- Inb(scc->data); /* discard char */- or(scc,R3,ENT_HM); /* enter hunt mode for next flag */- return;- }-- skb = scc->rx_buff;- - if (skb == NULL)- {- skb = dev_alloc_skb(scc->stat.bufsize);- if (skb == NULL)- {- scc->dev_stat.rx_dropped++;- scc->stat.nospace++;- Inb(scc->data);- or(scc, R3, ENT_HM);- return;- }- - scc->rx_buff = skb;- skb_put_u8(skb, 0); /* KISS data */- }- - if (skb->len >= scc->stat.bufsize)- {-#ifdef notdef- printk(KERN_DEBUG "z8530drv: oops, scc_rxint() received huge frame...\n");-#endif- dev_kfree_skb_irq(skb);- scc->rx_buff = NULL;- Inb(scc->data);- or(scc, R3, ENT_HM);- return;- }-- skb_put_u8(skb, Inb(scc->data));-}---/* Receive Special Condition interrupt handler */-static inline void scc_spint(struct scc_channel *scc)-{- unsigned char status;- struct sk_buff *skb;-- scc->stat.spints++;-- status = InReg(scc->ctrl,R1); /* read receiver status */- - Inb(scc->data); /* throw away Rx byte */- skb = scc->rx_buff;-- if(status & Rx_OVR) /* receiver overrun */- {- scc->stat.rx_over++; /* count them */- or(scc,R3,ENT_HM); /* enter hunt mode for next flag */- - if (skb != NULL) - dev_kfree_skb_irq(skb);- scc->rx_buff = skb = NULL;- }-- if(status & END_FR && skb != NULL) /* end of frame */- {- /* CRC okay, frame ends on 8 bit boundary and received something ? */- - if (!(status & CRC_ERR) && (status & 0xe) == RES8 && skb->len > 0)- {- /* ignore last received byte (first of the CRC bytes) */- skb_trim(skb, skb->len-1);- scc_net_rx(scc, skb);- scc->rx_buff = NULL;- scc->stat.rxframes++;- } else { /* a bad frame */- dev_kfree_skb_irq(skb);- scc->rx_buff = NULL;- scc->stat.rxerrs++;- }- } -- Outb(scc->ctrl,ERR_RES);-}---/* ----> interrupt service routine for the Z8530 <---- */--static void scc_isr_dispatch(struct scc_channel *scc, int vector)-{- spin_lock(&scc->lock);- switch (vector & VECTOR_MASK)- {- case TXINT: scc_txint(scc); break;- case EXINT: scc_exint(scc); break;- case RXINT: scc_rxint(scc); break;- case SPINT: scc_spint(scc); break;- }- spin_unlock(&scc->lock);-}--/* If the card has a latch for the interrupt vector (like the PA0HZP card)- use it to get the number of the chip that generated the int.- If not: poll all defined chips.- */--#define SCC_IRQTIMEOUT 30000--static irqreturn_t scc_isr(int irq, void *dev_id)-{- int chip_irq = (long) dev_id;- unsigned char vector; - struct scc_channel *scc;- struct scc_ctrl *ctrl;- int k;- - if (Vector_Latch)- {- for(k=0; k < SCC_IRQTIMEOUT; k++)- {- Outb(Vector_Latch, 0); /* Generate INTACK */- - /* Read the vector */- if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break; - if (vector & 0x01) break;- - scc=&SCC_Info[vector >> 3 ^ 0x01];- if (!scc->dev) break;-- scc_isr_dispatch(scc, vector);-- OutReg(scc->ctrl,R0,RES_H_IUS); /* Reset Highest IUS */- } -- if (k == SCC_IRQTIMEOUT)- printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");-- return IRQ_HANDLED;- }-- /* Find the SCC generating the interrupt by polling all attached SCCs- * reading RR3A (the interrupt pending register)- */-- ctrl = SCC_ctrl;- while (ctrl->chan_A)- {- if (ctrl->irq != chip_irq)- {- ctrl++;- continue;- }-- scc = NULL;- for (k = 0; InReg(ctrl->chan_A,R3) && k < SCC_IRQTIMEOUT; k++)- {- vector=InReg(ctrl->chan_B,R2); /* Read the vector */- if (vector & 0x01) break; -- scc = &SCC_Info[vector >> 3 ^ 0x01];- if (!scc->dev) break;-- scc_isr_dispatch(scc, vector);- }-- if (k == SCC_IRQTIMEOUT)- {- printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?!\n");- break;- }-- /* This looks weird and it is. At least the BayCom USCC doesn't- * use the Interrupt Daisy Chain, thus we'll have to start- * all over again to be sure not to miss an interrupt from - * (any of) the other chip(s)...- * Honestly, the situation *is* braindamaged...- */-- if (scc != NULL)- {- OutReg(scc->ctrl,R0,RES_H_IUS);- ctrl = SCC_ctrl; - } else- ctrl++;- }- return IRQ_HANDLED;-}----/* ******************************************************************** */-/* * Init Channel */-/* ******************************************************************** */---/* ----> set SCC channel speed <---- */--static inline void set_brg(struct scc_channel *scc, unsigned int tc)-{- cl(scc,R14,BRENABL); /* disable baudrate generator */- wr(scc,R12,tc & 255); /* brg rate LOW */- wr(scc,R13,tc >> 8); /* brg rate HIGH */- or(scc,R14,BRENABL); /* enable baudrate generator */-}--static inline void set_speed(struct scc_channel *scc)-{- unsigned long flags;- spin_lock_irqsave(&scc->lock, flags);-- if (scc->modem.speed > 0) /* paranoia... */- set_brg(scc, (unsigned) (scc->clock / (scc->modem.speed * 64)) - 2);- - spin_unlock_irqrestore(&scc->lock, flags);-}---/* ----> initialize a SCC channel <---- */--static inline void init_brg(struct scc_channel *scc)-{- wr(scc, R14, BRSRC); /* BRG source = PCLK */- OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]); /* DPLL source = BRG */- OutReg(scc->ctrl, R14, SNRZI|scc->wreg[R14]); /* DPLL NRZI mode */-}--/*- * Initialization according to the Z8530 manual (SGS-Thomson's version):- *- * 1. Modes and constants- *- * WR9 11000000 chip reset- * WR4 XXXXXXXX Tx/Rx control, async or sync mode- * WR1 0XX00X00 select W/REQ (optional)- * WR2 XXXXXXXX program interrupt vector- * WR3 XXXXXXX0 select Rx control- * WR5 XXXX0XXX select Tx control- * WR6 XXXXXXXX sync character- * WR7 XXXXXXXX sync character- * WR9 000X0XXX select interrupt control- * WR10 XXXXXXXX miscellaneous control (optional)- * WR11 XXXXXXXX clock control- * WR12 XXXXXXXX time constant lower byte (optional)- * WR13 XXXXXXXX time constant upper byte (optional)- * WR14 XXXXXXX0 miscellaneous control- * WR14 XXXSSSSS commands (optional)- *- * 2. Enables- *- * WR14 000SSSS1 baud rate enable- * WR3 SSSSSSS1 Rx enable- * WR5 SSSS1SSS Tx enable- * WR0 10000000 reset Tx CRG (optional)- * WR1 XSS00S00 DMA enable (optional)- *- * 3. Interrupt status- *- * WR15 XXXXXXXX enable external/status- * WR0 00010000 reset external status- * WR0 00010000 reset external status twice- * WR1 SSSXXSXX enable Rx, Tx and Ext/status- * WR9 000SXSSS enable master interrupt enable- *- * 1 = set to one, 0 = reset to zero- * X = user defined, S = same as previous init- *- *- * Note that the implementation differs in some points from above scheme.- *- */- -static void init_channel(struct scc_channel *scc)-{- timer_delete(&scc->tx_t);- timer_delete(&scc->tx_wdog);-- disable_irq(scc->irq);-- wr(scc,R4,X1CLK|SDLC); /* *1 clock, SDLC mode */- wr(scc,R1,0); /* no W/REQ operation */- wr(scc,R3,Rx8|RxCRC_ENAB); /* RX 8 bits/char, CRC, disabled */ - wr(scc,R5,Tx8|DTR|TxCRC_ENAB); /* TX 8 bits/char, disabled, DTR */- wr(scc,R6,0); /* SDLC address zero (not used) */- wr(scc,R7,FLAG); /* SDLC flag value */- wr(scc,R9,VIS); /* vector includes status */- wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */- wr(scc,R14, 0);---/* set clock sources:-- CLK_DPLL: normal halfduplex operation- - RxClk: use DPLL- TxClk: use DPLL- TRxC mode DPLL output- - CLK_EXTERNAL: external clocking (G3RUH or DF9IC modem)- - BayCom: others:- - TxClk = pin RTxC TxClk = pin TRxC- RxClk = pin TRxC RxClk = pin RTxC- -- CLK_DIVIDER:- RxClk = use DPLL- TxClk = pin RTxC- - BayCom: others:- pin TRxC = DPLL pin TRxC = BRG- (RxClk * 1) (RxClk * 32)-*/ -- - switch(scc->modem.clocksrc)- {- case CLK_DPLL:- wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);- init_brg(scc);- break;-- case CLK_DIVIDER:- wr(scc, R11, ((scc->brand & BAYCOM)? TRxCDP : TRxCBR) | RCDPLL|TCRTxCP|TRxCOI);- init_brg(scc);- break;-- case CLK_EXTERNAL:- wr(scc, R11, (scc->brand & BAYCOM)? RCTRxCP|TCRTxCP : RCRTxCP|TCTRxCP);- OutReg(scc->ctrl, R14, DISDPLL);- break;-- }- - set_speed(scc); /* set baudrate */- - if(scc->enhanced)- {- or(scc,R15,SHDLCE|FIFOE); /* enable FIFO, SDLC/HDLC Enhancements (From now R7 is R7') */- wr(scc,R7,AUTOEOM);- }-- if(scc->kiss.softdcd || (InReg(scc->ctrl,R0) & DCD))- /* DCD is now ON */- {- start_hunt(scc);- }- - /* enable ABORT, DCD & SYNC/HUNT interrupts */-- wr(scc,R15, BRKIE|TxUIE|(scc->kiss.softdcd? SYNCIE:DCDIE));-- Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */- Outb(scc->ctrl,RES_EXT_INT); /* must be done twice */-- or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */- - scc->status = InReg(scc->ctrl,R0); /* read initial status */- - or(scc,R9,MIE); /* master interrupt enable */- - scc_init_timer(scc);- - enable_irq(scc->irq);-}-----/* ******************************************************************** */-/* * SCC timer functions * */-/* ******************************************************************** */---/* ----> scc_key_trx sets the time constant for the baudrate - generator and keys the transmitter <---- */--static void scc_key_trx(struct scc_channel *scc, char tx)-{- unsigned int time_const;- - if (scc->brand & PRIMUS)- Outb(scc->ctrl + 4, scc->option | (tx? 0x80 : 0));-- if (scc->modem.speed < 300) - scc->modem.speed = 1200;-- time_const = (unsigned) (scc->clock / (scc->modem.speed * (tx? 2:64))) - 2;-- disable_irq(scc->irq);-- if (tx)- {- or(scc, R1, TxINT_ENAB); /* t_maxkeyup may have reset these */- or(scc, R15, TxUIE);- }-- if (scc->modem.clocksrc == CLK_DPLL)- { /* force simplex operation */- if (tx)- {-#ifdef CONFIG_SCC_TRXECHO- cl(scc, R3, RxENABLE|ENT_HM); /* switch off receiver */- cl(scc, R15, DCDIE|SYNCIE); /* No DCD changes, please */-#endif- set_brg(scc, time_const); /* reprogram baudrate generator */-- /* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */- wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);- - /* By popular demand: tx_inhibit */- if (scc->kiss.tx_inhibit)- {- or(scc,R5, TxENAB);- scc->wreg[R5] |= RTS;- } else {- or(scc,R5,RTS|TxENAB); /* set the RTS line and enable TX */- }- } else {- cl(scc,R5,RTS|TxENAB);- - set_brg(scc, time_const); /* reprogram baudrate generator */- - /* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */- wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);--#ifndef CONFIG_SCC_TRXECHO- if (scc->kiss.softdcd)-#endif- {- or(scc,R15, scc->kiss.softdcd? SYNCIE:DCDIE);- start_hunt(scc);- }- }- } else {- if (tx)- {-#ifdef CONFIG_SCC_TRXECHO- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)- {- cl(scc, R3, RxENABLE);- cl(scc, R15, DCDIE|SYNCIE);- }-#endif- - if (scc->kiss.tx_inhibit)- {- or(scc,R5, TxENAB);- scc->wreg[R5] |= RTS;- } else { - or(scc,R5,RTS|TxENAB); /* enable tx */- }- } else {- cl(scc,R5,RTS|TxENAB); /* disable tx */-- if ((scc->kiss.fulldup == KISS_DUPLEX_HALF) &&-#ifndef CONFIG_SCC_TRXECHO- scc->kiss.softdcd)-#else- 1)-#endif- {- or(scc, R15, scc->kiss.softdcd? SYNCIE:DCDIE);- start_hunt(scc);- }- }- }-- enable_irq(scc->irq);-}---/* ----> SCC timer interrupt handler and friends. <---- */--static void __scc_start_tx_timer(struct scc_channel *scc,- void (*handler)(struct timer_list *t),- unsigned long when)-{- timer_delete(&scc->tx_t);-- if (when == 0)- {- handler(&scc->tx_t);- } else - if (when != TIMER_OFF)- {- scc->tx_t.function = handler;- scc->tx_t.expires = jiffies + (when*HZ)/100;- add_timer(&scc->tx_t);- }-}--static void scc_start_tx_timer(struct scc_channel *scc,- void (*handler)(struct timer_list *t),- unsigned long when)-{- unsigned long flags;- - spin_lock_irqsave(&scc->lock, flags);- __scc_start_tx_timer(scc, handler, when);- spin_unlock_irqrestore(&scc->lock, flags);-}--static void scc_start_defer(struct scc_channel *scc)-{- unsigned long flags;- - spin_lock_irqsave(&scc->lock, flags);- timer_delete(&scc->tx_wdog);- - if (scc->kiss.maxdefer != 0 && scc->kiss.maxdefer != TIMER_OFF)- {- scc->tx_wdog.function = t_busy;- scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxdefer;- add_timer(&scc->tx_wdog);- }- spin_unlock_irqrestore(&scc->lock, flags);-}--static void scc_start_maxkeyup(struct scc_channel *scc)-{- unsigned long flags;- - spin_lock_irqsave(&scc->lock, flags);- timer_delete(&scc->tx_wdog);- - if (scc->kiss.maxkeyup != 0 && scc->kiss.maxkeyup != TIMER_OFF)- {- scc->tx_wdog.function = t_maxkeyup;- scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;- add_timer(&scc->tx_wdog);- }- spin_unlock_irqrestore(&scc->lock, flags);-}--/* - * This is called from scc_txint() when there are no more frames to send.- * Not exactly a timer function, but it is a close friend of the family...- */--static void scc_tx_done(struct scc_channel *scc)-{- /* - * trx remains keyed in fulldup mode 2 until t_idle expires.- */- - switch (scc->kiss.fulldup)- {- case KISS_DUPLEX_LINK:- scc->stat.tx_state = TXS_IDLE2;- if (scc->kiss.idletime != TIMER_OFF)- scc_start_tx_timer(scc, t_idle,- scc->kiss.idletime*100);- break;- case KISS_DUPLEX_OPTIMA:- scc_notify(scc, HWEV_ALL_SENT);- break;- default:- scc->stat.tx_state = TXS_BUSY;- scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);- }-- netif_wake_queue(scc->dev);-}---static unsigned char Rand = 17;--static inline int is_grouped(struct scc_channel *scc)-{- int k;- struct scc_channel *scc2;- unsigned char grp1, grp2;-- grp1 = scc->kiss.group;- - for (k = 0; k < (Nchips * 2); k++)- {- scc2 = &SCC_Info[k];- grp2 = scc2->kiss.group;- - if (scc2 == scc || !(scc2->dev && grp2))- continue;- - if ((grp1 & 0x3f) == (grp2 & 0x3f))- {- if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )- return 1;- - if ( (grp1 & RXGROUP) && scc2->dcd )- return 1;- }- }- return 0;-}--/* DWAIT and SLOTTIME expired- *- * fulldup == 0: DCD is active or Rand > P-persistence: start t_busy timer- * else key trx and start txdelay- * fulldup == 1: key trx and start txdelay- * fulldup == 2: mintime expired, reset status or key trx and start txdelay- */--static void t_dwait(struct timer_list *t)-{- struct scc_channel *scc = timer_container_of(scc, t, tx_t);- - if (scc->stat.tx_state == TXS_WAIT) /* maxkeyup or idle timeout */- {- if (skb_queue_empty(&scc->tx_queue)) { /* nothing to send */- scc->stat.tx_state = TXS_IDLE;- netif_wake_queue(scc->dev); /* t_maxkeyup locked it. */- return;- }-- scc->stat.tx_state = TXS_BUSY;- }-- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)- {- Rand = Rand * 17 + 31;- - if (scc->dcd || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )- {- scc_start_defer(scc);- scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);- return ;- }- }-- if ( !(scc->wreg[R5] & RTS) )- {- scc_key_trx(scc, TX_ON);- scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);- } else {- scc_start_tx_timer(scc, t_txdelay, 0);- }-}---/* TXDELAY expired- *- * kick transmission by a fake scc_txint(scc), start 'maxkeyup' watchdog.- */--static void t_txdelay(struct timer_list *t)-{- struct scc_channel *scc = timer_container_of(scc, t, tx_t);-- scc_start_maxkeyup(scc);-- if (scc->tx_buff == NULL)- {- disable_irq(scc->irq);- scc_txint(scc); - enable_irq(scc->irq);- }-}- --/* TAILTIME expired- *- * switch off transmitter. If we were stopped by Maxkeyup restart- * transmission after 'mintime' seconds- */--static void t_tail(struct timer_list *t)-{- struct scc_channel *scc = timer_container_of(scc, t, tx_t);- unsigned long flags;- - spin_lock_irqsave(&scc->lock, flags); - timer_delete(&scc->tx_wdog);- scc_key_trx(scc, TX_OFF);- spin_unlock_irqrestore(&scc->lock, flags);-- if (scc->stat.tx_state == TXS_TIMEOUT) /* we had a timeout? */- {- scc->stat.tx_state = TXS_WAIT;- scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);- return;- }-- scc->stat.tx_state = TXS_IDLE;- netif_wake_queue(scc->dev);-}---/* BUSY timeout- *- * throw away send buffers if DCD remains active too long.- */--static void t_busy(struct timer_list *t)-{- struct scc_channel *scc = timer_container_of(scc, t, tx_wdog);-- timer_delete(&scc->tx_t);- netif_stop_queue(scc->dev); /* don't pile on the wabbit! */-- scc_discard_buffers(scc);- scc->stat.txerrs++;- scc->stat.tx_state = TXS_IDLE;-- netif_wake_queue(scc->dev); -}--/* MAXKEYUP timeout- *- * this is our watchdog.- */--static void t_maxkeyup(struct timer_list *t)-{- struct scc_channel *scc = timer_container_of(scc, t, tx_wdog);- unsigned long flags;-- spin_lock_irqsave(&scc->lock, flags);- /* - * let things settle down before we start to- * accept new data.- */-- netif_stop_queue(scc->dev);- scc_discard_buffers(scc);-- timer_delete(&scc->tx_t);-- cl(scc, R1, TxINT_ENAB); /* force an ABORT, but don't */- cl(scc, R15, TxUIE); /* count it. */- OutReg(scc->ctrl, R0, RES_Tx_P);-- spin_unlock_irqrestore(&scc->lock, flags);-- scc->stat.txerrs++;- scc->stat.tx_state = TXS_TIMEOUT;- scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);-}--/* IDLE timeout- *- * in fulldup mode 2 it keys down the transmitter after 'idle' seconds- * of inactivity. We will not restart transmission before 'mintime'- * expires.- */--static void t_idle(struct timer_list *t)-{- struct scc_channel *scc = timer_container_of(scc, t, tx_t);- - timer_delete(&scc->tx_wdog);-- scc_key_trx(scc, TX_OFF);- if(scc->kiss.mintime)- scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);- scc->stat.tx_state = TXS_WAIT;-}--static void scc_init_timer(struct scc_channel *scc)-{- unsigned long flags;-- spin_lock_irqsave(&scc->lock, flags); - scc->stat.tx_state = TXS_IDLE;- spin_unlock_irqrestore(&scc->lock, flags);-}---/* ******************************************************************** */-/* * Set/get L1 parameters * */-/* ******************************************************************** */---/*- * this will set the "hardware" parameters through KISS commands or ioctl()- */--#define CAST(x) (unsigned long)(x)--static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg)-{- switch (cmd)- {- case PARAM_TXDELAY: scc->kiss.txdelay=arg; break;- case PARAM_PERSIST: scc->kiss.persist=arg; break;- case PARAM_SLOTTIME: scc->kiss.slottime=arg; break;- case PARAM_TXTAIL: scc->kiss.tailtime=arg; break;- case PARAM_FULLDUP: scc->kiss.fulldup=arg; break;- case PARAM_DTR: break; /* does someone need this? */- case PARAM_GROUP: scc->kiss.group=arg; break;- case PARAM_IDLE: scc->kiss.idletime=arg; break;- case PARAM_MIN: scc->kiss.mintime=arg; break;- case PARAM_MAXKEY: scc->kiss.maxkeyup=arg; break;- case PARAM_WAIT: scc->kiss.waittime=arg; break;- case PARAM_MAXDEFER: scc->kiss.maxdefer=arg; break;- case PARAM_TX: scc->kiss.tx_inhibit=arg; break;-- case PARAM_SOFTDCD: - scc->kiss.softdcd=arg;- if (arg)- {- or(scc, R15, SYNCIE);- cl(scc, R15, DCDIE);- start_hunt(scc);- } else {- or(scc, R15, DCDIE);- cl(scc, R15, SYNCIE);- }- break;- - case PARAM_SPEED:- if (arg < 256)- scc->modem.speed=arg*100;- else- scc->modem.speed=arg;-- if (scc->stat.tx_state == 0) /* only switch baudrate on rx... ;-) */- set_speed(scc);- break;- - case PARAM_RTS: - if ( !(scc->wreg[R5] & RTS) )- {- if (arg != TX_OFF) {- scc_key_trx(scc, TX_ON);- scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);- }- } else {- if (arg == TX_OFF)- {- scc->stat.tx_state = TXS_BUSY;- scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);- }- }- break;- - case PARAM_HWEVENT:- scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);- break;-- default: return -EINVAL;- }- - return 0;-}--- -static unsigned long scc_get_param(struct scc_channel *scc, unsigned int cmd)-{- switch (cmd)- {- case PARAM_TXDELAY: return CAST(scc->kiss.txdelay);- case PARAM_PERSIST: return CAST(scc->kiss.persist);- case PARAM_SLOTTIME: return CAST(scc->kiss.slottime);- case PARAM_TXTAIL: return CAST(scc->kiss.tailtime);- case PARAM_FULLDUP: return CAST(scc->kiss.fulldup);- case PARAM_SOFTDCD: return CAST(scc->kiss.softdcd);- case PARAM_DTR: return CAST((scc->wreg[R5] & DTR)? 1:0);- case PARAM_RTS: return CAST((scc->wreg[R5] & RTS)? 1:0);- case PARAM_SPEED: return CAST(scc->modem.speed);- case PARAM_GROUP: return CAST(scc->kiss.group);- case PARAM_IDLE: return CAST(scc->kiss.idletime);- case PARAM_MIN: return CAST(scc->kiss.mintime);- case PARAM_MAXKEY: return CAST(scc->kiss.maxkeyup);- case PARAM_WAIT: return CAST(scc->kiss.waittime);- case PARAM_MAXDEFER: return CAST(scc->kiss.maxdefer);- case PARAM_TX: return CAST(scc->kiss.tx_inhibit);- default: return NO_SUCH_PARAM;- }--}--#undef CAST--/* ******************************************************************* */-/* * Send calibration pattern * */-/* ******************************************************************* */--static void scc_stop_calibrate(struct timer_list *t)-{- struct scc_channel *scc = timer_container_of(scc, t, tx_wdog);- unsigned long flags;- - spin_lock_irqsave(&scc->lock, flags);- timer_delete(&scc->tx_wdog);- scc_key_trx(scc, TX_OFF);- wr(scc, R6, 0);- wr(scc, R7, FLAG);- Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */- Outb(scc->ctrl,RES_EXT_INT);-- netif_wake_queue(scc->dev);- spin_unlock_irqrestore(&scc->lock, flags);-}---static void-scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern)-{- unsigned long flags;- - spin_lock_irqsave(&scc->lock, flags);- netif_stop_queue(scc->dev);- scc_discard_buffers(scc);-- timer_delete(&scc->tx_wdog);-- scc->tx_wdog.function = scc_stop_calibrate;- scc->tx_wdog.expires = jiffies + HZ*duration;- add_timer(&scc->tx_wdog);-- /* This doesn't seem to work. Why not? */ - wr(scc, R6, 0);- wr(scc, R7, pattern);-- /* - * Don't know if this works. - * Damn, where is my Z8530 programming manual...? - */-- Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */- Outb(scc->ctrl,RES_EXT_INT);-- scc_key_trx(scc, TX_ON);- spin_unlock_irqrestore(&scc->lock, flags);-}--/* ******************************************************************* */-/* * Init channel structures, special HW, etc... * */-/* ******************************************************************* */--/*- * Reset the Z8530s and setup special hardware- */--static void z8530_init(void)-{- const unsigned int nr_irqs = irq_get_nr_irqs();- struct scc_channel *scc;- int chip, k;- unsigned long flags;- char *flag;--- printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);- - flag=" ";- for (k = 0; k < nr_irqs; k++)- if (Ivec[k].used) - {- printk("%s%d", flag, k);- flag=",";- }- printk("\n");--- /* reset and pre-init all chips in the system */- for (chip = 0; chip < Nchips; chip++)- {- scc=&SCC_Info[2*chip];- if (!scc->ctrl) continue;-- /* Special SCC cards */-- if(scc->brand & EAGLE) /* this is an EAGLE card */- Outb(scc->special,0x08); /* enable interrupt on the board */- - if(scc->brand & (PC100 | PRIMUS)) /* this is a PC100/PRIMUS card */- Outb(scc->special,scc->option); /* set the MODEM mode (0x22) */-- - /* Reset and pre-init Z8530 */-- spin_lock_irqsave(&scc->lock, flags);- - Outb(scc->ctrl, 0);- OutReg(scc->ctrl,R9,FHWRES); /* force hardware reset */- udelay(100); /* give it 'a bit' more time than required */- wr(scc, R2, chip*16); /* interrupt vector */- wr(scc, R9, VIS); /* vector includes status */- spin_unlock_irqrestore(&scc->lock, flags); - }-- - Driver_Initialized = 1;-}--/*- * Allocate device structure, err, instance, and register driver- */--static int scc_net_alloc(const char *name, struct scc_channel *scc)-{- int err;- struct net_device *dev;-- dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, scc_net_setup);- if (!dev) - return -ENOMEM;-- dev->ml_priv = scc;- scc->dev = dev;- spin_lock_init(&scc->lock);- timer_setup(&scc->tx_t, NULL, 0);- timer_setup(&scc->tx_wdog, NULL, 0);-- err = register_netdevice(dev);- if (err) {- printk(KERN_ERR "%s: can't register network device (%d)\n", - name, err);- free_netdev(dev);- scc->dev = NULL;- return err;- }-- return 0;-}----/* ******************************************************************** */-/* * Network driver methods * */-/* ******************************************************************** */--static const struct net_device_ops scc_netdev_ops = {- .ndo_open = scc_net_open,- .ndo_stop = scc_net_close,- .ndo_start_xmit = scc_net_tx,- .ndo_set_mac_address = scc_net_set_mac_address,- .ndo_get_stats = scc_net_get_stats,- .ndo_siocdevprivate = scc_net_siocdevprivate,-};--/* ----> Initialize device <----- */--static void scc_net_setup(struct net_device *dev)-{- dev->tx_queue_len = 16; /* should be enough... */-- dev->netdev_ops = &scc_netdev_ops;- dev->header_ops = &ax25_header_ops;-- dev->flags = 0;-- dev->type = ARPHRD_AX25;- dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;- dev->mtu = AX25_DEF_PACLEN;- dev->addr_len = AX25_ADDR_LEN;-- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);- dev_addr_set(dev, (u8 *)&ax25_defaddr);-}--/* ----> open network device <---- */--static int scc_net_open(struct net_device *dev)-{- struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;-- if (!scc->init)- return -EINVAL;-- scc->tx_buff = NULL;- skb_queue_head_init(&scc->tx_queue);- - init_channel(scc);-- netif_start_queue(dev);- return 0;-}--/* ----> close network device <---- */--static int scc_net_close(struct net_device *dev)-{- struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;- unsigned long flags;-- netif_stop_queue(dev);-- spin_lock_irqsave(&scc->lock, flags); - Outb(scc->ctrl,0); /* Make sure pointer is written */- wr(scc,R1,0); /* disable interrupts */- wr(scc,R3,0);- spin_unlock_irqrestore(&scc->lock, flags);-- timer_delete_sync(&scc->tx_t);- timer_delete_sync(&scc->tx_wdog);- - scc_discard_buffers(scc);-- return 0;-}--/* ----> receive frame, called from scc_rxint() <---- */--static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)-{- if (skb->len == 0) {- dev_kfree_skb_irq(skb);- return;- }- - scc->dev_stat.rx_packets++;- scc->dev_stat.rx_bytes += skb->len;-- skb->protocol = ax25_type_trans(skb, scc->dev);- - netif_rx(skb);-}--/* ----> transmit frame <---- */--static netdev_tx_t scc_net_tx(struct sk_buff *skb, struct net_device *dev)-{- struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;- unsigned long flags;- char kisscmd;-- if (skb->protocol == htons(ETH_P_IP))- return ax25_ip_xmit(skb);-- if (skb->len > scc->stat.bufsize || skb->len < 2) {- scc->dev_stat.tx_dropped++; /* bogus frame */- dev_kfree_skb(skb);- return NETDEV_TX_OK;- }- - scc->dev_stat.tx_packets++;- scc->dev_stat.tx_bytes += skb->len;- scc->stat.txframes++;- - kisscmd = *skb->data & 0x1f;- skb_pull(skb, 1);-- if (kisscmd) {- scc_set_param(scc, kisscmd, *skb->data);- dev_kfree_skb(skb);- return NETDEV_TX_OK;- }-- spin_lock_irqsave(&scc->lock, flags);- - if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len) {- struct sk_buff *skb_del;- skb_del = skb_dequeue(&scc->tx_queue);- dev_kfree_skb_irq(skb_del);- }- skb_queue_tail(&scc->tx_queue, skb);- netif_trans_update(dev);- -- /*- * Start transmission if the trx state is idle or- * t_idle hasn't expired yet. Use dwait/persistence/slottime- * algorithm for normal halfduplex operation.- */-- if(scc->stat.tx_state == TXS_IDLE || scc->stat.tx_state == TXS_IDLE2) {- scc->stat.tx_state = TXS_BUSY;- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)- __scc_start_tx_timer(scc, t_dwait, scc->kiss.waittime);- else- __scc_start_tx_timer(scc, t_dwait, 0);- }- spin_unlock_irqrestore(&scc->lock, flags);- return NETDEV_TX_OK;-}--/* ----> ioctl functions <---- */--/*- * SIOCSCCCFG - configure driver arg: (struct scc_hw_config *) arg- * SIOCSCCINI - initialize driver arg: ---- * SIOCSCCCHANINI - initialize channel arg: (struct scc_modem *) arg- * SIOCSCCSMEM - set memory arg: (struct scc_mem_config *) arg- * SIOCSCCGKISS - get level 1 parameter arg: (struct scc_kiss_cmd *) arg- * SIOCSCCSKISS - set level 1 parameter arg: (struct scc_kiss_cmd *) arg- * SIOCSCCGSTAT - get driver status arg: (struct scc_stat *) arg- * SIOCSCCCAL - send calib. pattern arg: (struct scc_calibrate *) arg- */--static int scc_net_siocdevprivate(struct net_device *dev,- struct ifreq *ifr, void __user *arg, int cmd)-{- struct scc_kiss_cmd kiss_cmd;- struct scc_mem_config memcfg;- struct scc_hw_config hwcfg;- struct scc_calibrate cal;- struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;- int chan;- unsigned char device_name[IFNAMSIZ];- - if (!Driver_Initialized)- {- if (cmd == SIOCSCCCFG)- {- int found = 1;-- if (!capable(CAP_SYS_RAWIO)) return -EPERM;- if (in_compat_syscall())- return -EOPNOTSUPP;-- if (!arg) return -EFAULT;-- if (Nchips >= SCC_MAXCHIPS) - return -EINVAL;-- if (copy_from_user(&hwcfg, arg, sizeof(hwcfg)))- return -EFAULT;-- if (hwcfg.irq == 2) hwcfg.irq = 9;-- if (hwcfg.irq < 0 || hwcfg.irq >= irq_get_nr_irqs())- return -EINVAL;- - if (!Ivec[hwcfg.irq].used && hwcfg.irq)- {- if (request_irq(hwcfg.irq, scc_isr,- 0, "AX.25 SCC",- (void *)(long) hwcfg.irq))- printk(KERN_WARNING "z8530drv: warning, cannot get IRQ %d\n", hwcfg.irq);- else- Ivec[hwcfg.irq].used = 1;- }-- if (hwcfg.vector_latch && !Vector_Latch) {- if (!request_region(hwcfg.vector_latch, 1, "scc vector latch"))- printk(KERN_WARNING "z8530drv: warning, cannot reserve vector latch port 0x%lx\n, disabled.", hwcfg.vector_latch);- else- Vector_Latch = hwcfg.vector_latch;- }-- if (hwcfg.clock == 0)- hwcfg.clock = SCC_DEFAULT_CLOCK;--#ifndef SCC_DONT_CHECK-- if(request_region(hwcfg.ctrl_a, 1, "scc-probe"))- {- disable_irq(hwcfg.irq);- Outb(hwcfg.ctrl_a, 0);- OutReg(hwcfg.ctrl_a, R9, FHWRES);- udelay(100);- OutReg(hwcfg.ctrl_a,R13,0x55); /* is this chip really there? */- udelay(5);-- if (InReg(hwcfg.ctrl_a,R13) != 0x55)- found = 0;- enable_irq(hwcfg.irq);- release_region(hwcfg.ctrl_a, 1);- }- else- found = 0;-#endif-- if (found)- {- SCC_Info[2*Nchips ].ctrl = hwcfg.ctrl_a;- SCC_Info[2*Nchips ].data = hwcfg.data_a;- SCC_Info[2*Nchips ].irq = hwcfg.irq;- SCC_Info[2*Nchips+1].ctrl = hwcfg.ctrl_b;- SCC_Info[2*Nchips+1].data = hwcfg.data_b;- SCC_Info[2*Nchips+1].irq = hwcfg.irq;- - SCC_ctrl[Nchips].chan_A = hwcfg.ctrl_a;- SCC_ctrl[Nchips].chan_B = hwcfg.ctrl_b;- SCC_ctrl[Nchips].irq = hwcfg.irq;- }--- for (chan = 0; chan < 2; chan++)- {- sprintf(device_name, "%s%i", SCC_DriverName, 2*Nchips+chan);-- SCC_Info[2*Nchips+chan].special = hwcfg.special;- SCC_Info[2*Nchips+chan].clock = hwcfg.clock;- SCC_Info[2*Nchips+chan].brand = hwcfg.brand;- SCC_Info[2*Nchips+chan].option = hwcfg.option;- SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;--#ifdef SCC_DONT_CHECK- printk(KERN_INFO "%s: data port = 0x%3.3x control port = 0x%3.3x\n",- device_name, - SCC_Info[2*Nchips+chan].data, - SCC_Info[2*Nchips+chan].ctrl);--#else- printk(KERN_INFO "%s: data port = 0x%3.3lx control port = 0x%3.3lx -- %s\n",- device_name,- chan? hwcfg.data_b : hwcfg.data_a, - chan? hwcfg.ctrl_b : hwcfg.ctrl_a,- found? "found" : "missing");-#endif-- if (found)- {- request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");- request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");- if (Nchips+chan != 0 &&- scc_net_alloc(device_name, - &SCC_Info[2*Nchips+chan]))- return -EINVAL;- }- }- - if (found) Nchips++;- - return 0;- }- - if (cmd == SIOCSCCINI)- {- if (!capable(CAP_SYS_RAWIO))- return -EPERM;- - if (Nchips == 0)- return -EINVAL;-- z8530_init();- return 0;- }- - return -EINVAL; /* confuse the user */- }- - if (!scc->init)- {- if (cmd == SIOCSCCCHANINI)- {- if (!capable(CAP_NET_ADMIN)) return -EPERM;- if (!arg) return -EINVAL;- - scc->stat.bufsize = SCC_BUFSIZE;-- if (copy_from_user(&scc->modem, arg, sizeof(struct scc_modem)))- return -EINVAL;- - /* default KISS Params */- - if (scc->modem.speed < 4800)- {- scc->kiss.txdelay = 36; /* 360 ms */- scc->kiss.persist = 42; /* 25% persistence */ /* was 25 */- scc->kiss.slottime = 16; /* 160 ms */- scc->kiss.tailtime = 4; /* minimal reasonable value */- scc->kiss.fulldup = 0; /* CSMA */- scc->kiss.waittime = 50; /* 500 ms */- scc->kiss.maxkeyup = 10; /* 10 s */- scc->kiss.mintime = 3; /* 3 s */- scc->kiss.idletime = 30; /* 30 s */- scc->kiss.maxdefer = 120; /* 2 min */- scc->kiss.softdcd = 0; /* hardware dcd */- } else {- scc->kiss.txdelay = 10; /* 100 ms */- scc->kiss.persist = 64; /* 25% persistence */ /* was 25 */- scc->kiss.slottime = 8; /* 160 ms */- scc->kiss.tailtime = 1; /* minimal reasonable value */- scc->kiss.fulldup = 0; /* CSMA */- scc->kiss.waittime = 50; /* 500 ms */- scc->kiss.maxkeyup = 7; /* 7 s */- scc->kiss.mintime = 3; /* 3 s */- scc->kiss.idletime = 30; /* 30 s */- scc->kiss.maxdefer = 120; /* 2 min */- scc->kiss.softdcd = 0; /* hardware dcd */- }- - scc->tx_buff = NULL;- skb_queue_head_init(&scc->tx_queue);- scc->init = 1;- - return 0;- }- - return -EINVAL;- }- - switch(cmd)- {- case SIOCSCCRESERVED:- return -ENOIOCTLCMD;-- case SIOCSCCSMEM:- if (!capable(CAP_SYS_RAWIO)) return -EPERM;- if (!arg || copy_from_user(&memcfg, arg, sizeof(memcfg)))- return -EINVAL;- if (memcfg.bufsize < 16)- return -EINVAL;- scc->stat.bufsize = memcfg.bufsize;- return 0;- - case SIOCSCCGSTAT:- if (!arg || copy_to_user(arg, &scc->stat, sizeof(scc->stat)))- return -EINVAL;- return 0;- - case SIOCSCCGKISS:- if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))- return -EINVAL;- kiss_cmd.param = scc_get_param(scc, kiss_cmd.command);- if (copy_to_user(arg, &kiss_cmd, sizeof(kiss_cmd)))- return -EINVAL;- return 0;- - case SIOCSCCSKISS:- if (!capable(CAP_NET_ADMIN)) return -EPERM;- if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))- return -EINVAL;- return scc_set_param(scc, kiss_cmd.command, kiss_cmd.param);- - case SIOCSCCCAL:- if (!capable(CAP_SYS_RAWIO)) return -EPERM;- if (!arg || copy_from_user(&cal, arg, sizeof(cal)) || cal.time == 0)- return -EINVAL;-- scc_start_calibrate(scc, cal.time, cal.pattern);- return 0;-- default:- return -ENOIOCTLCMD;- - }- - return -EINVAL;-}--/* ----> set interface callsign <---- */--static int scc_net_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr *sa = (struct sockaddr *) addr;- dev_addr_set(dev, sa->sa_data);- return 0;-}--/* ----> get statistics <---- */--static struct net_device_stats *scc_net_get_stats(struct net_device *dev)-{- struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;- - scc->dev_stat.rx_errors = scc->stat.rxerrs + scc->stat.rx_over;- scc->dev_stat.tx_errors = scc->stat.txerrs + scc->stat.tx_under;- scc->dev_stat.rx_fifo_errors = scc->stat.rx_over;- scc->dev_stat.tx_fifo_errors = scc->stat.tx_under;-- return &scc->dev_stat;-}--/* ******************************************************************** */-/* * dump statistics to /proc/net/z8530drv * */-/* ******************************************************************** */--#ifdef CONFIG_PROC_FS--static inline struct scc_channel *scc_net_seq_idx(loff_t pos)-{- int k;-- for (k = 0; k < Nchips*2; ++k) {- if (!SCC_Info[k].init) - continue;- if (pos-- == 0)- return &SCC_Info[k];- }- return NULL;-}--static void *scc_net_seq_start(struct seq_file *seq, loff_t *pos)-{- return *pos ? scc_net_seq_idx(*pos - 1) : SEQ_START_TOKEN;- -}--static void *scc_net_seq_next(struct seq_file *seq, void *v, loff_t *pos)-{- unsigned k;- struct scc_channel *scc = v;- ++*pos;- - for (k = (v == SEQ_START_TOKEN) ? 0 : (scc - SCC_Info)+1;- k < Nchips*2; ++k) {- if (SCC_Info[k].init) - return &SCC_Info[k];- }- return NULL;-}--static void scc_net_seq_stop(struct seq_file *seq, void *v)-{-}--static int scc_net_seq_show(struct seq_file *seq, void *v)-{- if (v == SEQ_START_TOKEN) {- seq_puts(seq, "z8530drv-"VERSION"\n");- } else if (!Driver_Initialized) {- seq_puts(seq, "not initialized\n");- } else if (!Nchips) {- seq_puts(seq, "chips missing\n");- } else {- const struct scc_channel *scc = v;- const struct scc_stat *stat = &scc->stat;- const struct scc_kiss *kiss = &scc->kiss;--- /* dev data ctrl irq clock brand enh vector special option - * baud nrz clocksrc softdcd bufsize- * rxints txints exints spints- * rcvd rxerrs over / xmit txerrs under / nospace bufsize- * txd pers slot tail ful wait min maxk idl defr txof grp- * W ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##- * R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##- */-- seq_printf(seq, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",- scc->dev->name,- scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand,- scc->enhanced, Vector_Latch, scc->special,- scc->option);- seq_printf(seq, "\t%lu %d %d %d %d\n",- scc->modem.speed, scc->modem.nrz,- scc->modem.clocksrc, kiss->softdcd,- stat->bufsize);- seq_printf(seq, "\t%lu %lu %lu %lu\n",- stat->rxints, stat->txints, stat->exints, stat->spints);- seq_printf(seq, "\t%lu %lu %d / %lu %lu %d / %d %d\n",- stat->rxframes, stat->rxerrs, stat->rx_over,- stat->txframes, stat->txerrs, stat->tx_under,- stat->nospace, stat->tx_state);--#define K(x) kiss->x- seq_printf(seq, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",- K(txdelay), K(persist), K(slottime), K(tailtime),- K(fulldup), K(waittime), K(mintime), K(maxkeyup),- K(idletime), K(maxdefer), K(tx_inhibit), K(group));-#undef K-#ifdef SCC_DEBUG- {- int reg;-- seq_printf(seq, "\tW ");- for (reg = 0; reg < 16; reg++)- seq_printf(seq, "%2.2x ", scc->wreg[reg]);- seq_printf(seq, "\n");- - seq_printf(seq, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));- for (reg = 3; reg < 8; reg++)- seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));- seq_printf(seq, "XX ");- for (reg = 9; reg < 16; reg++)- seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));- seq_printf(seq, "\n");- }-#endif- seq_putc(seq, '\n');- }-- return 0;-}--static const struct seq_operations scc_net_seq_ops = {- .start = scc_net_seq_start,- .next = scc_net_seq_next,- .stop = scc_net_seq_stop,- .show = scc_net_seq_show,-};-#endif /* CONFIG_PROC_FS */-- -/* ******************************************************************** */-/* * Init SCC driver * */-/* ******************************************************************** */--static int __init scc_init_driver (void)-{- char devname[IFNAMSIZ];- - printk(banner);- - sprintf(devname,"%s0", SCC_DriverName);- - rtnl_lock();- if (scc_net_alloc(devname, SCC_Info)) {- rtnl_unlock();- printk(KERN_ERR "z8530drv: cannot initialize module\n");- return -EIO;- }- rtnl_unlock();-- proc_create_seq("z8530drv", 0, init_net.proc_net, &scc_net_seq_ops);-- return 0;-}--static void __exit scc_cleanup_driver(void)-{- const unsigned int nr_irqs = irq_get_nr_irqs();- io_port ctrl;- int k;- struct scc_channel *scc;- struct net_device *dev;- - if (Nchips == 0 && (dev = SCC_Info[0].dev)) - {- unregister_netdev(dev);- free_netdev(dev);- }-- /* Guard against chip prattle */- local_irq_disable();- - for (k = 0; k < Nchips; k++)- if ( (ctrl = SCC_ctrl[k].chan_A) )- {- Outb(ctrl, 0);- OutReg(ctrl,R9,FHWRES); /* force hardware reset */- udelay(50);- }- - /* To unload the port must be closed so no real IRQ pending */- for (k = 0; k < nr_irqs ; k++)- if (Ivec[k].used) free_irq(k, NULL);- - local_irq_enable();- - /* Now clean up */- for (k = 0; k < Nchips*2; k++)- {- scc = &SCC_Info[k];- if (scc->ctrl)- {- release_region(scc->ctrl, 1);- release_region(scc->data, 1);- }- if (scc->dev)- {- unregister_netdev(scc->dev);- free_netdev(scc->dev);- }- }- - - if (Vector_Latch)- release_region(Vector_Latch, 1);-- remove_proc_entry("z8530drv", init_net.proc_net);-}--MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");-MODULE_DESCRIPTION("AX.25 Device Driver for Z8530 based HDLC cards");-MODULE_LICENSE("GPL");-module_init(scc_init_driver);-module_exit(scc_cleanup_driver);diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.cdeleted file mode 100644index 4106f0301ab4..000000000000--- a/drivers/net/hamradio/yam.c+++ /dev/null@@ -1,1191 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*****************************************************************************/--/*- * yam.c -- YAM radio modem driver.- *- * Copyright (C) 1998 Frederic Rible F1OAT (frible@teaser.fr)- * Adapted from baycom.c driver written by Thomas Sailer (sailer@ife.ee.ethz.ch)- *- * Please note that the GPL allows you to use the driver, NOT the radio.- * In order to use the radio, you need a license from the communications- * authority of your country.- *- * History:- * 0.0 F1OAT 06.06.98 Begin of work with baycom.c source code V 0.3- * 0.1 F1OAT 07.06.98 Add timer polling routine for channel arbitration- * 0.2 F6FBB 08.06.98 Added delay after FPGA programming- * 0.3 F6FBB 29.07.98 Delayed PTT implementation for dupmode=2- * 0.4 F6FBB 30.07.98 Added TxTail, Slottime and Persistence- * 0.5 F6FBB 01.08.98 Shared IRQs, /proc/net and network statistics- * 0.6 F6FBB 25.08.98 Added 1200Bds format- * 0.7 F6FBB 12.09.98 Added to the kernel configuration- * 0.8 F6FBB 14.10.98 Fixed slottime/persistence timing bug- * OK1ZIA 2.09.01 Fixed "kfree_skb on hard IRQ" - * using dev_kfree_skb_any(). (important in 2.4 kernel)- */--/*****************************************************************************/--#include <linux/module.h>-#include <linux/types.h>-#include <linux/net.h>-#include <linux/in.h>-#include <linux/if.h>-#include <linux/slab.h>-#include <linux/errno.h>-#include <linux/bitops.h>-#include <linux/random.h>-#include <asm/io.h>-#include <linux/interrupt.h>-#include <linux/ioport.h>-#include <linux/firmware.h>-#include <linux/platform_device.h>--#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/etherdevice.h>-#include <linux/skbuff.h>-#include <net/ax25.h>--#include <linux/kernel.h>-#include <linux/proc_fs.h>-#include <linux/seq_file.h>-#include <net/net_namespace.h>--#include <linux/uaccess.h>-#include <linux/init.h>--#include <linux/yam.h>--/* --------------------------------------------------------------------- */--static const char yam_drvname[] = "yam";-static const char yam_drvinfo[] __initconst = KERN_INFO \- "YAM driver version 0.8 by F1OAT/F6FBB\n";--/* --------------------------------------------------------------------- */--#define FIRMWARE_9600 "yam/9600.bin"-#define FIRMWARE_1200 "yam/1200.bin"--#define YAM_9600 1-#define YAM_1200 2--#define NR_PORTS 4-#define YAM_MAGIC 0xF10A7654--/* Transmitter states */--#define TX_OFF 0-#define TX_HEAD 1-#define TX_DATA 2-#define TX_CRC1 3-#define TX_CRC2 4-#define TX_TAIL 5--#define YAM_MAX_FRAME 1024--#define DEFAULT_BITRATE 9600 /* bps */-#define DEFAULT_HOLDD 10 /* sec */-#define DEFAULT_TXD 300 /* ms */-#define DEFAULT_TXTAIL 10 /* ms */-#define DEFAULT_SLOT 100 /* ms */-#define DEFAULT_PERS 64 /* 0->255 */--struct yam_port {- int magic;- int bitrate;- int baudrate;- int iobase;- int irq;- int dupmode;-- struct net_device *dev;-- int nb_rxint;- int nb_mdint;-- /* Parameters section */-- int txd; /* tx delay */- int holdd; /* duplex ptt delay */- int txtail; /* txtail delay */- int slot; /* slottime */- int pers; /* persistence */-- /* Tx section */-- int tx_state;- int tx_count;- int slotcnt;- unsigned char tx_buf[YAM_MAX_FRAME];- int tx_len;- int tx_crcl, tx_crch;- struct sk_buff_head send_queue; /* Packets awaiting transmission */-- /* Rx section */-- int dcd;- unsigned char rx_buf[YAM_MAX_FRAME];- int rx_len;- int rx_crcl, rx_crch;-};--struct yam_mcs {- unsigned char bits[YAM_FPGA_SIZE];- int bitrate;- struct yam_mcs *next;-};--static struct net_device *yam_devs[NR_PORTS];--static struct yam_mcs *yam_data;--static DEFINE_TIMER(yam_timer, NULL);--/* --------------------------------------------------------------------- */--#define RBR(iobase) (iobase+0)-#define THR(iobase) (iobase+0)-#define IER(iobase) (iobase+1)-#define IIR(iobase) (iobase+2)-#define FCR(iobase) (iobase+2)-#define LCR(iobase) (iobase+3)-#define MCR(iobase) (iobase+4)-#define LSR(iobase) (iobase+5)-#define MSR(iobase) (iobase+6)-#define SCR(iobase) (iobase+7)-#define DLL(iobase) (iobase+0)-#define DLM(iobase) (iobase+1)--#define YAM_EXTENT 8--/* Interrupt Identification Register Bit Masks */-#define IIR_NOPEND 1-#define IIR_MSR 0-#define IIR_TX 2-#define IIR_RX 4-#define IIR_LSR 6-#define IIR_TIMEOUT 12 /* Fifo mode only */--#define IIR_MASK 0x0F--/* Interrupt Enable Register Bit Masks */-#define IER_RX 1 /* enable rx interrupt */-#define IER_TX 2 /* enable tx interrupt */-#define IER_LSR 4 /* enable line status interrupts */-#define IER_MSR 8 /* enable modem status interrupts */--/* Modem Control Register Bit Masks */-#define MCR_DTR 0x01 /* DTR output */-#define MCR_RTS 0x02 /* RTS output */-#define MCR_OUT1 0x04 /* OUT1 output (not accessible in RS232) */-#define MCR_OUT2 0x08 /* Master Interrupt enable (must be set on PCs) */-#define MCR_LOOP 0x10 /* Loopback enable */--/* Modem Status Register Bit Masks */-#define MSR_DCTS 0x01 /* Delta CTS input */-#define MSR_DDSR 0x02 /* Delta DSR */-#define MSR_DRIN 0x04 /* Delta RI */-#define MSR_DDCD 0x08 /* Delta DCD */-#define MSR_CTS 0x10 /* CTS input */-#define MSR_DSR 0x20 /* DSR input */-#define MSR_RING 0x40 /* RI input */-#define MSR_DCD 0x80 /* DCD input */--/* line status register bit mask */-#define LSR_RXC 0x01-#define LSR_OE 0x02-#define LSR_PE 0x04-#define LSR_FE 0x08-#define LSR_BREAK 0x10-#define LSR_THRE 0x20-#define LSR_TSRE 0x40--/* Line Control Register Bit Masks */-#define LCR_DLAB 0x80-#define LCR_BREAK 0x40-#define LCR_PZERO 0x28-#define LCR_PEVEN 0x18-#define LCR_PODD 0x08-#define LCR_STOP1 0x00-#define LCR_STOP2 0x04-#define LCR_BIT5 0x00-#define LCR_BIT6 0x02-#define LCR_BIT7 0x01-#define LCR_BIT8 0x03--/* YAM Modem <-> UART Port mapping */--#define TX_RDY MSR_DCTS /* transmitter ready to send */-#define RX_DCD MSR_DCD /* carrier detect */-#define RX_FLAG MSR_RING /* hdlc flag received */-#define FPGA_DONE MSR_DSR /* FPGA is configured */-#define PTT_ON (MCR_RTS|MCR_OUT2) /* activate PTT */-#define PTT_OFF (MCR_DTR|MCR_OUT2) /* release PTT */--#define ENABLE_RXINT IER_RX /* enable uart rx interrupt during rx */-#define ENABLE_TXINT IER_MSR /* enable uart ms interrupt during tx */-#define ENABLE_RTXINT (IER_RX|IER_MSR) /* full duplex operations */---/*************************************************************************-* CRC Tables-************************************************************************/--static const unsigned char chktabl[256] =-{0x00, 0x89, 0x12, 0x9b, 0x24, 0xad, 0x36, 0xbf, 0x48, 0xc1, 0x5a, 0xd3, 0x6c, 0xe5, 0x7e,- 0xf7, 0x81, 0x08, 0x93, 0x1a, 0xa5, 0x2c, 0xb7, 0x3e, 0xc9, 0x40, 0xdb, 0x52, 0xed, 0x64,- 0xff, 0x76, 0x02, 0x8b, 0x10, 0x99, 0x26, 0xaf, 0x34, 0xbd, 0x4a, 0xc3, 0x58, 0xd1, 0x6e,- 0xe7, 0x7c, 0xf5, 0x83, 0x0a, 0x91, 0x18, 0xa7, 0x2e, 0xb5, 0x3c, 0xcb, 0x42, 0xd9, 0x50,- 0xef, 0x66, 0xfd, 0x74, 0x04, 0x8d, 0x16, 0x9f, 0x20, 0xa9, 0x32, 0xbb, 0x4c, 0xc5, 0x5e,- 0xd7, 0x68, 0xe1, 0x7a, 0xf3, 0x85, 0x0c, 0x97, 0x1e, 0xa1, 0x28, 0xb3, 0x3a, 0xcd, 0x44,- 0xdf, 0x56, 0xe9, 0x60, 0xfb, 0x72, 0x06, 0x8f, 0x14, 0x9d, 0x22, 0xab, 0x30, 0xb9, 0x4e,- 0xc7, 0x5c, 0xd5, 0x6a, 0xe3, 0x78, 0xf1, 0x87, 0x0e, 0x95, 0x1c, 0xa3, 0x2a, 0xb1, 0x38,- 0xcf, 0x46, 0xdd, 0x54, 0xeb, 0x62, 0xf9, 0x70, 0x08, 0x81, 0x1a, 0x93, 0x2c, 0xa5, 0x3e,- 0xb7, 0x40, 0xc9, 0x52, 0xdb, 0x64, 0xed, 0x76, 0xff, 0x89, 0x00, 0x9b, 0x12, 0xad, 0x24,- 0xbf, 0x36, 0xc1, 0x48, 0xd3, 0x5a, 0xe5, 0x6c, 0xf7, 0x7e, 0x0a, 0x83, 0x18, 0x91, 0x2e,- 0xa7, 0x3c, 0xb5, 0x42, 0xcb, 0x50, 0xd9, 0x66, 0xef, 0x74, 0xfd, 0x8b, 0x02, 0x99, 0x10,- 0xaf, 0x26, 0xbd, 0x34, 0xc3, 0x4a, 0xd1, 0x58, 0xe7, 0x6e, 0xf5, 0x7c, 0x0c, 0x85, 0x1e,- 0x97, 0x28, 0xa1, 0x3a, 0xb3, 0x44, 0xcd, 0x56, 0xdf, 0x60, 0xe9, 0x72, 0xfb, 0x8d, 0x04,- 0x9f, 0x16, 0xa9, 0x20, 0xbb, 0x32, 0xc5, 0x4c, 0xd7, 0x5e, 0xe1, 0x68, 0xf3, 0x7a, 0x0e,- 0x87, 0x1c, 0x95, 0x2a, 0xa3, 0x38, 0xb1, 0x46, 0xcf, 0x54, 0xdd, 0x62, 0xeb, 0x70, 0xf9,- 0x8f, 0x06, 0x9d, 0x14, 0xab, 0x22, 0xb9, 0x30, 0xc7, 0x4e, 0xd5, 0x5c, 0xe3, 0x6a, 0xf1,- 0x78};-static const unsigned char chktabh[256] =-{0x00, 0x11, 0x23, 0x32, 0x46, 0x57, 0x65, 0x74, 0x8c, 0x9d, 0xaf, 0xbe, 0xca, 0xdb, 0xe9,- 0xf8, 0x10, 0x01, 0x33, 0x22, 0x56, 0x47, 0x75, 0x64, 0x9c, 0x8d, 0xbf, 0xae, 0xda, 0xcb,- 0xf9, 0xe8, 0x21, 0x30, 0x02, 0x13, 0x67, 0x76, 0x44, 0x55, 0xad, 0xbc, 0x8e, 0x9f, 0xeb,- 0xfa, 0xc8, 0xd9, 0x31, 0x20, 0x12, 0x03, 0x77, 0x66, 0x54, 0x45, 0xbd, 0xac, 0x9e, 0x8f,- 0xfb, 0xea, 0xd8, 0xc9, 0x42, 0x53, 0x61, 0x70, 0x04, 0x15, 0x27, 0x36, 0xce, 0xdf, 0xed,- 0xfc, 0x88, 0x99, 0xab, 0xba, 0x52, 0x43, 0x71, 0x60, 0x14, 0x05, 0x37, 0x26, 0xde, 0xcf,- 0xfd, 0xec, 0x98, 0x89, 0xbb, 0xaa, 0x63, 0x72, 0x40, 0x51, 0x25, 0x34, 0x06, 0x17, 0xef,- 0xfe, 0xcc, 0xdd, 0xa9, 0xb8, 0x8a, 0x9b, 0x73, 0x62, 0x50, 0x41, 0x35, 0x24, 0x16, 0x07,- 0xff, 0xee, 0xdc, 0xcd, 0xb9, 0xa8, 0x9a, 0x8b, 0x84, 0x95, 0xa7, 0xb6, 0xc2, 0xd3, 0xe1,- 0xf0, 0x08, 0x19, 0x2b, 0x3a, 0x4e, 0x5f, 0x6d, 0x7c, 0x94, 0x85, 0xb7, 0xa6, 0xd2, 0xc3,- 0xf1, 0xe0, 0x18, 0x09, 0x3b, 0x2a, 0x5e, 0x4f, 0x7d, 0x6c, 0xa5, 0xb4, 0x86, 0x97, 0xe3,- 0xf2, 0xc0, 0xd1, 0x29, 0x38, 0x0a, 0x1b, 0x6f, 0x7e, 0x4c, 0x5d, 0xb5, 0xa4, 0x96, 0x87,- 0xf3, 0xe2, 0xd0, 0xc1, 0x39, 0x28, 0x1a, 0x0b, 0x7f, 0x6e, 0x5c, 0x4d, 0xc6, 0xd7, 0xe5,- 0xf4, 0x80, 0x91, 0xa3, 0xb2, 0x4a, 0x5b, 0x69, 0x78, 0x0c, 0x1d, 0x2f, 0x3e, 0xd6, 0xc7,- 0xf5, 0xe4, 0x90, 0x81, 0xb3, 0xa2, 0x5a, 0x4b, 0x79, 0x68, 0x1c, 0x0d, 0x3f, 0x2e, 0xe7,- 0xf6, 0xc4, 0xd5, 0xa1, 0xb0, 0x82, 0x93, 0x6b, 0x7a, 0x48, 0x59, 0x2d, 0x3c, 0x0e, 0x1f,- 0xf7, 0xe6, 0xd4, 0xc5, 0xb1, 0xa0, 0x92, 0x83, 0x7b, 0x6a, 0x58, 0x49, 0x3d, 0x2c, 0x1e,- 0x0f};--/*************************************************************************-* FPGA functions-************************************************************************/--static void delay(int ms)-{- unsigned long timeout = jiffies + ((ms * HZ) / 1000);- while (time_before(jiffies, timeout))- cpu_relax();-}--/*- * reset FPGA- */--static void fpga_reset(int iobase)-{- outb(0, IER(iobase));- outb(LCR_DLAB | LCR_BIT5, LCR(iobase));- outb(1, DLL(iobase));- outb(0, DLM(iobase));-- outb(LCR_BIT5, LCR(iobase));- inb(LSR(iobase));- inb(MSR(iobase));- /* turn off FPGA supply voltage */- outb(MCR_OUT1 | MCR_OUT2, MCR(iobase));- delay(100);- /* turn on FPGA supply voltage again */- outb(MCR_DTR | MCR_RTS | MCR_OUT1 | MCR_OUT2, MCR(iobase));- delay(100);-}--/*- * send one byte to FPGA- */--static int fpga_write(int iobase, unsigned char wrd)-{- unsigned char bit;- int k;- unsigned long timeout = jiffies + HZ / 10;-- for (k = 0; k < 8; k++) {- bit = (wrd & 0x80) ? (MCR_RTS | MCR_DTR) : MCR_DTR;- outb(bit | MCR_OUT1 | MCR_OUT2, MCR(iobase));- wrd <<= 1;- outb(0xfc, THR(iobase));- while ((inb(LSR(iobase)) & LSR_TSRE) == 0)- if (time_after(jiffies, timeout))- return -1;- }-- return 0;-}--/*- * predef should be 0 for loading user defined mcs- * predef should be YAM_1200 for loading predef 1200 mcs- * predef should be YAM_9600 for loading predef 9600 mcs- */-static unsigned char *add_mcs(unsigned char *bits, int bitrate,- unsigned int predef)-{- const char *fw_name[2] = {FIRMWARE_9600, FIRMWARE_1200};- const struct firmware *fw;- struct platform_device *pdev;- struct yam_mcs *p;- int err;-- switch (predef) {- case 0:- fw = NULL;- break;- case YAM_1200:- case YAM_9600:- predef--;- pdev = platform_device_register_simple("yam", 0, NULL, 0);- if (IS_ERR(pdev)) {- printk(KERN_ERR "yam: Failed to register firmware\n");- return NULL;- }- err = request_firmware(&fw, fw_name[predef], &pdev->dev);- platform_device_unregister(pdev);- if (err) {- printk(KERN_ERR "Failed to load firmware \"%s\"\n",- fw_name[predef]);- return NULL;- }- if (fw->size != YAM_FPGA_SIZE) {- printk(KERN_ERR "Bogus length %zu in firmware \"%s\"\n",- fw->size, fw_name[predef]);- release_firmware(fw);- return NULL;- }- bits = (unsigned char *)fw->data;- break;- default:- printk(KERN_ERR "yam: Invalid predef number %u\n", predef);- return NULL;- }-- /* If it already exists, replace the bit data */- p = yam_data;- while (p) {- if (p->bitrate == bitrate) {- memcpy(p->bits, bits, YAM_FPGA_SIZE);- goto out;- }- p = p->next;- }-- /* Allocate a new mcs */- if ((p = kmalloc_obj(struct yam_mcs)) == NULL) {- release_firmware(fw);- return NULL;- }- memcpy(p->bits, bits, YAM_FPGA_SIZE);- p->bitrate = bitrate;- p->next = yam_data;- yam_data = p;- out:- release_firmware(fw);- return p->bits;-}--static unsigned char *get_mcs(int bitrate)-{- struct yam_mcs *p;-- p = yam_data;- while (p) {- if (p->bitrate == bitrate)- return p->bits;- p = p->next;- }-- /* Load predefined mcs data */- switch (bitrate) {- case 1200:- /* setting predef as YAM_1200 for loading predef 1200 mcs */- return add_mcs(NULL, bitrate, YAM_1200);- default:- /* setting predef as YAM_9600 for loading predef 9600 mcs */- return add_mcs(NULL, bitrate, YAM_9600);- }-}--/*- * download bitstream to FPGA- * data is contained in bits[] array in yam1200.h resp. yam9600.h- */--static int fpga_download(int iobase, int bitrate)-{- int i, rc;- unsigned char *pbits;-- pbits = get_mcs(bitrate);- if (pbits == NULL)- return -1;-- fpga_reset(iobase);- for (i = 0; i < YAM_FPGA_SIZE; i++) {- if (fpga_write(iobase, pbits[i])) {- printk(KERN_ERR "yam: error in write cycle\n");- return -1; /* write... */- }- }-- fpga_write(iobase, 0xFF);- rc = inb(MSR(iobase)); /* check DONE signal */-- /* Needed for some hardwares */- delay(50);-- return (rc & MSR_DSR) ? 0 : -1;-}---/************************************************************************-* Serial port init -************************************************************************/--static void yam_set_uart(struct net_device *dev)-{- struct yam_port *yp = netdev_priv(dev);- int divisor = 115200 / yp->baudrate;-- outb(0, IER(dev->base_addr));- outb(LCR_DLAB | LCR_BIT8, LCR(dev->base_addr));- outb(divisor, DLL(dev->base_addr));- outb(0, DLM(dev->base_addr));- outb(LCR_BIT8, LCR(dev->base_addr));- outb(PTT_OFF, MCR(dev->base_addr));- outb(0x00, FCR(dev->base_addr));-- /* Flush pending irq */-- inb(RBR(dev->base_addr));- inb(MSR(dev->base_addr));-- /* Enable rx irq */-- outb(ENABLE_RTXINT, IER(dev->base_addr));-}---/* --------------------------------------------------------------------- */--enum uart {- c_uart_unknown, c_uart_8250,- c_uart_16450, c_uart_16550, c_uart_16550A-};--static const char *uart_str[] =-{"unknown", "8250", "16450", "16550", "16550A"};--static enum uart yam_check_uart(unsigned int iobase)-{- unsigned char b1, b2, b3;- enum uart u;- enum uart uart_tab[] =- {c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A};-- b1 = inb(MCR(iobase));- outb(b1 | 0x10, MCR(iobase)); /* loopback mode */- b2 = inb(MSR(iobase));- outb(0x1a, MCR(iobase));- b3 = inb(MSR(iobase)) & 0xf0;- outb(b1, MCR(iobase)); /* restore old values */- outb(b2, MSR(iobase));- if (b3 != 0x90)- return c_uart_unknown;- inb(RBR(iobase));- inb(RBR(iobase));- outb(0x01, FCR(iobase)); /* enable FIFOs */- u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];- if (u == c_uart_16450) {- outb(0x5a, SCR(iobase));- b1 = inb(SCR(iobase));- outb(0xa5, SCR(iobase));- b2 = inb(SCR(iobase));- if ((b1 != 0x5a) || (b2 != 0xa5))- u = c_uart_8250;- }- return u;-}--/******************************************************************************-* Rx Section-******************************************************************************/-static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp)-{- if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) {- int pkt_len = yp->rx_len - 2 + 1; /* -CRC + kiss */- struct sk_buff *skb;-- if ((yp->rx_crch & yp->rx_crcl) != 0xFF) {- /* Bad crc */- } else {- if (!(skb = dev_alloc_skb(pkt_len))) {- printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name);- ++dev->stats.rx_dropped;- } else {- unsigned char *cp;- cp = skb_put(skb, pkt_len);- *cp++ = 0; /* KISS kludge */- memcpy(cp, yp->rx_buf, pkt_len - 1);- skb->protocol = ax25_type_trans(skb, dev);- netif_rx(skb);- ++dev->stats.rx_packets;- }- }- }- yp->rx_len = 0;- yp->rx_crcl = 0x21;- yp->rx_crch = 0xf3;-}--static inline void yam_rx_byte(struct net_device *dev, struct yam_port *yp, unsigned char rxb)-{- if (yp->rx_len < YAM_MAX_FRAME) {- unsigned char c = yp->rx_crcl;- yp->rx_crcl = (chktabl[c] ^ yp->rx_crch);- yp->rx_crch = (chktabh[c] ^ rxb);- yp->rx_buf[yp->rx_len++] = rxb;- }-}--/********************************************************************************-* TX Section-********************************************************************************/--static void ptt_on(struct net_device *dev)-{- outb(PTT_ON, MCR(dev->base_addr));-}--static void ptt_off(struct net_device *dev)-{- outb(PTT_OFF, MCR(dev->base_addr));-}--static netdev_tx_t yam_send_packet(struct sk_buff *skb,- struct net_device *dev)-{- struct yam_port *yp = netdev_priv(dev);-- if (skb->protocol == htons(ETH_P_IP))- return ax25_ip_xmit(skb);-- skb_queue_tail(&yp->send_queue, skb);- netif_trans_update(dev);- return NETDEV_TX_OK;-}--static void yam_start_tx(struct net_device *dev, struct yam_port *yp)-{- if ((yp->tx_state == TX_TAIL) || (yp->txd == 0))- yp->tx_count = 1;- else- yp->tx_count = (yp->bitrate * yp->txd) / 8000;- yp->tx_state = TX_HEAD;- ptt_on(dev);-}--static void yam_arbitrate(struct net_device *dev)-{- struct yam_port *yp = netdev_priv(dev);-- if (yp->magic != YAM_MAGIC || yp->tx_state != TX_OFF ||- skb_queue_empty(&yp->send_queue))- return;- /* tx_state is TX_OFF and there is data to send */-- if (yp->dupmode) {- /* Full duplex mode, don't wait */- yam_start_tx(dev, yp);- return;- }- if (yp->dcd) {- /* DCD on, wait slotime ... */- yp->slotcnt = yp->slot / 10;- return;- }- /* Is slottime passed ? */- if ((--yp->slotcnt) > 0)- return;-- yp->slotcnt = yp->slot / 10;-- /* is random > persist ? */- if (get_random_u8() > yp->pers)- return;-- yam_start_tx(dev, yp);-}--static void yam_dotimer(struct timer_list *unused)-{- int i;-- for (i = 0; i < NR_PORTS; i++) {- struct net_device *dev = yam_devs[i];- if (dev && netif_running(dev))- yam_arbitrate(dev);- }- yam_timer.expires = jiffies + HZ / 100;- add_timer(&yam_timer);-}--static void yam_tx_byte(struct net_device *dev, struct yam_port *yp)-{- struct sk_buff *skb;- unsigned char b, temp;-- switch (yp->tx_state) {- case TX_OFF:- break;- case TX_HEAD:- if (--yp->tx_count <= 0) {- if (!(skb = skb_dequeue(&yp->send_queue))) {- ptt_off(dev);- yp->tx_state = TX_OFF;- break;- }- yp->tx_state = TX_DATA;- if (skb->data[0] != 0) {-/* do_kiss_params(s, skb->data, skb->len); */- dev_kfree_skb_any(skb);- break;- }- yp->tx_len = skb->len - 1; /* strip KISS byte */- if (yp->tx_len >= YAM_MAX_FRAME || yp->tx_len < 2) {- dev_kfree_skb_any(skb);- break;- }- skb_copy_from_linear_data_offset(skb, 1,- yp->tx_buf,- yp->tx_len);- dev_kfree_skb_any(skb);- yp->tx_count = 0;- yp->tx_crcl = 0x21;- yp->tx_crch = 0xf3;- yp->tx_state = TX_DATA;- }- break;- case TX_DATA:- b = yp->tx_buf[yp->tx_count++];- outb(b, THR(dev->base_addr));- temp = yp->tx_crcl;- yp->tx_crcl = chktabl[temp] ^ yp->tx_crch;- yp->tx_crch = chktabh[temp] ^ b;- if (yp->tx_count >= yp->tx_len) {- yp->tx_state = TX_CRC1;- }- break;- case TX_CRC1:- yp->tx_crch = chktabl[yp->tx_crcl] ^ yp->tx_crch;- yp->tx_crcl = chktabh[yp->tx_crcl] ^ chktabl[yp->tx_crch] ^ 0xff;- outb(yp->tx_crcl, THR(dev->base_addr));- yp->tx_state = TX_CRC2;- break;- case TX_CRC2:- outb(chktabh[yp->tx_crch] ^ 0xFF, THR(dev->base_addr));- if (skb_queue_empty(&yp->send_queue)) {- yp->tx_count = (yp->bitrate * yp->txtail) / 8000;- if (yp->dupmode == 2)- yp->tx_count += (yp->bitrate * yp->holdd) / 8;- if (yp->tx_count == 0)- yp->tx_count = 1;- yp->tx_state = TX_TAIL;- } else {- yp->tx_count = 1;- yp->tx_state = TX_HEAD;- }- ++dev->stats.tx_packets;- break;- case TX_TAIL:- if (--yp->tx_count <= 0) {- yp->tx_state = TX_OFF;- ptt_off(dev);- }- break;- }-}--/***********************************************************************************-* ISR routine-************************************************************************************/--static irqreturn_t yam_interrupt(int irq, void *dev_id)-{- struct net_device *dev;- struct yam_port *yp;- unsigned char iir;- int counter = 100;- int i;- int handled = 0;-- for (i = 0; i < NR_PORTS; i++) {- dev = yam_devs[i];- yp = netdev_priv(dev);-- if (!netif_running(dev))- continue;-- while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) {- unsigned char msr = inb(MSR(dev->base_addr));- unsigned char lsr = inb(LSR(dev->base_addr));- unsigned char rxb;-- handled = 1;-- if (lsr & LSR_OE)- ++dev->stats.rx_fifo_errors;-- yp->dcd = (msr & RX_DCD) ? 1 : 0;-- if (--counter <= 0) {- printk(KERN_ERR "%s: too many irq iir=%d\n",- dev->name, iir);- goto out;- }- if (msr & TX_RDY) {- ++yp->nb_mdint;- yam_tx_byte(dev, yp);- }- if (lsr & LSR_RXC) {- ++yp->nb_rxint;- rxb = inb(RBR(dev->base_addr));- if (msr & RX_FLAG)- yam_rx_flag(dev, yp);- else- yam_rx_byte(dev, yp, rxb);- }- }- }-out:- return IRQ_RETVAL(handled);-}--#ifdef CONFIG_PROC_FS--static void *yam_seq_start(struct seq_file *seq, loff_t *pos)-{- return (*pos < NR_PORTS) ? yam_devs[*pos] : NULL;-}--static void *yam_seq_next(struct seq_file *seq, void *v, loff_t *pos)-{- ++*pos;- return (*pos < NR_PORTS) ? yam_devs[*pos] : NULL;-}--static void yam_seq_stop(struct seq_file *seq, void *v)-{-}--static int yam_seq_show(struct seq_file *seq, void *v)-{- struct net_device *dev = v;- const struct yam_port *yp = netdev_priv(dev);-- seq_printf(seq, "Device %s\n", dev->name);- seq_printf(seq, " Up %d\n", netif_running(dev));- seq_printf(seq, " Speed %u\n", yp->bitrate);- seq_printf(seq, " IoBase 0x%x\n", yp->iobase);- seq_printf(seq, " BaudRate %u\n", yp->baudrate);- seq_printf(seq, " IRQ %u\n", yp->irq);- seq_printf(seq, " TxState %u\n", yp->tx_state);- seq_printf(seq, " Duplex %u\n", yp->dupmode);- seq_printf(seq, " HoldDly %u\n", yp->holdd);- seq_printf(seq, " TxDelay %u\n", yp->txd);- seq_printf(seq, " TxTail %u\n", yp->txtail);- seq_printf(seq, " SlotTime %u\n", yp->slot);- seq_printf(seq, " Persist %u\n", yp->pers);- seq_printf(seq, " TxFrames %lu\n", dev->stats.tx_packets);- seq_printf(seq, " RxFrames %lu\n", dev->stats.rx_packets);- seq_printf(seq, " TxInt %u\n", yp->nb_mdint);- seq_printf(seq, " RxInt %u\n", yp->nb_rxint);- seq_printf(seq, " RxOver %lu\n", dev->stats.rx_fifo_errors);- seq_printf(seq, "\n");- return 0;-}--static const struct seq_operations yam_seqops = {- .start = yam_seq_start,- .next = yam_seq_next,- .stop = yam_seq_stop,- .show = yam_seq_show,-};-#endif---/* --------------------------------------------------------------------- */--static int yam_open(struct net_device *dev)-{- struct yam_port *yp = netdev_priv(dev);- enum uart u;- int i;- int ret=0;-- printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq);-- if (!yp->bitrate)- return -ENXIO;- if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT ||- dev->irq < 2 || dev->irq > 15) {- return -ENXIO;- }- if (!request_region(dev->base_addr, YAM_EXTENT, dev->name))- {- printk(KERN_ERR "%s: cannot 0x%lx busy\n", dev->name, dev->base_addr);- return -EACCES;- }- if ((u = yam_check_uart(dev->base_addr)) == c_uart_unknown) {- printk(KERN_ERR "%s: cannot find uart type\n", dev->name);- ret = -EIO;- goto out_release_base;- }- if (fpga_download(dev->base_addr, yp->bitrate)) {- printk(KERN_ERR "%s: cannot init FPGA\n", dev->name);- ret = -EIO;- goto out_release_base;- }- outb(0, IER(dev->base_addr));- if (request_irq(dev->irq, yam_interrupt, IRQF_SHARED, dev->name, dev)) {- printk(KERN_ERR "%s: irq %d busy\n", dev->name, dev->irq);- ret = -EBUSY;- goto out_release_base;- }-- yam_set_uart(dev);-- netif_start_queue(dev);- - yp->slotcnt = yp->slot / 10;-- /* Reset overruns for all ports - FPGA programming makes overruns */- for (i = 0; i < NR_PORTS; i++) {- struct net_device *yam_dev = yam_devs[i];-- inb(LSR(yam_dev->base_addr));- yam_dev->stats.rx_fifo_errors = 0;- }-- printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq,- uart_str[u]);- return 0;--out_release_base:- release_region(dev->base_addr, YAM_EXTENT);- return ret;-}--/* --------------------------------------------------------------------- */--static int yam_close(struct net_device *dev)-{- struct sk_buff *skb;- struct yam_port *yp = netdev_priv(dev);-- if (!dev)- return -EINVAL;-- /*- * disable interrupts- */- outb(0, IER(dev->base_addr));- outb(1, MCR(dev->base_addr));- /* Remove IRQ handler if last */- free_irq(dev->irq,dev);- release_region(dev->base_addr, YAM_EXTENT);- netif_stop_queue(dev);- while ((skb = skb_dequeue(&yp->send_queue)))- dev_kfree_skb(skb);-- printk(KERN_INFO "%s: close yam at iobase 0x%lx irq %u\n",- yam_drvname, dev->base_addr, dev->irq);- return 0;-}--/* --------------------------------------------------------------------- */--static int yam_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data, int cmd)-{- struct yam_port *yp = netdev_priv(dev);- struct yamdrv_ioctl_cfg yi;- struct yamdrv_ioctl_mcs *ym;- int ioctl_cmd;-- if (copy_from_user(&ioctl_cmd, data, sizeof(int)))- return -EFAULT;-- if (yp->magic != YAM_MAGIC)- return -EINVAL;-- if (!capable(CAP_NET_ADMIN))- return -EPERM;-- if (cmd != SIOCDEVPRIVATE)- return -EINVAL;-- switch (ioctl_cmd) {-- case SIOCYAMRESERVED:- return -EINVAL; /* unused */-- case SIOCYAMSMCS:- if (netif_running(dev))- return -EINVAL; /* Cannot change this parameter when up */- ym = memdup_user(data, sizeof(struct yamdrv_ioctl_mcs));- if (IS_ERR(ym))- return PTR_ERR(ym);- if (ym->cmd != SIOCYAMSMCS || ym->bitrate > YAM_MAXBITRATE) {- kfree(ym);- return -EINVAL;- }- /* setting predef as 0 for loading userdefined mcs data */- add_mcs(ym->bits, ym->bitrate, 0);- kfree(ym);- break;-- case SIOCYAMSCFG:- if (!capable(CAP_SYS_RAWIO))- return -EPERM;- if (copy_from_user(&yi, data, sizeof(struct yamdrv_ioctl_cfg)))- return -EFAULT;-- if (yi.cmd != SIOCYAMSCFG)- return -EINVAL;- if ((yi.cfg.mask & YAM_IOBASE) && netif_running(dev))- return -EINVAL; /* Cannot change this parameter when up */- if ((yi.cfg.mask & YAM_IRQ) && netif_running(dev))- return -EINVAL; /* Cannot change this parameter when up */- if ((yi.cfg.mask & YAM_BITRATE) && netif_running(dev))- return -EINVAL; /* Cannot change this parameter when up */- if ((yi.cfg.mask & YAM_BAUDRATE) && netif_running(dev))- return -EINVAL; /* Cannot change this parameter when up */-- if (yi.cfg.mask & YAM_IOBASE) {- yp->iobase = yi.cfg.iobase;- dev->base_addr = yi.cfg.iobase;- }- if (yi.cfg.mask & YAM_IRQ) {- if (yi.cfg.irq > 15)- return -EINVAL;- yp->irq = yi.cfg.irq;- dev->irq = yi.cfg.irq;- }- if (yi.cfg.mask & YAM_BITRATE) {- if (yi.cfg.bitrate > YAM_MAXBITRATE)- return -EINVAL;- yp->bitrate = yi.cfg.bitrate;- }- if (yi.cfg.mask & YAM_BAUDRATE) {- if (yi.cfg.baudrate > YAM_MAXBAUDRATE)- return -EINVAL;- yp->baudrate = yi.cfg.baudrate;- }- if (yi.cfg.mask & YAM_MODE) {- if (yi.cfg.mode > YAM_MAXMODE)- return -EINVAL;- yp->dupmode = yi.cfg.mode;- }- if (yi.cfg.mask & YAM_HOLDDLY) {- if (yi.cfg.holddly > YAM_MAXHOLDDLY)- return -EINVAL;- yp->holdd = yi.cfg.holddly;- }- if (yi.cfg.mask & YAM_TXDELAY) {- if (yi.cfg.txdelay > YAM_MAXTXDELAY)- return -EINVAL;- yp->txd = yi.cfg.txdelay;- }- if (yi.cfg.mask & YAM_TXTAIL) {- if (yi.cfg.txtail > YAM_MAXTXTAIL)- return -EINVAL;- yp->txtail = yi.cfg.txtail;- }- if (yi.cfg.mask & YAM_PERSIST) {- if (yi.cfg.persist > YAM_MAXPERSIST)- return -EINVAL;- yp->pers = yi.cfg.persist;- }- if (yi.cfg.mask & YAM_SLOTTIME) {- if (yi.cfg.slottime > YAM_MAXSLOTTIME)- return -EINVAL;- yp->slot = yi.cfg.slottime;- yp->slotcnt = yp->slot / 10;- }- break;-- case SIOCYAMGCFG:- memset(&yi, 0, sizeof(yi));- yi.cfg.mask = 0xffffffff;- yi.cfg.iobase = yp->iobase;- yi.cfg.irq = yp->irq;- yi.cfg.bitrate = yp->bitrate;- yi.cfg.baudrate = yp->baudrate;- yi.cfg.mode = yp->dupmode;- yi.cfg.txdelay = yp->txd;- yi.cfg.holddly = yp->holdd;- yi.cfg.txtail = yp->txtail;- yi.cfg.persist = yp->pers;- yi.cfg.slottime = yp->slot;- if (copy_to_user(data, &yi, sizeof(struct yamdrv_ioctl_cfg)))- return -EFAULT;- break;-- default:- return -EINVAL;-- }-- return 0;-}--/* --------------------------------------------------------------------- */--static int yam_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr *sa = (struct sockaddr *) addr;-- /* addr is an AX.25 shifted ASCII mac address */- dev_addr_set(dev, sa->sa_data);- return 0;-}--/* --------------------------------------------------------------------- */--static const struct net_device_ops yam_netdev_ops = {- .ndo_open = yam_open,- .ndo_stop = yam_close,- .ndo_start_xmit = yam_send_packet,- .ndo_siocdevprivate = yam_siocdevprivate,- .ndo_set_mac_address = yam_set_mac_address,-};--static void yam_setup(struct net_device *dev)-{- struct yam_port *yp = netdev_priv(dev);-- yp->magic = YAM_MAGIC;- yp->bitrate = DEFAULT_BITRATE;- yp->baudrate = DEFAULT_BITRATE * 2;- yp->iobase = 0;- yp->irq = 0;- yp->dupmode = 0;- yp->holdd = DEFAULT_HOLDD;- yp->txd = DEFAULT_TXD;- yp->txtail = DEFAULT_TXTAIL;- yp->slot = DEFAULT_SLOT;- yp->pers = DEFAULT_PERS;- yp->dev = dev;-- dev->base_addr = yp->iobase;- dev->irq = yp->irq;-- skb_queue_head_init(&yp->send_queue);-- dev->netdev_ops = &yam_netdev_ops;- dev->header_ops = &ax25_header_ops;-- dev->type = ARPHRD_AX25;- dev->hard_header_len = AX25_MAX_HEADER_LEN;- dev->mtu = AX25_MTU;- dev->addr_len = AX25_ADDR_LEN;- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);- dev_addr_set(dev, (u8 *)&ax25_defaddr);-}--static int __init yam_init_driver(void)-{- struct net_device *dev;- int i, err;- char name[IFNAMSIZ];-- printk(yam_drvinfo);-- for (i = 0; i < NR_PORTS; i++) {- sprintf(name, "yam%d", i);- - dev = alloc_netdev(sizeof(struct yam_port), name,- NET_NAME_UNKNOWN, yam_setup);- if (!dev) {- pr_err("yam: cannot allocate net device\n");- err = -ENOMEM;- goto error;- }- - err = register_netdev(dev);- if (err) {- printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name);- free_netdev(dev);- goto error;- }- yam_devs[i] = dev;-- }-- timer_setup(&yam_timer, yam_dotimer, 0);- yam_timer.expires = jiffies + HZ / 100;- add_timer(&yam_timer);-- proc_create_seq("yam", 0444, init_net.proc_net, &yam_seqops);- return 0;- error:- while (--i >= 0) {- unregister_netdev(yam_devs[i]);- free_netdev(yam_devs[i]);- }- return err;-}--/* --------------------------------------------------------------------- */--static void __exit yam_cleanup_driver(void)-{- struct yam_mcs *p;- int i;-- timer_delete_sync(&yam_timer);- for (i = 0; i < NR_PORTS; i++) {- struct net_device *dev = yam_devs[i];- if (dev) {- unregister_netdev(dev);- free_netdev(dev);- }- }-- while (yam_data) {- p = yam_data;- yam_data = yam_data->next;- kfree(p);- }-- remove_proc_entry("yam", init_net.proc_net);-}--/* --------------------------------------------------------------------- */--MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr");-MODULE_DESCRIPTION("Yam amateur radio modem driver");-MODULE_LICENSE("GPL");-MODULE_FIRMWARE(FIRMWARE_1200);-MODULE_FIRMWARE(FIRMWARE_9600);--module_init(yam_init_driver);-module_exit(yam_cleanup_driver);--/* --------------------------------------------------------------------- */-diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.cdeleted file mode 100644index 9d236e64f5f5..000000000000--- a/net/ax25/af_ax25.c+++ /dev/null@@ -1,2089 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Darryl Miles G7LED (dlm@g7led.demon.co.uk)- * Copyright (C) Steven Whitehouse GW7RRM (stevew@acm.org)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)- * Copyright (C) Hans Alblas PE1AYX (hans@esrac.ele.tue.nl)- * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)- */-#include <linux/capability.h>-#include <linux/module.h>-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/sched/signal.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/termios.h> /* For TIOCINQ/OUTQ */-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/notifier.h>-#include <linux/proc_fs.h>-#include <linux/stat.h>-#include <linux/sysctl.h>-#include <linux/init.h>-#include <linux/spinlock.h>-#include <net/net_namespace.h>-#include <net/tcp_states.h>-#include <net/ip.h>-#include <net/arp.h>----HLIST_HEAD(ax25_list);-DEFINE_SPINLOCK(ax25_list_lock);--static const struct proto_ops ax25_proto_ops;--static void ax25_free_sock(struct sock *sk)-{- ax25_cb_put(sk_to_ax25(sk));-}--/*- * Socket removal during an interrupt is now safe.- */-static void ax25_cb_del(ax25_cb *ax25)-{- spin_lock_bh(&ax25_list_lock);- if (!hlist_unhashed(&ax25->ax25_node)) {- hlist_del_init(&ax25->ax25_node);- ax25_cb_put(ax25);- }- spin_unlock_bh(&ax25_list_lock);-}--/*- * Kill all bound sockets on a dropped device.- */-static void ax25_kill_by_device(struct net_device *dev)-{- ax25_dev *ax25_dev;- ax25_cb *s;- struct sock *sk;-- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)- return;- ax25_dev->device_up = false;-- spin_lock_bh(&ax25_list_lock);-again:- ax25_for_each(s, &ax25_list) {- if (s->ax25_dev == ax25_dev) {- sk = s->sk;- if (!sk) {- spin_unlock_bh(&ax25_list_lock);- ax25_disconnect(s, ENETUNREACH);- s->ax25_dev = NULL;- ax25_cb_del(s);- spin_lock_bh(&ax25_list_lock);- goto again;- }- sock_hold(sk);- spin_unlock_bh(&ax25_list_lock);- lock_sock(sk);- ax25_disconnect(s, ENETUNREACH);- s->ax25_dev = NULL;- if (sk->sk_socket) {- netdev_put(ax25_dev->dev,- &s->dev_tracker);- ax25_dev_put(ax25_dev);- }- ax25_cb_del(s);- release_sock(sk);- spin_lock_bh(&ax25_list_lock);- sock_put(sk);- /* The entry could have been deleted from the- * list meanwhile and thus the next pointer is- * no longer valid. Play it safe and restart- * the scan. Forward progress is ensured- * because we set s->ax25_dev to NULL and we- * are never passed a NULL 'dev' argument.- */- goto again;- }- }- spin_unlock_bh(&ax25_list_lock);-}--/*- * Handle device status changes.- */-static int ax25_device_event(struct notifier_block *this, unsigned long event,- void *ptr)-{- struct net_device *dev = netdev_notifier_info_to_dev(ptr);-- if (!net_eq(dev_net(dev), &init_net))- return NOTIFY_DONE;-- /* Reject non AX.25 devices */- if (dev->type != ARPHRD_AX25)- return NOTIFY_DONE;-- switch (event) {- case NETDEV_UP:- ax25_dev_device_up(dev);- break;- case NETDEV_DOWN:- ax25_kill_by_device(dev);- ax25_rt_device_down(dev);- ax25_dev_device_down(dev);- break;- default:- break;- }-- return NOTIFY_DONE;-}--/*- * Add a socket to the bound sockets list.- */-void ax25_cb_add(ax25_cb *ax25)-{- spin_lock_bh(&ax25_list_lock);- ax25_cb_hold(ax25);- hlist_add_head(&ax25->ax25_node, &ax25_list);- spin_unlock_bh(&ax25_list_lock);-}--/*- * Find a socket that wants to accept the SABM we have just- * received.- */-struct sock *ax25_find_listener(ax25_address *addr, int digi,- struct net_device *dev, int type)-{- ax25_cb *s;-- spin_lock(&ax25_list_lock);- ax25_for_each(s, &ax25_list) {- if ((s->iamdigi && !digi) || (!s->iamdigi && digi))- continue;- if (s->sk && !ax25cmp(&s->source_addr, addr) &&- s->sk->sk_type == type && s->sk->sk_state == TCP_LISTEN) {- /* If device is null we match any device */- if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) {- sock_hold(s->sk);- spin_unlock(&ax25_list_lock);- return s->sk;- }- }- }- spin_unlock(&ax25_list_lock);-- return NULL;-}--/*- * Find an AX.25 socket given both ends.- */-struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr,- int type)-{- struct sock *sk = NULL;- ax25_cb *s;-- spin_lock(&ax25_list_lock);- ax25_for_each(s, &ax25_list) {- if (s->sk && !ax25cmp(&s->source_addr, my_addr) &&- !ax25cmp(&s->dest_addr, dest_addr) &&- s->sk->sk_type == type) {- sk = s->sk;- sock_hold(sk);- break;- }- }-- spin_unlock(&ax25_list_lock);-- return sk;-}--/*- * Find an AX.25 control block given both ends. It will only pick up- * floating AX.25 control blocks or non Raw socket bound control blocks.- */-ax25_cb *ax25_find_cb(const ax25_address *src_addr, ax25_address *dest_addr,- ax25_digi *digi, struct net_device *dev)-{- ax25_cb *s;-- spin_lock_bh(&ax25_list_lock);- ax25_for_each(s, &ax25_list) {- if (s->sk && s->sk->sk_type != SOCK_SEQPACKET)- continue;- if (s->ax25_dev == NULL)- continue;- if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {- if (digi != NULL && digi->ndigi != 0) {- if (s->digipeat == NULL)- continue;- if (ax25digicmp(s->digipeat, digi) != 0)- continue;- } else {- if (s->digipeat != NULL && s->digipeat->ndigi != 0)- continue;- }- ax25_cb_hold(s);- spin_unlock_bh(&ax25_list_lock);-- return s;- }- }- spin_unlock_bh(&ax25_list_lock);-- return NULL;-}--EXPORT_SYMBOL(ax25_find_cb);--void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)-{- ax25_cb *s;- struct sk_buff *copy;-- spin_lock(&ax25_list_lock);- ax25_for_each(s, &ax25_list) {- if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 &&- s->sk->sk_type == SOCK_RAW &&- s->sk->sk_protocol == proto &&- s->ax25_dev->dev == skb->dev &&- atomic_read(&s->sk->sk_rmem_alloc) <= s->sk->sk_rcvbuf) {- if ((copy = skb_clone(skb, GFP_ATOMIC)) == NULL)- continue;- if (sock_queue_rcv_skb(s->sk, copy) != 0)- kfree_skb(copy);- }- }- spin_unlock(&ax25_list_lock);-}--/*- * Deferred destroy.- */-void ax25_destroy_socket(ax25_cb *);--/*- * Handler for deferred kills.- */-static void ax25_destroy_timer(struct timer_list *t)-{- ax25_cb *ax25 = timer_container_of(ax25, t, dtimer);- struct sock *sk;-- sk=ax25->sk;-- bh_lock_sock(sk);- sock_hold(sk);- ax25_destroy_socket(ax25);- bh_unlock_sock(sk);- sock_put(sk);-}--/*- * This is called from user mode and the timers. Thus it protects itself- * against interrupt users but doesn't worry about being called during- * work. Once it is removed from the queue no interrupt or bottom half- * will touch it and we are (fairly 8-) ) safe.- */-void ax25_destroy_socket(ax25_cb *ax25)-{- struct sk_buff *skb;-- ax25_cb_del(ax25);-- ax25_stop_heartbeat(ax25);- ax25_stop_t1timer(ax25);- ax25_stop_t2timer(ax25);- ax25_stop_t3timer(ax25);- ax25_stop_idletimer(ax25);-- ax25_clear_queues(ax25); /* Flush the queues */-- if (ax25->sk != NULL) {- while ((skb = skb_dequeue(&ax25->sk->sk_receive_queue)) != NULL) {- if (skb->sk != ax25->sk) {- /* A pending connection */- ax25_cb *sax25 = sk_to_ax25(skb->sk);-- /* Queue the unaccepted socket for death */- sock_orphan(skb->sk);-- /* 9A4GL: hack to release unaccepted sockets */- skb->sk->sk_state = TCP_LISTEN;-- ax25_start_heartbeat(sax25);- sax25->state = AX25_STATE_0;- }-- kfree_skb(skb);- }- skb_queue_purge(&ax25->sk->sk_write_queue);- }-- if (ax25->sk != NULL) {- if (sk_has_allocations(ax25->sk)) {- /* Defer: outstanding buffers */- timer_setup(&ax25->dtimer, ax25_destroy_timer, 0);- ax25->dtimer.expires = jiffies + 2 * HZ;- add_timer(&ax25->dtimer);- } else {- struct sock *sk=ax25->sk;- ax25->sk=NULL;- sock_put(sk);- }- } else {- ax25_cb_put(ax25);- }-}--/*- * dl1bke 960311: set parameters for existing AX.25 connections,- * includes a KILL command to abort any connection.- * VERY useful for debugging ;-)- */-static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)-{- struct ax25_ctl_struct ax25_ctl;- ax25_digi digi;- ax25_dev *ax25_dev;- ax25_cb *ax25;- unsigned int k;- int ret = 0;-- if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))- return -EFAULT;-- if (ax25_ctl.digi_count > AX25_MAX_DIGIS)- return -EINVAL;-- if (ax25_ctl.arg > ULONG_MAX / HZ && ax25_ctl.cmd != AX25_KILL)- return -EINVAL;-- ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr);- if (!ax25_dev)- return -ENODEV;-- digi.ndigi = ax25_ctl.digi_count;- for (k = 0; k < digi.ndigi; k++)- digi.calls[k] = ax25_ctl.digi_addr[k];-- ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev);- if (!ax25) {- ax25_dev_put(ax25_dev);- return -ENOTCONN;- }-- switch (ax25_ctl.cmd) {- case AX25_KILL:- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);-#ifdef CONFIG_AX25_DAMA_SLAVE- if (ax25_dev->dama.slave && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE)- ax25_dama_off(ax25);-#endif- ax25_disconnect(ax25, ENETRESET);- break;-- case AX25_WINDOW:- if (ax25->modulus == AX25_MODULUS) {- if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)- goto einval_put;- } else {- if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)- goto einval_put;- }- ax25->window = ax25_ctl.arg;- break;-- case AX25_T1:- if (ax25_ctl.arg < 1 || ax25_ctl.arg > ULONG_MAX / HZ)- goto einval_put;- ax25->rtt = (ax25_ctl.arg * HZ) / 2;- ax25->t1 = ax25_ctl.arg * HZ;- break;-- case AX25_T2:- if (ax25_ctl.arg < 1 || ax25_ctl.arg > ULONG_MAX / HZ)- goto einval_put;- ax25->t2 = ax25_ctl.arg * HZ;- break;-- case AX25_N2:- if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)- goto einval_put;- ax25->n2count = 0;- ax25->n2 = ax25_ctl.arg;- break;-- case AX25_T3:- if (ax25_ctl.arg > ULONG_MAX / HZ)- goto einval_put;- ax25->t3 = ax25_ctl.arg * HZ;- break;-- case AX25_IDLE:- if (ax25_ctl.arg > ULONG_MAX / (60 * HZ))- goto einval_put;-- ax25->idle = ax25_ctl.arg * 60 * HZ;- break;-- case AX25_PACLEN:- if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)- goto einval_put;- ax25->paclen = ax25_ctl.arg;- break;-- default:- goto einval_put;- }--out_put:- ax25_dev_put(ax25_dev);- ax25_cb_put(ax25);- return ret;--einval_put:- ret = -EINVAL;- goto out_put;-}--static void ax25_fillin_cb_from_dev(ax25_cb *ax25, const ax25_dev *ax25_dev)-{- ax25->rtt = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2;- ax25->t1 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]);- ax25->t2 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T2]);- ax25->t3 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T3]);- ax25->n2 = ax25_dev->values[AX25_VALUES_N2];- ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];- ax25->idle = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_IDLE]);- ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];-- if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {- ax25->modulus = AX25_EMODULUS;- ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];- } else {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];- }-}--/*- * Fill in a created AX.25 created control block with the default- * values for a particular device.- */-void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)-{- ax25->ax25_dev = ax25_dev;-- if (ax25->ax25_dev != NULL) {- ax25_fillin_cb_from_dev(ax25, ax25_dev);- return;- }-- /*- * No device, use kernel / AX.25 spec default values- */- ax25->rtt = msecs_to_jiffies(AX25_DEF_T1) / 2;- ax25->t1 = msecs_to_jiffies(AX25_DEF_T1);- ax25->t2 = msecs_to_jiffies(AX25_DEF_T2);- ax25->t3 = msecs_to_jiffies(AX25_DEF_T3);- ax25->n2 = AX25_DEF_N2;- ax25->paclen = AX25_DEF_PACLEN;- ax25->idle = msecs_to_jiffies(AX25_DEF_IDLE);- ax25->backoff = AX25_DEF_BACKOFF;-- if (AX25_DEF_AXDEFMODE) {- ax25->modulus = AX25_EMODULUS;- ax25->window = AX25_DEF_EWINDOW;- } else {- ax25->modulus = AX25_MODULUS;- ax25->window = AX25_DEF_WINDOW;- }-}--/*- * Create an empty AX.25 control block.- */-ax25_cb *ax25_create_cb(void)-{- ax25_cb *ax25;-- if ((ax25 = kzalloc_obj(*ax25, GFP_ATOMIC)) == NULL)- return NULL;-- refcount_set(&ax25->refcount, 1);-- skb_queue_head_init(&ax25->write_queue);- skb_queue_head_init(&ax25->frag_queue);- skb_queue_head_init(&ax25->ack_queue);- skb_queue_head_init(&ax25->reseq_queue);-- ax25_setup_timers(ax25);-- ax25_fillin_cb(ax25, NULL);-- ax25->state = AX25_STATE_0;-- return ax25;-}--/*- * Handling for system calls applied via the various interfaces to an- * AX25 socket object- */--static int ax25_setsockopt(struct socket *sock, int level, int optname,- sockptr_t optval, unsigned int optlen)-{- struct sock *sk = sock->sk;- ax25_cb *ax25;- struct net_device *dev;- char devname[IFNAMSIZ];- unsigned int opt;- int res = 0;-- if (level != SOL_AX25)- return -ENOPROTOOPT;-- if (optlen < sizeof(unsigned int))- return -EINVAL;-- if (copy_from_sockptr(&opt, optval, sizeof(unsigned int)))- return -EFAULT;-- lock_sock(sk);- ax25 = sk_to_ax25(sk);-- switch (optname) {- case AX25_WINDOW:- if (ax25->modulus == AX25_MODULUS) {- if (opt < 1 || opt > 7) {- res = -EINVAL;- break;- }- } else {- if (opt < 1 || opt > 63) {- res = -EINVAL;- break;- }- }- ax25->window = opt;- break;-- case AX25_T1:- if (opt < 1 || opt > UINT_MAX / HZ) {- res = -EINVAL;- break;- }- ax25->rtt = (opt * HZ) >> 1;- ax25->t1 = opt * HZ;- break;-- case AX25_T2:- if (opt < 1 || opt > UINT_MAX / HZ) {- res = -EINVAL;- break;- }- ax25->t2 = opt * HZ;- break;-- case AX25_N2:- if (opt < 1 || opt > 31) {- res = -EINVAL;- break;- }- ax25->n2 = opt;- break;-- case AX25_T3:- if (opt < 1 || opt > UINT_MAX / HZ) {- res = -EINVAL;- break;- }- ax25->t3 = opt * HZ;- break;-- case AX25_IDLE:- if (opt > UINT_MAX / (60 * HZ)) {- res = -EINVAL;- break;- }- ax25->idle = opt * 60 * HZ;- break;-- case AX25_BACKOFF:- if (opt > 2) {- res = -EINVAL;- break;- }- ax25->backoff = opt;- break;-- case AX25_EXTSEQ:- ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS;- break;-- case AX25_PIDINCL:- ax25->pidincl = opt ? 1 : 0;- break;-- case AX25_IAMDIGI:- ax25->iamdigi = opt ? 1 : 0;- break;-- case AX25_PACLEN:- if (opt < 16 || opt > 65535) {- res = -EINVAL;- break;- }- ax25->paclen = opt;- break;-- case SO_BINDTODEVICE:- if (optlen > IFNAMSIZ - 1)- optlen = IFNAMSIZ - 1;-- memset(devname, 0, sizeof(devname));-- if (copy_from_sockptr(devname, optval, optlen)) {- res = -EFAULT;- break;- }-- if (sk->sk_type == SOCK_SEQPACKET &&- (sock->state != SS_UNCONNECTED ||- sk->sk_state == TCP_LISTEN)) {- res = -EADDRNOTAVAIL;- break;- }-- rcu_read_lock();- dev = dev_get_by_name_rcu(&init_net, devname);- if (!dev) {- rcu_read_unlock();- res = -ENODEV;- break;- }-- if (ax25->ax25_dev) {- if (dev == ax25->ax25_dev->dev) {- rcu_read_unlock();- break;- }- netdev_put(ax25->ax25_dev->dev, &ax25->dev_tracker);- ax25_dev_put(ax25->ax25_dev);- }-- ax25->ax25_dev = ax25_dev_ax25dev(dev);- if (!ax25->ax25_dev) {- rcu_read_unlock();- res = -ENODEV;- break;- }- ax25_fillin_cb(ax25, ax25->ax25_dev);- netdev_hold(dev, &ax25->dev_tracker, GFP_ATOMIC);- ax25_dev_hold(ax25->ax25_dev);- rcu_read_unlock();- break;-- default:- res = -ENOPROTOOPT;- }- release_sock(sk);-- return res;-}--static int ax25_getsockopt(struct socket *sock, int level, int optname,- char __user *optval, int __user *optlen)-{- struct sock *sk = sock->sk;- ax25_cb *ax25;- struct ax25_dev *ax25_dev;- char devname[IFNAMSIZ];- void *valptr;- int val = 0;- int maxlen, length;-- if (level != SOL_AX25)- return -ENOPROTOOPT;-- if (get_user(maxlen, optlen))- return -EFAULT;-- if (maxlen < 1)- return -EFAULT;-- valptr = &val;- length = min_t(unsigned int, maxlen, sizeof(int));-- lock_sock(sk);- ax25 = sk_to_ax25(sk);-- switch (optname) {- case AX25_WINDOW:- val = ax25->window;- break;-- case AX25_T1:- val = ax25->t1 / HZ;- break;-- case AX25_T2:- val = ax25->t2 / HZ;- break;-- case AX25_N2:- val = ax25->n2;- break;-- case AX25_T3:- val = ax25->t3 / HZ;- break;-- case AX25_IDLE:- val = ax25->idle / (60 * HZ);- break;-- case AX25_BACKOFF:- val = ax25->backoff;- break;-- case AX25_EXTSEQ:- val = (ax25->modulus == AX25_EMODULUS);- break;-- case AX25_PIDINCL:- val = ax25->pidincl;- break;-- case AX25_IAMDIGI:- val = ax25->iamdigi;- break;-- case AX25_PACLEN:- val = ax25->paclen;- break;-- case SO_BINDTODEVICE:- ax25_dev = ax25->ax25_dev;-- if (ax25_dev != NULL && ax25_dev->dev != NULL) {- strscpy(devname, ax25_dev->dev->name, sizeof(devname));- length = strlen(devname) + 1;- } else {- *devname = '\0';- length = 1;- }-- valptr = devname;- break;-- default:- release_sock(sk);- return -ENOPROTOOPT;- }- release_sock(sk);-- if (put_user(length, optlen))- return -EFAULT;-- return copy_to_user(optval, valptr, length) ? -EFAULT : 0;-}--static int ax25_listen(struct socket *sock, int backlog)-{- struct sock *sk = sock->sk;- int res = 0;-- lock_sock(sk);- if (sk->sk_type == SOCK_SEQPACKET && sk->sk_state != TCP_LISTEN) {- sk->sk_max_ack_backlog = backlog;- sk->sk_state = TCP_LISTEN;- goto out;- }- res = -EOPNOTSUPP;--out:- release_sock(sk);-- return res;-}--/*- * XXX: when creating ax25_sock we should update the .obj_size setting- * below.- */-static struct proto ax25_proto = {- .name = "AX25",- .owner = THIS_MODULE,- .obj_size = sizeof(struct ax25_sock),-};--static int ax25_create(struct net *net, struct socket *sock, int protocol,- int kern)-{- struct sock *sk;- ax25_cb *ax25;-- if (protocol < 0 || protocol > U8_MAX)- return -EINVAL;-- if (!net_eq(net, &init_net))- return -EAFNOSUPPORT;-- switch (sock->type) {- case SOCK_DGRAM:- if (protocol == 0 || protocol == PF_AX25)- protocol = AX25_P_TEXT;- break;-- case SOCK_SEQPACKET:- switch (protocol) {- case 0:- case PF_AX25: /* For CLX */- protocol = AX25_P_TEXT;- break;- case AX25_P_SEGMENT:-#ifdef CONFIG_INET- case AX25_P_ARP:- case AX25_P_IP:-#endif-#ifdef CONFIG_NETROM- case AX25_P_NETROM:-#endif-#ifdef CONFIG_ROSE- case AX25_P_ROSE:-#endif- return -ESOCKTNOSUPPORT;-#ifdef CONFIG_NETROM_MODULE- case AX25_P_NETROM:- if (ax25_protocol_is_registered(AX25_P_NETROM))- return -ESOCKTNOSUPPORT;- break;-#endif-#ifdef CONFIG_ROSE_MODULE- case AX25_P_ROSE:- if (ax25_protocol_is_registered(AX25_P_ROSE))- return -ESOCKTNOSUPPORT;- break;-#endif- default:- break;- }- break;-- case SOCK_RAW:- if (!capable(CAP_NET_RAW))- return -EPERM;- break;- default:- return -ESOCKTNOSUPPORT;- }-- sk = sk_alloc(net, PF_AX25, GFP_ATOMIC, &ax25_proto, kern);- if (sk == NULL)- return -ENOMEM;-- ax25 = ax25_sk(sk)->cb = ax25_create_cb();- if (!ax25) {- sk_free(sk);- return -ENOMEM;- }-- sock_init_data(sock, sk);-- sk->sk_destruct = ax25_free_sock;- sock->ops = &ax25_proto_ops;- sk->sk_protocol = protocol;-- ax25->sk = sk;-- return 0;-}--struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)-{- struct sock *sk;- ax25_cb *ax25, *oax25;-- sk = sk_alloc(sock_net(osk), PF_AX25, GFP_ATOMIC, osk->sk_prot, 0);- if (sk == NULL)- return NULL;-- if ((ax25 = ax25_create_cb()) == NULL) {- sk_free(sk);- return NULL;- }-- switch (osk->sk_type) {- case SOCK_DGRAM:- break;- case SOCK_SEQPACKET:- break;- default:- sk_free(sk);- ax25_cb_put(ax25);- return NULL;- }-- sock_init_data(NULL, sk);-- sk->sk_type = osk->sk_type;- sk->sk_priority = READ_ONCE(osk->sk_priority);- sk->sk_protocol = osk->sk_protocol;- sk->sk_rcvbuf = osk->sk_rcvbuf;- sk->sk_sndbuf = osk->sk_sndbuf;- sk->sk_state = TCP_ESTABLISHED;- sock_copy_flags(sk, osk);-- oax25 = sk_to_ax25(osk);-- ax25->modulus = oax25->modulus;- ax25->backoff = oax25->backoff;- ax25->pidincl = oax25->pidincl;- ax25->iamdigi = oax25->iamdigi;- ax25->rtt = oax25->rtt;- ax25->t1 = oax25->t1;- ax25->t2 = oax25->t2;- ax25->t3 = oax25->t3;- ax25->n2 = oax25->n2;- ax25->idle = oax25->idle;- ax25->paclen = oax25->paclen;- ax25->window = oax25->window;-- ax25->ax25_dev = ax25_dev;- ax25->source_addr = oax25->source_addr;-- if (oax25->digipeat != NULL) {- ax25->digipeat = kmemdup(oax25->digipeat, sizeof(ax25_digi),- GFP_ATOMIC);- if (ax25->digipeat == NULL) {- sk_free(sk);- ax25_cb_put(ax25);- return NULL;- }- }-- ax25_sk(sk)->cb = ax25;- sk->sk_destruct = ax25_free_sock;- ax25->sk = sk;-- return sk;-}--static int ax25_release(struct socket *sock)-{- struct sock *sk = sock->sk;- ax25_cb *ax25;- ax25_dev *ax25_dev;-- if (sk == NULL)- return 0;-- sock_hold(sk);- lock_sock(sk);- sock_orphan(sk);- ax25 = sk_to_ax25(sk);- ax25_dev = ax25->ax25_dev;-- if (sk->sk_type == SOCK_SEQPACKET) {- switch (ax25->state) {- case AX25_STATE_0:- if (!sock_flag(ax25->sk, SOCK_DEAD)) {- release_sock(sk);- ax25_disconnect(ax25, 0);- lock_sock(sk);- }- ax25_destroy_socket(ax25);- break;-- case AX25_STATE_1:- case AX25_STATE_2:- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- release_sock(sk);- ax25_disconnect(ax25, 0);- lock_sock(sk);- if (!sock_flag(ax25->sk, SOCK_DESTROY))- ax25_destroy_socket(ax25);- break;-- case AX25_STATE_3:- case AX25_STATE_4:- ax25_clear_queues(ax25);- ax25->n2count = 0;-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_send_control(ax25,- AX25_DISC,- AX25_POLLON,- AX25_COMMAND);- ax25_stop_t2timer(ax25);- ax25_stop_t3timer(ax25);- ax25_stop_idletimer(ax25);- break;-#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- ax25_stop_t3timer(ax25);- ax25_stop_idletimer(ax25);- break;-#endif- }- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);- ax25->state = AX25_STATE_2;- sk->sk_state = TCP_CLOSE;- sk->sk_shutdown |= SEND_SHUTDOWN;- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DESTROY);- break;-- default:- break;- }- } else {- sk->sk_state = TCP_CLOSE;- sk->sk_shutdown |= SEND_SHUTDOWN;- sk->sk_state_change(sk);- ax25_destroy_socket(ax25);- }- if (ax25_dev) {- if (!ax25_dev->device_up) {- timer_delete_sync(&ax25->timer);- timer_delete_sync(&ax25->t1timer);- timer_delete_sync(&ax25->t2timer);- timer_delete_sync(&ax25->t3timer);- timer_delete_sync(&ax25->idletimer);- }- netdev_put(ax25_dev->dev, &ax25->dev_tracker);- ax25_dev_put(ax25_dev);- }-- sock->sk = NULL;- release_sock(sk);- sock_put(sk);-- return 0;-}--/*- * We support a funny extension here so you can (as root) give any callsign- * digipeated via a local address as source. This hack is obsolete now- * that we've implemented support for SO_BINDTODEVICE. It is however small- * and trivially backward compatible.- */-static int ax25_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int addr_len)-{- struct sock *sk = sock->sk;- struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;- ax25_dev *ax25_dev = NULL;- ax25_uid_assoc *user;- ax25_address call;- ax25_cb *ax25;- int err = 0;-- if (addr_len != sizeof(struct sockaddr_ax25) &&- addr_len != sizeof(struct full_sockaddr_ax25))- /* support for old structure may go away some time- * ax25_bind(): uses old (6 digipeater) socket structure.- */- if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||- (addr_len > sizeof(struct full_sockaddr_ax25)))- return -EINVAL;-- if (addr->fsa_ax25.sax25_family != AF_AX25)- return -EINVAL;-- user = ax25_findbyuid(current_euid());- if (user) {- call = user->call;- ax25_uid_put(user);- } else {- if (ax25_uid_policy && !capable(CAP_NET_ADMIN))- return -EACCES;-- call = addr->fsa_ax25.sax25_call;- }-- lock_sock(sk);-- ax25 = sk_to_ax25(sk);- if (!sock_flag(sk, SOCK_ZAPPED)) {- err = -EINVAL;- goto out;- }-- ax25->source_addr = call;-- /*- * User already set interface with SO_BINDTODEVICE- */- if (ax25->ax25_dev != NULL)- goto done;-- if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) {- if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) != 0 &&- (ax25_dev = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL) {- err = -EADDRNOTAVAIL;- goto out;- }- } else {- if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) {- err = -EADDRNOTAVAIL;- goto out;- }- }-- if (ax25_dev) {- ax25_fillin_cb(ax25, ax25_dev);- netdev_hold(ax25_dev->dev, &ax25->dev_tracker, GFP_ATOMIC);- }--done:- ax25_cb_add(ax25);- sock_reset_flag(sk, SOCK_ZAPPED);--out:- release_sock(sk);-- return err;-}--/*- * FIXME: nonblock behaviour looks like it may have a bug.- */-static int __must_check ax25_connect(struct socket *sock,- struct sockaddr_unsized *uaddr, int addr_len, int flags)-{- struct sock *sk = sock->sk;- ax25_cb *ax25 = sk_to_ax25(sk), *ax25t;- struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;- ax25_digi *digi = NULL;- int ct = 0, err = 0;-- /*- * some sanity checks. code further down depends on this- */-- if (addr_len == sizeof(struct sockaddr_ax25))- /* support for this will go away in early 2.5.x- * ax25_connect(): uses obsolete socket structure- */- ;- else if (addr_len != sizeof(struct full_sockaddr_ax25))- /* support for old structure may go away some time- * ax25_connect(): uses old (6 digipeater) socket structure.- */- if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||- (addr_len > sizeof(struct full_sockaddr_ax25)))- return -EINVAL;--- if (fsa->fsa_ax25.sax25_family != AF_AX25)- return -EINVAL;-- lock_sock(sk);-- /* deal with restarts */- if (sock->state == SS_CONNECTING) {- switch (sk->sk_state) {- case TCP_SYN_SENT: /* still trying */- err = -EINPROGRESS;- goto out_release;-- case TCP_ESTABLISHED: /* connection established */- sock->state = SS_CONNECTED;- goto out_release;-- case TCP_CLOSE: /* connection refused */- sock->state = SS_UNCONNECTED;- err = -ECONNREFUSED;- goto out_release;- }- }-- if (sk->sk_state == TCP_ESTABLISHED && sk->sk_type == SOCK_SEQPACKET) {- err = -EISCONN; /* No reconnect on a seqpacket socket */- goto out_release;- }-- sk->sk_state = TCP_CLOSE;- sock->state = SS_UNCONNECTED;-- kfree(ax25->digipeat);- ax25->digipeat = NULL;-- /*- * Handle digi-peaters to be used.- */- if (addr_len > sizeof(struct sockaddr_ax25) &&- fsa->fsa_ax25.sax25_ndigis != 0) {- /* Valid number of digipeaters ? */- if (fsa->fsa_ax25.sax25_ndigis < 1 ||- fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS ||- addr_len < sizeof(struct sockaddr_ax25) +- sizeof(ax25_address) * fsa->fsa_ax25.sax25_ndigis) {- err = -EINVAL;- goto out_release;- }-- if ((digi = kmalloc_obj(ax25_digi)) == NULL) {- err = -ENOBUFS;- goto out_release;- }-- digi->ndigi = fsa->fsa_ax25.sax25_ndigis;- digi->lastrepeat = -1;-- while (ct < fsa->fsa_ax25.sax25_ndigis) {- if ((fsa->fsa_digipeater[ct].ax25_call[6] &- AX25_HBIT) && ax25->iamdigi) {- digi->repeated[ct] = 1;- digi->lastrepeat = ct;- } else {- digi->repeated[ct] = 0;- }- digi->calls[ct] = fsa->fsa_digipeater[ct];- ct++;- }- }-- /* Must bind first - autobinding does not work. */- if (sock_flag(sk, SOCK_ZAPPED)) {- kfree(digi);- err = -EINVAL;- goto out_release;- }-- /* Check to see if the device has been filled in, error if it hasn't. */- if (ax25->ax25_dev == NULL) {- kfree(digi);- err = -EHOSTUNREACH;- goto out_release;- }-- if (sk->sk_type == SOCK_SEQPACKET &&- (ax25t=ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,- ax25->ax25_dev->dev))) {- kfree(digi);- err = -EADDRINUSE; /* Already such a connection */- ax25_cb_put(ax25t);- goto out_release;- }-- ax25->dest_addr = fsa->fsa_ax25.sax25_call;- ax25->digipeat = digi;-- /* First the easy one */- if (sk->sk_type != SOCK_SEQPACKET) {- sock->state = SS_CONNECTED;- sk->sk_state = TCP_ESTABLISHED;- goto out_release;- }-- /* Move to connecting socket, ax.25 lapb WAIT_UA.. */- sock->state = SS_CONNECTING;- sk->sk_state = TCP_SYN_SENT;-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_std_establish_data_link(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- if (ax25->ax25_dev->dama.slave)- ax25_ds_establish_data_link(ax25);- else- ax25_std_establish_data_link(ax25);- break;-#endif- }-- ax25->state = AX25_STATE_1;-- ax25_start_heartbeat(ax25);-- /* Now the loop */- if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {- err = -EINPROGRESS;- goto out_release;- }-- if (sk->sk_state == TCP_SYN_SENT) {- DEFINE_WAIT(wait);-- for (;;) {- prepare_to_wait(sk_sleep(sk), &wait,- TASK_INTERRUPTIBLE);- if (sk->sk_state != TCP_SYN_SENT)- break;- if (!signal_pending(current)) {- release_sock(sk);- schedule();- lock_sock(sk);- continue;- }- err = -ERESTARTSYS;- break;- }- finish_wait(sk_sleep(sk), &wait);-- if (err)- goto out_release;- }-- if (sk->sk_state != TCP_ESTABLISHED) {- /* Not in ABM, not in WAIT_UA -> failed */- sock->state = SS_UNCONNECTED;- err = sock_error(sk); /* Always set at this point */- goto out_release;- }-- sock->state = SS_CONNECTED;-- err = 0;-out_release:- release_sock(sk);-- return err;-}--static int ax25_accept(struct socket *sock, struct socket *newsock,- struct proto_accept_arg *arg)-{- struct sk_buff *skb;- struct sock *newsk;- ax25_dev *ax25_dev;- DEFINE_WAIT(wait);- struct sock *sk;- ax25_cb *ax25;- int err = 0;-- if (sock->state != SS_UNCONNECTED)- return -EINVAL;-- if ((sk = sock->sk) == NULL)- return -EINVAL;-- lock_sock(sk);- if (sk->sk_type != SOCK_SEQPACKET) {- err = -EOPNOTSUPP;- goto out;- }-- if (sk->sk_state != TCP_LISTEN) {- err = -EINVAL;- goto out;- }-- /*- * The read queue this time is holding sockets ready to use- * hooked into the SABM we saved- */- for (;;) {- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);- skb = skb_dequeue(&sk->sk_receive_queue);- if (skb)- break;-- if (arg->flags & O_NONBLOCK) {- err = -EWOULDBLOCK;- break;- }- if (!signal_pending(current)) {- release_sock(sk);- schedule();- lock_sock(sk);- continue;- }- err = -ERESTARTSYS;- break;- }- finish_wait(sk_sleep(sk), &wait);-- if (err)- goto out;-- newsk = skb->sk;- sock_graft(newsk, newsock);-- /* Now attach up the new socket */- kfree_skb(skb);- sk_acceptq_removed(sk);- newsock->state = SS_CONNECTED;- ax25 = sk_to_ax25(newsk);- ax25_dev = ax25->ax25_dev;- netdev_hold(ax25_dev->dev, &ax25->dev_tracker, GFP_ATOMIC);- ax25_dev_hold(ax25_dev);--out:- release_sock(sk);-- return err;-}--static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,- int peer)-{- struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;- struct sock *sk = sock->sk;- unsigned char ndigi, i;- ax25_cb *ax25;- int err = 0;-- memset(fsa, 0, sizeof(*fsa));- lock_sock(sk);- ax25 = sk_to_ax25(sk);-- if (peer != 0) {- if (sk->sk_state != TCP_ESTABLISHED) {- err = -ENOTCONN;- goto out;- }-- fsa->fsa_ax25.sax25_family = AF_AX25;- fsa->fsa_ax25.sax25_call = ax25->dest_addr;-- if (ax25->digipeat != NULL) {- ndigi = ax25->digipeat->ndigi;- fsa->fsa_ax25.sax25_ndigis = ndigi;- for (i = 0; i < ndigi; i++)- fsa->fsa_digipeater[i] =- ax25->digipeat->calls[i];- }- } else {- fsa->fsa_ax25.sax25_family = AF_AX25;- fsa->fsa_ax25.sax25_call = ax25->source_addr;- fsa->fsa_ax25.sax25_ndigis = 1;- if (ax25->ax25_dev != NULL) {- memcpy(&fsa->fsa_digipeater[0],- ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN);- } else {- fsa->fsa_digipeater[0] = null_ax25_address;- }- }- err = sizeof (struct full_sockaddr_ax25);--out:- release_sock(sk);-- return err;-}--static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)-{- DECLARE_SOCKADDR(struct sockaddr_ax25 *, usax, msg->msg_name);- struct sock *sk = sock->sk;- struct sockaddr_ax25 sax;- struct sk_buff *skb;- ax25_digi dtmp, *dp;- ax25_cb *ax25;- size_t size;- int lv, err, addr_len = msg->msg_namelen;-- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))- return -EINVAL;-- lock_sock(sk);- ax25 = sk_to_ax25(sk);-- if (sock_flag(sk, SOCK_ZAPPED)) {- err = -EADDRNOTAVAIL;- goto out;- }-- if (sk->sk_shutdown & SEND_SHUTDOWN) {- send_sig(SIGPIPE, current, 0);- err = -EPIPE;- goto out;- }-- if (ax25->ax25_dev == NULL) {- err = -ENETUNREACH;- goto out;- }-- if (len > ax25->ax25_dev->dev->mtu) {- err = -EMSGSIZE;- goto out;- }-- if (usax != NULL) {- if (usax->sax25_family != AF_AX25) {- err = -EINVAL;- goto out;- }-- if (addr_len == sizeof(struct sockaddr_ax25))- /* ax25_sendmsg(): uses obsolete socket structure */- ;- else if (addr_len != sizeof(struct full_sockaddr_ax25))- /* support for old structure may go away some time- * ax25_sendmsg(): uses old (6 digipeater)- * socket structure.- */- if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||- (addr_len > sizeof(struct full_sockaddr_ax25))) {- err = -EINVAL;- goto out;- }--- if (addr_len > sizeof(struct sockaddr_ax25) && usax->sax25_ndigis != 0) {- int ct = 0;- struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax;-- /* Valid number of digipeaters ? */- if (usax->sax25_ndigis < 1 ||- usax->sax25_ndigis > AX25_MAX_DIGIS ||- addr_len < sizeof(struct sockaddr_ax25) +- sizeof(ax25_address) * usax->sax25_ndigis) {- err = -EINVAL;- goto out;- }-- dtmp.ndigi = usax->sax25_ndigis;-- while (ct < usax->sax25_ndigis) {- dtmp.repeated[ct] = 0;- dtmp.calls[ct] = fsa->fsa_digipeater[ct];- ct++;- }-- dtmp.lastrepeat = 0;- }-- sax = *usax;- if (sk->sk_type == SOCK_SEQPACKET &&- ax25cmp(&ax25->dest_addr, &sax.sax25_call)) {- err = -EISCONN;- goto out;- }- if (usax->sax25_ndigis == 0)- dp = NULL;- else- dp = &dtmp;- } else {- /*- * FIXME: 1003.1g - if the socket is like this because- * it has become closed (not started closed) and is VC- * we ought to SIGPIPE, EPIPE- */- if (sk->sk_state != TCP_ESTABLISHED) {- err = -ENOTCONN;- goto out;- }- sax.sax25_family = AF_AX25;- sax.sax25_call = ax25->dest_addr;- dp = ax25->digipeat;- }-- /* Build a packet */- /* Assume the worst case */- size = len + ax25->ax25_dev->dev->hard_header_len;-- skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT, &err);- if (skb == NULL)- goto out;-- skb_reserve(skb, size - len);-- /* User data follows immediately after the AX.25 data */- if (memcpy_from_msg(skb_put(skb, len), msg, len)) {- err = -EFAULT;- kfree_skb(skb);- goto out;- }-- skb_reset_network_header(skb);-- /* Add the PID if one is not supplied by the user in the skb */- if (!ax25->pidincl)- *(u8 *)skb_push(skb, 1) = sk->sk_protocol;-- if (sk->sk_type == SOCK_SEQPACKET) {- /* Connected mode sockets go via the LAPB machine */- if (sk->sk_state != TCP_ESTABLISHED) {- kfree_skb(skb);- err = -ENOTCONN;- goto out;- }-- /* Shove it onto the queue and kick */- ax25_output(ax25, ax25->paclen, skb);-- err = len;- goto out;- }-- skb_push(skb, 1 + ax25_addr_size(dp));-- /* Building AX.25 Header */-- /* Build an AX.25 header */- lv = ax25_addr_build(skb->data, &ax25->source_addr, &sax.sax25_call,- dp, AX25_COMMAND, AX25_MODULUS);-- skb_set_transport_header(skb, lv);-- *skb_transport_header(skb) = AX25_UI;-- /* Datagram frames go straight out of the door as UI */- ax25_queue_xmit(skb, ax25->ax25_dev->dev);-- err = len;--out:- release_sock(sk);-- return err;-}--static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,- int flags)-{- struct sock *sk = sock->sk;- struct sk_buff *skb, *last;- struct sk_buff_head *sk_queue;- int copied;- int err = 0;- int off = 0;- long timeo;-- lock_sock(sk);- /*- * This works for seqpacket too. The receiver has ordered the- * queue for us! We do one quick check first though- */- if (sk->sk_type == SOCK_SEQPACKET && sk->sk_state != TCP_ESTABLISHED) {- err = -ENOTCONN;- goto out;- }-- /* We need support for non-blocking reads. */- sk_queue = &sk->sk_receive_queue;- skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off, &err, &last);- /* If no packet is available, release_sock(sk) and try again. */- if (!skb) {- if (err != -EAGAIN)- goto out;- release_sock(sk);- timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);- while (timeo && !__skb_wait_for_more_packets(sk, sk_queue, &err,- &timeo, last)) {- skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off,- &err, &last);- if (skb)- break;-- if (err != -EAGAIN)- goto done;- }- if (!skb)- goto done;- lock_sock(sk);- }-- if (!sk_to_ax25(sk)->pidincl)- skb_pull(skb, 1); /* Remove PID */-- skb_reset_transport_header(skb);- copied = skb->len;-- if (copied > size) {- copied = size;- msg->msg_flags |= MSG_TRUNC;- }-- skb_copy_datagram_msg(skb, 0, msg, copied);-- if (msg->msg_name) {- ax25_digi digi;- ax25_address src;- const unsigned char *mac = skb_mac_header(skb);- DECLARE_SOCKADDR(struct sockaddr_ax25 *, sax, msg->msg_name);-- memset(sax, 0, sizeof(struct full_sockaddr_ax25));- ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,- &digi, NULL, NULL);- sax->sax25_family = AF_AX25;- /* We set this correctly, even though we may not let the- application know the digi calls further down (because it- did NOT ask to know them). This could get political... **/- sax->sax25_ndigis = digi.ndigi;- sax->sax25_call = src;-- if (sax->sax25_ndigis != 0) {- int ct;- struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)sax;-- for (ct = 0; ct < digi.ndigi; ct++)- fsa->fsa_digipeater[ct] = digi.calls[ct];- }- msg->msg_namelen = sizeof(struct full_sockaddr_ax25);- }-- skb_free_datagram(sk, skb);- err = copied;--out:- release_sock(sk);--done:- return err;-}--static int ax25_shutdown(struct socket *sk, int how)-{- /* FIXME - generate DM and RNR states */- return -EOPNOTSUPP;-}--static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)-{- struct sock *sk = sock->sk;- void __user *argp = (void __user *)arg;- int res = 0;-- lock_sock(sk);- switch (cmd) {- case TIOCOUTQ: {- long amount;-- amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);- if (amount < 0)- amount = 0;- res = put_user(amount, (int __user *)argp);- break;- }-- case TIOCINQ: {- struct sk_buff *skb;- long amount = 0L;- /* These two are safe on a single CPU system as only user tasks fiddle here */- if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)- amount = skb->len;- res = put_user(amount, (int __user *) argp);- break;- }-- case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */- case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */- case SIOCAX25GETUID: {- struct sockaddr_ax25 sax25;- if (copy_from_user(&sax25, argp, sizeof(sax25))) {- res = -EFAULT;- break;- }- res = ax25_uid_ioctl(cmd, &sax25);- break;- }-- case SIOCAX25NOUID: { /* Set the default policy (default/bar) */- long amount;- if (!capable(CAP_NET_ADMIN)) {- res = -EPERM;- break;- }- if (get_user(amount, (long __user *)argp)) {- res = -EFAULT;- break;- }- if (amount < 0 || amount > AX25_NOUID_BLOCK) {- res = -EINVAL;- break;- }- ax25_uid_policy = amount;- res = 0;- break;- }-- case SIOCADDRT:- case SIOCDELRT:- case SIOCAX25OPTRT:- if (!capable(CAP_NET_ADMIN)) {- res = -EPERM;- break;- }- res = ax25_rt_ioctl(cmd, argp);- break;-- case SIOCAX25CTLCON:- if (!capable(CAP_NET_ADMIN)) {- res = -EPERM;- break;- }- res = ax25_ctl_ioctl(cmd, argp);- break;-- case SIOCAX25GETINFO:- case SIOCAX25GETINFOOLD: {- ax25_cb *ax25 = sk_to_ax25(sk);- struct ax25_info_struct ax25_info;-- ax25_info.t1 = ax25->t1 / HZ;- ax25_info.t2 = ax25->t2 / HZ;- ax25_info.t3 = ax25->t3 / HZ;- ax25_info.idle = ax25->idle / (60 * HZ);- ax25_info.n2 = ax25->n2;- ax25_info.t1timer = ax25_display_timer(&ax25->t1timer) / HZ;- ax25_info.t2timer = ax25_display_timer(&ax25->t2timer) / HZ;- ax25_info.t3timer = ax25_display_timer(&ax25->t3timer) / HZ;- ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);- ax25_info.n2count = ax25->n2count;- ax25_info.state = ax25->state;- ax25_info.rcv_q = sk_rmem_alloc_get(sk);- ax25_info.snd_q = sk_wmem_alloc_get(sk);- ax25_info.vs = ax25->vs;- ax25_info.vr = ax25->vr;- ax25_info.va = ax25->va;- ax25_info.vs_max = ax25->vs; /* reserved */- ax25_info.paclen = ax25->paclen;- ax25_info.window = ax25->window;-- /* old structure? */- if (cmd == SIOCAX25GETINFOOLD) {- static int warned = 0;- if (!warned) {- printk(KERN_INFO "%s uses old SIOCAX25GETINFO\n",- current->comm);- warned=1;- }-- if (copy_to_user(argp, &ax25_info, sizeof(struct ax25_info_struct_deprecated))) {- res = -EFAULT;- break;- }- } else {- if (copy_to_user(argp, &ax25_info, sizeof(struct ax25_info_struct))) {- res = -EINVAL;- break;- }- }- res = 0;- break;- }-- case SIOCAX25ADDFWD:- case SIOCAX25DELFWD: {- struct ax25_fwd_struct ax25_fwd;- if (!capable(CAP_NET_ADMIN)) {- res = -EPERM;- break;- }- if (copy_from_user(&ax25_fwd, argp, sizeof(ax25_fwd))) {- res = -EFAULT;- break;- }- res = ax25_fwd_ioctl(cmd, &ax25_fwd);- break;- }-- case SIOCGIFADDR:- case SIOCSIFADDR:- case SIOCGIFDSTADDR:- case SIOCSIFDSTADDR:- case SIOCGIFBRDADDR:- case SIOCSIFBRDADDR:- case SIOCGIFNETMASK:- case SIOCSIFNETMASK:- case SIOCGIFMETRIC:- case SIOCSIFMETRIC:- res = -EINVAL;- break;-- default:- res = -ENOIOCTLCMD;- break;- }- release_sock(sk);-- return res;-}--#ifdef CONFIG_PROC_FS--static void *ax25_info_start(struct seq_file *seq, loff_t *pos)- __acquires(ax25_list_lock)-{- spin_lock_bh(&ax25_list_lock);- return seq_hlist_start(&ax25_list, *pos);-}--static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos)-{- return seq_hlist_next(v, &ax25_list, pos);-}--static void ax25_info_stop(struct seq_file *seq, void *v)- __releases(ax25_list_lock)-{- spin_unlock_bh(&ax25_list_lock);-}--static int ax25_info_show(struct seq_file *seq, void *v)-{- ax25_cb *ax25 = hlist_entry(v, struct ax25_cb, ax25_node);- char buf[11];- int k;--- /*- * New format:- * magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 t2 t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q inode- */-- seq_printf(seq, "%p %s %s%s ",- ax25,- ax25->ax25_dev == NULL? "???" : ax25->ax25_dev->dev->name,- ax2asc(buf, &ax25->source_addr),- ax25->iamdigi? "*":"");- seq_printf(seq, "%s", ax2asc(buf, &ax25->dest_addr));-- for (k=0; (ax25->digipeat != NULL) && (k < ax25->digipeat->ndigi); k++) {- seq_printf(seq, ",%s%s",- ax2asc(buf, &ax25->digipeat->calls[k]),- ax25->digipeat->repeated[k]? "*":"");- }-- seq_printf(seq, " %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %d %d",- ax25->state,- ax25->vs, ax25->vr, ax25->va,- ax25_display_timer(&ax25->t1timer) / HZ, ax25->t1 / HZ,- ax25_display_timer(&ax25->t2timer) / HZ, ax25->t2 / HZ,- ax25_display_timer(&ax25->t3timer) / HZ, ax25->t3 / HZ,- ax25_display_timer(&ax25->idletimer) / (60 * HZ),- ax25->idle / (60 * HZ),- ax25->n2count, ax25->n2,- ax25->rtt / HZ,- ax25->window,- ax25->paclen);-- if (ax25->sk != NULL) {- seq_printf(seq, " %d %d %llu\n",- sk_wmem_alloc_get(ax25->sk),- sk_rmem_alloc_get(ax25->sk),- sock_i_ino(ax25->sk));- } else {- seq_puts(seq, " * * *\n");- }- return 0;-}--static const struct seq_operations ax25_info_seqops = {- .start = ax25_info_start,- .next = ax25_info_next,- .stop = ax25_info_stop,- .show = ax25_info_show,-};-#endif--static const struct net_proto_family ax25_family_ops = {- .family = PF_AX25,- .create = ax25_create,- .owner = THIS_MODULE,-};--static const struct proto_ops ax25_proto_ops = {- .family = PF_AX25,- .owner = THIS_MODULE,- .release = ax25_release,- .bind = ax25_bind,- .connect = ax25_connect,- .socketpair = sock_no_socketpair,- .accept = ax25_accept,- .getname = ax25_getname,- .poll = datagram_poll,- .ioctl = ax25_ioctl,- .gettstamp = sock_gettstamp,- .listen = ax25_listen,- .shutdown = ax25_shutdown,- .setsockopt = ax25_setsockopt,- .getsockopt = ax25_getsockopt,- .sendmsg = ax25_sendmsg,- .recvmsg = ax25_recvmsg,- .mmap = sock_no_mmap,-};--/*- * Called by socket.c on kernel start up- */-static struct packet_type ax25_packet_type __read_mostly = {- .type = cpu_to_be16(ETH_P_AX25),- .func = ax25_kiss_rcv,-};--static struct notifier_block ax25_dev_notifier = {- .notifier_call = ax25_device_event,-};--static int __init ax25_init(void)-{- int rc = proto_register(&ax25_proto, 0);-- if (rc != 0)- goto out;-- sock_register(&ax25_family_ops);- dev_add_pack(&ax25_packet_type);- register_netdevice_notifier(&ax25_dev_notifier);-- proc_create_seq("ax25_route", 0444, init_net.proc_net, &ax25_rt_seqops);- proc_create_seq("ax25", 0444, init_net.proc_net, &ax25_info_seqops);- proc_create_seq("ax25_calls", 0444, init_net.proc_net,- &ax25_uid_seqops);-out:- return rc;-}-module_init(ax25_init);---MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");-MODULE_DESCRIPTION("The amateur radio AX.25 link layer protocol");-MODULE_LICENSE("GPL");-MODULE_ALIAS_NETPROTO(PF_AX25);--static void __exit ax25_exit(void)-{- remove_proc_entry("ax25_route", init_net.proc_net);- remove_proc_entry("ax25", init_net.proc_net);- remove_proc_entry("ax25_calls", init_net.proc_net);-- unregister_netdevice_notifier(&ax25_dev_notifier);-- dev_remove_pack(&ax25_packet_type);-- sock_unregister(PF_AX25);- proto_unregister(&ax25_proto);-- ax25_rt_free();- ax25_uid_free();- ax25_dev_free();-}-module_exit(ax25_exit);diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.cdeleted file mode 100644index f68865a4d0ab..000000000000--- a/net/ax25/ax25_addr.c+++ /dev/null@@ -1,303 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/module.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--/*- * The default broadcast address of an interface is QST-0; the default address- * is LINUX-1. The null address is defined as a callsign of all spaces with- * an SSID of zero.- */--const ax25_address ax25_bcast =- {{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};-const ax25_address ax25_defaddr =- {{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, 1 << 1}};-const ax25_address null_ax25_address =- {{' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};--EXPORT_SYMBOL_GPL(ax25_bcast);-EXPORT_SYMBOL_GPL(ax25_defaddr);-EXPORT_SYMBOL(null_ax25_address);--/*- * ax25 -> ascii conversion- */-char *ax2asc(char *buf, const ax25_address *a)-{- char c, *s;- int n;-- for (n = 0, s = buf; n < 6; n++) {- c = (a->ax25_call[n] >> 1) & 0x7F;-- if (c != ' ') *s++ = c;- }-- *s++ = '-';-- if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {- *s++ = '1';- n -= 10;- }-- *s++ = n + '0';- *s++ = '\0';-- if (*buf == '\0' || *buf == '-')- return "*";-- return buf;--}--EXPORT_SYMBOL(ax2asc);--/*- * ascii -> ax25 conversion- */-void asc2ax(ax25_address *addr, const char *callsign)-{- const char *s;- int n;-- for (s = callsign, n = 0; n < 6; n++) {- if (*s != '\0' && *s != '-')- addr->ax25_call[n] = *s++;- else- addr->ax25_call[n] = ' ';- addr->ax25_call[n] <<= 1;- addr->ax25_call[n] &= 0xFE;- }-- if (*s++ == '\0') {- addr->ax25_call[6] = 0x00;- return;- }-- addr->ax25_call[6] = *s++ - '0';-- if (*s != '\0') {- addr->ax25_call[6] *= 10;- addr->ax25_call[6] += *s++ - '0';- }-- addr->ax25_call[6] <<= 1;- addr->ax25_call[6] &= 0x1E;-}--EXPORT_SYMBOL(asc2ax);--/*- * Compare two ax.25 addresses- */-int ax25cmp(const ax25_address *a, const ax25_address *b)-{- int ct = 0;-- while (ct < 6) {- if ((a->ax25_call[ct] & 0xFE) != (b->ax25_call[ct] & 0xFE)) /* Clean off repeater bits */- return 1;- ct++;- }-- if ((a->ax25_call[ct] & 0x1E) == (b->ax25_call[ct] & 0x1E)) /* SSID without control bit */- return 0;-- return 2; /* Partial match */-}--EXPORT_SYMBOL(ax25cmp);--/*- * Compare two AX.25 digipeater paths.- */-int ax25digicmp(const ax25_digi *digi1, const ax25_digi *digi2)-{- int i;-- if (digi1->ndigi != digi2->ndigi)- return 1;-- if (digi1->lastrepeat != digi2->lastrepeat)- return 1;-- for (i = 0; i < digi1->ndigi; i++)- if (ax25cmp(&digi1->calls[i], &digi2->calls[i]) != 0)- return 1;-- return 0;-}--/*- * Given an AX.25 address pull of to, from, digi list, command/response and the start of data- *- */-const unsigned char *ax25_addr_parse(const unsigned char *buf, int len,- ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags,- int *dama)-{- int d = 0;-- if (len < 14) return NULL;-- if (flags != NULL) {- *flags = 0;-- if (buf[6] & AX25_CBIT)- *flags = AX25_COMMAND;- if (buf[13] & AX25_CBIT)- *flags = AX25_RESPONSE;- }-- if (dama != NULL)- *dama = ~buf[13] & AX25_DAMA_FLAG;-- /* Copy to, from */- if (dest != NULL)- memcpy(dest, buf + 0, AX25_ADDR_LEN);- if (src != NULL)- memcpy(src, buf + 7, AX25_ADDR_LEN);-- buf += 2 * AX25_ADDR_LEN;- len -= 2 * AX25_ADDR_LEN;-- digi->lastrepeat = -1;- digi->ndigi = 0;-- while (!(buf[-1] & AX25_EBIT)) {- if (d >= AX25_MAX_DIGIS)- return NULL;- if (len < AX25_ADDR_LEN)- return NULL;-- memcpy(&digi->calls[d], buf, AX25_ADDR_LEN);- digi->ndigi = d + 1;-- if (buf[6] & AX25_HBIT) {- digi->repeated[d] = 1;- digi->lastrepeat = d;- } else {- digi->repeated[d] = 0;- }-- buf += AX25_ADDR_LEN;- len -= AX25_ADDR_LEN;- d++;- }-- return buf;-}--/*- * Assemble an AX.25 header from the bits- */-int ax25_addr_build(unsigned char *buf, const ax25_address *src,- const ax25_address *dest, const ax25_digi *d, int flag, int modulus)-{- int len = 0;- int ct = 0;-- memcpy(buf, dest, AX25_ADDR_LEN);- buf[6] &= ~(AX25_EBIT | AX25_CBIT);- buf[6] |= AX25_SSSID_SPARE;-- if (flag == AX25_COMMAND) buf[6] |= AX25_CBIT;-- buf += AX25_ADDR_LEN;- len += AX25_ADDR_LEN;-- memcpy(buf, src, AX25_ADDR_LEN);- buf[6] &= ~(AX25_EBIT | AX25_CBIT);- buf[6] &= ~AX25_SSSID_SPARE;-- if (modulus == AX25_MODULUS)- buf[6] |= AX25_SSSID_SPARE;- else- buf[6] |= AX25_ESSID_SPARE;-- if (flag == AX25_RESPONSE) buf[6] |= AX25_CBIT;-- /*- * Fast path the normal digiless path- */- if (d == NULL || d->ndigi == 0) {- buf[6] |= AX25_EBIT;- return 2 * AX25_ADDR_LEN;- }-- buf += AX25_ADDR_LEN;- len += AX25_ADDR_LEN;-- while (ct < d->ndigi) {- memcpy(buf, &d->calls[ct], AX25_ADDR_LEN);-- if (d->repeated[ct])- buf[6] |= AX25_HBIT;- else- buf[6] &= ~AX25_HBIT;-- buf[6] &= ~AX25_EBIT;- buf[6] |= AX25_SSSID_SPARE;-- buf += AX25_ADDR_LEN;- len += AX25_ADDR_LEN;- ct++;- }-- buf[-1] |= AX25_EBIT;-- return len;-}--int ax25_addr_size(const ax25_digi *dp)-{- if (dp == NULL)- return 2 * AX25_ADDR_LEN;-- return AX25_ADDR_LEN * (2 + dp->ndigi);-}--/*- * Reverse Digipeat List. May not pass both parameters as same struct- */-void ax25_digi_invert(const ax25_digi *in, ax25_digi *out)-{- int ct;-- out->ndigi = in->ndigi;- out->lastrepeat = in->ndigi - in->lastrepeat - 2;-- /* Invert the digipeaters */- for (ct = 0; ct < in->ndigi; ct++) {- out->calls[ct] = in->calls[in->ndigi - ct - 1];-- if (ct <= out->lastrepeat) {- out->calls[ct].ax25_call[6] |= AX25_HBIT;- out->repeated[ct] = 1;- } else {- out->calls[ct].ax25_call[6] &= ~AX25_HBIT;- out->repeated[ct] = 0;- }- }-}diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.cdeleted file mode 100644index 3c0544fc4ad5..000000000000--- a/net/ax25/ax25_dev.c+++ /dev/null@@ -1,200 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/slab.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/spinlock.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/list.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/init.h>--static LIST_HEAD(ax25_dev_list);-DEFINE_SPINLOCK(ax25_dev_lock);--ax25_dev *ax25_addr_ax25dev(ax25_address *addr)-{- ax25_dev *ax25_dev, *res = NULL;-- spin_lock_bh(&ax25_dev_lock);- list_for_each_entry(ax25_dev, &ax25_dev_list, list)- if (ax25cmp(addr, (const ax25_address *)ax25_dev->dev->dev_addr) == 0) {- res = ax25_dev;- ax25_dev_hold(ax25_dev);- break;- }- spin_unlock_bh(&ax25_dev_lock);-- return res;-}--/*- * This is called when an interface is brought up. These are- * reasonable defaults.- */-void ax25_dev_device_up(struct net_device *dev)-{- ax25_dev *ax25_dev;-- ax25_dev = kzalloc_obj(*ax25_dev);- if (!ax25_dev) {- printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");- return;- }-- refcount_set(&ax25_dev->refcount, 1);- ax25_dev->dev = dev;- netdev_hold(dev, &ax25_dev->dev_tracker, GFP_KERNEL);- ax25_dev->forward = NULL;- ax25_dev->device_up = true;-- ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;- ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;- ax25_dev->values[AX25_VALUES_BACKOFF] = AX25_DEF_BACKOFF;- ax25_dev->values[AX25_VALUES_CONMODE] = AX25_DEF_CONMODE;- ax25_dev->values[AX25_VALUES_WINDOW] = AX25_DEF_WINDOW;- ax25_dev->values[AX25_VALUES_EWINDOW] = AX25_DEF_EWINDOW;- ax25_dev->values[AX25_VALUES_T1] = AX25_DEF_T1;- ax25_dev->values[AX25_VALUES_T2] = AX25_DEF_T2;- ax25_dev->values[AX25_VALUES_T3] = AX25_DEF_T3;- ax25_dev->values[AX25_VALUES_IDLE] = AX25_DEF_IDLE;- ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2;- ax25_dev->values[AX25_VALUES_PACLEN] = AX25_DEF_PACLEN;- ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL;--#ifdef CONFIG_AX25_DAMA_SLAVE- ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;-- ax25_ds_setup_timer(ax25_dev);-#endif-- spin_lock_bh(&ax25_dev_lock);- list_add(&ax25_dev->list, &ax25_dev_list);- rcu_assign_pointer(dev->ax25_ptr, ax25_dev);- spin_unlock_bh(&ax25_dev_lock);-- ax25_register_dev_sysctl(ax25_dev);-}--void ax25_dev_device_down(struct net_device *dev)-{- ax25_dev *s, *ax25_dev;-- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)- return;-- ax25_unregister_dev_sysctl(ax25_dev);-- spin_lock_bh(&ax25_dev_lock);--#ifdef CONFIG_AX25_DAMA_SLAVE- timer_shutdown_sync(&ax25_dev->dama.slave_timer);-#endif-- /*- * Remove any packet forwarding that points to this device.- */- list_for_each_entry(s, &ax25_dev_list, list)- if (s->forward == dev)- s->forward = NULL;-- list_for_each_entry(s, &ax25_dev_list, list) {- if (s == ax25_dev) {- list_del(&s->list);- break;- }- }-- RCU_INIT_POINTER(dev->ax25_ptr, NULL);- spin_unlock_bh(&ax25_dev_lock);- netdev_put(dev, &ax25_dev->dev_tracker);- ax25_dev_put(ax25_dev);-}--int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)-{- ax25_dev *ax25_dev, *fwd_dev;-- if ((ax25_dev = ax25_addr_ax25dev(&fwd->port_from)) == NULL)- return -EINVAL;-- switch (cmd) {- case SIOCAX25ADDFWD:- fwd_dev = ax25_addr_ax25dev(&fwd->port_to);- if (!fwd_dev) {- ax25_dev_put(ax25_dev);- return -EINVAL;- }- if (ax25_dev->forward) {- ax25_dev_put(fwd_dev);- ax25_dev_put(ax25_dev);- return -EINVAL;- }- ax25_dev->forward = fwd_dev->dev;- ax25_dev_put(fwd_dev);- ax25_dev_put(ax25_dev);- break;-- case SIOCAX25DELFWD:- if (!ax25_dev->forward) {- ax25_dev_put(ax25_dev);- return -EINVAL;- }- ax25_dev->forward = NULL;- ax25_dev_put(ax25_dev);- break;-- default:- ax25_dev_put(ax25_dev);- return -EINVAL;- }-- return 0;-}--struct net_device *ax25_fwd_dev(struct net_device *dev)-{- ax25_dev *ax25_dev;-- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)- return dev;-- if (ax25_dev->forward == NULL)- return dev;-- return ax25_dev->forward;-}--/*- * Free all memory associated with device structures.- */-void __exit ax25_dev_free(void)-{- ax25_dev *s, *n;-- spin_lock_bh(&ax25_dev_lock);- list_for_each_entry_safe(s, n, &ax25_dev_list, list) {- netdev_put(s->dev, &s->dev_tracker);- list_del(&s->list);- ax25_dev_put(s);- }- spin_unlock_bh(&ax25_dev_lock);-}diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.cdeleted file mode 100644index c62f8fb06189..000000000000--- a/net/ax25/ax25_ds_in.c+++ /dev/null@@ -1,298 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--/*- * State machine for state 1, Awaiting Connection State.- * The handling of the timer(s) is in file ax25_ds_timer.c.- * Handling of state 0 and connection release is in ax25.c.- */-static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)-{- switch (frametype) {- case AX25_SABM:- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- break;-- case AX25_SABME:- ax25->modulus = AX25_EMODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- break;-- case AX25_DISC:- ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);- break;-- case AX25_UA:- ax25_calculate_rtt(ax25);- ax25_stop_t1timer(ax25);- ax25_start_t3timer(ax25);- ax25_start_idletimer(ax25);- ax25->vs = 0;- ax25->va = 0;- ax25->vr = 0;- ax25->state = AX25_STATE_3;- ax25->n2count = 0;- if (ax25->sk != NULL) {- bh_lock_sock(ax25->sk);- ax25->sk->sk_state = TCP_ESTABLISHED;- /*- * For WAIT_SABM connections we will produce an accept- * ready socket here- */- if (!sock_flag(ax25->sk, SOCK_DEAD))- ax25->sk->sk_state_change(ax25->sk);- bh_unlock_sock(ax25->sk);- }- ax25_dama_on(ax25);-- /* according to DK4EG's spec we are required to- * send a RR RESPONSE FINAL NR=0.- */-- ax25_std_enquiry_response(ax25);- break;-- case AX25_DM:- if (pf)- ax25_disconnect(ax25, ECONNREFUSED);- break;-- default:- if (pf)- ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);- break;- }-- return 0;-}--/*- * State machine for state 2, Awaiting Release State.- * The handling of the timer(s) is in file ax25_ds_timer.c- * Handling of state 0 and connection release is in ax25.c.- */-static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)-{- switch (frametype) {- case AX25_SABM:- case AX25_SABME:- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- ax25_dama_off(ax25);- break;-- case AX25_DISC:- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_dama_off(ax25);- ax25_disconnect(ax25, 0);- break;-- case AX25_DM:- case AX25_UA:- if (pf) {- ax25_dama_off(ax25);- ax25_disconnect(ax25, 0);- }- break;-- case AX25_I:- case AX25_REJ:- case AX25_RNR:- case AX25_RR:- if (pf) {- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- ax25_dama_off(ax25);- }- break;-- default:- break;- }-- return 0;-}--/*- * State machine for state 3, Connected State.- * The handling of the timer(s) is in file ax25_timer.c- * Handling of state 0 and connection release is in ax25.c.- */-static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)-{- int queued = 0;-- switch (frametype) {- case AX25_SABM:- case AX25_SABME:- if (frametype == AX25_SABM) {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- } else {- ax25->modulus = AX25_EMODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];- }- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_stop_t1timer(ax25);- ax25_start_t3timer(ax25);- ax25_start_idletimer(ax25);- ax25->condition = 0x00;- ax25->vs = 0;- ax25->va = 0;- ax25->vr = 0;- ax25_requeue_frames(ax25);- ax25_dama_on(ax25);- break;-- case AX25_DISC:- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_dama_off(ax25);- ax25_disconnect(ax25, 0);- break;-- case AX25_DM:- ax25_dama_off(ax25);- ax25_disconnect(ax25, ECONNRESET);- break;-- case AX25_RR:- case AX25_RNR:- if (frametype == AX25_RR)- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;- else- ax25->condition |= AX25_COND_PEER_RX_BUSY;-- if (ax25_validate_nr(ax25, nr)) {- if (ax25_check_iframes_acked(ax25, nr))- ax25->n2count=0;- if (type == AX25_COMMAND && pf)- ax25_ds_enquiry_response(ax25);- } else {- ax25_ds_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;-- case AX25_REJ:- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;-- if (ax25_validate_nr(ax25, nr)) {- if (ax25->va != nr)- ax25->n2count=0;-- ax25_frames_acked(ax25, nr);- ax25_calculate_rtt(ax25);- ax25_stop_t1timer(ax25);- ax25_start_t3timer(ax25);- ax25_requeue_frames(ax25);-- if (type == AX25_COMMAND && pf)- ax25_ds_enquiry_response(ax25);- } else {- ax25_ds_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;-- case AX25_I:- if (!ax25_validate_nr(ax25, nr)) {- ax25_ds_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- break;- }- if (ax25->condition & AX25_COND_PEER_RX_BUSY) {- ax25_frames_acked(ax25, nr);- ax25->n2count = 0;- } else {- if (ax25_check_iframes_acked(ax25, nr))- ax25->n2count = 0;- }- if (ax25->condition & AX25_COND_OWN_RX_BUSY) {- if (pf) ax25_ds_enquiry_response(ax25);- break;- }- if (ns == ax25->vr) {- ax25->vr = (ax25->vr + 1) % ax25->modulus;- queued = ax25_rx_iframe(ax25, skb);- if (ax25->condition & AX25_COND_OWN_RX_BUSY)- ax25->vr = ns; /* ax25->vr - 1 */- ax25->condition &= ~AX25_COND_REJECT;- if (pf) {- ax25_ds_enquiry_response(ax25);- } else {- if (!(ax25->condition & AX25_COND_ACK_PENDING)) {- ax25->condition |= AX25_COND_ACK_PENDING;- ax25_start_t2timer(ax25);- }- }- } else {- if (ax25->condition & AX25_COND_REJECT) {- if (pf) ax25_ds_enquiry_response(ax25);- } else {- ax25->condition |= AX25_COND_REJECT;- ax25_ds_enquiry_response(ax25);- ax25->condition &= ~AX25_COND_ACK_PENDING;- }- }- break;-- case AX25_FRMR:- case AX25_ILLEGAL:- ax25_ds_establish_data_link(ax25);- ax25->state = AX25_STATE_1;- break;-- default:- break;- }-- return queued;-}--/*- * Higher level upcall for a LAPB frame- */-int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)-{- int queued = 0, frametype, ns, nr, pf;-- frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);-- switch (ax25->state) {- case AX25_STATE_1:- queued = ax25_ds_state1_machine(ax25, skb, frametype, pf, type);- break;- case AX25_STATE_2:- queued = ax25_ds_state2_machine(ax25, skb, frametype, pf, type);- break;- case AX25_STATE_3:- queued = ax25_ds_state3_machine(ax25, skb, frametype, ns, nr, pf, type);- break;- }-- return queued;-}diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.cdeleted file mode 100644index f00e27df3c76..000000000000--- a/net/ax25/ax25_ds_subr.c+++ /dev/null@@ -1,204 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/spinlock.h>-#include <linux/net.h>-#include <linux/gfp.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--void ax25_ds_nr_error_recovery(ax25_cb *ax25)-{- ax25_ds_establish_data_link(ax25);-}--/*- * dl1bke 960114: transmit I frames on DAMA poll- */-void ax25_ds_enquiry_response(ax25_cb *ax25)-{- ax25_cb *ax25o;-- /* Please note that neither DK4EG's nor DG2FEF's- * DAMA spec mention the following behaviour as seen- * with TheFirmware:- *- * DB0ACH->DL1BKE <RR C P R0> [DAMA]- * DL1BKE->DB0ACH <I NR=0 NS=0>- * DL1BKE-7->DB0PRA-6 DB0ACH <I C S3 R5>- * DL1BKE->DB0ACH <RR R F R0>- *- * The Flexnet DAMA Master implementation apparently- * insists on the "proper" AX.25 behaviour:- *- * DB0ACH->DL1BKE <RR C P R0> [DAMA]- * DL1BKE->DB0ACH <RR R F R0>- * DL1BKE->DB0ACH <I NR=0 NS=0>- * DL1BKE-7->DB0PRA-6 DB0ACH <I C S3 R5>- *- * Flexnet refuses to send us *any* I frame if we send- * a REJ in case AX25_COND_REJECT is set. It is superfluous in- * this mode anyway (a RR or RNR invokes the retransmission).- * Is this a Flexnet bug?- */-- ax25_std_enquiry_response(ax25);-- if (!(ax25->condition & AX25_COND_PEER_RX_BUSY)) {- ax25_requeue_frames(ax25);- ax25_kick(ax25);- }-- if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2 || skb_peek(&ax25->ack_queue) != NULL)- ax25_ds_t1_timeout(ax25);- else- ax25->n2count = 0;-- ax25_start_t3timer(ax25);- ax25_ds_set_timer(ax25->ax25_dev);-- spin_lock(&ax25_list_lock);- ax25_for_each(ax25o, &ax25_list) {- if (ax25o == ax25)- continue;-- if (ax25o->ax25_dev != ax25->ax25_dev)- continue;-- if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2) {- ax25_ds_t1_timeout(ax25o);- continue;- }-- if (!(ax25o->condition & AX25_COND_PEER_RX_BUSY) && ax25o->state == AX25_STATE_3) {- ax25_requeue_frames(ax25o);- ax25_kick(ax25o);- }-- if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 || skb_peek(&ax25o->ack_queue) != NULL)- ax25_ds_t1_timeout(ax25o);-- /* do not start T3 for listening sockets (tnx DD8NE) */-- if (ax25o->state != AX25_STATE_0)- ax25_start_t3timer(ax25o);- }- spin_unlock(&ax25_list_lock);-}--void ax25_ds_establish_data_link(ax25_cb *ax25)-{- ax25->condition &= AX25_COND_DAMA_MODE;- ax25->n2count = 0;- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);- ax25_stop_t2timer(ax25);- ax25_start_t3timer(ax25);-}--/*- * :::FIXME:::- * This is a kludge. Not all drivers recognize kiss commands.- * We need a driver level request to switch duplex mode, that does- * either SCC changing, PI config or KISS as required. Currently- * this request isn't reliable.- */-static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char param)-{- struct sk_buff *skb;- unsigned char *p;-- if (ax25_dev->dev == NULL)- return;-- if ((skb = alloc_skb(2, GFP_ATOMIC)) == NULL)- return;-- skb_reset_network_header(skb);- p = skb_put(skb, 2);-- *p++ = cmd;- *p++ = param;-- skb->protocol = ax25_type_trans(skb, ax25_dev->dev);-- dev_queue_xmit(skb);-}--/*- * A nasty problem arises if we count the number of DAMA connections- * wrong, especially when connections on the device already existed- * and our network node (or the sysop) decides to turn on DAMA Master- * mode. We thus flag the 'real' slave connections with- * ax25->dama_slave=1 and look on every disconnect if still slave- * connections exist.- */-static int ax25_check_dama_slave(ax25_dev *ax25_dev)-{- ax25_cb *ax25;- int res = 0;-- spin_lock(&ax25_list_lock);- ax25_for_each(ax25, &ax25_list)- if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1) {- res = 1;- break;- }- spin_unlock(&ax25_list_lock);-- return res;-}--static void ax25_dev_dama_on(ax25_dev *ax25_dev)-{- if (ax25_dev == NULL)- return;-- if (ax25_dev->dama.slave == 0)- ax25_kiss_cmd(ax25_dev, 5, 1);-- ax25_dev->dama.slave = 1;- ax25_ds_set_timer(ax25_dev);-}--void ax25_dev_dama_off(ax25_dev *ax25_dev)-{- if (ax25_dev == NULL)- return;-- if (ax25_dev->dama.slave && !ax25_check_dama_slave(ax25_dev)) {- ax25_kiss_cmd(ax25_dev, 5, 0);- ax25_dev->dama.slave = 0;- ax25_ds_del_timer(ax25_dev);- }-}--void ax25_dama_on(ax25_cb *ax25)-{- ax25_dev_dama_on(ax25->ax25_dev);- ax25->condition |= AX25_COND_DAMA_MODE;-}--void ax25_dama_off(ax25_cb *ax25)-{- ax25->condition &= ~AX25_COND_DAMA_MODE;- ax25_dev_dama_off(ax25->ax25_dev);-}diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.cdeleted file mode 100644index 0c9e7775aa54..000000000000--- a/net/ax25/ax25_ds_timer.c+++ /dev/null@@ -1,235 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/spinlock.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/jiffies.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/tcp_states.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--static void ax25_ds_timeout(struct timer_list *);--/*- * Add DAMA slave timeout timer to timer list.- * Unlike the connection based timers the timeout function gets- * triggered every second. Please note that NET_AX25_DAMA_SLAVE_TIMEOUT- * (aka /proc/sys/net/ax25/{dev}/dama_slave_timeout) is still in- * 1/10th of a second.- */--void ax25_ds_setup_timer(ax25_dev *ax25_dev)-{- timer_setup(&ax25_dev->dama.slave_timer, ax25_ds_timeout, 0);-}--void ax25_ds_del_timer(ax25_dev *ax25_dev)-{- if (ax25_dev)- timer_delete(&ax25_dev->dama.slave_timer);-}--void ax25_ds_set_timer(ax25_dev *ax25_dev)-{- if (ax25_dev == NULL) /* paranoia */- return;-- ax25_dev->dama.slave_timeout =- msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10;- mod_timer(&ax25_dev->dama.slave_timer, jiffies + HZ);-}--/*- * DAMA Slave Timeout- * Silently discard all (slave) connections in case our master forgot us...- */--static void ax25_ds_timeout(struct timer_list *t)-{- ax25_dev *ax25_dev = timer_container_of(ax25_dev, t, dama.slave_timer);- ax25_cb *ax25;-- if (ax25_dev == NULL || !ax25_dev->dama.slave)- return; /* Yikes! */-- if (!ax25_dev->dama.slave_timeout || --ax25_dev->dama.slave_timeout) {- ax25_ds_set_timer(ax25_dev);- return;- }-- spin_lock(&ax25_list_lock);- ax25_for_each(ax25, &ax25_list) {- if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))- continue;-- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- ax25_disconnect(ax25, ETIMEDOUT);- }- spin_unlock(&ax25_list_lock);-- ax25_dev_dama_off(ax25_dev);-}--void ax25_ds_heartbeat_expiry(ax25_cb *ax25)-{- struct sock *sk=ax25->sk;-- if (sk)- bh_lock_sock(sk);-- switch (ax25->state) {-- case AX25_STATE_0:- case AX25_STATE_2:- /* Magic here: If we listen() and a new link dies before it- is accepted() it isn't 'dead' so doesn't get removed. */- if (!sk || sock_flag(sk, SOCK_DESTROY) ||- (sk->sk_state == TCP_LISTEN &&- sock_flag(sk, SOCK_DEAD))) {- if (sk) {- sock_hold(sk);- ax25_destroy_socket(ax25);- bh_unlock_sock(sk);- /* Ungrab socket and destroy it */- sock_put(sk);- } else- ax25_destroy_socket(ax25);- return;- }- break;-- case AX25_STATE_3:- /*- * Check the state of the receive buffer.- */- if (sk != NULL) {- if (atomic_read(&sk->sk_rmem_alloc) <- (sk->sk_rcvbuf >> 1) &&- (ax25->condition & AX25_COND_OWN_RX_BUSY)) {- ax25->condition &= ~AX25_COND_OWN_RX_BUSY;- ax25->condition &= ~AX25_COND_ACK_PENDING;- break;- }- }- break;- }-- if (sk)- bh_unlock_sock(sk);-- ax25_start_heartbeat(ax25);-}--/* dl1bke 960114: T3 works much like the IDLE timeout, but- * gets reloaded with every frame for this- * connection.- */-void ax25_ds_t3timer_expiry(ax25_cb *ax25)-{- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- ax25_dama_off(ax25);- ax25_disconnect(ax25, ETIMEDOUT);-}--/* dl1bke 960228: close the connection when IDLE expires.- * unlike T3 this timer gets reloaded only on- * I frames.- */-void ax25_ds_idletimer_expiry(ax25_cb *ax25)-{- ax25_clear_queues(ax25);-- ax25->n2count = 0;- ax25->state = AX25_STATE_2;-- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);- ax25_stop_t3timer(ax25);-- if (ax25->sk != NULL) {- bh_lock_sock(ax25->sk);- ax25->sk->sk_state = TCP_CLOSE;- ax25->sk->sk_err = 0;- ax25->sk->sk_shutdown |= SEND_SHUTDOWN;- if (!sock_flag(ax25->sk, SOCK_DEAD)) {- ax25->sk->sk_state_change(ax25->sk);- sock_set_flag(ax25->sk, SOCK_DEAD);- }- bh_unlock_sock(ax25->sk);- }-}--/* dl1bke 960114: The DAMA protocol requires to send data and SABM/DISC- * within the poll of any connected channel. Remember- * that we are not allowed to send anything unless we- * get polled by the Master.- *- * Thus we'll have to do parts of our T1 handling in- * ax25_enquiry_response().- */-void ax25_ds_t1_timeout(ax25_cb *ax25)-{- switch (ax25->state) {- case AX25_STATE_1:- if (ax25->n2count == ax25->n2) {- if (ax25->modulus == AX25_MODULUS) {- ax25_disconnect(ax25, ETIMEDOUT);- return;- } else {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- ax25->n2count = 0;- ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);- }- } else {- ax25->n2count++;- if (ax25->modulus == AX25_MODULUS)- ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);- else- ax25_send_control(ax25, AX25_SABME, AX25_POLLOFF, AX25_COMMAND);- }- break;-- case AX25_STATE_2:- if (ax25->n2count == ax25->n2) {- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- if (!sock_flag(ax25->sk, SOCK_DESTROY))- ax25_disconnect(ax25, ETIMEDOUT);- return;- } else {- ax25->n2count++;- }- break;-- case AX25_STATE_3:- if (ax25->n2count == ax25->n2) {- ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);- ax25_disconnect(ax25, ETIMEDOUT);- return;- } else {- ax25->n2count++;- }- break;- }-- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);-}diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.cdeleted file mode 100644index 3ad454416a5c..000000000000--- a/net/ax25/ax25_iface.c+++ /dev/null@@ -1,214 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/module.h>-#include <linux/spinlock.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--static struct ax25_protocol *protocol_list;-static DEFINE_RWLOCK(protocol_list_lock);--static HLIST_HEAD(ax25_linkfail_list);-static DEFINE_SPINLOCK(linkfail_lock);--static struct listen_struct {- struct listen_struct *next;- ax25_address callsign;- struct net_device *dev;-} *listen_list = NULL;-static DEFINE_SPINLOCK(listen_lock);--/*- * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT,- * AX25_P_IP or AX25_P_ARP ...- */-void ax25_register_pid(struct ax25_protocol *ap)-{- write_lock_bh(&protocol_list_lock);- ap->next = protocol_list;- protocol_list = ap;- write_unlock_bh(&protocol_list_lock);-}--EXPORT_SYMBOL_GPL(ax25_register_pid);--void ax25_protocol_release(unsigned int pid)-{- struct ax25_protocol *protocol;-- write_lock_bh(&protocol_list_lock);- protocol = protocol_list;- if (protocol == NULL)- goto out;-- if (protocol->pid == pid) {- protocol_list = protocol->next;- goto out;- }-- while (protocol != NULL && protocol->next != NULL) {- if (protocol->next->pid == pid) {- protocol->next = protocol->next->next;- goto out;- }-- protocol = protocol->next;- }-out:- write_unlock_bh(&protocol_list_lock);-}--EXPORT_SYMBOL(ax25_protocol_release);--void ax25_linkfail_register(struct ax25_linkfail *lf)-{- spin_lock_bh(&linkfail_lock);- hlist_add_head(&lf->lf_node, &ax25_linkfail_list);- spin_unlock_bh(&linkfail_lock);-}--EXPORT_SYMBOL(ax25_linkfail_register);--void ax25_linkfail_release(struct ax25_linkfail *lf)-{- spin_lock_bh(&linkfail_lock);- hlist_del_init(&lf->lf_node);- spin_unlock_bh(&linkfail_lock);-}--EXPORT_SYMBOL(ax25_linkfail_release);--int ax25_listen_register(const ax25_address *callsign, struct net_device *dev)-{- struct listen_struct *listen;-- if (ax25_listen_mine(callsign, dev))- return 0;-- if ((listen = kmalloc_obj(*listen, GFP_ATOMIC)) == NULL)- return -ENOMEM;-- listen->callsign = *callsign;- listen->dev = dev;-- spin_lock_bh(&listen_lock);- listen->next = listen_list;- listen_list = listen;- spin_unlock_bh(&listen_lock);-- return 0;-}--EXPORT_SYMBOL(ax25_listen_register);--void ax25_listen_release(const ax25_address *callsign, struct net_device *dev)-{- struct listen_struct *s, *listen;-- spin_lock_bh(&listen_lock);- listen = listen_list;- if (listen == NULL) {- spin_unlock_bh(&listen_lock);- return;- }-- if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) {- listen_list = listen->next;- spin_unlock_bh(&listen_lock);- kfree(listen);- return;- }-- while (listen != NULL && listen->next != NULL) {- if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) {- s = listen->next;- listen->next = listen->next->next;- spin_unlock_bh(&listen_lock);- kfree(s);- return;- }-- listen = listen->next;- }- spin_unlock_bh(&listen_lock);-}--EXPORT_SYMBOL(ax25_listen_release);--int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)-{- int (*res)(struct sk_buff *, ax25_cb *) = NULL;- struct ax25_protocol *protocol;-- read_lock(&protocol_list_lock);- for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)- if (protocol->pid == pid) {- res = protocol->func;- break;- }- read_unlock(&protocol_list_lock);-- return res;-}--int ax25_listen_mine(const ax25_address *callsign, struct net_device *dev)-{- struct listen_struct *listen;-- spin_lock_bh(&listen_lock);- for (listen = listen_list; listen != NULL; listen = listen->next)- if (ax25cmp(&listen->callsign, callsign) == 0 &&- (listen->dev == dev || listen->dev == NULL)) {- spin_unlock_bh(&listen_lock);- return 1;- }- spin_unlock_bh(&listen_lock);-- return 0;-}--void ax25_link_failed(ax25_cb *ax25, int reason)-{- struct ax25_linkfail *lf;-- spin_lock_bh(&linkfail_lock);- hlist_for_each_entry(lf, &ax25_linkfail_list, lf_node)- lf->func(ax25, reason);- spin_unlock_bh(&linkfail_lock);-}--int ax25_protocol_is_registered(unsigned int pid)-{- struct ax25_protocol *protocol;- int res = 0;-- read_lock_bh(&protocol_list_lock);- for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)- if (protocol->pid == pid) {- res = 1;- break;- }- read_unlock_bh(&protocol_list_lock);-- return res;-}diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.cdeleted file mode 100644index d75b3e9ed93d..000000000000--- a/net/ax25/ax25_in.c+++ /dev/null@@ -1,455 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--/*- * Given a fragment, queue it on the fragment queue and if the fragment- * is complete, send it back to ax25_rx_iframe.- */-static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)-{- struct sk_buff *skbn, *skbo;-- if (ax25->fragno != 0) {- if (!(*skb->data & AX25_SEG_FIRST)) {- if ((ax25->fragno - 1) == (*skb->data & AX25_SEG_REM)) {- /* Enqueue fragment */- ax25->fragno = *skb->data & AX25_SEG_REM;- skb_pull(skb, 1); /* skip fragno */- ax25->fraglen += skb->len;- skb_queue_tail(&ax25->frag_queue, skb);-- /* Last fragment received ? */- if (ax25->fragno == 0) {- skbn = alloc_skb(AX25_MAX_HEADER_LEN +- ax25->fraglen,- GFP_ATOMIC);- if (!skbn) {- skb_queue_purge(&ax25->frag_queue);- return 1;- }-- skb_reserve(skbn, AX25_MAX_HEADER_LEN);-- skbn->dev = ax25->ax25_dev->dev;- skb_reset_network_header(skbn);- skb_reset_transport_header(skbn);-- /* Copy data from the fragments */- while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {- skb_copy_from_linear_data(skbo,- skb_put(skbn, skbo->len),- skbo->len);- kfree_skb(skbo);- }-- ax25->fraglen = 0;-- if (ax25_rx_iframe(ax25, skbn) == 0)- kfree_skb(skbn);- }-- return 1;- }- }- } else {- /* First fragment received */- if (*skb->data & AX25_SEG_FIRST) {- skb_queue_purge(&ax25->frag_queue);- ax25->fragno = *skb->data & AX25_SEG_REM;- skb_pull(skb, 1); /* skip fragno */- ax25->fraglen = skb->len;- skb_queue_tail(&ax25->frag_queue, skb);- return 1;- }- }-- return 0;-}--/*- * This is where all valid I frames are sent to, to be dispatched to- * whichever protocol requires them.- */-int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)-{- int (*func)(struct sk_buff *, ax25_cb *);- unsigned char pid;- int queued = 0;-- if (skb == NULL) return 0;-- ax25_start_idletimer(ax25);-- pid = *skb->data;-- if (pid == AX25_P_IP) {- /* working around a TCP bug to keep additional listeners- * happy. TCP re-uses the buffer and destroys the original- * content.- */- struct sk_buff *skbn = skb_copy(skb, GFP_ATOMIC);- if (skbn != NULL) {- kfree_skb(skb);- skb = skbn;- }-- skb_pull(skb, 1); /* Remove PID */- skb->mac_header = skb->network_header;- skb_reset_network_header(skb);- skb->dev = ax25->ax25_dev->dev;- skb->pkt_type = PACKET_HOST;- skb->protocol = htons(ETH_P_IP);- netif_rx(skb);- return 1;- }- if (pid == AX25_P_SEGMENT) {- skb_pull(skb, 1); /* Remove PID */- return ax25_rx_fragment(ax25, skb);- }-- if ((func = ax25_protocol_function(pid)) != NULL) {- skb_pull(skb, 1); /* Remove PID */- return (*func)(skb, ax25);- }-- if (ax25->sk != NULL && ax25->ax25_dev->values[AX25_VALUES_CONMODE] == 2) {- if ((!ax25->pidincl && ax25->sk->sk_protocol == pid) ||- ax25->pidincl) {- if (sock_queue_rcv_skb(ax25->sk, skb) == 0)- queued = 1;- else- ax25->condition |= AX25_COND_OWN_RX_BUSY;- }- }-- return queued;-}--/*- * Higher level upcall for a LAPB frame- */-static int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, int dama)-{- int queued = 0;-- if (ax25->state == AX25_STATE_0)- return 0;-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- queued = ax25_std_frame_in(ax25, skb, type);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- if (dama || ax25->ax25_dev->dama.slave)- queued = ax25_ds_frame_in(ax25, skb, type);- else- queued = ax25_std_frame_in(ax25, skb, type);- break;-#endif- }-- return queued;-}--static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,- const ax25_address *dev_addr, struct packet_type *ptype)-{- ax25_address src, dest, *next_digi = NULL;- int type = 0, mine = 0, dama;- struct sock *make, *sk;- ax25_digi dp, reverse_dp;- ax25_cb *ax25;- ax25_dev *ax25_dev;-- /*- * Process the AX.25/LAPB frame.- */-- skb_reset_transport_header(skb);-- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)- goto free;-- /*- * Parse the address header.- */-- if (ax25_addr_parse(skb->data, skb->len, &src, &dest, &dp, &type, &dama) == NULL)- goto free;-- /*- * Ours perhaps ?- */- if (dp.lastrepeat + 1 < dp.ndigi) /* Not yet digipeated completely */- next_digi = &dp.calls[dp.lastrepeat + 1];-- /*- * Pull of the AX.25 headers leaving the CTRL/PID bytes- */- skb_pull(skb, ax25_addr_size(&dp));-- /* For our port addresses ? */- if (ax25cmp(&dest, dev_addr) == 0 && dp.lastrepeat + 1 == dp.ndigi)- mine = 1;-- /* Also match on any registered callsign from L3/4 */- if (!mine && ax25_listen_mine(&dest, dev) && dp.lastrepeat + 1 == dp.ndigi)- mine = 1;-- /* UI frame - bypass LAPB processing */- if ((*skb->data & ~0x10) == AX25_UI && dp.lastrepeat + 1 == dp.ndigi) {- skb_set_transport_header(skb, 2); /* skip control and pid */-- ax25_send_to_raw(&dest, skb, skb->data[1]);-- if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0)- goto free;-- /* Now we are pointing at the pid byte */- switch (skb->data[1]) {- case AX25_P_IP:- skb_pull(skb,2); /* drop PID/CTRL */- skb_reset_transport_header(skb);- skb_reset_network_header(skb);- skb->dev = dev;- skb->pkt_type = PACKET_HOST;- skb->protocol = htons(ETH_P_IP);- netif_rx(skb);- break;-- case AX25_P_ARP:- skb_pull(skb,2);- skb_reset_transport_header(skb);- skb_reset_network_header(skb);- skb->dev = dev;- skb->pkt_type = PACKET_HOST;- skb->protocol = htons(ETH_P_ARP);- netif_rx(skb);- break;- case AX25_P_TEXT:- /* Now find a suitable dgram socket */- sk = ax25_get_socket(&dest, &src, SOCK_DGRAM);- if (sk != NULL) {- bh_lock_sock(sk);- if (atomic_read(&sk->sk_rmem_alloc) >=- sk->sk_rcvbuf) {- kfree_skb(skb);- } else {- /*- * Remove the control and PID.- */- skb_pull(skb, 2);- if (sock_queue_rcv_skb(sk, skb) != 0)- kfree_skb(skb);- }- bh_unlock_sock(sk);- sock_put(sk);- } else {- kfree_skb(skb);- }- break;-- default:- kfree_skb(skb); /* Will scan SOCK_AX25 RAW sockets */- break;- }-- return 0;- }-- /*- * Is connected mode supported on this device ?- * If not, should we DM the incoming frame (except DMs) or- * silently ignore them. For now we stay quiet.- */- if (ax25_dev->values[AX25_VALUES_CONMODE] == 0)- goto free;-- /* LAPB */-- /* AX.25 state 1-4 */-- ax25_digi_invert(&dp, &reverse_dp);-- if ((ax25 = ax25_find_cb(&dest, &src, &reverse_dp, dev)) != NULL) {- /*- * Process the frame. If it is queued up internally it- * returns one otherwise we free it immediately. This- * routine itself wakes the user context layers so we do- * no further work- */- if (ax25_process_rx_frame(ax25, skb, type, dama) == 0)- kfree_skb(skb);-- ax25_cb_put(ax25);- return 0;- }-- /* AX.25 state 0 (disconnected) */-- /* a) received not a SABM(E) */-- if ((*skb->data & ~AX25_PF) != AX25_SABM &&- (*skb->data & ~AX25_PF) != AX25_SABME) {- /*- * Never reply to a DM. Also ignore any connects for- * addresses that are not our interfaces and not a socket.- */- if ((*skb->data & ~AX25_PF) != AX25_DM && mine)- ax25_return_dm(dev, &src, &dest, &dp);-- goto free;- }-- /* b) received SABM(E) */-- if (dp.lastrepeat + 1 == dp.ndigi)- sk = ax25_find_listener(&dest, 0, dev, SOCK_SEQPACKET);- else- sk = ax25_find_listener(next_digi, 1, dev, SOCK_SEQPACKET);-- if (sk != NULL) {- bh_lock_sock(sk);- if (sk_acceptq_is_full(sk) ||- (make = ax25_make_new(sk, ax25_dev)) == NULL) {- if (mine)- ax25_return_dm(dev, &src, &dest, &dp);- kfree_skb(skb);- bh_unlock_sock(sk);- sock_put(sk);-- return 0;- }-- ax25 = sk_to_ax25(make);- skb_set_owner_r(skb, make);- skb_queue_head(&sk->sk_receive_queue, skb);-- make->sk_state = TCP_ESTABLISHED;-- sk_acceptq_added(sk);- bh_unlock_sock(sk);- } else {- if (!mine)- goto free;-- if ((ax25 = ax25_create_cb()) == NULL) {- ax25_return_dm(dev, &src, &dest, &dp);- goto free;- }-- ax25_fillin_cb(ax25, ax25_dev);- }-- ax25->source_addr = dest;- ax25->dest_addr = src;-- /*- * Sort out any digipeated paths.- */- if (dp.ndigi && !ax25->digipeat &&- (ax25->digipeat = kmalloc_obj(ax25_digi, GFP_ATOMIC)) == NULL) {- kfree_skb(skb);- ax25_destroy_socket(ax25);- if (sk)- sock_put(sk);- return 0;- }-- if (dp.ndigi == 0) {- kfree(ax25->digipeat);- ax25->digipeat = NULL;- } else {- /* Reverse the source SABM's path */- memcpy(ax25->digipeat, &reverse_dp, sizeof(ax25_digi));- }-- if ((*skb->data & ~AX25_PF) == AX25_SABME) {- ax25->modulus = AX25_EMODULUS;- ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];- } else {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];- }-- ax25_send_control(ax25, AX25_UA, AX25_POLLON, AX25_RESPONSE);--#ifdef CONFIG_AX25_DAMA_SLAVE- if (dama && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE)- ax25_dama_on(ax25);-#endif-- ax25->state = AX25_STATE_3;-- ax25_cb_add(ax25);-- ax25_start_heartbeat(ax25);- ax25_start_t3timer(ax25);- ax25_start_idletimer(ax25);-- if (sk) {- if (!sock_flag(sk, SOCK_DEAD))- sk->sk_data_ready(sk);- sock_put(sk);- } else {-free:- kfree_skb(skb);- }- return 0;-}--/*- * Receive an AX.25 frame via a SLIP interface.- */-int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,- struct packet_type *ptype, struct net_device *orig_dev)-{- skb = skb_share_check(skb, GFP_ATOMIC);- if (!skb)- return NET_RX_DROP;-- skb_orphan(skb);-- if (!net_eq(dev_net(dev), &init_net)) {- kfree_skb(skb);- return 0;- }-- if ((*skb->data & 0x0F) != 0) {- kfree_skb(skb); /* Not a KISS data frame */- return 0;- }-- skb_pull(skb, AX25_KISS_HEADER_LEN); /* Remove the KISS byte */-- return ax25_rcv(skb, dev, (const ax25_address *)dev->dev_addr, ptype);-}diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.cdeleted file mode 100644index 215d4ccf12b9..000000000000--- a/net/ax25/ax25_ip.c+++ /dev/null@@ -1,247 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/module.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/termios.h> /* For TIOCINQ/OUTQ */-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/notifier.h>-#include <linux/proc_fs.h>-#include <linux/stat.h>-#include <linux/sysctl.h>-#include <net/ip.h>-#include <net/arp.h>--/*- * IP over AX.25 encapsulation.- */--/*- * Shove an AX.25 UI header on an IP packet and handle ARP- */--#ifdef CONFIG_INET--static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,- unsigned short type, const void *daddr,- const void *saddr, unsigned int len)-{- unsigned char *buff;-- /* they sometimes come back to us... */- if (type == ETH_P_AX25)- return 0;-- /* header is an AX.25 UI frame from us to them */- buff = skb_push(skb, AX25_HEADER_LEN);- *buff++ = 0x00; /* KISS DATA */-- if (daddr != NULL)- memcpy(buff, daddr, dev->addr_len); /* Address specified */-- buff[6] &= ~AX25_CBIT;- buff[6] &= ~AX25_EBIT;- buff[6] |= AX25_SSSID_SPARE;- buff += AX25_ADDR_LEN;-- if (saddr != NULL)- memcpy(buff, saddr, dev->addr_len);- else- memcpy(buff, dev->dev_addr, dev->addr_len);-- buff[6] &= ~AX25_CBIT;- buff[6] |= AX25_EBIT;- buff[6] |= AX25_SSSID_SPARE;- buff += AX25_ADDR_LEN;-- *buff++ = AX25_UI; /* UI */-- /* Append a suitable AX.25 PID */- switch (type) {- case ETH_P_IP:- *buff++ = AX25_P_IP;- break;- case ETH_P_ARP:- *buff++ = AX25_P_ARP;- break;- default:- printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);- *buff++ = 0;- break;- }-- if (daddr != NULL)- return AX25_HEADER_LEN;-- return -AX25_HEADER_LEN; /* Unfinished header */-}--netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)-{- struct sk_buff *ourskb;- unsigned char *bp = skb->data;- ax25_route *route;- struct net_device *dev = NULL;- ax25_address *src, *dst;- ax25_digi *digipeat = NULL;- ax25_dev *ax25_dev;- ax25_cb *ax25;- char ip_mode = ' ';-- dst = (ax25_address *)(bp + 1);- src = (ax25_address *)(bp + 8);-- ax25_route_lock_use();- route = ax25_get_route(dst, NULL);- if (route) {- digipeat = route->digipeat;- dev = route->dev;- ip_mode = route->ip_mode;- }-- if (dev == NULL)- dev = skb->dev;-- rcu_read_lock();- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {- kfree_skb(skb);- goto put;- }-- if (bp[16] == AX25_P_IP) {- if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {- /*- * We copy the buffer and release the original thereby- * keeping it straight- *- * Note: we report 1 back so the caller will- * not feed the frame direct to the physical device- * We don't want that to happen. (It won't be upset- * as we have pulled the frame from the queue by- * freeing it).- *- * NB: TCP modifies buffers that are still- * on a device queue, thus we use skb_copy()- * instead of using skb_clone() unless this- * gets fixed.- */-- ax25_address src_c;- ax25_address dst_c;-- if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {- kfree_skb(skb);- goto put;- }-- if (skb->sk != NULL)- skb_set_owner_w(ourskb, skb->sk);-- kfree_skb(skb);- /* dl9sau: bugfix- * after kfree_skb(), dst and src which were pointer- * to bp which is part of skb->data would not be valid- * anymore hope that after skb_pull(ourskb, ..) our- * dsc_c and src_c will not become invalid- */- bp = ourskb->data;- dst_c = *(ax25_address *)(bp + 1);- src_c = *(ax25_address *)(bp + 8);-- skb_pull(ourskb, AX25_HEADER_LEN - 1); /* Keep PID */- skb_reset_network_header(ourskb);-- ax25=ax25_send_frame(- ourskb,- ax25_dev->values[AX25_VALUES_PACLEN],- &src_c,- &dst_c, digipeat, dev);- if (ax25) {- ax25_cb_put(ax25);- }- goto put;- }- }-- bp[7] &= ~AX25_CBIT;- bp[7] &= ~AX25_EBIT;- bp[7] |= AX25_SSSID_SPARE;-- bp[14] &= ~AX25_CBIT;- bp[14] |= AX25_EBIT;- bp[14] |= AX25_SSSID_SPARE;-- skb_pull(skb, AX25_KISS_HEADER_LEN);-- if (digipeat != NULL) {- if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL)- goto put;-- skb = ourskb;- }-- ax25_queue_xmit(skb, dev);--put:- rcu_read_unlock();- ax25_route_lock_unuse();- return NETDEV_TX_OK;-}--#else /* INET */--static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,- unsigned short type, const void *daddr,- const void *saddr, unsigned int len)-{- return -AX25_HEADER_LEN;-}--netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)-{- kfree_skb(skb);- return NETDEV_TX_OK;-}-#endif--static bool ax25_validate_header(const char *header, unsigned int len)-{- ax25_digi digi;-- if (!len)- return false;-- if (header[0])- return true;-- return ax25_addr_parse(header + 1, len - 1, NULL, NULL, &digi, NULL,- NULL);-}--const struct header_ops ax25_header_ops = {- .create = ax25_hard_header,- .validate = ax25_validate_header,-};--EXPORT_SYMBOL(ax25_header_ops);-EXPORT_SYMBOL(ax25_ip_xmit);diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.cdeleted file mode 100644index 8bca2ace98e5..000000000000--- a/net/ax25/ax25_out.c+++ /dev/null@@ -1,398 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/module.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/spinlock.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--static DEFINE_SPINLOCK(ax25_frag_lock);--ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)-{- ax25_dev *ax25_dev;- ax25_cb *ax25;-- /*- * Take the default packet length for the device if zero is- * specified.- */- if (paclen == 0) {- rcu_read_lock();- ax25_dev = ax25_dev_ax25dev(dev);- if (!ax25_dev) {- rcu_read_unlock();- return NULL;- }- paclen = ax25_dev->values[AX25_VALUES_PACLEN];- rcu_read_unlock();- }-- /*- * Look for an existing connection.- */- if ((ax25 = ax25_find_cb(src, dest, digi, dev)) != NULL) {- ax25_output(ax25, paclen, skb);- return ax25; /* It already existed */- }-- rcu_read_lock();- ax25_dev = ax25_dev_ax25dev(dev);- if (!ax25_dev) {- rcu_read_unlock();- return NULL;- }-- if ((ax25 = ax25_create_cb()) == NULL) {- rcu_read_unlock();- return NULL;- }- ax25_fillin_cb(ax25, ax25_dev);- rcu_read_unlock();-- ax25->source_addr = *src;- ax25->dest_addr = *dest;-- if (digi != NULL) {- ax25->digipeat = kmemdup(digi, sizeof(*digi), GFP_ATOMIC);- if (ax25->digipeat == NULL) {- ax25_cb_put(ax25);- return NULL;- }- }-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_std_establish_data_link(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- if (ax25_dev->dama.slave)- ax25_ds_establish_data_link(ax25);- else- ax25_std_establish_data_link(ax25);- break;-#endif- }-- /*- * There is one ref for the state machine; a caller needs- * one more to put it back, just like with the existing one.- */- ax25_cb_hold(ax25);-- ax25_cb_add(ax25);-- ax25->state = AX25_STATE_1;-- ax25_start_heartbeat(ax25);-- ax25_output(ax25, paclen, skb);-- return ax25; /* We had to create it */-}--EXPORT_SYMBOL(ax25_send_frame);--/*- * All outgoing AX.25 I frames pass via this routine. Therefore this is- * where the fragmentation of frames takes place. If fragment is set to- * zero then we are not allowed to do fragmentation, even if the frame- * is too large.- */-void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)-{- struct sk_buff *skbn;- unsigned char *p;- int frontlen, len, fragno, ka9qfrag, first = 1;-- if (paclen < 16) {- WARN_ON_ONCE(1);- kfree_skb(skb);- return;- }-- if ((skb->len - 1) > paclen) {- if (*skb->data == AX25_P_TEXT) {- skb_pull(skb, 1); /* skip PID */- ka9qfrag = 0;- } else {- paclen -= 2; /* Allow for fragment control info */- ka9qfrag = 1;- }-- fragno = skb->len / paclen;- if (skb->len % paclen == 0) fragno--;-- frontlen = skb_headroom(skb); /* Address space + CTRL */-- while (skb->len > 0) {- spin_lock_bh(&ax25_frag_lock);- if ((skbn = alloc_skb(paclen + 2 + frontlen, GFP_ATOMIC)) == NULL) {- spin_unlock_bh(&ax25_frag_lock);- printk(KERN_CRIT "AX.25: ax25_output - out of memory\n");- return;- }-- if (skb->sk != NULL)- skb_set_owner_w(skbn, skb->sk);-- spin_unlock_bh(&ax25_frag_lock);-- len = (paclen > skb->len) ? skb->len : paclen;-- if (ka9qfrag == 1) {- skb_reserve(skbn, frontlen + 2);- skb_set_network_header(skbn,- skb_network_offset(skb));- skb_copy_from_linear_data(skb, skb_put(skbn, len), len);- p = skb_push(skbn, 2);-- *p++ = AX25_P_SEGMENT;-- *p = fragno--;- if (first) {- *p |= AX25_SEG_FIRST;- first = 0;- }- } else {- skb_reserve(skbn, frontlen + 1);- skb_set_network_header(skbn,- skb_network_offset(skb));- skb_copy_from_linear_data(skb, skb_put(skbn, len), len);- p = skb_push(skbn, 1);- *p = AX25_P_TEXT;- }-- skb_pull(skb, len);- skb_queue_tail(&ax25->write_queue, skbn); /* Throw it on the queue */- }-- kfree_skb(skb);- } else {- skb_queue_tail(&ax25->write_queue, skb); /* Throw it on the queue */- }-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_kick(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- /*- * A DAMA slave is _required_ to work as normal AX.25L2V2- * if no DAMA master is available.- */- case AX25_PROTO_DAMA_SLAVE:- if (!ax25->ax25_dev->dama.slave) ax25_kick(ax25);- break;-#endif- }-}--/*- * This procedure is passed a buffer descriptor for an iframe. It builds- * the rest of the control part of the frame and then writes it out.- */-static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)-{- unsigned char *frame;-- if (skb == NULL)- return;-- skb_reset_network_header(skb);-- if (ax25->modulus == AX25_MODULUS) {- frame = skb_push(skb, 1);-- *frame = AX25_I;- *frame |= (poll_bit) ? AX25_PF : 0;- *frame |= (ax25->vr << 5);- *frame |= (ax25->vs << 1);- } else {- frame = skb_push(skb, 2);-- frame[0] = AX25_I;- frame[0] |= (ax25->vs << 1);- frame[1] = (poll_bit) ? AX25_EPF : 0;- frame[1] |= (ax25->vr << 1);- }-- ax25_start_idletimer(ax25);-- ax25_transmit_buffer(ax25, skb, AX25_COMMAND);-}--void ax25_kick(ax25_cb *ax25)-{- struct sk_buff *skb, *skbn;- int last = 1;- unsigned short start, end, next;-- if (ax25->state != AX25_STATE_3 && ax25->state != AX25_STATE_4)- return;-- if (ax25->condition & AX25_COND_PEER_RX_BUSY)- return;-- if (skb_peek(&ax25->write_queue) == NULL)- return;-- start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;- end = (ax25->va + ax25->window) % ax25->modulus;-- if (start == end)- return;-- /*- * Transmit data until either we're out of data to send or- * the window is full. Send a poll on the final I frame if- * the window is filled.- */-- /*- * Dequeue the frame and copy it.- * Check for race with ax25_clear_queues().- */- skb = skb_dequeue(&ax25->write_queue);- if (!skb)- return;-- ax25->vs = start;-- do {- if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {- skb_queue_head(&ax25->write_queue, skb);- break;- }-- if (skb->sk != NULL)- skb_set_owner_w(skbn, skb->sk);-- next = (ax25->vs + 1) % ax25->modulus;- last = (next == end);-- /*- * Transmit the frame copy.- * bke 960114: do not set the Poll bit on the last frame- * in DAMA mode.- */- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_send_iframe(ax25, skbn, (last) ? AX25_POLLON : AX25_POLLOFF);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- ax25_send_iframe(ax25, skbn, AX25_POLLOFF);- break;-#endif- }-- ax25->vs = next;-- /*- * Requeue the original data frame.- */- skb_queue_tail(&ax25->ack_queue, skb);-- } while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);-- ax25->condition &= ~AX25_COND_ACK_PENDING;-- if (!ax25_t1timer_running(ax25)) {- ax25_stop_t3timer(ax25);- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);- }-}--void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)-{- unsigned char *ptr;- int headroom;-- if (ax25->ax25_dev == NULL) {- ax25_disconnect(ax25, ENETUNREACH);- return;- }-- headroom = ax25_addr_size(ax25->digipeat);-- if (unlikely(skb_headroom(skb) < headroom)) {- skb = skb_expand_head(skb, headroom);- if (!skb) {- printk(KERN_CRIT "AX.25: ax25_transmit_buffer - out of memory\n");- return;- }- }-- ptr = skb_push(skb, headroom);-- ax25_addr_build(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);-- ax25_queue_xmit(skb, ax25->ax25_dev->dev);-}--/*- * A small shim to dev_queue_xmit to add the KISS control byte, and do- * any packet forwarding in operation.- */-void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev)-{- unsigned char *ptr;-- rcu_read_lock();- skb->protocol = ax25_type_trans(skb, ax25_fwd_dev(dev));- rcu_read_unlock();-- ptr = skb_push(skb, 1);- *ptr = 0x00; /* KISS */-- dev_queue_xmit(skb);-}--int ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)-{- if (ax25->vs == nr) {- ax25_frames_acked(ax25, nr);- ax25_calculate_rtt(ax25);- ax25_stop_t1timer(ax25);- ax25_start_t3timer(ax25);- return 1;- } else {- if (ax25->va != nr) {- ax25_frames_acked(ax25, nr);- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);- return 1;- }- }- return 0;-}diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.cdeleted file mode 100644index 1d5c59ccf142..000000000000--- a/net/ax25/ax25_route.c+++ /dev/null@@ -1,416 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Steven Whitehouse GW7RRM (stevew@acm.org)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)- * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)- */--#include <linux/capability.h>-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/timer.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/sched.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <linux/spinlock.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/init.h>-#include <linux/seq_file.h>-#include <linux/export.h>--static ax25_route *ax25_route_list;-DEFINE_RWLOCK(ax25_route_lock);--void ax25_rt_device_down(struct net_device *dev)-{- ax25_route *s, *t, *ax25_rt;-- write_lock_bh(&ax25_route_lock);- ax25_rt = ax25_route_list;- while (ax25_rt != NULL) {- s = ax25_rt;- ax25_rt = ax25_rt->next;-- if (s->dev == dev) {- if (ax25_route_list == s) {- ax25_route_list = s->next;- kfree(s->digipeat);- kfree(s);- } else {- for (t = ax25_route_list; t != NULL; t = t->next) {- if (t->next == s) {- t->next = s->next;- kfree(s->digipeat);- kfree(s);- break;- }- }- }- }- }- write_unlock_bh(&ax25_route_lock);-}--static int __must_check ax25_rt_add(struct ax25_routes_struct *route)-{- ax25_route *ax25_rt;- ax25_dev *ax25_dev;- int i;-- if (route->digi_count > AX25_MAX_DIGIS)- return -EINVAL;-- ax25_dev = ax25_addr_ax25dev(&route->port_addr);- if (!ax25_dev)- return -EINVAL;-- write_lock_bh(&ax25_route_lock);-- ax25_rt = ax25_route_list;- while (ax25_rt != NULL) {- if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 &&- ax25_rt->dev == ax25_dev->dev) {- kfree(ax25_rt->digipeat);- ax25_rt->digipeat = NULL;- if (route->digi_count != 0) {- if ((ax25_rt->digipeat = kmalloc_obj(ax25_digi, GFP_ATOMIC)) == NULL) {- write_unlock_bh(&ax25_route_lock);- ax25_dev_put(ax25_dev);- return -ENOMEM;- }- ax25_rt->digipeat->lastrepeat = -1;- ax25_rt->digipeat->ndigi = route->digi_count;- for (i = 0; i < route->digi_count; i++) {- ax25_rt->digipeat->repeated[i] = 0;- ax25_rt->digipeat->calls[i] = route->digi_addr[i];- }- }- write_unlock_bh(&ax25_route_lock);- ax25_dev_put(ax25_dev);- return 0;- }- ax25_rt = ax25_rt->next;- }-- if ((ax25_rt = kmalloc_obj(ax25_route, GFP_ATOMIC)) == NULL) {- write_unlock_bh(&ax25_route_lock);- ax25_dev_put(ax25_dev);- return -ENOMEM;- }-- ax25_rt->callsign = route->dest_addr;- ax25_rt->dev = ax25_dev->dev;- ax25_rt->digipeat = NULL;- ax25_rt->ip_mode = ' ';- if (route->digi_count != 0) {- if ((ax25_rt->digipeat = kmalloc_obj(ax25_digi, GFP_ATOMIC)) == NULL) {- write_unlock_bh(&ax25_route_lock);- kfree(ax25_rt);- ax25_dev_put(ax25_dev);- return -ENOMEM;- }- ax25_rt->digipeat->lastrepeat = -1;- ax25_rt->digipeat->ndigi = route->digi_count;- for (i = 0; i < route->digi_count; i++) {- ax25_rt->digipeat->repeated[i] = 0;- ax25_rt->digipeat->calls[i] = route->digi_addr[i];- }- }- ax25_rt->next = ax25_route_list;- ax25_route_list = ax25_rt;- write_unlock_bh(&ax25_route_lock);- ax25_dev_put(ax25_dev);-- return 0;-}--void __ax25_put_route(ax25_route *ax25_rt)-{- kfree(ax25_rt->digipeat);- kfree(ax25_rt);-}--static int ax25_rt_del(struct ax25_routes_struct *route)-{- ax25_route *s, *t, *ax25_rt;- ax25_dev *ax25_dev;-- if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)- return -EINVAL;-- write_lock_bh(&ax25_route_lock);-- ax25_rt = ax25_route_list;- while (ax25_rt != NULL) {- s = ax25_rt;- ax25_rt = ax25_rt->next;- if (s->dev == ax25_dev->dev &&- ax25cmp(&route->dest_addr, &s->callsign) == 0) {- if (ax25_route_list == s) {- ax25_route_list = s->next;- __ax25_put_route(s);- } else {- for (t = ax25_route_list; t != NULL; t = t->next) {- if (t->next == s) {- t->next = s->next;- __ax25_put_route(s);- break;- }- }- }- }- }- write_unlock_bh(&ax25_route_lock);- ax25_dev_put(ax25_dev);-- return 0;-}--static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)-{- ax25_route *ax25_rt;- ax25_dev *ax25_dev;- int err = 0;-- if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL)- return -EINVAL;-- write_lock_bh(&ax25_route_lock);-- ax25_rt = ax25_route_list;- while (ax25_rt != NULL) {- if (ax25_rt->dev == ax25_dev->dev &&- ax25cmp(&rt_option->dest_addr, &ax25_rt->callsign) == 0) {- switch (rt_option->cmd) {- case AX25_SET_RT_IPMODE:- switch (rt_option->arg) {- case ' ':- case 'D':- case 'V':- ax25_rt->ip_mode = rt_option->arg;- break;- default:- err = -EINVAL;- goto out;- }- break;- default:- err = -EINVAL;- goto out;- }- }- ax25_rt = ax25_rt->next;- }--out:- write_unlock_bh(&ax25_route_lock);- ax25_dev_put(ax25_dev);- return err;-}--int ax25_rt_ioctl(unsigned int cmd, void __user *arg)-{- struct ax25_route_opt_struct rt_option;- struct ax25_routes_struct route;-- switch (cmd) {- case SIOCADDRT:- if (copy_from_user(&route, arg, sizeof(route)))- return -EFAULT;- return ax25_rt_add(&route);-- case SIOCDELRT:- if (copy_from_user(&route, arg, sizeof(route)))- return -EFAULT;- return ax25_rt_del(&route);-- case SIOCAX25OPTRT:- if (copy_from_user(&rt_option, arg, sizeof(rt_option)))- return -EFAULT;- return ax25_rt_opt(&rt_option);-- default:- return -EINVAL;- }-}--#ifdef CONFIG_PROC_FS--static void *ax25_rt_seq_start(struct seq_file *seq, loff_t *pos)- __acquires(ax25_route_lock)-{- struct ax25_route *ax25_rt;- int i = 1;-- read_lock(&ax25_route_lock);- if (*pos == 0)- return SEQ_START_TOKEN;-- for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {- if (i == *pos)- return ax25_rt;- ++i;- }-- return NULL;-}--static void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos)-{- ++*pos;- return (v == SEQ_START_TOKEN) ? ax25_route_list :- ((struct ax25_route *) v)->next;-}--static void ax25_rt_seq_stop(struct seq_file *seq, void *v)- __releases(ax25_route_lock)-{- read_unlock(&ax25_route_lock);-}--static int ax25_rt_seq_show(struct seq_file *seq, void *v)-{- char buf[11];-- if (v == SEQ_START_TOKEN)- seq_puts(seq, "callsign dev mode digipeaters\n");- else {- struct ax25_route *ax25_rt = v;- const char *callsign;- int i;-- if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)- callsign = "default";- else- callsign = ax2asc(buf, &ax25_rt->callsign);-- seq_printf(seq, "%-9s %-4s",- callsign,- ax25_rt->dev ? ax25_rt->dev->name : "???");-- switch (ax25_rt->ip_mode) {- case 'V':- seq_puts(seq, " vc");- break;- case 'D':- seq_puts(seq, " dg");- break;- default:- seq_puts(seq, " *");- break;- }-- if (ax25_rt->digipeat != NULL)- for (i = 0; i < ax25_rt->digipeat->ndigi; i++)- seq_printf(seq, " %s",- ax2asc(buf, &ax25_rt->digipeat->calls[i]));-- seq_puts(seq, "\n");- }- return 0;-}--const struct seq_operations ax25_rt_seqops = {- .start = ax25_rt_seq_start,- .next = ax25_rt_seq_next,- .stop = ax25_rt_seq_stop,- .show = ax25_rt_seq_show,-};-#endif--/*- * Find AX.25 route- *- * Only routes with a reference count of zero can be destroyed.- * Must be called with ax25_route_lock read locked.- */-ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)-{- ax25_route *ax25_spe_rt = NULL;- ax25_route *ax25_def_rt = NULL;- ax25_route *ax25_rt;-- /*- * Bind to the physical interface we heard them on, or the default- * route if none is found;- */- for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {- if (dev == NULL) {- if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)- ax25_spe_rt = ax25_rt;- if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)- ax25_def_rt = ax25_rt;- } else {- if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev)- ax25_spe_rt = ax25_rt;- if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev)- ax25_def_rt = ax25_rt;- }- }-- ax25_rt = ax25_def_rt;- if (ax25_spe_rt != NULL)- ax25_rt = ax25_spe_rt;-- return ax25_rt;-}---struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src,- ax25_address *dest, ax25_digi *digi)-{- unsigned char *bp;- int len;-- len = digi->ndigi * AX25_ADDR_LEN;-- if (unlikely(skb_headroom(skb) < len)) {- skb = skb_expand_head(skb, len);- if (!skb) {- printk(KERN_CRIT "AX.25: ax25_dg_build_path - out of memory\n");- return NULL;- }- }-- bp = skb_push(skb, len);-- ax25_addr_build(bp, src, dest, digi, AX25_COMMAND, AX25_MODULUS);-- return skb;-}--/*- * Free all memory associated with routing structures.- */-void __exit ax25_rt_free(void)-{- ax25_route *s, *ax25_rt = ax25_route_list;-- write_lock_bh(&ax25_route_lock);- while (ax25_rt != NULL) {- s = ax25_rt;- ax25_rt = ax25_rt->next;-- kfree(s->digipeat);- kfree(s);- }- write_unlock_bh(&ax25_route_lock);-}diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.cdeleted file mode 100644index ba176196ae06..000000000000--- a/net/ax25/ax25_std_in.c+++ /dev/null@@ -1,443 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)- *- * Most of this code is based on the SDL diagrams published in the 7th ARRL- * Computer Networking Conference papers. The diagrams have mistakes in them,- * but are mostly correct. Before you modify the code could you read the SDL- * diagrams as the code is not obvious and probably very easy to break.- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--/*- * State machine for state 1, Awaiting Connection State.- * The handling of the timer(s) is in file ax25_std_timer.c.- * Handling of state 0 and connection release is in ax25.c.- */-static int ax25_std_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)-{- switch (frametype) {- case AX25_SABM:- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- break;-- case AX25_SABME:- ax25->modulus = AX25_EMODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- break;-- case AX25_DISC:- ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);- break;-- case AX25_UA:- if (pf) {- ax25_calculate_rtt(ax25);- ax25_stop_t1timer(ax25);- ax25_start_t3timer(ax25);- ax25_start_idletimer(ax25);- ax25->vs = 0;- ax25->va = 0;- ax25->vr = 0;- ax25->state = AX25_STATE_3;- ax25->n2count = 0;- if (ax25->sk != NULL) {- bh_lock_sock(ax25->sk);- ax25->sk->sk_state = TCP_ESTABLISHED;- /* For WAIT_SABM connections we will produce an accept ready socket here */- if (!sock_flag(ax25->sk, SOCK_DEAD))- ax25->sk->sk_state_change(ax25->sk);- bh_unlock_sock(ax25->sk);- }- }- break;-- case AX25_DM:- if (pf) {- if (ax25->modulus == AX25_MODULUS) {- ax25_disconnect(ax25, ECONNREFUSED);- } else {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- }- }- break;-- default:- break;- }-- return 0;-}--/*- * State machine for state 2, Awaiting Release State.- * The handling of the timer(s) is in file ax25_std_timer.c- * Handling of state 0 and connection release is in ax25.c.- */-static int ax25_std_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)-{- switch (frametype) {- case AX25_SABM:- case AX25_SABME:- ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);- break;-- case AX25_DISC:- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_disconnect(ax25, 0);- break;-- case AX25_DM:- case AX25_UA:- if (pf)- ax25_disconnect(ax25, 0);- break;-- case AX25_I:- case AX25_REJ:- case AX25_RNR:- case AX25_RR:- if (pf) ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);- break;-- default:- break;- }-- return 0;-}--/*- * State machine for state 3, Connected State.- * The handling of the timer(s) is in file ax25_std_timer.c- * Handling of state 0 and connection release is in ax25.c.- */-static int ax25_std_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)-{- int queued = 0;-- switch (frametype) {- case AX25_SABM:- case AX25_SABME:- if (frametype == AX25_SABM) {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- } else {- ax25->modulus = AX25_EMODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];- }- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_stop_t1timer(ax25);- ax25_stop_t2timer(ax25);- ax25_start_t3timer(ax25);- ax25_start_idletimer(ax25);- ax25->condition = 0x00;- ax25->vs = 0;- ax25->va = 0;- ax25->vr = 0;- ax25_requeue_frames(ax25);- break;-- case AX25_DISC:- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_disconnect(ax25, 0);- break;-- case AX25_DM:- ax25_disconnect(ax25, ECONNRESET);- break;-- case AX25_RR:- case AX25_RNR:- if (frametype == AX25_RR)- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;- else- ax25->condition |= AX25_COND_PEER_RX_BUSY;- if (type == AX25_COMMAND && pf)- ax25_std_enquiry_response(ax25);- if (ax25_validate_nr(ax25, nr)) {- ax25_check_iframes_acked(ax25, nr);- } else {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;-- case AX25_REJ:- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;- if (type == AX25_COMMAND && pf)- ax25_std_enquiry_response(ax25);- if (ax25_validate_nr(ax25, nr)) {- ax25_frames_acked(ax25, nr);- ax25_calculate_rtt(ax25);- ax25_stop_t1timer(ax25);- ax25_start_t3timer(ax25);- ax25_requeue_frames(ax25);- } else {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;-- case AX25_I:- if (!ax25_validate_nr(ax25, nr)) {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- break;- }- if (ax25->condition & AX25_COND_PEER_RX_BUSY) {- ax25_frames_acked(ax25, nr);- } else {- ax25_check_iframes_acked(ax25, nr);- }- if (ax25->condition & AX25_COND_OWN_RX_BUSY) {- if (pf) ax25_std_enquiry_response(ax25);- break;- }- if (ns == ax25->vr) {- ax25->vr = (ax25->vr + 1) % ax25->modulus;- queued = ax25_rx_iframe(ax25, skb);- if (ax25->condition & AX25_COND_OWN_RX_BUSY)- ax25->vr = ns; /* ax25->vr - 1 */- ax25->condition &= ~AX25_COND_REJECT;- if (pf) {- ax25_std_enquiry_response(ax25);- } else {- if (!(ax25->condition & AX25_COND_ACK_PENDING)) {- ax25->condition |= AX25_COND_ACK_PENDING;- ax25_start_t2timer(ax25);- }- }- } else {- if (ax25->condition & AX25_COND_REJECT) {- if (pf) ax25_std_enquiry_response(ax25);- } else {- ax25->condition |= AX25_COND_REJECT;- ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);- ax25->condition &= ~AX25_COND_ACK_PENDING;- }- }- break;-- case AX25_FRMR:- case AX25_ILLEGAL:- ax25_std_establish_data_link(ax25);- ax25->state = AX25_STATE_1;- break;-- default:- break;- }-- return queued;-}--/*- * State machine for state 4, Timer Recovery State.- * The handling of the timer(s) is in file ax25_std_timer.c- * Handling of state 0 and connection release is in ax25.c.- */-static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)-{- int queued = 0;-- switch (frametype) {- case AX25_SABM:- case AX25_SABME:- if (frametype == AX25_SABM) {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- } else {- ax25->modulus = AX25_EMODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];- }- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_stop_t1timer(ax25);- ax25_stop_t2timer(ax25);- ax25_start_t3timer(ax25);- ax25_start_idletimer(ax25);- ax25->condition = 0x00;- ax25->vs = 0;- ax25->va = 0;- ax25->vr = 0;- ax25->state = AX25_STATE_3;- ax25->n2count = 0;- ax25_requeue_frames(ax25);- break;-- case AX25_DISC:- ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);- ax25_disconnect(ax25, 0);- break;-- case AX25_DM:- ax25_disconnect(ax25, ECONNRESET);- break;-- case AX25_RR:- case AX25_RNR:- if (frametype == AX25_RR)- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;- else- ax25->condition |= AX25_COND_PEER_RX_BUSY;- if (type == AX25_RESPONSE && pf) {- ax25_stop_t1timer(ax25);- ax25->n2count = 0;- if (ax25_validate_nr(ax25, nr)) {- ax25_frames_acked(ax25, nr);- if (ax25->vs == ax25->va) {- ax25_start_t3timer(ax25);- ax25->state = AX25_STATE_3;- } else {- ax25_requeue_frames(ax25);- }- } else {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;- }- if (type == AX25_COMMAND && pf)- ax25_std_enquiry_response(ax25);- if (ax25_validate_nr(ax25, nr)) {- ax25_frames_acked(ax25, nr);- } else {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;-- case AX25_REJ:- ax25->condition &= ~AX25_COND_PEER_RX_BUSY;- if (pf && type == AX25_RESPONSE) {- ax25_stop_t1timer(ax25);- ax25->n2count = 0;- if (ax25_validate_nr(ax25, nr)) {- ax25_frames_acked(ax25, nr);- if (ax25->vs == ax25->va) {- ax25_start_t3timer(ax25);- ax25->state = AX25_STATE_3;- } else {- ax25_requeue_frames(ax25);- }- } else {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;- }- if (type == AX25_COMMAND && pf)- ax25_std_enquiry_response(ax25);- if (ax25_validate_nr(ax25, nr)) {- ax25_frames_acked(ax25, nr);- ax25_requeue_frames(ax25);- } else {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- }- break;-- case AX25_I:- if (!ax25_validate_nr(ax25, nr)) {- ax25_std_nr_error_recovery(ax25);- ax25->state = AX25_STATE_1;- break;- }- ax25_frames_acked(ax25, nr);- if (ax25->condition & AX25_COND_OWN_RX_BUSY) {- if (pf)- ax25_std_enquiry_response(ax25);- break;- }- if (ns == ax25->vr) {- ax25->vr = (ax25->vr + 1) % ax25->modulus;- queued = ax25_rx_iframe(ax25, skb);- if (ax25->condition & AX25_COND_OWN_RX_BUSY)- ax25->vr = ns; /* ax25->vr - 1 */- ax25->condition &= ~AX25_COND_REJECT;- if (pf) {- ax25_std_enquiry_response(ax25);- } else {- if (!(ax25->condition & AX25_COND_ACK_PENDING)) {- ax25->condition |= AX25_COND_ACK_PENDING;- ax25_start_t2timer(ax25);- }- }- } else {- if (ax25->condition & AX25_COND_REJECT) {- if (pf) ax25_std_enquiry_response(ax25);- } else {- ax25->condition |= AX25_COND_REJECT;- ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);- ax25->condition &= ~AX25_COND_ACK_PENDING;- }- }- break;-- case AX25_FRMR:- case AX25_ILLEGAL:- ax25_std_establish_data_link(ax25);- ax25->state = AX25_STATE_1;- break;-- default:- break;- }-- return queued;-}--/*- * Higher level upcall for a LAPB frame- */-int ax25_std_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)-{- int queued = 0, frametype, ns, nr, pf;-- frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);-- switch (ax25->state) {- case AX25_STATE_1:- queued = ax25_std_state1_machine(ax25, skb, frametype, pf, type);- break;- case AX25_STATE_2:- queued = ax25_std_state2_machine(ax25, skb, frametype, pf, type);- break;- case AX25_STATE_3:- queued = ax25_std_state3_machine(ax25, skb, frametype, ns, nr, pf, type);- break;- case AX25_STATE_4:- queued = ax25_std_state4_machine(ax25, skb, frametype, ns, nr, pf, type);- break;- }-- ax25_kick(ax25);-- return queued;-}diff --git a/net/ax25/ax25_std_subr.c b/net/ax25/ax25_std_subr.cdeleted file mode 100644index 4c36f1342558..000000000000--- a/net/ax25/ax25_std_subr.c+++ /dev/null@@ -1,83 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--/*- * The following routines are taken from page 170 of the 7th ARRL Computer- * Networking Conference paper, as is the whole state machine.- */--void ax25_std_nr_error_recovery(ax25_cb *ax25)-{- ax25_std_establish_data_link(ax25);-}--void ax25_std_establish_data_link(ax25_cb *ax25)-{- ax25->condition = 0x00;- ax25->n2count = 0;-- if (ax25->modulus == AX25_MODULUS)- ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);- else- ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);-- ax25_calculate_t1(ax25);- ax25_stop_idletimer(ax25);- ax25_stop_t3timer(ax25);- ax25_stop_t2timer(ax25);- ax25_start_t1timer(ax25);-}--void ax25_std_transmit_enquiry(ax25_cb *ax25)-{- if (ax25->condition & AX25_COND_OWN_RX_BUSY)- ax25_send_control(ax25, AX25_RNR, AX25_POLLON, AX25_COMMAND);- else- ax25_send_control(ax25, AX25_RR, AX25_POLLON, AX25_COMMAND);-- ax25->condition &= ~AX25_COND_ACK_PENDING;-- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);-}--void ax25_std_enquiry_response(ax25_cb *ax25)-{- if (ax25->condition & AX25_COND_OWN_RX_BUSY)- ax25_send_control(ax25, AX25_RNR, AX25_POLLON, AX25_RESPONSE);- else- ax25_send_control(ax25, AX25_RR, AX25_POLLON, AX25_RESPONSE);-- ax25->condition &= ~AX25_COND_ACK_PENDING;-}--void ax25_std_timeout_response(ax25_cb *ax25)-{- if (ax25->condition & AX25_COND_OWN_RX_BUSY)- ax25_send_control(ax25, AX25_RNR, AX25_POLLOFF, AX25_RESPONSE);- else- ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE);-- ax25->condition &= ~AX25_COND_ACK_PENDING;-}diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.cdeleted file mode 100644index b17da41210cb..000000000000--- a/net/ax25/ax25_std_timer.c+++ /dev/null@@ -1,175 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--void ax25_std_heartbeat_expiry(ax25_cb *ax25)-{- struct sock *sk = ax25->sk;-- if (sk)- bh_lock_sock(sk);-- switch (ax25->state) {- case AX25_STATE_0:- case AX25_STATE_2:- /* Magic here: If we listen() and a new link dies before it- is accepted() it isn't 'dead' so doesn't get removed. */- if (!sk || sock_flag(sk, SOCK_DESTROY) ||- (sk->sk_state == TCP_LISTEN &&- sock_flag(sk, SOCK_DEAD))) {- if (sk) {- sock_hold(sk);- ax25_destroy_socket(ax25);- bh_unlock_sock(sk);- /* Ungrab socket and destroy it */- sock_put(sk);- } else- ax25_destroy_socket(ax25);- return;- }- break;-- case AX25_STATE_3:- case AX25_STATE_4:- /*- * Check the state of the receive buffer.- */- if (sk != NULL) {- if (atomic_read(&sk->sk_rmem_alloc) <- (sk->sk_rcvbuf >> 1) &&- (ax25->condition & AX25_COND_OWN_RX_BUSY)) {- ax25->condition &= ~AX25_COND_OWN_RX_BUSY;- ax25->condition &= ~AX25_COND_ACK_PENDING;- ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE);- break;- }- }- }-- if (sk)- bh_unlock_sock(sk);-- ax25_start_heartbeat(ax25);-}--void ax25_std_t2timer_expiry(ax25_cb *ax25)-{- if (ax25->condition & AX25_COND_ACK_PENDING) {- ax25->condition &= ~AX25_COND_ACK_PENDING;- ax25_std_timeout_response(ax25);- }-}--void ax25_std_t3timer_expiry(ax25_cb *ax25)-{- ax25->n2count = 0;- ax25_std_transmit_enquiry(ax25);- ax25->state = AX25_STATE_4;-}--void ax25_std_idletimer_expiry(ax25_cb *ax25)-{- ax25_clear_queues(ax25);-- ax25->n2count = 0;- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- ax25->state = AX25_STATE_2;-- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);- ax25_stop_t2timer(ax25);- ax25_stop_t3timer(ax25);-- if (ax25->sk != NULL) {- bh_lock_sock(ax25->sk);- ax25->sk->sk_state = TCP_CLOSE;- ax25->sk->sk_err = 0;- ax25->sk->sk_shutdown |= SEND_SHUTDOWN;- if (!sock_flag(ax25->sk, SOCK_DEAD)) {- ax25->sk->sk_state_change(ax25->sk);- sock_set_flag(ax25->sk, SOCK_DEAD);- }- bh_unlock_sock(ax25->sk);- }-}--void ax25_std_t1timer_expiry(ax25_cb *ax25)-{- switch (ax25->state) {- case AX25_STATE_1:- if (ax25->n2count == ax25->n2) {- if (ax25->modulus == AX25_MODULUS) {- ax25_disconnect(ax25, ETIMEDOUT);- return;- } else {- ax25->modulus = AX25_MODULUS;- ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];- ax25->n2count = 0;- ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);- }- } else {- ax25->n2count++;- if (ax25->modulus == AX25_MODULUS)- ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);- else- ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);- }- break;-- case AX25_STATE_2:- if (ax25->n2count == ax25->n2) {- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- if (!sock_flag(ax25->sk, SOCK_DESTROY))- ax25_disconnect(ax25, ETIMEDOUT);- return;- } else {- ax25->n2count++;- ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);- }- break;-- case AX25_STATE_3:- ax25->n2count = 1;- ax25_std_transmit_enquiry(ax25);- ax25->state = AX25_STATE_4;- break;-- case AX25_STATE_4:- if (ax25->n2count == ax25->n2) {- ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);- ax25_disconnect(ax25, ETIMEDOUT);- return;- } else {- ax25->n2count++;- ax25_std_transmit_enquiry(ax25);- }- break;- }-- ax25_calculate_t1(ax25);- ax25_start_t1timer(ax25);-}diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.cdeleted file mode 100644index bff4b203a893..000000000000--- a/net/ax25/ax25_subr.c+++ /dev/null@@ -1,296 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--/*- * This routine purges all the queues of frames.- */-void ax25_clear_queues(ax25_cb *ax25)-{- skb_queue_purge(&ax25->write_queue);- skb_queue_purge(&ax25->ack_queue);- skb_queue_purge(&ax25->reseq_queue);- skb_queue_purge(&ax25->frag_queue);-}--/*- * This routine purges the input queue of those frames that have been- * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the- * SDL diagram.- */-void ax25_frames_acked(ax25_cb *ax25, unsigned short nr)-{- struct sk_buff *skb;-- /*- * Remove all the ack-ed frames from the ack queue.- */- if (ax25->va != nr) {- while (skb_peek(&ax25->ack_queue) != NULL && ax25->va != nr) {- skb = skb_dequeue(&ax25->ack_queue);- kfree_skb(skb);- ax25->va = (ax25->va + 1) % ax25->modulus;- }- }-}--void ax25_requeue_frames(ax25_cb *ax25)-{- struct sk_buff *skb;-- /*- * Requeue all the un-ack-ed frames on the output queue to be picked- * up by ax25_kick called from the timer. This arrangement handles the- * possibility of an empty output queue.- */- while ((skb = skb_dequeue_tail(&ax25->ack_queue)) != NULL)- skb_queue_head(&ax25->write_queue, skb);-}--/*- * Validate that the value of nr is between va and vs. Return true or- * false for testing.- */-int ax25_validate_nr(ax25_cb *ax25, unsigned short nr)-{- unsigned short vc = ax25->va;-- while (vc != ax25->vs) {- if (nr == vc) return 1;- vc = (vc + 1) % ax25->modulus;- }-- if (nr == ax25->vs) return 1;-- return 0;-}--/*- * This routine is the centralised routine for parsing the control- * information for the different frame formats.- */-int ax25_decode(ax25_cb *ax25, struct sk_buff *skb, int *ns, int *nr, int *pf)-{- unsigned char *frame;- int frametype = AX25_ILLEGAL;-- frame = skb->data;- *ns = *nr = *pf = 0;-- if (ax25->modulus == AX25_MODULUS) {- if ((frame[0] & AX25_S) == 0) {- frametype = AX25_I; /* I frame - carries NR/NS/PF */- *ns = (frame[0] >> 1) & 0x07;- *nr = (frame[0] >> 5) & 0x07;- *pf = frame[0] & AX25_PF;- } else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */- frametype = frame[0] & 0x0F;- *nr = (frame[0] >> 5) & 0x07;- *pf = frame[0] & AX25_PF;- } else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */- frametype = frame[0] & ~AX25_PF;- *pf = frame[0] & AX25_PF;- }- skb_pull(skb, 1);- } else {- if ((frame[0] & AX25_S) == 0) {- frametype = AX25_I; /* I frame - carries NR/NS/PF */- *ns = (frame[0] >> 1) & 0x7F;- *nr = (frame[1] >> 1) & 0x7F;- *pf = frame[1] & AX25_EPF;- skb_pull(skb, 2);- } else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */- frametype = frame[0] & 0x0F;- *nr = (frame[1] >> 1) & 0x7F;- *pf = frame[1] & AX25_EPF;- skb_pull(skb, 2);- } else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */- frametype = frame[0] & ~AX25_PF;- *pf = frame[0] & AX25_PF;- skb_pull(skb, 1);- }- }-- return frametype;-}--/*- * This routine is called when the HDLC layer internally generates a- * command or response for the remote machine ( eg. RR, UA etc. ).- * Only supervisory or unnumbered frames are processed.- */-void ax25_send_control(ax25_cb *ax25, int frametype, int poll_bit, int type)-{- struct sk_buff *skb;- unsigned char *dptr;-- if ((skb = alloc_skb(ax25->ax25_dev->dev->hard_header_len + 2, GFP_ATOMIC)) == NULL)- return;-- skb_reserve(skb, ax25->ax25_dev->dev->hard_header_len);-- skb_reset_network_header(skb);-- /* Assume a response - address structure for DTE */- if (ax25->modulus == AX25_MODULUS) {- dptr = skb_put(skb, 1);- *dptr = frametype;- *dptr |= (poll_bit) ? AX25_PF : 0;- if ((frametype & AX25_U) == AX25_S) /* S frames carry NR */- *dptr |= (ax25->vr << 5);- } else {- if ((frametype & AX25_U) == AX25_U) {- dptr = skb_put(skb, 1);- *dptr = frametype;- *dptr |= (poll_bit) ? AX25_PF : 0;- } else {- dptr = skb_put(skb, 2);- dptr[0] = frametype;- dptr[1] = (ax25->vr << 1);- dptr[1] |= (poll_bit) ? AX25_EPF : 0;- }- }-- ax25_transmit_buffer(ax25, skb, type);-}--/*- * Send a 'DM' to an unknown connection attempt, or an invalid caller.- *- * Note: src here is the sender, thus it's the target of the DM- */-void ax25_return_dm(struct net_device *dev, ax25_address *src, ax25_address *dest, ax25_digi *digi)-{- struct sk_buff *skb;- char *dptr;- ax25_digi retdigi;-- if (dev == NULL)- return;-- if ((skb = alloc_skb(dev->hard_header_len + 1, GFP_ATOMIC)) == NULL)- return; /* Next SABM will get DM'd */-- skb_reserve(skb, dev->hard_header_len);- skb_reset_network_header(skb);-- ax25_digi_invert(digi, &retdigi);-- dptr = skb_put(skb, 1);-- *dptr = AX25_DM | AX25_PF;-- /*- * Do the address ourselves- */- dptr = skb_push(skb, ax25_addr_size(digi));- dptr += ax25_addr_build(dptr, dest, src, &retdigi, AX25_RESPONSE, AX25_MODULUS);-- ax25_queue_xmit(skb, dev);-}--/*- * Exponential backoff for AX.25- */-void ax25_calculate_t1(ax25_cb *ax25)-{- int n, t = 2;-- switch (ax25->backoff) {- case 0:- break;-- case 1:- t += 2 * ax25->n2count;- break;-- case 2:- for (n = 0; n < ax25->n2count; n++)- t *= 2;- if (t > 8) t = 8;- break;- }-- ax25->t1 = t * ax25->rtt;-}--/*- * Calculate the Round Trip Time- */-void ax25_calculate_rtt(ax25_cb *ax25)-{- if (ax25->backoff == 0)- return;-- if (ax25_t1timer_running(ax25) && ax25->n2count == 0)- ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25_display_timer(&ax25->t1timer)) / 10;-- if (ax25->rtt < AX25_T1CLAMPLO)- ax25->rtt = AX25_T1CLAMPLO;-- if (ax25->rtt > AX25_T1CLAMPHI)- ax25->rtt = AX25_T1CLAMPHI;-}--void ax25_disconnect(ax25_cb *ax25, int reason)-{- ax25_clear_queues(ax25);-- if (reason == ENETUNREACH) {- timer_delete_sync(&ax25->timer);- timer_delete_sync(&ax25->t1timer);- timer_delete_sync(&ax25->t2timer);- timer_delete_sync(&ax25->t3timer);- timer_delete_sync(&ax25->idletimer);- } else {- if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY))- ax25_stop_heartbeat(ax25);- ax25_stop_t1timer(ax25);- ax25_stop_t2timer(ax25);- ax25_stop_t3timer(ax25);- ax25_stop_idletimer(ax25);- }-- ax25->state = AX25_STATE_0;-- ax25_link_failed(ax25, reason);-- if (ax25->sk != NULL) {- local_bh_disable();- bh_lock_sock(ax25->sk);- ax25->sk->sk_state = TCP_CLOSE;- ax25->sk->sk_err = reason;- ax25->sk->sk_shutdown |= SEND_SHUTDOWN;- if (!sock_flag(ax25->sk, SOCK_DEAD)) {- ax25->sk->sk_state_change(ax25->sk);- sock_set_flag(ax25->sk, SOCK_DEAD);- }- bh_unlock_sock(ax25->sk);- local_bh_enable();- }-}diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.cdeleted file mode 100644index a69bfbc8b679..000000000000--- a/net/ax25/ax25_timer.c+++ /dev/null@@ -1,224 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)- * Copyright (C) Darryl Miles G7LED (dlm@g7led.demon.co.uk)- * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)- * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)- * Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/module.h>-#include <linux/jiffies.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>--static void ax25_heartbeat_expiry(struct timer_list *);-static void ax25_t1timer_expiry(struct timer_list *);-static void ax25_t2timer_expiry(struct timer_list *);-static void ax25_t3timer_expiry(struct timer_list *);-static void ax25_idletimer_expiry(struct timer_list *);--void ax25_setup_timers(ax25_cb *ax25)-{- timer_setup(&ax25->timer, ax25_heartbeat_expiry, 0);- timer_setup(&ax25->t1timer, ax25_t1timer_expiry, 0);- timer_setup(&ax25->t2timer, ax25_t2timer_expiry, 0);- timer_setup(&ax25->t3timer, ax25_t3timer_expiry, 0);- timer_setup(&ax25->idletimer, ax25_idletimer_expiry, 0);-}--void ax25_start_heartbeat(ax25_cb *ax25)-{- mod_timer(&ax25->timer, jiffies + 5 * HZ);-}--void ax25_start_t1timer(ax25_cb *ax25)-{- mod_timer(&ax25->t1timer, jiffies + ax25->t1);-}--void ax25_start_t2timer(ax25_cb *ax25)-{- mod_timer(&ax25->t2timer, jiffies + ax25->t2);-}--void ax25_start_t3timer(ax25_cb *ax25)-{- if (ax25->t3 > 0)- mod_timer(&ax25->t3timer, jiffies + ax25->t3);- else- timer_delete(&ax25->t3timer);-}--void ax25_start_idletimer(ax25_cb *ax25)-{- if (ax25->idle > 0)- mod_timer(&ax25->idletimer, jiffies + ax25->idle);- else- timer_delete(&ax25->idletimer);-}--void ax25_stop_heartbeat(ax25_cb *ax25)-{- timer_delete(&ax25->timer);-}--void ax25_stop_t1timer(ax25_cb *ax25)-{- timer_delete(&ax25->t1timer);-}--void ax25_stop_t2timer(ax25_cb *ax25)-{- timer_delete(&ax25->t2timer);-}--void ax25_stop_t3timer(ax25_cb *ax25)-{- timer_delete(&ax25->t3timer);-}--void ax25_stop_idletimer(ax25_cb *ax25)-{- timer_delete(&ax25->idletimer);-}--int ax25_t1timer_running(ax25_cb *ax25)-{- return timer_pending(&ax25->t1timer);-}--unsigned long ax25_display_timer(struct timer_list *timer)-{- long delta = timer->expires - jiffies;-- if (!timer_pending(timer))- return 0;-- return max(0L, delta);-}--EXPORT_SYMBOL(ax25_display_timer);--static void ax25_heartbeat_expiry(struct timer_list *t)-{- int proto = AX25_PROTO_STD_SIMPLEX;- ax25_cb *ax25 = timer_container_of(ax25, t, timer);-- if (ax25->ax25_dev)- proto = ax25->ax25_dev->values[AX25_VALUES_PROTOCOL];-- switch (proto) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_std_heartbeat_expiry(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- if (ax25->ax25_dev->dama.slave)- ax25_ds_heartbeat_expiry(ax25);- else- ax25_std_heartbeat_expiry(ax25);- break;-#endif- }-}--static void ax25_t1timer_expiry(struct timer_list *t)-{- ax25_cb *ax25 = timer_container_of(ax25, t, t1timer);-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_std_t1timer_expiry(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- if (!ax25->ax25_dev->dama.slave)- ax25_std_t1timer_expiry(ax25);- break;-#endif- }-}--static void ax25_t2timer_expiry(struct timer_list *t)-{- ax25_cb *ax25 = timer_container_of(ax25, t, t2timer);-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_std_t2timer_expiry(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- if (!ax25->ax25_dev->dama.slave)- ax25_std_t2timer_expiry(ax25);- break;-#endif- }-}--static void ax25_t3timer_expiry(struct timer_list *t)-{- ax25_cb *ax25 = timer_container_of(ax25, t, t3timer);-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_std_t3timer_expiry(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- if (ax25->ax25_dev->dama.slave)- ax25_ds_t3timer_expiry(ax25);- else- ax25_std_t3timer_expiry(ax25);- break;-#endif- }-}--static void ax25_idletimer_expiry(struct timer_list *t)-{- ax25_cb *ax25 = timer_container_of(ax25, t, idletimer);-- switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {- case AX25_PROTO_STD_SIMPLEX:- case AX25_PROTO_STD_DUPLEX:- ax25_std_idletimer_expiry(ax25);- break;--#ifdef CONFIG_AX25_DAMA_SLAVE- case AX25_PROTO_DAMA_SLAVE:- if (ax25->ax25_dev->dama.slave)- ax25_ds_idletimer_expiry(ax25);- else- ax25_std_idletimer_expiry(ax25);- break;-#endif- }-}diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.cdeleted file mode 100644index 159ce74273f0..000000000000--- a/net/ax25/ax25_uid.c+++ /dev/null@@ -1,204 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */--#include <linux/capability.h>-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/spinlock.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/list.h>-#include <linux/notifier.h>-#include <linux/proc_fs.h>-#include <linux/seq_file.h>-#include <linux/stat.h>-#include <linux/sysctl.h>-#include <linux/export.h>-#include <net/ip.h>-#include <net/arp.h>--/*- * Callsign/UID mapper. This is in kernel space for security on multi-amateur machines.- */--static HLIST_HEAD(ax25_uid_list);-static DEFINE_RWLOCK(ax25_uid_lock);--int ax25_uid_policy;--EXPORT_SYMBOL(ax25_uid_policy);--ax25_uid_assoc *ax25_findbyuid(kuid_t uid)-{- ax25_uid_assoc *ax25_uid, *res = NULL;-- read_lock(&ax25_uid_lock);- ax25_uid_for_each(ax25_uid, &ax25_uid_list) {- if (uid_eq(ax25_uid->uid, uid)) {- ax25_uid_hold(ax25_uid);- res = ax25_uid;- break;- }- }- read_unlock(&ax25_uid_lock);-- return res;-}--EXPORT_SYMBOL(ax25_findbyuid);--int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)-{- ax25_uid_assoc *ax25_uid;- ax25_uid_assoc *user;- unsigned long res;-- switch (cmd) {- case SIOCAX25GETUID:- res = -ENOENT;- read_lock(&ax25_uid_lock);- ax25_uid_for_each(ax25_uid, &ax25_uid_list) {- if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {- res = from_kuid_munged(current_user_ns(), ax25_uid->uid);- break;- }- }- read_unlock(&ax25_uid_lock);-- return res;-- case SIOCAX25ADDUID:- {- kuid_t sax25_kuid;- if (!capable(CAP_NET_ADMIN))- return -EPERM;- sax25_kuid = make_kuid(current_user_ns(), sax->sax25_uid);- if (!uid_valid(sax25_kuid))- return -EINVAL;- user = ax25_findbyuid(sax25_kuid);- if (user) {- ax25_uid_put(user);- return -EEXIST;- }- if (sax->sax25_uid == 0)- return -EINVAL;- if ((ax25_uid = kmalloc_obj(*ax25_uid)) == NULL)- return -ENOMEM;-- refcount_set(&ax25_uid->refcount, 1);- ax25_uid->uid = sax25_kuid;- ax25_uid->call = sax->sax25_call;-- write_lock(&ax25_uid_lock);- hlist_add_head(&ax25_uid->uid_node, &ax25_uid_list);- write_unlock(&ax25_uid_lock);-- return 0;- }- case SIOCAX25DELUID:- if (!capable(CAP_NET_ADMIN))- return -EPERM;-- ax25_uid = NULL;- write_lock(&ax25_uid_lock);- ax25_uid_for_each(ax25_uid, &ax25_uid_list) {- if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)- break;- }- if (ax25_uid == NULL) {- write_unlock(&ax25_uid_lock);- return -ENOENT;- }- hlist_del_init(&ax25_uid->uid_node);- ax25_uid_put(ax25_uid);- write_unlock(&ax25_uid_lock);-- return 0;-- default:- return -EINVAL;- }-- return -EINVAL; /*NOTREACHED */-}--#ifdef CONFIG_PROC_FS--static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos)- __acquires(ax25_uid_lock)-{- read_lock(&ax25_uid_lock);- return seq_hlist_start_head(&ax25_uid_list, *pos);-}--static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)-{- return seq_hlist_next(v, &ax25_uid_list, pos);-}--static void ax25_uid_seq_stop(struct seq_file *seq, void *v)- __releases(ax25_uid_lock)-{- read_unlock(&ax25_uid_lock);-}--static int ax25_uid_seq_show(struct seq_file *seq, void *v)-{- char buf[11];-- if (v == SEQ_START_TOKEN)- seq_printf(seq, "Policy: %d\n", ax25_uid_policy);- else {- struct ax25_uid_assoc *pt;-- pt = hlist_entry(v, struct ax25_uid_assoc, uid_node);- seq_printf(seq, "%6d %s\n",- from_kuid_munged(seq_user_ns(seq), pt->uid),- ax2asc(buf, &pt->call));- }- return 0;-}--const struct seq_operations ax25_uid_seqops = {- .start = ax25_uid_seq_start,- .next = ax25_uid_seq_next,- .stop = ax25_uid_seq_stop,- .show = ax25_uid_seq_show,-};-#endif--/*- * Free all memory associated with UID/Callsign structures.- */-void __exit ax25_uid_free(void)-{- ax25_uid_assoc *ax25_uid;-- write_lock(&ax25_uid_lock);-again:- ax25_uid_for_each(ax25_uid, &ax25_uid_list) {- hlist_del_init(&ax25_uid->uid_node);- ax25_uid_put(ax25_uid);- goto again;- }- write_unlock(&ax25_uid_lock);-}diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.cdeleted file mode 100644index 68753aa30334..000000000000--- a/net/ax25/sysctl_net_ax25.c+++ /dev/null@@ -1,181 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)- */-#include <linux/mm.h>-#include <linux/slab.h>-#include <linux/sysctl.h>-#include <linux/spinlock.h>-#include <net/ax25.h>--static int min_ipdefmode[1], max_ipdefmode[] = {1};-static int min_axdefmode[1], max_axdefmode[] = {1};-static int min_backoff[1], max_backoff[] = {2};-static int min_conmode[1], max_conmode[] = {2};-static int min_window[] = {1}, max_window[] = {7};-static int min_ewindow[] = {1}, max_ewindow[] = {63};-static int min_t1[] = {1}, max_t1[] = {30000};-static int min_t2[] = {1}, max_t2[] = {20000};-static int min_t3[1], max_t3[] = {3600000};-static int min_idle[1], max_idle[] = {65535000};-static int min_n2[] = {1}, max_n2[] = {31};-static int min_paclen[] = {1}, max_paclen[] = {512};-static int min_proto[1], max_proto[] = { AX25_PROTO_MAX };-#ifdef CONFIG_AX25_DAMA_SLAVE-static int min_ds_timeout[1], max_ds_timeout[] = {65535000};-#endif--static const struct ctl_table ax25_param_table[] = {- {- .procname = "ip_default_mode",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_ipdefmode,- .extra2 = &max_ipdefmode- },- {- .procname = "ax25_default_mode",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_axdefmode,- .extra2 = &max_axdefmode- },- {- .procname = "backoff_type",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_backoff,- .extra2 = &max_backoff- },- {- .procname = "connect_mode",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_conmode,- .extra2 = &max_conmode- },- {- .procname = "standard_window_size",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_window,- .extra2 = &max_window- },- {- .procname = "extended_window_size",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_ewindow,- .extra2 = &max_ewindow- },- {- .procname = "t1_timeout",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_t1,- .extra2 = &max_t1- },- {- .procname = "t2_timeout",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_t2,- .extra2 = &max_t2- },- {- .procname = "t3_timeout",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_t3,- .extra2 = &max_t3- },- {- .procname = "idle_timeout",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_idle,- .extra2 = &max_idle- },- {- .procname = "maximum_retry_count",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_n2,- .extra2 = &max_n2- },- {- .procname = "maximum_packet_length",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_paclen,- .extra2 = &max_paclen- },- {- .procname = "protocol",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_proto,- .extra2 = &max_proto- },-#ifdef CONFIG_AX25_DAMA_SLAVE- {- .procname = "dama_slave_timeout",- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_ds_timeout,- .extra2 = &max_ds_timeout- },-#endif-};--int ax25_register_dev_sysctl(ax25_dev *ax25_dev)-{- char path[sizeof("net/ax25/") + IFNAMSIZ];- int k;- struct ctl_table *table;-- table = kmemdup(ax25_param_table, sizeof(ax25_param_table), GFP_KERNEL);- if (!table)- return -ENOMEM;-- BUILD_BUG_ON(ARRAY_SIZE(ax25_param_table) != AX25_MAX_VALUES);- for (k = 0; k < AX25_MAX_VALUES; k++)- table[k].data = &ax25_dev->values[k];-- snprintf(path, sizeof(path), "net/ax25/%s", ax25_dev->dev->name);- ax25_dev->sysheader = register_net_sysctl_sz(&init_net, path, table,- ARRAY_SIZE(ax25_param_table));- if (!ax25_dev->sysheader) {- kfree(table);- return -ENOMEM;- }- return 0;-}--void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev)-{- struct ctl_table_header *header = ax25_dev->sysheader;- const struct ctl_table *table;-- if (header) {- ax25_dev->sysheader = NULL;- table = header->ctl_table_arg;- unregister_net_sysctl_table(header);- kfree(table);- }-}diff --git a/net/ipv4/arp.c b/net/ipv4/arp.cindex 51d70180e1cc..d409f606aec0 100644--- a/net/ipv4/arp.c+++ b/net/ipv4/arp.c@@ -109,7 +109,6 @@ #include <net/sock.h> #include <net/arp.h> #include <net/ax25.h>-#include <net/netrom.h> #include <net/dst_metadata.h> #include <net/ip_tunnels.h> diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.cdeleted file mode 100644index 5fc54836dfa8..000000000000--- a/net/netrom/af_netrom.c+++ /dev/null@@ -1,1536 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk)- */-#include <linux/module.h>-#include <linux/moduleparam.h>-#include <linux/capability.h>-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/slab.h>-#include <linux/kernel.h>-#include <linux/sched/signal.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/stat.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/net_namespace.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/termios.h> /* For TIOCINQ/OUTQ */-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/notifier.h>-#include <net/netrom.h>-#include <linux/proc_fs.h>-#include <linux/seq_file.h>-#include <net/ip.h>-#include <net/tcp_states.h>-#include <net/arp.h>-#include <linux/init.h>--static int nr_ndevs = 4;--int sysctl_netrom_default_path_quality = NR_DEFAULT_QUAL;-int sysctl_netrom_obsolescence_count_initialiser = NR_DEFAULT_OBS;-int sysctl_netrom_network_ttl_initialiser = NR_DEFAULT_TTL;-int sysctl_netrom_transport_timeout = NR_DEFAULT_T1;-int sysctl_netrom_transport_maximum_tries = NR_DEFAULT_N2;-int sysctl_netrom_transport_acknowledge_delay = NR_DEFAULT_T2;-int sysctl_netrom_transport_busy_delay = NR_DEFAULT_T4;-int sysctl_netrom_transport_requested_window_size = NR_DEFAULT_WINDOW;-int sysctl_netrom_transport_no_activity_timeout = NR_DEFAULT_IDLE;-int sysctl_netrom_routing_control = NR_DEFAULT_ROUTING;-int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS;-int sysctl_netrom_reset_circuit = NR_DEFAULT_RESET;--static unsigned short circuit = 0x101;--static HLIST_HEAD(nr_list);-static DEFINE_SPINLOCK(nr_list_lock);--static const struct proto_ops nr_proto_ops;--/*- * NETROM network devices are virtual network devices encapsulating NETROM- * frames into AX.25 which will be sent through an AX.25 device, so form a- * special "super class" of normal net devices; split their locks off into a- * separate class since they always nest.- */-static struct lock_class_key nr_netdev_xmit_lock_key;-static struct lock_class_key nr_netdev_addr_lock_key;--static void nr_set_lockdep_one(struct net_device *dev,- struct netdev_queue *txq,- void *_unused)-{- lockdep_set_class(&txq->_xmit_lock, &nr_netdev_xmit_lock_key);-}--static void nr_set_lockdep_key(struct net_device *dev)-{- lockdep_set_class(&dev->addr_list_lock, &nr_netdev_addr_lock_key);- netdev_for_each_tx_queue(dev, nr_set_lockdep_one, NULL);-}--/*- * Socket removal during an interrupt is now safe.- */-static void nr_remove_socket(struct sock *sk)-{- spin_lock_bh(&nr_list_lock);- sk_del_node_init(sk);- spin_unlock_bh(&nr_list_lock);-}--/*- * Kill all bound sockets on a dropped device.- */-static void nr_kill_by_device(struct net_device *dev)-{- struct sock *s;-- spin_lock_bh(&nr_list_lock);- sk_for_each(s, &nr_list)- if (nr_sk(s)->device == dev)- nr_disconnect(s, ENETUNREACH);- spin_unlock_bh(&nr_list_lock);-}--/*- * Handle device status changes.- */-static int nr_device_event(struct notifier_block *this, unsigned long event, void *ptr)-{- struct net_device *dev = netdev_notifier_info_to_dev(ptr);-- if (!net_eq(dev_net(dev), &init_net))- return NOTIFY_DONE;-- if (event != NETDEV_DOWN)- return NOTIFY_DONE;-- nr_kill_by_device(dev);- nr_rt_device_down(dev);-- return NOTIFY_DONE;-}--/*- * Add a socket to the bound sockets list.- */-static void nr_insert_socket(struct sock *sk)-{- spin_lock_bh(&nr_list_lock);- sk_add_node(sk, &nr_list);- spin_unlock_bh(&nr_list_lock);-}--/*- * Find a socket that wants to accept the Connect Request we just- * received.- */-static struct sock *nr_find_listener(ax25_address *addr)-{- struct sock *s;-- spin_lock_bh(&nr_list_lock);- sk_for_each(s, &nr_list)- if (!ax25cmp(&nr_sk(s)->source_addr, addr) &&- s->sk_state == TCP_LISTEN) {- sock_hold(s);- goto found;- }- s = NULL;-found:- spin_unlock_bh(&nr_list_lock);- return s;-}--/*- * Find a connected NET/ROM socket given my circuit IDs.- */-static struct sock *nr_find_socket(unsigned char index, unsigned char id)-{- struct sock *s;-- spin_lock_bh(&nr_list_lock);- sk_for_each(s, &nr_list) {- struct nr_sock *nr = nr_sk(s);-- if (nr->my_index == index && nr->my_id == id) {- sock_hold(s);- goto found;- }- }- s = NULL;-found:- spin_unlock_bh(&nr_list_lock);- return s;-}--/*- * Find a connected NET/ROM socket given their circuit IDs.- */-static struct sock *nr_find_peer(unsigned char index, unsigned char id,- ax25_address *dest)-{- struct sock *s;-- spin_lock_bh(&nr_list_lock);- sk_for_each(s, &nr_list) {- struct nr_sock *nr = nr_sk(s);-- if (nr->your_index == index && nr->your_id == id &&- !ax25cmp(&nr->dest_addr, dest)) {- sock_hold(s);- goto found;- }- }- s = NULL;-found:- spin_unlock_bh(&nr_list_lock);- return s;-}--/*- * Find next free circuit ID.- */-static unsigned short nr_find_next_circuit(void)-{- unsigned short id = circuit;- unsigned char i, j;- struct sock *sk;-- for (;;) {- i = id / 256;- j = id % 256;-- if (i != 0 && j != 0) {- if ((sk=nr_find_socket(i, j)) == NULL)- break;- sock_put(sk);- }-- id++;- }-- return id;-}--/*- * Deferred destroy.- */-void nr_destroy_socket(struct sock *);--/*- * Handler for deferred kills.- */-static void nr_destroy_timer(struct timer_list *t)-{- struct sock *sk = timer_container_of(sk, t, sk_timer);- bh_lock_sock(sk);- sock_hold(sk);- nr_destroy_socket(sk);- bh_unlock_sock(sk);- sock_put(sk);-}--/*- * This is called from user mode and the timers. Thus it protects itself- * against interrupt users but doesn't worry about being called during- * work. Once it is removed from the queue no interrupt or bottom half- * will touch it and we are (fairly 8-) ) safe.- */-void nr_destroy_socket(struct sock *sk)-{- struct sk_buff *skb;-- nr_remove_socket(sk);-- nr_stop_heartbeat(sk);- nr_stop_t1timer(sk);- nr_stop_t2timer(sk);- nr_stop_t4timer(sk);- nr_stop_idletimer(sk);-- nr_clear_queues(sk); /* Flush the queues */-- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {- if (skb->sk != sk) { /* A pending connection */- /* Queue the unaccepted socket for death */- sock_set_flag(skb->sk, SOCK_DEAD);- nr_start_heartbeat(skb->sk);- nr_sk(skb->sk)->state = NR_STATE_0;- }-- kfree_skb(skb);- }-- if (sk_has_allocations(sk)) {- /* Defer: outstanding buffers */- sk->sk_timer.function = nr_destroy_timer;- sk->sk_timer.expires = jiffies + 2 * HZ;- add_timer(&sk->sk_timer);- } else- sock_put(sk);-}--/*- * Handling for system calls applied via the various interfaces to a- * NET/ROM socket object.- */--static int nr_setsockopt(struct socket *sock, int level, int optname,- sockptr_t optval, unsigned int optlen)-{- struct sock *sk = sock->sk;- struct nr_sock *nr = nr_sk(sk);- unsigned int opt;-- if (level != SOL_NETROM)- return -ENOPROTOOPT;-- if (optlen < sizeof(unsigned int))- return -EINVAL;-- if (copy_from_sockptr(&opt, optval, sizeof(opt)))- return -EFAULT;-- switch (optname) {- case NETROM_T1:- if (opt < 1 || opt > UINT_MAX / HZ)- return -EINVAL;- nr->t1 = opt * HZ;- return 0;-- case NETROM_T2:- if (opt < 1 || opt > UINT_MAX / HZ)- return -EINVAL;- nr->t2 = opt * HZ;- return 0;-- case NETROM_N2:- if (opt < 1 || opt > 31)- return -EINVAL;- nr->n2 = opt;- return 0;-- case NETROM_T4:- if (opt < 1 || opt > UINT_MAX / HZ)- return -EINVAL;- nr->t4 = opt * HZ;- return 0;-- case NETROM_IDLE:- if (opt > UINT_MAX / (60 * HZ))- return -EINVAL;- nr->idle = opt * 60 * HZ;- return 0;-- default:- return -ENOPROTOOPT;- }-}--static int nr_getsockopt(struct socket *sock, int level, int optname,- char __user *optval, int __user *optlen)-{- struct sock *sk = sock->sk;- struct nr_sock *nr = nr_sk(sk);- int val = 0;- int len;-- if (level != SOL_NETROM)- return -ENOPROTOOPT;-- if (get_user(len, optlen))- return -EFAULT;-- if (len < 0)- return -EINVAL;-- switch (optname) {- case NETROM_T1:- val = nr->t1 / HZ;- break;-- case NETROM_T2:- val = nr->t2 / HZ;- break;-- case NETROM_N2:- val = nr->n2;- break;-- case NETROM_T4:- val = nr->t4 / HZ;- break;-- case NETROM_IDLE:- val = nr->idle / (60 * HZ);- break;-- default:- return -ENOPROTOOPT;- }-- len = min_t(unsigned int, len, sizeof(int));-- if (put_user(len, optlen))- return -EFAULT;-- return copy_to_user(optval, &val, len) ? -EFAULT : 0;-}--static int nr_listen(struct socket *sock, int backlog)-{- struct sock *sk = sock->sk;-- lock_sock(sk);- if (sock->state != SS_UNCONNECTED) {- release_sock(sk);- return -EINVAL;- }-- if (sk->sk_state != TCP_LISTEN) {- memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);- sk->sk_max_ack_backlog = backlog;- sk->sk_state = TCP_LISTEN;- release_sock(sk);- return 0;- }- release_sock(sk);-- return -EOPNOTSUPP;-}--static struct proto nr_proto = {- .name = "NETROM",- .owner = THIS_MODULE,- .obj_size = sizeof(struct nr_sock),-};--static int nr_create(struct net *net, struct socket *sock, int protocol,- int kern)-{- struct sock *sk;- struct nr_sock *nr;-- if (!net_eq(net, &init_net))- return -EAFNOSUPPORT;-- if (sock->type != SOCK_SEQPACKET || protocol != 0)- return -ESOCKTNOSUPPORT;-- sk = sk_alloc(net, PF_NETROM, GFP_ATOMIC, &nr_proto, kern);- if (sk == NULL)- return -ENOMEM;-- nr = nr_sk(sk);-- sock_init_data(sock, sk);-- sock->ops = &nr_proto_ops;- sk->sk_protocol = protocol;-- skb_queue_head_init(&nr->ack_queue);- skb_queue_head_init(&nr->reseq_queue);- skb_queue_head_init(&nr->frag_queue);-- nr_init_timers(sk);-- nr->t1 =- msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_timeout));- nr->t2 =- msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_acknowledge_delay));- nr->n2 =- msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries));- nr->t4 =- msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay));- nr->idle =- msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_no_activity_timeout));- nr->window = READ_ONCE(sysctl_netrom_transport_requested_window_size);-- nr->bpqext = 1;- nr->state = NR_STATE_0;-- return 0;-}--static struct sock *nr_make_new(struct sock *osk)-{- struct sock *sk;- struct nr_sock *nr, *onr;-- if (osk->sk_type != SOCK_SEQPACKET)- return NULL;-- sk = sk_alloc(sock_net(osk), PF_NETROM, GFP_ATOMIC, osk->sk_prot, 0);- if (sk == NULL)- return NULL;-- nr = nr_sk(sk);-- sock_init_data(NULL, sk);-- sk->sk_type = osk->sk_type;- sk->sk_priority = READ_ONCE(osk->sk_priority);- sk->sk_protocol = osk->sk_protocol;- sk->sk_rcvbuf = osk->sk_rcvbuf;- sk->sk_sndbuf = osk->sk_sndbuf;- sk->sk_state = TCP_ESTABLISHED;- sock_copy_flags(sk, osk);-- skb_queue_head_init(&nr->ack_queue);- skb_queue_head_init(&nr->reseq_queue);- skb_queue_head_init(&nr->frag_queue);-- nr_init_timers(sk);-- onr = nr_sk(osk);-- nr->t1 = onr->t1;- nr->t2 = onr->t2;- nr->n2 = onr->n2;- nr->t4 = onr->t4;- nr->idle = onr->idle;- nr->window = onr->window;-- nr->device = onr->device;- nr->bpqext = onr->bpqext;-- return sk;-}--static int nr_release(struct socket *sock)-{- struct sock *sk = sock->sk;- struct nr_sock *nr;-- if (sk == NULL) return 0;-- sock_hold(sk);- sock_orphan(sk);- lock_sock(sk);- nr = nr_sk(sk);-- switch (nr->state) {- case NR_STATE_0:- case NR_STATE_1:- case NR_STATE_2:- nr_disconnect(sk, 0);- nr_destroy_socket(sk);- break;-- case NR_STATE_3:- nr_clear_queues(sk);- nr->n2count = 0;- nr_write_internal(sk, NR_DISCREQ);- nr_start_t1timer(sk);- nr_stop_t2timer(sk);- nr_stop_t4timer(sk);- nr_stop_idletimer(sk);- nr->state = NR_STATE_2;- sk->sk_state = TCP_CLOSE;- sk->sk_shutdown |= SEND_SHUTDOWN;- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DESTROY);- break;-- default:- break;- }-- sock->sk = NULL;- release_sock(sk);- sock_put(sk);-- return 0;-}--static int nr_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int addr_len)-{- struct sock *sk = sock->sk;- struct nr_sock *nr = nr_sk(sk);- struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;- struct net_device *dev;- ax25_uid_assoc *user;- ax25_address *source;-- lock_sock(sk);- if (!sock_flag(sk, SOCK_ZAPPED)) {- release_sock(sk);- return -EINVAL;- }- if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25)) {- release_sock(sk);- return -EINVAL;- }- if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25))) {- release_sock(sk);- return -EINVAL;- }- if (addr->fsa_ax25.sax25_family != AF_NETROM) {- release_sock(sk);- return -EINVAL;- }- if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) {- release_sock(sk);- return -EADDRNOTAVAIL;- }-- /*- * Only the super user can set an arbitrary user callsign.- */- if (addr->fsa_ax25.sax25_ndigis == 1) {- if (!capable(CAP_NET_BIND_SERVICE)) {- dev_put(dev);- release_sock(sk);- return -EPERM;- }- nr->user_addr = addr->fsa_digipeater[0];- nr->source_addr = addr->fsa_ax25.sax25_call;- } else {- source = &addr->fsa_ax25.sax25_call;-- user = ax25_findbyuid(current_euid());- if (user) {- nr->user_addr = user->call;- ax25_uid_put(user);- } else {- if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {- release_sock(sk);- dev_put(dev);- return -EPERM;- }- nr->user_addr = *source;- }-- nr->source_addr = *source;- }-- nr->device = dev;- nr_insert_socket(sk);-- sock_reset_flag(sk, SOCK_ZAPPED);- dev_put(dev);- release_sock(sk);-- return 0;-}--static int nr_connect(struct socket *sock, struct sockaddr_unsized *uaddr,- int addr_len, int flags)-{- struct sock *sk = sock->sk;- struct nr_sock *nr = nr_sk(sk);- struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;- const ax25_address *source = NULL;- ax25_uid_assoc *user;- struct net_device *dev;- int err = 0;-- lock_sock(sk);- if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {- sock->state = SS_CONNECTED;- goto out_release; /* Connect completed during a ERESTARTSYS event */- }-- if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {- sock->state = SS_UNCONNECTED;- err = -ECONNREFUSED;- goto out_release;- }-- if (sk->sk_state == TCP_ESTABLISHED) {- err = -EISCONN; /* No reconnect on a seqpacket socket */- goto out_release;- }-- if (sock->state == SS_CONNECTING) {- err = -EALREADY;- goto out_release;- }-- sk->sk_state = TCP_CLOSE;- sock->state = SS_UNCONNECTED;-- if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) {- err = -EINVAL;- goto out_release;- }- if (addr->sax25_family != AF_NETROM) {- err = -EINVAL;- goto out_release;- }- if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */- sock_reset_flag(sk, SOCK_ZAPPED);-- if ((dev = nr_dev_first()) == NULL) {- err = -ENETUNREACH;- goto out_release;- }- source = (const ax25_address *)dev->dev_addr;-- user = ax25_findbyuid(current_euid());- if (user) {- nr->user_addr = user->call;- ax25_uid_put(user);- } else {- if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) {- dev_put(dev);- err = -EPERM;- goto out_release;- }- nr->user_addr = *source;- }-- nr->source_addr = *source;- nr->device = dev;-- dev_put(dev);- nr_insert_socket(sk); /* Finish the bind */- }-- nr->dest_addr = addr->sax25_call;-- release_sock(sk);- circuit = nr_find_next_circuit();- lock_sock(sk);-- nr->my_index = circuit / 256;- nr->my_id = circuit % 256;-- circuit++;-- /* Move to connecting socket, start sending Connect Requests */- sock->state = SS_CONNECTING;- sk->sk_state = TCP_SYN_SENT;-- nr_establish_data_link(sk);-- nr->state = NR_STATE_1;-- nr_start_heartbeat(sk);-- /* Now the loop */- if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {- err = -EINPROGRESS;- goto out_release;- }-- /*- * A Connect Ack with Choke or timeout or failed routing will go to- * closed.- */- if (sk->sk_state == TCP_SYN_SENT) {- DEFINE_WAIT(wait);-- for (;;) {- prepare_to_wait(sk_sleep(sk), &wait,- TASK_INTERRUPTIBLE);- if (sk->sk_state != TCP_SYN_SENT)- break;- if (!signal_pending(current)) {- release_sock(sk);- schedule();- lock_sock(sk);- continue;- }- err = -ERESTARTSYS;- break;- }- finish_wait(sk_sleep(sk), &wait);- if (err)- goto out_release;- }-- if (sk->sk_state != TCP_ESTABLISHED) {- sock->state = SS_UNCONNECTED;- err = sock_error(sk); /* Always set at this point */- goto out_release;- }-- sock->state = SS_CONNECTED;--out_release:- release_sock(sk);-- return err;-}--static int nr_accept(struct socket *sock, struct socket *newsock,- struct proto_accept_arg *arg)-{- struct sk_buff *skb;- struct sock *newsk;- DEFINE_WAIT(wait);- struct sock *sk;- int err = 0;-- if ((sk = sock->sk) == NULL)- return -EINVAL;-- lock_sock(sk);- if (sk->sk_type != SOCK_SEQPACKET) {- err = -EOPNOTSUPP;- goto out_release;- }-- if (sk->sk_state != TCP_LISTEN) {- err = -EINVAL;- goto out_release;- }-- /*- * The write queue this time is holding sockets ready to use- * hooked into the SABM we saved- */- for (;;) {- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);- skb = skb_dequeue(&sk->sk_receive_queue);- if (skb)- break;-- if (arg->flags & O_NONBLOCK) {- err = -EWOULDBLOCK;- break;- }- if (!signal_pending(current)) {- release_sock(sk);- schedule();- lock_sock(sk);- continue;- }- err = -ERESTARTSYS;- break;- }- finish_wait(sk_sleep(sk), &wait);- if (err)- goto out_release;-- newsk = skb->sk;- sock_graft(newsk, newsock);-- /* Now attach up the new socket */- kfree_skb(skb);- sk_acceptq_removed(sk);--out_release:- release_sock(sk);-- return err;-}--static int nr_getname(struct socket *sock, struct sockaddr *uaddr,- int peer)-{- struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;- struct sock *sk = sock->sk;- struct nr_sock *nr = nr_sk(sk);- int uaddr_len;-- memset(&sax->fsa_ax25, 0, sizeof(struct sockaddr_ax25));-- lock_sock(sk);- if (peer != 0) {- if (sk->sk_state != TCP_ESTABLISHED) {- release_sock(sk);- return -ENOTCONN;- }- sax->fsa_ax25.sax25_family = AF_NETROM;- sax->fsa_ax25.sax25_ndigis = 1;- sax->fsa_ax25.sax25_call = nr->user_addr;- memset(sax->fsa_digipeater, 0, sizeof(sax->fsa_digipeater));- sax->fsa_digipeater[0] = nr->dest_addr;- uaddr_len = sizeof(struct full_sockaddr_ax25);- } else {- sax->fsa_ax25.sax25_family = AF_NETROM;- sax->fsa_ax25.sax25_ndigis = 0;- sax->fsa_ax25.sax25_call = nr->source_addr;- uaddr_len = sizeof(struct sockaddr_ax25);- }- release_sock(sk);-- return uaddr_len;-}--int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)-{- struct sock *sk;- struct sock *make;- struct nr_sock *nr_make;- ax25_address *src, *dest, *user;- unsigned short circuit_index, circuit_id;- unsigned short peer_circuit_index, peer_circuit_id;- unsigned short frametype, flags, window, timeout;- int ret;-- skb_orphan(skb);-- /*- * skb->data points to the netrom frame start- */-- src = (ax25_address *)(skb->data + 0);- dest = (ax25_address *)(skb->data + 7);-- circuit_index = skb->data[15];- circuit_id = skb->data[16];- peer_circuit_index = skb->data[17];- peer_circuit_id = skb->data[18];- frametype = skb->data[19] & 0x0F;- flags = skb->data[19] & 0xF0;-- /*- * Check for an incoming IP over NET/ROM frame.- */- if (frametype == NR_PROTOEXT &&- circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {- skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);- skb_reset_transport_header(skb);-- return nr_rx_ip(skb, dev);- }-- /*- * Find an existing socket connection, based on circuit ID, if it's- * a Connect Request base it on their circuit ID.- *- * Circuit ID 0/0 is not valid but it could still be a "reset" for a- * circuit that no longer exists at the other end ...- */-- sk = NULL;-- if (circuit_index == 0 && circuit_id == 0) {- if (frametype == NR_CONNACK && flags == NR_CHOKE_FLAG)- sk = nr_find_peer(peer_circuit_index, peer_circuit_id, src);- } else {- if (frametype == NR_CONNREQ)- sk = nr_find_peer(circuit_index, circuit_id, src);- else- sk = nr_find_socket(circuit_index, circuit_id);- }-- if (sk != NULL) {- bh_lock_sock(sk);- skb_reset_transport_header(skb);-- if (frametype == NR_CONNACK && skb->len == 22)- nr_sk(sk)->bpqext = 1;- else- nr_sk(sk)->bpqext = 0;-- ret = nr_process_rx_frame(sk, skb);- bh_unlock_sock(sk);- sock_put(sk);- return ret;- }-- /*- * Now it should be a CONNREQ.- */- if (frametype != NR_CONNREQ) {- /*- * Here it would be nice to be able to send a reset but- * NET/ROM doesn't have one. We've tried to extend the protocol- * by sending NR_CONNACK | NR_CHOKE_FLAGS replies but that- * apparently kills BPQ boxes... :-(- * So now we try to follow the established behaviour of- * G8PZT's Xrouter which is sending packets with command type 7- * as an extension of the protocol.- */- if (READ_ONCE(sysctl_netrom_reset_circuit) &&- (frametype != NR_RESET || flags != 0))- nr_transmit_reset(skb, 1);-- return 0;- }-- sk = nr_find_listener(dest);-- user = (ax25_address *)(skb->data + 21);-- if (sk == NULL || sk_acceptq_is_full(sk) ||- (make = nr_make_new(sk)) == NULL) {- nr_transmit_refusal(skb, 0);- if (sk)- sock_put(sk);- return 0;- }-- bh_lock_sock(sk);-- window = skb->data[20];-- sock_hold(make);- skb->sk = make;- skb->destructor = sock_efree;- make->sk_state = TCP_ESTABLISHED;-- /* Fill in his circuit details */- nr_make = nr_sk(make);- nr_make->source_addr = *dest;- nr_make->dest_addr = *src;- nr_make->user_addr = *user;-- nr_make->your_index = circuit_index;- nr_make->your_id = circuit_id;-- bh_unlock_sock(sk);- circuit = nr_find_next_circuit();- bh_lock_sock(sk);-- nr_make->my_index = circuit / 256;- nr_make->my_id = circuit % 256;-- circuit++;-- /* Window negotiation */- if (window < nr_make->window)- nr_make->window = window;-- /* L4 timeout negotiation */- if (skb->len == 37) {- timeout = skb->data[36] * 256 + skb->data[35];- if (timeout * HZ < nr_make->t1)- nr_make->t1 = timeout * HZ;- nr_make->bpqext = 1;- } else {- nr_make->bpqext = 0;- }-- nr_write_internal(make, NR_CONNACK);-- nr_make->condition = 0x00;- nr_make->vs = 0;- nr_make->va = 0;- nr_make->vr = 0;- nr_make->vl = 0;- nr_make->state = NR_STATE_3;- sk_acceptq_added(sk);- skb_queue_head(&sk->sk_receive_queue, skb);-- if (!sock_flag(sk, SOCK_DEAD))- sk->sk_data_ready(sk);-- bh_unlock_sock(sk);- sock_put(sk);-- nr_insert_socket(make);-- nr_start_heartbeat(make);- nr_start_idletimer(make);-- return 1;-}--static int nr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)-{- struct sock *sk = sock->sk;- struct nr_sock *nr = nr_sk(sk);- DECLARE_SOCKADDR(struct sockaddr_ax25 *, usax, msg->msg_name);- int err;- struct sockaddr_ax25 sax;- struct sk_buff *skb;- unsigned char *asmptr;- int size;-- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))- return -EINVAL;-- lock_sock(sk);- if (sock_flag(sk, SOCK_ZAPPED)) {- err = -EADDRNOTAVAIL;- goto out;- }-- if (sk->sk_shutdown & SEND_SHUTDOWN) {- send_sig(SIGPIPE, current, 0);- err = -EPIPE;- goto out;- }-- if (nr->device == NULL) {- err = -ENETUNREACH;- goto out;- }-- if (usax) {- if (msg->msg_namelen < sizeof(sax)) {- err = -EINVAL;- goto out;- }- sax = *usax;- if (ax25cmp(&nr->dest_addr, &sax.sax25_call) != 0) {- err = -EISCONN;- goto out;- }- if (sax.sax25_family != AF_NETROM) {- err = -EINVAL;- goto out;- }- } else {- if (sk->sk_state != TCP_ESTABLISHED) {- err = -ENOTCONN;- goto out;- }- sax.sax25_family = AF_NETROM;- sax.sax25_call = nr->dest_addr;- }-- /* Build a packet - the conventional user limit is 236 bytes. We can- do ludicrously large NetROM frames but must not overflow */- if (len > 65536) {- err = -EMSGSIZE;- goto out;- }-- size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN;-- if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)- goto out;-- skb_reserve(skb, size - len);- skb_reset_transport_header(skb);-- /*- * Push down the NET/ROM header- */-- asmptr = skb_push(skb, NR_TRANSPORT_LEN);-- /* Build a NET/ROM Transport header */-- *asmptr++ = nr->your_index;- *asmptr++ = nr->your_id;- *asmptr++ = 0; /* To be filled in later */- *asmptr++ = 0; /* Ditto */- *asmptr++ = NR_INFO;-- /*- * Put the data on the end- */- skb_put(skb, len);-- /* User data follows immediately after the NET/ROM transport header */- if (memcpy_from_msg(skb_transport_header(skb), msg, len)) {- kfree_skb(skb);- err = -EFAULT;- goto out;- }-- if (sk->sk_state != TCP_ESTABLISHED) {- kfree_skb(skb);- err = -ENOTCONN;- goto out;- }-- nr_output(sk, skb); /* Shove it onto the queue */-- err = len;-out:- release_sock(sk);- return err;-}--static int nr_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,- int flags)-{- struct sock *sk = sock->sk;- DECLARE_SOCKADDR(struct sockaddr_ax25 *, sax, msg->msg_name);- size_t copied;- struct sk_buff *skb;- int er;-- /*- * This works for seqpacket too. The receiver has ordered the queue for- * us! We do one quick check first though- */-- lock_sock(sk);- if (sk->sk_state != TCP_ESTABLISHED) {- release_sock(sk);- return -ENOTCONN;- }-- /* Now we can treat all alike */- skb = skb_recv_datagram(sk, flags, &er);- if (!skb) {- release_sock(sk);- return er;- }-- skb_reset_transport_header(skb);- copied = skb->len;-- if (copied > size) {- copied = size;- msg->msg_flags |= MSG_TRUNC;- }-- er = skb_copy_datagram_msg(skb, 0, msg, copied);- if (er < 0) {- skb_free_datagram(sk, skb);- release_sock(sk);- return er;- }-- if (sax != NULL) {- memset(sax, 0, sizeof(*sax));- sax->sax25_family = AF_NETROM;- skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,- AX25_ADDR_LEN);- msg->msg_namelen = sizeof(*sax);- }-- skb_free_datagram(sk, skb);-- release_sock(sk);- return copied;-}---static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)-{- struct sock *sk = sock->sk;- void __user *argp = (void __user *)arg;-- switch (cmd) {- case TIOCOUTQ: {- long amount;-- lock_sock(sk);- amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);- if (amount < 0)- amount = 0;- release_sock(sk);- return put_user(amount, (int __user *)argp);- }-- case TIOCINQ: {- struct sk_buff *skb;- long amount = 0L;-- lock_sock(sk);- /* These two are safe on a single CPU system as only user tasks fiddle here */- if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)- amount = skb->len;- release_sock(sk);- return put_user(amount, (int __user *)argp);- }-- case SIOCGIFADDR:- case SIOCSIFADDR:- case SIOCGIFDSTADDR:- case SIOCSIFDSTADDR:- case SIOCGIFBRDADDR:- case SIOCSIFBRDADDR:- case SIOCGIFNETMASK:- case SIOCSIFNETMASK:- case SIOCGIFMETRIC:- case SIOCSIFMETRIC:- return -EINVAL;-- case SIOCADDRT:- case SIOCDELRT:- case SIOCNRDECOBS:- if (!capable(CAP_NET_ADMIN))- return -EPERM;- return nr_rt_ioctl(cmd, argp);-- default:- return -ENOIOCTLCMD;- }-- return 0;-}--#ifdef CONFIG_PROC_FS--static void *nr_info_start(struct seq_file *seq, loff_t *pos)- __acquires(&nr_list_lock)-{- spin_lock_bh(&nr_list_lock);- return seq_hlist_start_head(&nr_list, *pos);-}--static void *nr_info_next(struct seq_file *seq, void *v, loff_t *pos)-{- return seq_hlist_next(v, &nr_list, pos);-}--static void nr_info_stop(struct seq_file *seq, void *v)- __releases(&nr_list_lock)-{- spin_unlock_bh(&nr_list_lock);-}--static int nr_info_show(struct seq_file *seq, void *v)-{- struct sock *s = sk_entry(v);- struct net_device *dev;- struct nr_sock *nr;- const char *devname;- char buf[11];-- if (v == SEQ_START_TOKEN)- seq_puts(seq,-"user_addr dest_node src_node dev my your st vs vr va t1 t2 t4 idle n2 wnd Snd-Q Rcv-Q inode\n");-- else {-- bh_lock_sock(s);- nr = nr_sk(s);-- if ((dev = nr->device) == NULL)- devname = "???";- else- devname = dev->name;-- seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr));- seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr));- seq_printf(seq,-"%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %llu\n",- ax2asc(buf, &nr->source_addr),- devname,- nr->my_index,- nr->my_id,- nr->your_index,- nr->your_id,- nr->state,- nr->vs,- nr->vr,- nr->va,- ax25_display_timer(&nr->t1timer) / HZ,- nr->t1 / HZ,- ax25_display_timer(&nr->t2timer) / HZ,- nr->t2 / HZ,- ax25_display_timer(&nr->t4timer) / HZ,- nr->t4 / HZ,- ax25_display_timer(&nr->idletimer) / (60 * HZ),- nr->idle / (60 * HZ),- nr->n2count,- nr->n2,- nr->window,- sk_wmem_alloc_get(s),- sk_rmem_alloc_get(s),- s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : (u64)0);-- bh_unlock_sock(s);- }- return 0;-}--static const struct seq_operations nr_info_seqops = {- .start = nr_info_start,- .next = nr_info_next,- .stop = nr_info_stop,- .show = nr_info_show,-};-#endif /* CONFIG_PROC_FS */--static const struct net_proto_family nr_family_ops = {- .family = PF_NETROM,- .create = nr_create,- .owner = THIS_MODULE,-};--static const struct proto_ops nr_proto_ops = {- .family = PF_NETROM,- .owner = THIS_MODULE,- .release = nr_release,- .bind = nr_bind,- .connect = nr_connect,- .socketpair = sock_no_socketpair,- .accept = nr_accept,- .getname = nr_getname,- .poll = datagram_poll,- .ioctl = nr_ioctl,- .gettstamp = sock_gettstamp,- .listen = nr_listen,- .shutdown = sock_no_shutdown,- .setsockopt = nr_setsockopt,- .getsockopt = nr_getsockopt,- .sendmsg = nr_sendmsg,- .recvmsg = nr_recvmsg,- .mmap = sock_no_mmap,-};--static struct notifier_block nr_dev_notifier = {- .notifier_call = nr_device_event,-};--static struct net_device **dev_nr;--static struct ax25_protocol nr_pid = {- .pid = AX25_P_NETROM,- .func = nr_route_frame-};--static struct ax25_linkfail nr_linkfail_notifier = {- .func = nr_link_failed,-};--static int __init nr_proto_init(void)-{- int i;- int rc = proto_register(&nr_proto, 0);-- if (rc)- return rc;-- if (nr_ndevs > 0x7fffffff/sizeof(struct net_device *)) {- pr_err("NET/ROM: %s - nr_ndevs parameter too large\n",- __func__);- rc = -EINVAL;- goto unregister_proto;- }-- dev_nr = kzalloc_objs(struct net_device *, nr_ndevs);- if (!dev_nr) {- pr_err("NET/ROM: %s - unable to allocate device array\n",- __func__);- rc = -ENOMEM;- goto unregister_proto;- }-- for (i = 0; i < nr_ndevs; i++) {- char name[IFNAMSIZ];- struct net_device *dev;-- sprintf(name, "nr%d", i);- dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, nr_setup);- if (!dev) {- rc = -ENOMEM;- goto fail;- }-- dev->base_addr = i;- rc = register_netdev(dev);- if (rc) {- free_netdev(dev);- goto fail;- }- nr_set_lockdep_key(dev);- dev_nr[i] = dev;- }-- rc = sock_register(&nr_family_ops);- if (rc)- goto fail;-- rc = register_netdevice_notifier(&nr_dev_notifier);- if (rc)- goto out_sock;-- ax25_register_pid(&nr_pid);- ax25_linkfail_register(&nr_linkfail_notifier);--#ifdef CONFIG_SYSCTL- rc = nr_register_sysctl();- if (rc)- goto out_sysctl;-#endif-- nr_loopback_init();-- rc = -ENOMEM;- if (!proc_create_seq("nr", 0444, init_net.proc_net, &nr_info_seqops))- goto proc_remove1;- if (!proc_create_seq("nr_neigh", 0444, init_net.proc_net,- &nr_neigh_seqops))- goto proc_remove2;- if (!proc_create_seq("nr_nodes", 0444, init_net.proc_net,- &nr_node_seqops))- goto proc_remove3;-- return 0;--proc_remove3:- remove_proc_entry("nr_neigh", init_net.proc_net);-proc_remove2:- remove_proc_entry("nr", init_net.proc_net);-proc_remove1:-- nr_loopback_clear();- nr_rt_free();--#ifdef CONFIG_SYSCTL- nr_unregister_sysctl();-out_sysctl:-#endif- ax25_linkfail_release(&nr_linkfail_notifier);- ax25_protocol_release(AX25_P_NETROM);- unregister_netdevice_notifier(&nr_dev_notifier);-out_sock:- sock_unregister(PF_NETROM);-fail:- while (--i >= 0) {- unregister_netdev(dev_nr[i]);- free_netdev(dev_nr[i]);- }- kfree(dev_nr);-unregister_proto:- proto_unregister(&nr_proto);- return rc;-}--module_init(nr_proto_init);--module_param(nr_ndevs, int, 0);-MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices");--MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");-MODULE_DESCRIPTION("The amateur radio NET/ROM network and transport layer protocol");-MODULE_LICENSE("GPL");-MODULE_ALIAS_NETPROTO(PF_NETROM);--static void __exit nr_exit(void)-{- int i;-- remove_proc_entry("nr", init_net.proc_net);- remove_proc_entry("nr_neigh", init_net.proc_net);- remove_proc_entry("nr_nodes", init_net.proc_net);- nr_loopback_clear();-- nr_rt_free();--#ifdef CONFIG_SYSCTL- nr_unregister_sysctl();-#endif-- ax25_linkfail_release(&nr_linkfail_notifier);- ax25_protocol_release(AX25_P_NETROM);-- unregister_netdevice_notifier(&nr_dev_notifier);-- sock_unregister(PF_NETROM);-- for (i = 0; i < nr_ndevs; i++) {- struct net_device *dev = dev_nr[i];- if (dev) {- unregister_netdev(dev);- free_netdev(dev);- }- }-- kfree(dev_nr);- proto_unregister(&nr_proto);-}-module_exit(nr_exit);diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.cdeleted file mode 100644index 2c34389c3ce6..000000000000--- a/net/netrom/nr_dev.c+++ /dev/null@@ -1,178 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/module.h>-#include <linux/proc_fs.h>-#include <linux/kernel.h>-#include <linux/interrupt.h>-#include <linux/fs.h>-#include <linux/types.h>-#include <linux/sysctl.h>-#include <linux/string.h>-#include <linux/socket.h>-#include <linux/errno.h>-#include <linux/fcntl.h>-#include <linux/in.h>-#include <linux/if_ether.h> /* For the statistics structure. */-#include <linux/slab.h>-#include <linux/uaccess.h>--#include <asm/io.h>--#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/etherdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>--#include <net/ip.h>-#include <net/arp.h>--#include <net/ax25.h>-#include <net/netrom.h>--/*- * Only allow IP over NET/ROM frames through if the netrom device is up.- */--int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)-{- struct net_device_stats *stats = &dev->stats;-- if (!netif_running(dev)) {- stats->rx_dropped++;- return 0;- }-- stats->rx_packets++;- stats->rx_bytes += skb->len;-- skb->protocol = htons(ETH_P_IP);-- /* Spoof incoming device */- skb->dev = dev;- skb->mac_header = skb->network_header;- skb_reset_network_header(skb);- skb->pkt_type = PACKET_HOST;-- netif_rx(skb);-- return 1;-}--static int nr_header(struct sk_buff *skb, struct net_device *dev,- unsigned short type,- const void *daddr, const void *saddr, unsigned int len)-{- unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);-- memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len);- buff[6] &= ~AX25_CBIT;- buff[6] &= ~AX25_EBIT;- buff[6] |= AX25_SSSID_SPARE;- buff += AX25_ADDR_LEN;-- if (daddr != NULL)- memcpy(buff, daddr, dev->addr_len);- buff[6] &= ~AX25_CBIT;- buff[6] |= AX25_EBIT;- buff[6] |= AX25_SSSID_SPARE;- buff += AX25_ADDR_LEN;-- *buff++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);-- *buff++ = NR_PROTO_IP;- *buff++ = NR_PROTO_IP;- *buff++ = 0;- *buff++ = 0;- *buff++ = NR_PROTOEXT;-- if (daddr != NULL)- return 37;-- return -37;-}--static int __must_check nr_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr *sa = addr;- int err;-- if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))- return 0;-- if (dev->flags & IFF_UP) {- err = ax25_listen_register((ax25_address *)sa->sa_data, NULL);- if (err)- return err;-- ax25_listen_release((const ax25_address *)dev->dev_addr, NULL);- }-- dev_addr_set(dev, sa->sa_data);-- return 0;-}--static int nr_open(struct net_device *dev)-{- int err;-- err = ax25_listen_register((const ax25_address *)dev->dev_addr, NULL);- if (err)- return err;-- netif_start_queue(dev);-- return 0;-}--static int nr_close(struct net_device *dev)-{- ax25_listen_release((const ax25_address *)dev->dev_addr, NULL);- netif_stop_queue(dev);- return 0;-}--static netdev_tx_t nr_xmit(struct sk_buff *skb, struct net_device *dev)-{- struct net_device_stats *stats = &dev->stats;- unsigned int len = skb->len;-- if (!nr_route_frame(skb, NULL)) {- kfree_skb(skb);- stats->tx_errors++;- return NETDEV_TX_OK;- }-- stats->tx_packets++;- stats->tx_bytes += len;-- return NETDEV_TX_OK;-}--static const struct header_ops nr_header_ops = {- .create = nr_header,-};--static const struct net_device_ops nr_netdev_ops = {- .ndo_open = nr_open,- .ndo_stop = nr_close,- .ndo_start_xmit = nr_xmit,- .ndo_set_mac_address = nr_set_mac_address,-};--void nr_setup(struct net_device *dev)-{- dev->mtu = NR_MAX_PACKET_SIZE;- dev->netdev_ops = &nr_netdev_ops;- dev->header_ops = &nr_header_ops;- dev->hard_header_len = NR_NETWORK_LEN + NR_TRANSPORT_LEN;- dev->addr_len = AX25_ADDR_LEN;- dev->type = ARPHRD_NETROM;-- /* New-style flags. */- dev->flags = IFF_NOARP;-}diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.cdeleted file mode 100644index 97944db6b5ac..000000000000--- a/net/netrom/nr_in.c+++ /dev/null@@ -1,301 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/netrom.h>--static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)-{- struct sk_buff *skbo, *skbn = skb;- struct nr_sock *nr = nr_sk(sk);-- skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);-- nr_start_idletimer(sk);-- if (more) {- nr->fraglen += skb->len;- skb_queue_tail(&nr->frag_queue, skb);- return 0;- }-- if (!more && nr->fraglen > 0) { /* End of fragment */- nr->fraglen += skb->len;- skb_queue_tail(&nr->frag_queue, skb);-- if ((skbn = alloc_skb(nr->fraglen, GFP_ATOMIC)) == NULL)- return 1;-- skb_reset_transport_header(skbn);-- while ((skbo = skb_dequeue(&nr->frag_queue)) != NULL) {- skb_copy_from_linear_data(skbo,- skb_put(skbn, skbo->len),- skbo->len);- kfree_skb(skbo);- }-- nr->fraglen = 0;- }-- return sock_queue_rcv_skb(sk, skbn);-}--/*- * State machine for state 1, Awaiting Connection State.- * The handling of the timer(s) is in file nr_timer.c.- * Handling of state 0 and connection release is in netrom.c.- */-static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,- int frametype)-{- switch (frametype) {- case NR_CONNACK: {- struct nr_sock *nr = nr_sk(sk);-- nr_stop_t1timer(sk);- nr_start_idletimer(sk);- nr->your_index = skb->data[17];- nr->your_id = skb->data[18];- nr->vs = 0;- nr->va = 0;- nr->vr = 0;- nr->vl = 0;- nr->state = NR_STATE_3;- nr->n2count = 0;- nr->window = skb->data[20];- sk->sk_state = TCP_ESTABLISHED;- if (!sock_flag(sk, SOCK_DEAD))- sk->sk_state_change(sk);- break;- }-- case NR_CONNACK | NR_CHOKE_FLAG:- nr_disconnect(sk, ECONNREFUSED);- break;-- case NR_RESET:- if (READ_ONCE(sysctl_netrom_reset_circuit))- nr_disconnect(sk, ECONNRESET);- break;-- default:- break;- }- return 0;-}--/*- * State machine for state 2, Awaiting Release State.- * The handling of the timer(s) is in file nr_timer.c- * Handling of state 0 and connection release is in netrom.c.- */-static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,- int frametype)-{- switch (frametype) {- case NR_CONNACK | NR_CHOKE_FLAG:- nr_disconnect(sk, ECONNRESET);- break;-- case NR_DISCREQ:- nr_write_internal(sk, NR_DISCACK);- fallthrough;- case NR_DISCACK:- nr_disconnect(sk, 0);- break;-- case NR_RESET:- if (READ_ONCE(sysctl_netrom_reset_circuit))- nr_disconnect(sk, ECONNRESET);- break;-- default:- break;- }- return 0;-}--/*- * State machine for state 3, Connected State.- * The handling of the timer(s) is in file nr_timer.c- * Handling of state 0 and connection release is in netrom.c.- */-static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype)-{- struct nr_sock *nrom = nr_sk(sk);- struct sk_buff_head temp_queue;- struct sk_buff *skbn;- unsigned short save_vr;- unsigned short nr, ns;- int queued = 0;-- nr = skb->data[18];-- switch (frametype) {- case NR_CONNREQ:- nr_write_internal(sk, NR_CONNACK);- break;-- case NR_DISCREQ:- nr_write_internal(sk, NR_DISCACK);- nr_disconnect(sk, 0);- break;-- case NR_CONNACK | NR_CHOKE_FLAG:- case NR_DISCACK:- nr_disconnect(sk, ECONNRESET);- break;-- case NR_INFOACK:- case NR_INFOACK | NR_CHOKE_FLAG:- case NR_INFOACK | NR_NAK_FLAG:- case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG:- if (frametype & NR_CHOKE_FLAG) {- nrom->condition |= NR_COND_PEER_RX_BUSY;- nr_start_t4timer(sk);- } else {- nrom->condition &= ~NR_COND_PEER_RX_BUSY;- nr_stop_t4timer(sk);- }- if (!nr_validate_nr(sk, nr)) {- break;- }- if (frametype & NR_NAK_FLAG) {- nr_frames_acked(sk, nr);- nr_send_nak_frame(sk);- } else {- if (nrom->condition & NR_COND_PEER_RX_BUSY) {- nr_frames_acked(sk, nr);- } else {- nr_check_iframes_acked(sk, nr);- }- }- break;-- case NR_INFO:- case NR_INFO | NR_NAK_FLAG:- case NR_INFO | NR_CHOKE_FLAG:- case NR_INFO | NR_MORE_FLAG:- case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG:- case NR_INFO | NR_CHOKE_FLAG | NR_MORE_FLAG:- case NR_INFO | NR_NAK_FLAG | NR_MORE_FLAG:- case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG:- if (frametype & NR_CHOKE_FLAG) {- nrom->condition |= NR_COND_PEER_RX_BUSY;- nr_start_t4timer(sk);- } else {- nrom->condition &= ~NR_COND_PEER_RX_BUSY;- nr_stop_t4timer(sk);- }- if (nr_validate_nr(sk, nr)) {- if (frametype & NR_NAK_FLAG) {- nr_frames_acked(sk, nr);- nr_send_nak_frame(sk);- } else {- if (nrom->condition & NR_COND_PEER_RX_BUSY) {- nr_frames_acked(sk, nr);- } else {- nr_check_iframes_acked(sk, nr);- }- }- }- queued = 1;- skb_queue_head(&nrom->reseq_queue, skb);- if (nrom->condition & NR_COND_OWN_RX_BUSY)- break;- skb_queue_head_init(&temp_queue);- do {- save_vr = nrom->vr;- while ((skbn = skb_dequeue(&nrom->reseq_queue)) != NULL) {- ns = skbn->data[17];- if (ns == nrom->vr) {- if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) {- nrom->vr = (nrom->vr + 1) % NR_MODULUS;- } else {- nrom->condition |= NR_COND_OWN_RX_BUSY;- skb_queue_tail(&temp_queue, skbn);- }- } else if (nr_in_rx_window(sk, ns)) {- skb_queue_tail(&temp_queue, skbn);- } else {- kfree_skb(skbn);- }- }- while ((skbn = skb_dequeue(&temp_queue)) != NULL) {- skb_queue_tail(&nrom->reseq_queue, skbn);- }- } while (save_vr != nrom->vr);- /*- * Window is full, ack it immediately.- */- if (((nrom->vl + nrom->window) % NR_MODULUS) == nrom->vr) {- nr_enquiry_response(sk);- } else {- if (!(nrom->condition & NR_COND_ACK_PENDING)) {- nrom->condition |= NR_COND_ACK_PENDING;- nr_start_t2timer(sk);- }- }- break;-- case NR_RESET:- if (READ_ONCE(sysctl_netrom_reset_circuit))- nr_disconnect(sk, ECONNRESET);- break;-- default:- break;- }- return queued;-}--/* Higher level upcall for a LAPB frame - called with sk locked */-int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)-{- struct nr_sock *nr = nr_sk(sk);- int queued = 0, frametype;-- if (nr->state == NR_STATE_0)- return 0;-- frametype = skb->data[19];-- switch (nr->state) {- case NR_STATE_1:- queued = nr_state1_machine(sk, skb, frametype);- break;- case NR_STATE_2:- queued = nr_state2_machine(sk, skb, frametype);- break;- case NR_STATE_3:- queued = nr_state3_machine(sk, skb, frametype);- break;- }-- nr_kick(sk);-- return queued;-}diff --git a/net/netrom/nr_loopback.c b/net/netrom/nr_loopback.cdeleted file mode 100644index 7a9d765b30c0..000000000000--- a/net/netrom/nr_loopback.c+++ /dev/null@@ -1,73 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)- */-#include <linux/types.h>-#include <linux/slab.h>-#include <linux/socket.h>-#include <linux/timer.h>-#include <net/ax25.h>-#include <linux/skbuff.h>-#include <net/netrom.h>-#include <linux/init.h>--static void nr_loopback_timer(struct timer_list *);--static struct sk_buff_head loopback_queue;-static DEFINE_TIMER(loopback_timer, nr_loopback_timer);--void __init nr_loopback_init(void)-{- skb_queue_head_init(&loopback_queue);-}--static inline int nr_loopback_running(void)-{- return timer_pending(&loopback_timer);-}--int nr_loopback_queue(struct sk_buff *skb)-{- struct sk_buff *skbn;-- if ((skbn = alloc_skb(skb->len, GFP_ATOMIC)) != NULL) {- skb_copy_from_linear_data(skb, skb_put(skbn, skb->len), skb->len);- skb_reset_transport_header(skbn);-- skb_queue_tail(&loopback_queue, skbn);-- if (!nr_loopback_running())- mod_timer(&loopback_timer, jiffies + 10);- }-- kfree_skb(skb);- return 1;-}--static void nr_loopback_timer(struct timer_list *unused)-{- struct sk_buff *skb;- ax25_address *nr_dest;- struct net_device *dev;-- if ((skb = skb_dequeue(&loopback_queue)) != NULL) {- nr_dest = (ax25_address *)(skb->data + 7);-- dev = nr_dev_get(nr_dest);-- if (dev == NULL || nr_rx_frame(skb, dev) == 0)- kfree_skb(skb);-- dev_put(dev);-- if (!skb_queue_empty(&loopback_queue) && !nr_loopback_running())- mod_timer(&loopback_timer, jiffies + 10);- }-}--void nr_loopback_clear(void)-{- timer_delete_sync(&loopback_timer);- skb_queue_purge(&loopback_queue);-}diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.cdeleted file mode 100644index 2b3cbceb0b52..000000000000--- a/net/netrom/nr_out.c+++ /dev/null@@ -1,272 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/netrom.h>--/*- * This is where all NET/ROM frames pass, except for IP-over-NET/ROM which- * cannot be fragmented in this manner.- */-void nr_output(struct sock *sk, struct sk_buff *skb)-{- struct sk_buff *skbn;- unsigned char transport[NR_TRANSPORT_LEN];- int err, frontlen, len;-- if (skb->len - NR_TRANSPORT_LEN > NR_MAX_PACKET_SIZE) {- /* Save a copy of the Transport Header */- skb_copy_from_linear_data(skb, transport, NR_TRANSPORT_LEN);- skb_pull(skb, NR_TRANSPORT_LEN);-- frontlen = skb_headroom(skb);-- while (skb->len > 0) {- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) {- kfree_skb(skb);- return;- }-- skb_reserve(skbn, frontlen);-- len = (NR_MAX_PACKET_SIZE > skb->len) ? skb->len : NR_MAX_PACKET_SIZE;-- /* Copy the user data */- skb_copy_from_linear_data(skb, skb_put(skbn, len), len);- skb_pull(skb, len);-- /* Duplicate the Transport Header */- skb_push(skbn, NR_TRANSPORT_LEN);- skb_copy_to_linear_data(skbn, transport,- NR_TRANSPORT_LEN);- if (skb->len > 0)- skbn->data[4] |= NR_MORE_FLAG;-- skb_queue_tail(&sk->sk_write_queue, skbn); /* Throw it on the queue */- }-- kfree_skb(skb);- } else {- skb_queue_tail(&sk->sk_write_queue, skb); /* Throw it on the queue */- }-- nr_kick(sk);-}--/*- * This procedure is passed a buffer descriptor for an iframe. It builds- * the rest of the control part of the frame and then writes it out.- */-static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)-{- struct nr_sock *nr = nr_sk(sk);-- if (skb == NULL)- return;-- skb->data[2] = nr->vs;- skb->data[3] = nr->vr;-- if (nr->condition & NR_COND_OWN_RX_BUSY)- skb->data[4] |= NR_CHOKE_FLAG;-- nr_start_idletimer(sk);-- nr_transmit_buffer(sk, skb);-}--void nr_send_nak_frame(struct sock *sk)-{- struct sk_buff *skb, *skbn;- struct nr_sock *nr = nr_sk(sk);-- if ((skb = skb_peek(&nr->ack_queue)) == NULL)- return;-- if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL)- return;-- skbn->data[2] = nr->va;- skbn->data[3] = nr->vr;-- if (nr->condition & NR_COND_OWN_RX_BUSY)- skbn->data[4] |= NR_CHOKE_FLAG;-- nr_transmit_buffer(sk, skbn);-- nr->condition &= ~NR_COND_ACK_PENDING;- nr->vl = nr->vr;-- nr_stop_t1timer(sk);-}--void nr_kick(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);- struct sk_buff *skb, *skbn;- unsigned short start, end;-- if (nr->state != NR_STATE_3)- return;-- if (nr->condition & NR_COND_PEER_RX_BUSY)- return;-- if (!skb_peek(&sk->sk_write_queue))- return;-- start = (skb_peek(&nr->ack_queue) == NULL) ? nr->va : nr->vs;- end = (nr->va + nr->window) % NR_MODULUS;-- if (start == end)- return;-- nr->vs = start;-- /*- * Transmit data until either we're out of data to send or- * the window is full.- */-- /*- * Dequeue the frame and copy it.- */- skb = skb_dequeue(&sk->sk_write_queue);-- do {- if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {- skb_queue_head(&sk->sk_write_queue, skb);- break;- }-- skb_set_owner_w(skbn, sk);-- /*- * Transmit the frame copy.- */- nr_send_iframe(sk, skbn);-- nr->vs = (nr->vs + 1) % NR_MODULUS;-- /*- * Requeue the original data frame.- */- skb_queue_tail(&nr->ack_queue, skb);-- } while (nr->vs != end &&- (skb = skb_dequeue(&sk->sk_write_queue)) != NULL);-- nr->vl = nr->vr;- nr->condition &= ~NR_COND_ACK_PENDING;-- if (!nr_t1timer_running(sk))- nr_start_t1timer(sk);-}--void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)-{- struct nr_sock *nr = nr_sk(sk);- unsigned char *dptr;-- /*- * Add the protocol byte and network header.- */- dptr = skb_push(skb, NR_NETWORK_LEN);-- memcpy(dptr, &nr->source_addr, AX25_ADDR_LEN);- dptr[6] &= ~AX25_CBIT;- dptr[6] &= ~AX25_EBIT;- dptr[6] |= AX25_SSSID_SPARE;- dptr += AX25_ADDR_LEN;-- memcpy(dptr, &nr->dest_addr, AX25_ADDR_LEN);- dptr[6] &= ~AX25_CBIT;- dptr[6] |= AX25_EBIT;- dptr[6] |= AX25_SSSID_SPARE;- dptr += AX25_ADDR_LEN;-- *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);-- if (!nr_route_frame(skb, NULL)) {- kfree_skb(skb);- nr_disconnect(sk, ENETUNREACH);- }-}--/*- * The following routines are taken from page 170 of the 7th ARRL Computer- * Networking Conference paper, as is the whole state machine.- */--void nr_establish_data_link(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);-- nr->condition = 0x00;- nr->n2count = 0;-- nr_write_internal(sk, NR_CONNREQ);-- nr_stop_t2timer(sk);- nr_stop_t4timer(sk);- nr_stop_idletimer(sk);- nr_start_t1timer(sk);-}--/*- * Never send a NAK when we are CHOKEd.- */-void nr_enquiry_response(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);- int frametype = NR_INFOACK;-- if (nr->condition & NR_COND_OWN_RX_BUSY) {- frametype |= NR_CHOKE_FLAG;- } else {- if (skb_peek(&nr->reseq_queue) != NULL)- frametype |= NR_NAK_FLAG;- }-- nr_write_internal(sk, frametype);-- nr->vl = nr->vr;- nr->condition &= ~NR_COND_ACK_PENDING;-}--void nr_check_iframes_acked(struct sock *sk, unsigned short nr)-{- struct nr_sock *nrom = nr_sk(sk);-- if (nrom->vs == nr) {- nr_frames_acked(sk, nr);- nr_stop_t1timer(sk);- nrom->n2count = 0;- } else {- if (nrom->va != nr) {- nr_frames_acked(sk, nr);- nr_start_t1timer(sk);- }- }-}diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.cdeleted file mode 100644index 9cc29ae85b06..000000000000--- a/net/netrom/nr_route.c+++ /dev/null@@ -1,989 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <net/arp.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/termios.h> /* For TIOCINQ/OUTQ */-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/notifier.h>-#include <linux/init.h>-#include <linux/spinlock.h>-#include <net/netrom.h>-#include <linux/seq_file.h>-#include <linux/export.h>--static unsigned int nr_neigh_no = 1;--static HLIST_HEAD(nr_node_list);-static DEFINE_SPINLOCK(nr_node_list_lock);-static HLIST_HEAD(nr_neigh_list);-static DEFINE_SPINLOCK(nr_neigh_list_lock);--static struct nr_node *nr_node_get(ax25_address *callsign)-{- struct nr_node *found = NULL;- struct nr_node *nr_node;-- spin_lock_bh(&nr_node_list_lock);- nr_node_for_each(nr_node, &nr_node_list)- if (ax25cmp(callsign, &nr_node->callsign) == 0) {- nr_node_hold(nr_node);- found = nr_node;- break;- }- spin_unlock_bh(&nr_node_list_lock);- return found;-}--static struct nr_neigh *nr_neigh_get_dev(ax25_address *callsign,- struct net_device *dev)-{- struct nr_neigh *found = NULL;- struct nr_neigh *nr_neigh;-- spin_lock_bh(&nr_neigh_list_lock);- nr_neigh_for_each(nr_neigh, &nr_neigh_list)- if (ax25cmp(callsign, &nr_neigh->callsign) == 0 &&- nr_neigh->dev == dev) {- nr_neigh_hold(nr_neigh);- found = nr_neigh;- break;- }- spin_unlock_bh(&nr_neigh_list_lock);- return found;-}--static void nr_remove_neigh(struct nr_neigh *);--/* re-sort the routes in quality order. */-static void re_sort_routes(struct nr_node *nr_node, int x, int y)-{- if (nr_node->routes[y].quality > nr_node->routes[x].quality) {- if (nr_node->which == x)- nr_node->which = y;- else if (nr_node->which == y)- nr_node->which = x;-- swap(nr_node->routes[x], nr_node->routes[y]);- }-}--/*- * Add a new route to a node, and in the process add the node and the- * neighbour if it is new.- */-static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,- ax25_address *ax25, ax25_digi *ax25_digi, struct net_device *dev,- int quality, int obs_count)-{- struct nr_node *nr_node;- struct nr_neigh *nr_neigh;- int i, found;- struct net_device *odev;-- if ((odev=nr_dev_get(nr)) != NULL) { /* Can't add routes to ourself */- dev_put(odev);- return -EINVAL;- }-- nr_node = nr_node_get(nr);-- nr_neigh = nr_neigh_get_dev(ax25, dev);-- /*- * The L2 link to a neighbour has failed in the past- * and now a frame comes from this neighbour. We assume- * it was a temporary trouble with the link and reset the- * routes now (and not wait for a node broadcast).- */- if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) {- struct nr_node *nr_nodet;-- spin_lock_bh(&nr_node_list_lock);- nr_node_for_each(nr_nodet, &nr_node_list) {- nr_node_lock(nr_nodet);- for (i = 0; i < nr_nodet->count; i++)- if (nr_nodet->routes[i].neighbour == nr_neigh)- if (i < nr_nodet->which)- nr_nodet->which = i;- nr_node_unlock(nr_nodet);- }- spin_unlock_bh(&nr_node_list_lock);- }-- if (nr_neigh != NULL)- nr_neigh->failed = 0;-- if (quality == 0 && nr_neigh != NULL && nr_node != NULL) {- nr_neigh_put(nr_neigh);- nr_node_put(nr_node);- return 0;- }-- if (nr_neigh == NULL) {- if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL) {- if (nr_node)- nr_node_put(nr_node);- return -ENOMEM;- }-- nr_neigh->callsign = *ax25;- nr_neigh->digipeat = NULL;- nr_neigh->ax25 = NULL;- nr_neigh->dev = dev;- nr_neigh->quality = READ_ONCE(sysctl_netrom_default_path_quality);- nr_neigh->locked = 0;- nr_neigh->count = 0;- nr_neigh->number = nr_neigh_no++;- nr_neigh->failed = 0;- refcount_set(&nr_neigh->refcount, 1);-- if (ax25_digi != NULL && ax25_digi->ndigi > 0) {- nr_neigh->digipeat = kmemdup(ax25_digi,- sizeof(*ax25_digi),- GFP_KERNEL);- if (nr_neigh->digipeat == NULL) {- kfree(nr_neigh);- if (nr_node)- nr_node_put(nr_node);- return -ENOMEM;- }- }-- spin_lock_bh(&nr_neigh_list_lock);- hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);- nr_neigh_hold(nr_neigh);- spin_unlock_bh(&nr_neigh_list_lock);- }-- if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)- nr_neigh->quality = quality;-- if (nr_node == NULL) {- if ((nr_node = kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL) {- if (nr_neigh)- nr_neigh_put(nr_neigh);- return -ENOMEM;- }-- nr_node->callsign = *nr;- strscpy(nr_node->mnemonic, mnemonic);-- nr_node->which = 0;- nr_node->count = 1;- refcount_set(&nr_node->refcount, 1);- spin_lock_init(&nr_node->node_lock);-- nr_node->routes[0].quality = quality;- nr_node->routes[0].obs_count = obs_count;- nr_node->routes[0].neighbour = nr_neigh;-- nr_neigh_hold(nr_neigh);- nr_neigh->count++;-- spin_lock_bh(&nr_node_list_lock);- hlist_add_head(&nr_node->node_node, &nr_node_list);- /* refcount initialized at 1 */- spin_unlock_bh(&nr_node_list_lock);-- nr_neigh_put(nr_neigh);- return 0;- }- nr_node_lock(nr_node);-- if (quality != 0)- strscpy(nr_node->mnemonic, mnemonic);-- for (found = 0, i = 0; i < nr_node->count; i++) {- if (nr_node->routes[i].neighbour == nr_neigh) {- nr_node->routes[i].quality = quality;- nr_node->routes[i].obs_count = obs_count;- found = 1;- break;- }- }-- if (!found) {- /* We have space at the bottom, slot it in */- if (nr_node->count < 3) {- nr_node->routes[2] = nr_node->routes[1];- nr_node->routes[1] = nr_node->routes[0];-- nr_node->routes[0].quality = quality;- nr_node->routes[0].obs_count = obs_count;- nr_node->routes[0].neighbour = nr_neigh;-- nr_node->which++;- nr_node->count++;- nr_neigh_hold(nr_neigh);- nr_neigh->count++;- } else {- /* It must be better than the worst */- if (quality > nr_node->routes[2].quality) {- nr_node->routes[2].neighbour->count--;- nr_neigh_put(nr_node->routes[2].neighbour);-- if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)- nr_remove_neigh(nr_node->routes[2].neighbour);-- nr_node->routes[2].quality = quality;- nr_node->routes[2].obs_count = obs_count;- nr_node->routes[2].neighbour = nr_neigh;-- nr_neigh_hold(nr_neigh);- nr_neigh->count++;- }- }- }-- /* Now re-sort the routes in quality order */- switch (nr_node->count) {- case 3:- re_sort_routes(nr_node, 0, 1);- re_sort_routes(nr_node, 1, 2);- fallthrough;- case 2:- re_sort_routes(nr_node, 0, 1);- break;- case 1:- break;- }-- for (i = 0; i < nr_node->count; i++) {- if (nr_node->routes[i].neighbour == nr_neigh) {- if (i < nr_node->which)- nr_node->which = i;- break;- }- }-- nr_neigh_put(nr_neigh);- nr_node_unlock(nr_node);- nr_node_put(nr_node);- return 0;-}--static void nr_remove_node_locked(struct nr_node *nr_node)-{- lockdep_assert_held(&nr_node_list_lock);-- hlist_del_init(&nr_node->node_node);- nr_node_put(nr_node);-}--static inline void __nr_remove_neigh(struct nr_neigh *nr_neigh)-{- hlist_del_init(&nr_neigh->neigh_node);- nr_neigh_put(nr_neigh);-}--#define nr_remove_neigh_locked(__neigh) \- __nr_remove_neigh(__neigh)--static void nr_remove_neigh(struct nr_neigh *nr_neigh)-{- spin_lock_bh(&nr_neigh_list_lock);- __nr_remove_neigh(nr_neigh);- spin_unlock_bh(&nr_neigh_list_lock);-}--/*- * "Delete" a node. Strictly speaking remove a route to a node. The node- * is only deleted if no routes are left to it.- */-static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct net_device *dev)-{- struct nr_node *nr_node;- struct nr_neigh *nr_neigh;- int i;-- nr_node = nr_node_get(callsign);-- if (nr_node == NULL)- return -EINVAL;-- nr_neigh = nr_neigh_get_dev(neighbour, dev);-- if (nr_neigh == NULL) {- nr_node_put(nr_node);- return -EINVAL;- }-- spin_lock_bh(&nr_node_list_lock);- nr_node_lock(nr_node);- for (i = 0; i < nr_node->count; i++) {- if (nr_node->routes[i].neighbour == nr_neigh) {- nr_neigh->count--;- nr_neigh_put(nr_neigh);-- if (nr_neigh->count == 0 && !nr_neigh->locked)- nr_remove_neigh(nr_neigh);- nr_neigh_put(nr_neigh);-- nr_node->count--;-- if (nr_node->count == 0) {- nr_remove_node_locked(nr_node);- } else {- switch (i) {- case 0:- nr_node->routes[0] = nr_node->routes[1];- fallthrough;- case 1:- nr_node->routes[1] = nr_node->routes[2];- fallthrough;- case 2:- break;- }- nr_node_put(nr_node);- }- nr_node_unlock(nr_node);- spin_unlock_bh(&nr_node_list_lock);-- return 0;- }- }- nr_neigh_put(nr_neigh);- nr_node_unlock(nr_node);- spin_unlock_bh(&nr_node_list_lock);- nr_node_put(nr_node);-- return -EINVAL;-}--/*- * Lock a neighbour with a quality.- */-static int __must_check nr_add_neigh(ax25_address *callsign,- ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)-{- struct nr_neigh *nr_neigh;-- nr_neigh = nr_neigh_get_dev(callsign, dev);- if (nr_neigh) {- nr_neigh->quality = quality;- nr_neigh->locked = 1;- nr_neigh_put(nr_neigh);- return 0;- }-- if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)- return -ENOMEM;-- nr_neigh->callsign = *callsign;- nr_neigh->digipeat = NULL;- nr_neigh->ax25 = NULL;- nr_neigh->dev = dev;- nr_neigh->quality = quality;- nr_neigh->locked = 1;- nr_neigh->count = 0;- nr_neigh->number = nr_neigh_no++;- nr_neigh->failed = 0;- refcount_set(&nr_neigh->refcount, 1);-- if (ax25_digi != NULL && ax25_digi->ndigi > 0) {- nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),- GFP_KERNEL);- if (nr_neigh->digipeat == NULL) {- kfree(nr_neigh);- return -ENOMEM;- }- }-- spin_lock_bh(&nr_neigh_list_lock);- hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);- /* refcount is initialized at 1 */- spin_unlock_bh(&nr_neigh_list_lock);-- return 0;-}--/*- * "Delete" a neighbour. The neighbour is only removed if the number- * of nodes that may use it is zero.- */-static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned int quality)-{- struct nr_neigh *nr_neigh;-- nr_neigh = nr_neigh_get_dev(callsign, dev);-- if (nr_neigh == NULL) return -EINVAL;-- nr_neigh->quality = quality;- nr_neigh->locked = 0;-- if (nr_neigh->count == 0)- nr_remove_neigh(nr_neigh);- nr_neigh_put(nr_neigh);-- return 0;-}--/*- * Decrement the obsolescence count by one. If a route is reduced to a- * count of zero, remove it. Also remove any unlocked neighbours with- * zero nodes routing via it.- */-static int nr_dec_obs(void)-{- struct nr_neigh *nr_neigh;- struct nr_node *s;- struct hlist_node *nodet;- int i;-- spin_lock_bh(&nr_node_list_lock);- nr_node_for_each_safe(s, nodet, &nr_node_list) {- nr_node_lock(s);- for (i = 0; i < s->count; i++) {- switch (s->routes[i].obs_count) {- case 0: /* A locked entry */- break;-- case 1: /* From 1 -> 0 */- nr_neigh = s->routes[i].neighbour;-- nr_neigh->count--;- nr_neigh_put(nr_neigh);-- if (nr_neigh->count == 0 && !nr_neigh->locked)- nr_remove_neigh(nr_neigh);-- s->count--;-- switch (i) {- case 0:- s->routes[0] = s->routes[1];- fallthrough;- case 1:- s->routes[1] = s->routes[2];- break;- case 2:- break;- }- break;-- default:- s->routes[i].obs_count--;- break;-- }- }-- if (s->count <= 0)- nr_remove_node_locked(s);- nr_node_unlock(s);- }- spin_unlock_bh(&nr_node_list_lock);-- return 0;-}--/*- * A device has been removed. Remove its routes and neighbours.- */-void nr_rt_device_down(struct net_device *dev)-{- struct nr_neigh *s;- struct hlist_node *nodet, *node2t;- struct nr_node *t;- int i;-- spin_lock_bh(&nr_neigh_list_lock);- nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {- if (s->dev == dev) {- spin_lock_bh(&nr_node_list_lock);- nr_node_for_each_safe(t, node2t, &nr_node_list) {- nr_node_lock(t);- for (i = 0; i < t->count; i++) {- if (t->routes[i].neighbour == s) {- t->count--;-- switch (i) {- case 0:- t->routes[0] = t->routes[1];- fallthrough;- case 1:- t->routes[1] = t->routes[2];- break;- case 2:- break;- }- }- }-- if (t->count <= 0)- nr_remove_node_locked(t);- nr_node_unlock(t);- }- spin_unlock_bh(&nr_node_list_lock);-- nr_remove_neigh_locked(s);- }- }- spin_unlock_bh(&nr_neigh_list_lock);-}--/*- * Check that the device given is a valid AX.25 interface that is "up".- * Or a valid ethernet interface with an AX.25 callsign binding.- */-static struct net_device *nr_ax25_dev_get(char *devname)-{- struct net_device *dev;-- if ((dev = dev_get_by_name(&init_net, devname)) == NULL)- return NULL;-- if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)- return dev;-- dev_put(dev);- return NULL;-}--/*- * Find the first active NET/ROM device, usually "nr0".- */-struct net_device *nr_dev_first(void)-{- struct net_device *dev, *first = NULL;-- rcu_read_lock();- for_each_netdev_rcu(&init_net, dev) {- if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)- if (first == NULL || strncmp(dev->name, first->name, 3) < 0)- first = dev;- }- dev_hold(first);- rcu_read_unlock();-- return first;-}--/*- * Find the NET/ROM device for the given callsign.- */-struct net_device *nr_dev_get(ax25_address *addr)-{- struct net_device *dev;-- rcu_read_lock();- for_each_netdev_rcu(&init_net, dev) {- if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM &&- ax25cmp(addr, (const ax25_address *)dev->dev_addr) == 0) {- dev_hold(dev);- goto out;- }- }- dev = NULL;-out:- rcu_read_unlock();- return dev;-}--static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis,- ax25_address *digipeaters)-{- int i;-- if (ndigis == 0)- return NULL;-- for (i = 0; i < ndigis; i++) {- digi->calls[i] = digipeaters[i];- digi->repeated[i] = 0;- }-- digi->ndigi = ndigis;- digi->lastrepeat = -1;-- return digi;-}--/*- * Handle the ioctls that control the routing functions.- */-int nr_rt_ioctl(unsigned int cmd, void __user *arg)-{- struct nr_route_struct nr_route;- struct net_device *dev;- ax25_digi digi;- int ret;-- switch (cmd) {- case SIOCADDRT:- if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))- return -EFAULT;- if (nr_route.ndigis > AX25_MAX_DIGIS)- return -EINVAL;- if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)- return -EINVAL;- switch (nr_route.type) {- case NETROM_NODE:- if (strnlen(nr_route.mnemonic, 7) == 7) {- ret = -EINVAL;- break;- }-- ret = nr_add_node(&nr_route.callsign,- nr_route.mnemonic,- &nr_route.neighbour,- nr_call_to_digi(&digi, nr_route.ndigis,- nr_route.digipeaters),- dev, nr_route.quality,- nr_route.obs_count);- break;- case NETROM_NEIGH:- ret = nr_add_neigh(&nr_route.callsign,- nr_call_to_digi(&digi, nr_route.ndigis,- nr_route.digipeaters),- dev, nr_route.quality);- break;- default:- ret = -EINVAL;- }- dev_put(dev);- return ret;-- case SIOCDELRT:- if (copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct)))- return -EFAULT;- if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)- return -EINVAL;- switch (nr_route.type) {- case NETROM_NODE:- ret = nr_del_node(&nr_route.callsign,- &nr_route.neighbour, dev);- break;- case NETROM_NEIGH:- ret = nr_del_neigh(&nr_route.callsign,- dev, nr_route.quality);- break;- default:- ret = -EINVAL;- }- dev_put(dev);- return ret;-- case SIOCNRDECOBS:- return nr_dec_obs();-- default:- return -EINVAL;- }-- return 0;-}--/*- * A level 2 link has timed out, therefore it appears to be a poor link,- * then don't use that neighbour until it is reset.- */-void nr_link_failed(ax25_cb *ax25, int reason)-{- struct nr_neigh *s, *nr_neigh = NULL;- struct nr_node *nr_node = NULL;-- spin_lock_bh(&nr_neigh_list_lock);- nr_neigh_for_each(s, &nr_neigh_list) {- if (s->ax25 == ax25) {- nr_neigh_hold(s);- nr_neigh = s;- break;- }- }- spin_unlock_bh(&nr_neigh_list_lock);-- if (nr_neigh == NULL)- return;-- nr_neigh->ax25 = NULL;- ax25_cb_put(ax25);-- if (++nr_neigh->failed < READ_ONCE(sysctl_netrom_link_fails_count)) {- nr_neigh_put(nr_neigh);- return;- }- spin_lock_bh(&nr_node_list_lock);- nr_node_for_each(nr_node, &nr_node_list) {- nr_node_lock(nr_node);- if (nr_node->which < nr_node->count &&- nr_node->routes[nr_node->which].neighbour == nr_neigh)- nr_node->which++;- nr_node_unlock(nr_node);- }- spin_unlock_bh(&nr_node_list_lock);- nr_neigh_put(nr_neigh);-}--/*- * Route a frame to an appropriate AX.25 connection. A NULL ax25_cb- * indicates an internally generated frame.- */-int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)-{- ax25_address *nr_src, *nr_dest;- struct nr_neigh *nr_neigh;- struct nr_node *nr_node;- struct net_device *dev;- unsigned char *dptr;- ax25_cb *ax25s;- int ret;- struct sk_buff *nskb, *oskb;-- /*- * Reject malformed packets early. Check that it contains at least 2- * addresses and 1 byte more for Time-To-Live- */- if (skb->len < 2 * sizeof(ax25_address) + 1)- return 0;-- nr_src = (ax25_address *)(skb->data + 0);- nr_dest = (ax25_address *)(skb->data + 7);-- if (ax25 != NULL) {- ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,- ax25->ax25_dev->dev, 0,- READ_ONCE(sysctl_netrom_obsolescence_count_initialiser));- if (ret)- return ret;- }-- if ((dev = nr_dev_get(nr_dest)) != NULL) { /* Its for me */- if (ax25 == NULL) /* Its from me */- ret = nr_loopback_queue(skb);- else- ret = nr_rx_frame(skb, dev);- dev_put(dev);- return ret;- }-- if (!READ_ONCE(sysctl_netrom_routing_control) && ax25 != NULL)- return 0;-- /* Its Time-To-Live has expired */- if (skb->data[14] == 1) {- return 0;- }-- nr_node = nr_node_get(nr_dest);- if (nr_node == NULL)- return 0;- nr_node_lock(nr_node);-- if (nr_node->which >= nr_node->count) {- nr_node_unlock(nr_node);- nr_node_put(nr_node);- return 0;- }-- nr_neigh = nr_node->routes[nr_node->which].neighbour;-- if ((dev = nr_dev_first()) == NULL) {- nr_node_unlock(nr_node);- nr_node_put(nr_node);- return 0;- }-- /* We are going to change the netrom headers so we should get our- own skb, we also did not know until now how much header space- we had to reserve... - RXQ */- nskb = skb_copy_expand(skb, dev->hard_header_len, 0, GFP_ATOMIC);-- if (!nskb) {- nr_node_unlock(nr_node);- nr_node_put(nr_node);- dev_put(dev);- return 0;- }- oskb = skb;- skb = nskb;- skb->data[14]--;-- dptr = skb_push(skb, 1);- *dptr = AX25_P_NETROM;-- ax25s = nr_neigh->ax25;- nr_neigh->ax25 = ax25_send_frame(skb, 256,- (const ax25_address *)dev->dev_addr,- &nr_neigh->callsign,- nr_neigh->digipeat, nr_neigh->dev);- if (ax25s)- ax25_cb_put(ax25s);-- dev_put(dev);- ret = (nr_neigh->ax25 != NULL);- nr_node_unlock(nr_node);- nr_node_put(nr_node);-- if (ret)- kfree_skb(oskb);-- return ret;-}--#ifdef CONFIG_PROC_FS--static void *nr_node_start(struct seq_file *seq, loff_t *pos)- __acquires(&nr_node_list_lock)-{- spin_lock_bh(&nr_node_list_lock);- return seq_hlist_start_head(&nr_node_list, *pos);-}--static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos)-{- return seq_hlist_next(v, &nr_node_list, pos);-}--static void nr_node_stop(struct seq_file *seq, void *v)- __releases(&nr_node_list_lock)-{- spin_unlock_bh(&nr_node_list_lock);-}--static int nr_node_show(struct seq_file *seq, void *v)-{- char buf[11];- int i;-- if (v == SEQ_START_TOKEN)- seq_puts(seq,- "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");- else {- struct nr_node *nr_node = hlist_entry(v, struct nr_node,- node_node);-- nr_node_lock(nr_node);- seq_printf(seq, "%-9s %-7s %d %d",- ax2asc(buf, &nr_node->callsign),- (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,- nr_node->which + 1,- nr_node->count);-- for (i = 0; i < nr_node->count; i++) {- seq_printf(seq, " %3d %d %05d",- nr_node->routes[i].quality,- nr_node->routes[i].obs_count,- nr_node->routes[i].neighbour->number);- }- nr_node_unlock(nr_node);-- seq_puts(seq, "\n");- }- return 0;-}--const struct seq_operations nr_node_seqops = {- .start = nr_node_start,- .next = nr_node_next,- .stop = nr_node_stop,- .show = nr_node_show,-};--static void *nr_neigh_start(struct seq_file *seq, loff_t *pos)- __acquires(&nr_neigh_list_lock)-{- spin_lock_bh(&nr_neigh_list_lock);- return seq_hlist_start_head(&nr_neigh_list, *pos);-}--static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos)-{- return seq_hlist_next(v, &nr_neigh_list, pos);-}--static void nr_neigh_stop(struct seq_file *seq, void *v)- __releases(&nr_neigh_list_lock)-{- spin_unlock_bh(&nr_neigh_list_lock);-}--static int nr_neigh_show(struct seq_file *seq, void *v)-{- char buf[11];- int i;-- if (v == SEQ_START_TOKEN)- seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n");- else {- struct nr_neigh *nr_neigh;-- nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node);- seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d",- nr_neigh->number,- ax2asc(buf, &nr_neigh->callsign),- nr_neigh->dev ? nr_neigh->dev->name : "???",- nr_neigh->quality,- nr_neigh->locked,- nr_neigh->count,- nr_neigh->failed);-- if (nr_neigh->digipeat != NULL) {- for (i = 0; i < nr_neigh->digipeat->ndigi; i++)- seq_printf(seq, " %s",- ax2asc(buf, &nr_neigh->digipeat->calls[i]));- }-- seq_puts(seq, "\n");- }- return 0;-}--const struct seq_operations nr_neigh_seqops = {- .start = nr_neigh_start,- .next = nr_neigh_next,- .stop = nr_neigh_stop,- .show = nr_neigh_show,-};-#endif--/*- * Free all memory associated with the nodes and routes lists.- */-void nr_rt_free(void)-{- struct nr_neigh *s = NULL;- struct nr_node *t = NULL;- struct hlist_node *nodet;-- spin_lock_bh(&nr_neigh_list_lock);- spin_lock_bh(&nr_node_list_lock);- nr_node_for_each_safe(t, nodet, &nr_node_list) {- nr_node_lock(t);- nr_remove_node_locked(t);- nr_node_unlock(t);- }- nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {- while(s->count) {- s->count--;- nr_neigh_put(s);- }- nr_remove_neigh_locked(s);- }- spin_unlock_bh(&nr_node_list_lock);- spin_unlock_bh(&nr_neigh_list_lock);-}diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.cdeleted file mode 100644index c3bbd5880850..000000000000--- a/net/netrom/nr_subr.c+++ /dev/null@@ -1,280 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/netrom.h>--/*- * This routine purges all of the queues of frames.- */-void nr_clear_queues(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);-- skb_queue_purge(&sk->sk_write_queue);- skb_queue_purge(&nr->ack_queue);- skb_queue_purge(&nr->reseq_queue);- skb_queue_purge(&nr->frag_queue);-}--/*- * This routine purges the input queue of those frames that have been- * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the- * SDL diagram.- */-void nr_frames_acked(struct sock *sk, unsigned short nr)-{- struct nr_sock *nrom = nr_sk(sk);- struct sk_buff *skb;-- /*- * Remove all the ack-ed frames from the ack queue.- */- if (nrom->va != nr) {- while (skb_peek(&nrom->ack_queue) != NULL && nrom->va != nr) {- skb = skb_dequeue(&nrom->ack_queue);- kfree_skb(skb);- nrom->va = (nrom->va + 1) % NR_MODULUS;- }- }-}--/*- * Requeue all the un-ack-ed frames on the output queue to be picked- * up by nr_kick called from the timer. This arrangement handles the- * possibility of an empty output queue.- */-void nr_requeue_frames(struct sock *sk)-{- struct sk_buff *skb, *skb_prev = NULL;-- while ((skb = skb_dequeue(&nr_sk(sk)->ack_queue)) != NULL) {- if (skb_prev == NULL)- skb_queue_head(&sk->sk_write_queue, skb);- else- skb_append(skb_prev, skb, &sk->sk_write_queue);- skb_prev = skb;- }-}--/*- * Validate that the value of nr is between va and vs. Return true or- * false for testing.- */-int nr_validate_nr(struct sock *sk, unsigned short nr)-{- struct nr_sock *nrom = nr_sk(sk);- unsigned short vc = nrom->va;-- while (vc != nrom->vs) {- if (nr == vc) return 1;- vc = (vc + 1) % NR_MODULUS;- }-- return nr == nrom->vs;-}--/*- * Check that ns is within the receive window.- */-int nr_in_rx_window(struct sock *sk, unsigned short ns)-{- struct nr_sock *nr = nr_sk(sk);- unsigned short vc = nr->vr;- unsigned short vt = (nr->vl + nr->window) % NR_MODULUS;-- while (vc != vt) {- if (ns == vc) return 1;- vc = (vc + 1) % NR_MODULUS;- }-- return 0;-}--/*- * This routine is called when the HDLC layer internally generates a- * control frame.- */-void nr_write_internal(struct sock *sk, int frametype)-{- struct nr_sock *nr = nr_sk(sk);- struct sk_buff *skb;- unsigned char *dptr;- int len, timeout;-- len = NR_TRANSPORT_LEN;-- switch (frametype & 0x0F) {- case NR_CONNREQ:- len += 17;- break;- case NR_CONNACK:- len += (nr->bpqext) ? 2 : 1;- break;- case NR_DISCREQ:- case NR_DISCACK:- case NR_INFOACK:- break;- default:- printk(KERN_ERR "NET/ROM: nr_write_internal - invalid frame type %d\n", frametype);- return;- }-- skb = alloc_skb(NR_NETWORK_LEN + len, GFP_ATOMIC);- if (!skb)- return;-- /*- * Space for AX.25 and NET/ROM network header- */- skb_reserve(skb, NR_NETWORK_LEN);-- dptr = skb_put(skb, len);-- switch (frametype & 0x0F) {- case NR_CONNREQ:- timeout = nr->t1 / HZ;- *dptr++ = nr->my_index;- *dptr++ = nr->my_id;- *dptr++ = 0;- *dptr++ = 0;- *dptr++ = frametype;- *dptr++ = nr->window;- memcpy(dptr, &nr->user_addr, AX25_ADDR_LEN);- dptr[6] &= ~AX25_CBIT;- dptr[6] &= ~AX25_EBIT;- dptr[6] |= AX25_SSSID_SPARE;- dptr += AX25_ADDR_LEN;- memcpy(dptr, &nr->source_addr, AX25_ADDR_LEN);- dptr[6] &= ~AX25_CBIT;- dptr[6] &= ~AX25_EBIT;- dptr[6] |= AX25_SSSID_SPARE;- dptr += AX25_ADDR_LEN;- *dptr++ = timeout % 256;- *dptr++ = timeout / 256;- break;-- case NR_CONNACK:- *dptr++ = nr->your_index;- *dptr++ = nr->your_id;- *dptr++ = nr->my_index;- *dptr++ = nr->my_id;- *dptr++ = frametype;- *dptr++ = nr->window;- if (nr->bpqext)- *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);- break;-- case NR_DISCREQ:- case NR_DISCACK:- *dptr++ = nr->your_index;- *dptr++ = nr->your_id;- *dptr++ = 0;- *dptr++ = 0;- *dptr++ = frametype;- break;-- case NR_INFOACK:- *dptr++ = nr->your_index;- *dptr++ = nr->your_id;- *dptr++ = 0;- *dptr++ = nr->vr;- *dptr++ = frametype;- break;- }-- nr_transmit_buffer(sk, skb);-}--/*- * This routine is called to send an error reply.- */-void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags)-{- struct sk_buff *skbn;- unsigned char *dptr;- int len;-- len = NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1;-- if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL)- return;-- skb_reserve(skbn, 0);-- dptr = skb_put(skbn, NR_NETWORK_LEN + NR_TRANSPORT_LEN);-- skb_copy_from_linear_data_offset(skb, 7, dptr, AX25_ADDR_LEN);- dptr[6] &= ~AX25_CBIT;- dptr[6] &= ~AX25_EBIT;- dptr[6] |= AX25_SSSID_SPARE;- dptr += AX25_ADDR_LEN;-- skb_copy_from_linear_data(skb, dptr, AX25_ADDR_LEN);- dptr[6] &= ~AX25_CBIT;- dptr[6] |= AX25_EBIT;- dptr[6] |= AX25_SSSID_SPARE;- dptr += AX25_ADDR_LEN;-- *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);-- if (mine) {- *dptr++ = 0;- *dptr++ = 0;- *dptr++ = skb->data[15];- *dptr++ = skb->data[16];- } else {- *dptr++ = skb->data[15];- *dptr++ = skb->data[16];- *dptr++ = 0;- *dptr++ = 0;- }-- *dptr++ = cmdflags;- *dptr++ = 0;-- if (!nr_route_frame(skbn, NULL))- kfree_skb(skbn);-}--void nr_disconnect(struct sock *sk, int reason)-{- nr_stop_t1timer(sk);- nr_stop_t2timer(sk);- nr_stop_t4timer(sk);- nr_stop_idletimer(sk);-- nr_clear_queues(sk);-- nr_sk(sk)->state = NR_STATE_0;-- sk->sk_state = TCP_CLOSE;- sk->sk_err = reason;- sk->sk_shutdown |= SEND_SHUTDOWN;-- if (!sock_flag(sk, SOCK_DEAD)) {- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DEAD);- }-}diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.cdeleted file mode 100644index b3a62b1f3a09..000000000000--- a/net/netrom/nr_timer.c+++ /dev/null@@ -1,249 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/jiffies.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/netrom.h>--static void nr_heartbeat_expiry(struct timer_list *);-static void nr_t1timer_expiry(struct timer_list *);-static void nr_t2timer_expiry(struct timer_list *);-static void nr_t4timer_expiry(struct timer_list *);-static void nr_idletimer_expiry(struct timer_list *);--void nr_init_timers(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);-- timer_setup(&nr->t1timer, nr_t1timer_expiry, 0);- timer_setup(&nr->t2timer, nr_t2timer_expiry, 0);- timer_setup(&nr->t4timer, nr_t4timer_expiry, 0);- timer_setup(&nr->idletimer, nr_idletimer_expiry, 0);-- /* initialized by sock_init_data */- sk->sk_timer.function = nr_heartbeat_expiry;-}--void nr_start_t1timer(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);-- sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1);-}--void nr_start_t2timer(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);-- sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2);-}--void nr_start_t4timer(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);-- sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4);-}--void nr_start_idletimer(struct sock *sk)-{- struct nr_sock *nr = nr_sk(sk);-- if (nr->idle > 0)- sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle);-}--void nr_start_heartbeat(struct sock *sk)-{- sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ);-}--void nr_stop_t1timer(struct sock *sk)-{- sk_stop_timer(sk, &nr_sk(sk)->t1timer);-}--void nr_stop_t2timer(struct sock *sk)-{- sk_stop_timer(sk, &nr_sk(sk)->t2timer);-}--void nr_stop_t4timer(struct sock *sk)-{- sk_stop_timer(sk, &nr_sk(sk)->t4timer);-}--void nr_stop_idletimer(struct sock *sk)-{- sk_stop_timer(sk, &nr_sk(sk)->idletimer);-}--void nr_stop_heartbeat(struct sock *sk)-{- sk_stop_timer(sk, &sk->sk_timer);-}--int nr_t1timer_running(struct sock *sk)-{- return timer_pending(&nr_sk(sk)->t1timer);-}--static void nr_heartbeat_expiry(struct timer_list *t)-{- struct sock *sk = timer_container_of(sk, t, sk_timer);- struct nr_sock *nr = nr_sk(sk);-- bh_lock_sock(sk);- switch (nr->state) {- case NR_STATE_0:- /* Magic here: If we listen() and a new link dies before it- is accepted() it isn't 'dead' so doesn't get removed. */- if (sock_flag(sk, SOCK_DESTROY) ||- (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {- if (sk->sk_state == TCP_LISTEN)- sock_hold(sk);- bh_unlock_sock(sk);- nr_destroy_socket(sk);- goto out;- }- break;-- case NR_STATE_3:- /*- * Check for the state of the receive buffer.- */- if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) &&- (nr->condition & NR_COND_OWN_RX_BUSY)) {- nr->condition &= ~NR_COND_OWN_RX_BUSY;- nr->condition &= ~NR_COND_ACK_PENDING;- nr->vl = nr->vr;- nr_write_internal(sk, NR_INFOACK);- break;- }- break;- }-- nr_start_heartbeat(sk);- bh_unlock_sock(sk);-out:- sock_put(sk);-}--static void nr_t2timer_expiry(struct timer_list *t)-{- struct nr_sock *nr = timer_container_of(nr, t, t2timer);- struct sock *sk = &nr->sock;-- bh_lock_sock(sk);- if (nr->condition & NR_COND_ACK_PENDING) {- nr->condition &= ~NR_COND_ACK_PENDING;- nr_enquiry_response(sk);- }- bh_unlock_sock(sk);- sock_put(sk);-}--static void nr_t4timer_expiry(struct timer_list *t)-{- struct nr_sock *nr = timer_container_of(nr, t, t4timer);- struct sock *sk = &nr->sock;-- bh_lock_sock(sk);- nr_sk(sk)->condition &= ~NR_COND_PEER_RX_BUSY;- bh_unlock_sock(sk);- sock_put(sk);-}--static void nr_idletimer_expiry(struct timer_list *t)-{- struct nr_sock *nr = timer_container_of(nr, t, idletimer);- struct sock *sk = &nr->sock;-- bh_lock_sock(sk);-- nr_clear_queues(sk);-- nr->n2count = 0;- nr_write_internal(sk, NR_DISCREQ);- nr->state = NR_STATE_2;-- nr_start_t1timer(sk);- nr_stop_t2timer(sk);- nr_stop_t4timer(sk);-- sk->sk_state = TCP_CLOSE;- sk->sk_err = 0;- sk->sk_shutdown |= SEND_SHUTDOWN;-- if (!sock_flag(sk, SOCK_DEAD)) {- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DEAD);- }- bh_unlock_sock(sk);- sock_put(sk);-}--static void nr_t1timer_expiry(struct timer_list *t)-{- struct nr_sock *nr = timer_container_of(nr, t, t1timer);- struct sock *sk = &nr->sock;-- bh_lock_sock(sk);- switch (nr->state) {- case NR_STATE_1:- if (nr->n2count == nr->n2) {- nr_disconnect(sk, ETIMEDOUT);- goto out;- } else {- nr->n2count++;- nr_write_internal(sk, NR_CONNREQ);- }- break;-- case NR_STATE_2:- if (nr->n2count == nr->n2) {- nr_disconnect(sk, ETIMEDOUT);- goto out;- } else {- nr->n2count++;- nr_write_internal(sk, NR_DISCREQ);- }- break;-- case NR_STATE_3:- if (nr->n2count == nr->n2) {- nr_disconnect(sk, ETIMEDOUT);- goto out;- } else {- nr->n2count++;- nr_requeue_frames(sk);- }- break;- }-- nr_start_t1timer(sk);-out:- bh_unlock_sock(sk);- sock_put(sk);-}diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.cdeleted file mode 100644index 7dc0fa628f2e..000000000000--- a/net/netrom/sysctl_net_netrom.c+++ /dev/null@@ -1,156 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)- */-#include <linux/mm.h>-#include <linux/sysctl.h>-#include <linux/init.h>-#include <net/ax25.h>-#include <net/netrom.h>--/*- * Values taken from NET/ROM documentation.- */-static int min_quality[] = {0}, max_quality[] = {255};-static int min_obs[] = {0}, max_obs[] = {255};-static int min_ttl[] = {0}, max_ttl[] = {255};-static int min_t1[] = {5 * HZ};-static int max_t1[] = {600 * HZ};-static int min_n2[] = {2}, max_n2[] = {127};-static int min_t2[] = {1 * HZ};-static int max_t2[] = {60 * HZ};-static int min_t4[] = {1 * HZ};-static int max_t4[] = {1000 * HZ};-static int min_window[] = {1}, max_window[] = {127};-static int min_idle[] = {0 * HZ};-static int max_idle[] = {65535 * HZ};-static int min_route[] = {0}, max_route[] = {1};-static int min_fails[] = {1}, max_fails[] = {10};-static int min_reset[] = {0}, max_reset[] = {1};--static struct ctl_table_header *nr_table_header;--static struct ctl_table nr_table[] = {- {- .procname = "default_path_quality",- .data = &sysctl_netrom_default_path_quality,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_quality,- .extra2 = &max_quality- },- {- .procname = "obsolescence_count_initialiser",- .data = &sysctl_netrom_obsolescence_count_initialiser,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_obs,- .extra2 = &max_obs- },- {- .procname = "network_ttl_initialiser",- .data = &sysctl_netrom_network_ttl_initialiser,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_ttl,- .extra2 = &max_ttl- },- {- .procname = "transport_timeout",- .data = &sysctl_netrom_transport_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_t1,- .extra2 = &max_t1- },- {- .procname = "transport_maximum_tries",- .data = &sysctl_netrom_transport_maximum_tries,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_n2,- .extra2 = &max_n2- },- {- .procname = "transport_acknowledge_delay",- .data = &sysctl_netrom_transport_acknowledge_delay,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_t2,- .extra2 = &max_t2- },- {- .procname = "transport_busy_delay",- .data = &sysctl_netrom_transport_busy_delay,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_t4,- .extra2 = &max_t4- },- {- .procname = "transport_requested_window_size",- .data = &sysctl_netrom_transport_requested_window_size,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_window,- .extra2 = &max_window- },- {- .procname = "transport_no_activity_timeout",- .data = &sysctl_netrom_transport_no_activity_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_idle,- .extra2 = &max_idle- },- {- .procname = "routing_control",- .data = &sysctl_netrom_routing_control,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_route,- .extra2 = &max_route- },- {- .procname = "link_fails_count",- .data = &sysctl_netrom_link_fails_count,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_fails,- .extra2 = &max_fails- },- {- .procname = "reset",- .data = &sysctl_netrom_reset_circuit,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_reset,- .extra2 = &max_reset- },-};--int __init nr_register_sysctl(void)-{- nr_table_header = register_net_sysctl(&init_net, "net/netrom", nr_table);- if (!nr_table_header)- return -ENOMEM;- return 0;-}--void nr_unregister_sysctl(void)-{- unregister_net_sysctl_table(nr_table_header);-}diff --git a/net/rose/af_rose.c b/net/rose/af_rose.cdeleted file mode 100644index d5032840ee48..000000000000--- a/net/rose/af_rose.c+++ /dev/null@@ -1,1687 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)- * Copyright (C) Terry Dawson VK2KTJ (terry@animats.net)- * Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)- */--#include <linux/capability.h>-#include <linux/module.h>-#include <linux/moduleparam.h>-#include <linux/init.h>-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/slab.h>-#include <linux/kernel.h>-#include <linux/sched/signal.h>-#include <linux/spinlock.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/stat.h>-#include <net/net_namespace.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/termios.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/notifier.h>-#include <net/rose.h>-#include <linux/proc_fs.h>-#include <linux/seq_file.h>-#include <net/tcp_states.h>-#include <net/ip.h>-#include <net/arp.h>--static int rose_ndevs = 10;--int sysctl_rose_restart_request_timeout = ROSE_DEFAULT_T0;-int sysctl_rose_call_request_timeout = ROSE_DEFAULT_T1;-int sysctl_rose_reset_request_timeout = ROSE_DEFAULT_T2;-int sysctl_rose_clear_request_timeout = ROSE_DEFAULT_T3;-int sysctl_rose_no_activity_timeout = ROSE_DEFAULT_IDLE;-int sysctl_rose_ack_hold_back_timeout = ROSE_DEFAULT_HB;-int sysctl_rose_routing_control = ROSE_DEFAULT_ROUTING;-int sysctl_rose_link_fail_timeout = ROSE_DEFAULT_FAIL_TIMEOUT;-int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC;-int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE;--static HLIST_HEAD(rose_list);-static DEFINE_SPINLOCK(rose_list_lock);--static const struct proto_ops rose_proto_ops;--ax25_address rose_callsign;--/*- * ROSE network devices are virtual network devices encapsulating ROSE- * frames into AX.25 which will be sent through an AX.25 device, so form a- * special "super class" of normal net devices; split their locks off into a- * separate class since they always nest.- */-static struct lock_class_key rose_netdev_xmit_lock_key;-static struct lock_class_key rose_netdev_addr_lock_key;--static void rose_set_lockdep_one(struct net_device *dev,- struct netdev_queue *txq,- void *_unused)-{- lockdep_set_class(&txq->_xmit_lock, &rose_netdev_xmit_lock_key);-}--static void rose_set_lockdep_key(struct net_device *dev)-{- lockdep_set_class(&dev->addr_list_lock, &rose_netdev_addr_lock_key);- netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL);-}--/*- * Convert a ROSE address into text.- */-char *rose2asc(char *buf, const rose_address *addr)-{- if (addr->rose_addr[0] == 0x00 && addr->rose_addr[1] == 0x00 &&- addr->rose_addr[2] == 0x00 && addr->rose_addr[3] == 0x00 &&- addr->rose_addr[4] == 0x00) {- strcpy(buf, "*");- } else {- sprintf(buf, "%02X%02X%02X%02X%02X", addr->rose_addr[0] & 0xFF,- addr->rose_addr[1] & 0xFF,- addr->rose_addr[2] & 0xFF,- addr->rose_addr[3] & 0xFF,- addr->rose_addr[4] & 0xFF);- }-- return buf;-}--/*- * Compare two ROSE addresses, 0 == equal.- */-int rosecmp(const rose_address *addr1, const rose_address *addr2)-{- int i;-- for (i = 0; i < 5; i++)- if (addr1->rose_addr[i] != addr2->rose_addr[i])- return 1;-- return 0;-}--/*- * Compare two ROSE addresses for only mask digits, 0 == equal.- */-int rosecmpm(const rose_address *addr1, const rose_address *addr2,- unsigned short mask)-{- unsigned int i, j;-- if (mask > 10)- return 1;-- for (i = 0; i < mask; i++) {- j = i / 2;-- if ((i % 2) != 0) {- if ((addr1->rose_addr[j] & 0x0F) != (addr2->rose_addr[j] & 0x0F))- return 1;- } else {- if ((addr1->rose_addr[j] & 0xF0) != (addr2->rose_addr[j] & 0xF0))- return 1;- }- }-- return 0;-}--/*- * Socket removal during an interrupt is now safe.- */-static void rose_remove_socket(struct sock *sk)-{- spin_lock_bh(&rose_list_lock);- sk_del_node_init(sk);- spin_unlock_bh(&rose_list_lock);-}--/*- * Kill all bound sockets on a broken link layer connection to a- * particular neighbour.- */-void rose_kill_by_neigh(struct rose_neigh *neigh)-{- struct sock *s;-- spin_lock_bh(&rose_list_lock);- sk_for_each(s, &rose_list) {- struct rose_sock *rose = rose_sk(s);-- if (rose->neighbour == neigh) {- rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);- rose_neigh_put(rose->neighbour);- rose->neighbour = NULL;- }- }- spin_unlock_bh(&rose_list_lock);-}--/*- * Kill all bound sockets on a dropped device.- */-static void rose_kill_by_device(struct net_device *dev)-{- struct sock *sk, *array[16];- struct rose_sock *rose;- bool rescan;- int i, cnt;--start:- rescan = false;- cnt = 0;- spin_lock_bh(&rose_list_lock);- sk_for_each(sk, &rose_list) {- rose = rose_sk(sk);- if (rose->device == dev) {- if (cnt == ARRAY_SIZE(array)) {- rescan = true;- break;- }- sock_hold(sk);- array[cnt++] = sk;- }- }- spin_unlock_bh(&rose_list_lock);-- for (i = 0; i < cnt; i++) {- sk = array[i];- rose = rose_sk(sk);- lock_sock(sk);- spin_lock_bh(&rose_list_lock);- if (rose->device == dev) {- rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);- if (rose->neighbour)- rose_neigh_put(rose->neighbour);- netdev_put(rose->device, &rose->dev_tracker);- rose->device = NULL;- }- spin_unlock_bh(&rose_list_lock);- release_sock(sk);- sock_put(sk);- cond_resched();- }- if (rescan)- goto start;-}--/*- * Handle device status changes.- */-static int rose_device_event(struct notifier_block *this,- unsigned long event, void *ptr)-{- struct net_device *dev = netdev_notifier_info_to_dev(ptr);-- if (!net_eq(dev_net(dev), &init_net))- return NOTIFY_DONE;-- if (event != NETDEV_DOWN)- return NOTIFY_DONE;-- switch (dev->type) {- case ARPHRD_ROSE:- rose_kill_by_device(dev);- break;- case ARPHRD_AX25:- rose_link_device_down(dev);- rose_rt_device_down(dev);- break;- }-- return NOTIFY_DONE;-}--/*- * Add a socket to the bound sockets list.- */-static void rose_insert_socket(struct sock *sk)-{-- spin_lock_bh(&rose_list_lock);- sk_add_node(sk, &rose_list);- spin_unlock_bh(&rose_list_lock);-}--/*- * Find a socket that wants to accept the Call Request we just- * received.- */-static struct sock *rose_find_listener(rose_address *addr, ax25_address *call)-{- struct sock *s;-- spin_lock_bh(&rose_list_lock);- sk_for_each(s, &rose_list) {- struct rose_sock *rose = rose_sk(s);-- if (!rosecmp(&rose->source_addr, addr) &&- !ax25cmp(&rose->source_call, call) &&- !rose->source_ndigis && s->sk_state == TCP_LISTEN)- goto found;- }-- sk_for_each(s, &rose_list) {- struct rose_sock *rose = rose_sk(s);-- if (!rosecmp(&rose->source_addr, addr) &&- !ax25cmp(&rose->source_call, &null_ax25_address) &&- s->sk_state == TCP_LISTEN)- goto found;- }- s = NULL;-found:- spin_unlock_bh(&rose_list_lock);- return s;-}--/*- * Find a connected ROSE socket given my LCI and device.- */-struct sock *rose_find_socket(unsigned int lci, struct rose_neigh *neigh)-{- struct sock *s;-- spin_lock_bh(&rose_list_lock);- sk_for_each(s, &rose_list) {- struct rose_sock *rose = rose_sk(s);-- if (rose->lci == lci && rose->neighbour == neigh)- goto found;- }- s = NULL;-found:- spin_unlock_bh(&rose_list_lock);- return s;-}--/*- * Find a unique LCI for a given device.- */-unsigned int rose_new_lci(struct rose_neigh *neigh)-{- int lci;-- if (neigh->dce_mode) {- for (lci = 1; lci <= sysctl_rose_maximum_vcs; lci++)- if (rose_find_socket(lci, neigh) == NULL && rose_route_free_lci(lci, neigh) == NULL)- return lci;- } else {- for (lci = sysctl_rose_maximum_vcs; lci > 0; lci--)- if (rose_find_socket(lci, neigh) == NULL && rose_route_free_lci(lci, neigh) == NULL)- return lci;- }-- return 0;-}--/*- * Deferred destroy.- */-void rose_destroy_socket(struct sock *);--/*- * Handler for deferred kills.- */-static void rose_destroy_timer(struct timer_list *t)-{- struct sock *sk = timer_container_of(sk, t, sk_timer);-- rose_destroy_socket(sk);-}--/*- * This is called from user mode and the timers. Thus it protects itself- * against interrupt users but doesn't worry about being called during- * work. Once it is removed from the queue no interrupt or bottom half- * will touch it and we are (fairly 8-) ) safe.- */-void rose_destroy_socket(struct sock *sk)-{- struct sk_buff *skb;-- rose_remove_socket(sk);- rose_stop_heartbeat(sk);- rose_stop_idletimer(sk);- rose_stop_timer(sk);-- rose_clear_queues(sk); /* Flush the queues */-- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {- if (skb->sk != sk) { /* A pending connection */- /* Queue the unaccepted socket for death */- sock_set_flag(skb->sk, SOCK_DEAD);- rose_start_heartbeat(skb->sk);- rose_sk(skb->sk)->state = ROSE_STATE_0;- }-- kfree_skb(skb);- }-- if (sk_has_allocations(sk)) {- /* Defer: outstanding buffers */- timer_setup(&sk->sk_timer, rose_destroy_timer, 0);- sk->sk_timer.expires = jiffies + 10 * HZ;- add_timer(&sk->sk_timer);- } else- sock_put(sk);-}--/*- * Handling for system calls applied via the various interfaces to a- * ROSE socket object.- */--static int rose_setsockopt(struct socket *sock, int level, int optname,- sockptr_t optval, unsigned int optlen)-{- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- unsigned int opt;-- if (level != SOL_ROSE)- return -ENOPROTOOPT;-- if (optlen < sizeof(unsigned int))- return -EINVAL;-- if (copy_from_sockptr(&opt, optval, sizeof(unsigned int)))- return -EFAULT;-- switch (optname) {- case ROSE_DEFER:- rose->defer = opt ? 1 : 0;- return 0;-- case ROSE_T1:- if (opt < 1 || opt > UINT_MAX / HZ)- return -EINVAL;- rose->t1 = opt * HZ;- return 0;-- case ROSE_T2:- if (opt < 1 || opt > UINT_MAX / HZ)- return -EINVAL;- rose->t2 = opt * HZ;- return 0;-- case ROSE_T3:- if (opt < 1 || opt > UINT_MAX / HZ)- return -EINVAL;- rose->t3 = opt * HZ;- return 0;-- case ROSE_HOLDBACK:- if (opt < 1 || opt > UINT_MAX / HZ)- return -EINVAL;- rose->hb = opt * HZ;- return 0;-- case ROSE_IDLE:- if (opt > UINT_MAX / (60 * HZ))- return -EINVAL;- rose->idle = opt * 60 * HZ;- return 0;-- case ROSE_QBITINCL:- rose->qbitincl = opt ? 1 : 0;- return 0;-- default:- return -ENOPROTOOPT;- }-}--static int rose_getsockopt(struct socket *sock, int level, int optname,- char __user *optval, int __user *optlen)-{- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- int val = 0;- int len;-- if (level != SOL_ROSE)- return -ENOPROTOOPT;-- if (get_user(len, optlen))- return -EFAULT;-- if (len < 0)- return -EINVAL;-- switch (optname) {- case ROSE_DEFER:- val = rose->defer;- break;-- case ROSE_T1:- val = rose->t1 / HZ;- break;-- case ROSE_T2:- val = rose->t2 / HZ;- break;-- case ROSE_T3:- val = rose->t3 / HZ;- break;-- case ROSE_HOLDBACK:- val = rose->hb / HZ;- break;-- case ROSE_IDLE:- val = rose->idle / (60 * HZ);- break;-- case ROSE_QBITINCL:- val = rose->qbitincl;- break;-- default:- return -ENOPROTOOPT;- }-- len = min_t(unsigned int, len, sizeof(int));-- if (put_user(len, optlen))- return -EFAULT;-- return copy_to_user(optval, &val, len) ? -EFAULT : 0;-}--static int rose_listen(struct socket *sock, int backlog)-{- struct sock *sk = sock->sk;-- lock_sock(sk);- if (sock->state != SS_UNCONNECTED) {- release_sock(sk);- return -EINVAL;- }-- if (sk->sk_state != TCP_LISTEN) {- struct rose_sock *rose = rose_sk(sk);-- rose->dest_ndigis = 0;- memset(&rose->dest_addr, 0, ROSE_ADDR_LEN);- memset(&rose->dest_call, 0, AX25_ADDR_LEN);- memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS);- sk->sk_max_ack_backlog = backlog;- sk->sk_state = TCP_LISTEN;- release_sock(sk);- return 0;- }- release_sock(sk);-- return -EOPNOTSUPP;-}--static struct proto rose_proto = {- .name = "ROSE",- .owner = THIS_MODULE,- .obj_size = sizeof(struct rose_sock),-};--static int rose_create(struct net *net, struct socket *sock, int protocol,- int kern)-{- struct sock *sk;- struct rose_sock *rose;-- if (!net_eq(net, &init_net))- return -EAFNOSUPPORT;-- if (sock->type != SOCK_SEQPACKET || protocol != 0)- return -ESOCKTNOSUPPORT;-- sk = sk_alloc(net, PF_ROSE, GFP_ATOMIC, &rose_proto, kern);- if (sk == NULL)- return -ENOMEM;-- rose = rose_sk(sk);-- sock_init_data(sock, sk);-- skb_queue_head_init(&rose->ack_queue);-#ifdef M_BIT- skb_queue_head_init(&rose->frag_queue);- rose->fraglen = 0;-#endif-- sock->ops = &rose_proto_ops;- sk->sk_protocol = protocol;-- timer_setup(&rose->timer, NULL, 0);- timer_setup(&rose->idletimer, NULL, 0);-- rose->t1 = msecs_to_jiffies(sysctl_rose_call_request_timeout);- rose->t2 = msecs_to_jiffies(sysctl_rose_reset_request_timeout);- rose->t3 = msecs_to_jiffies(sysctl_rose_clear_request_timeout);- rose->hb = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout);- rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout);-- rose->state = ROSE_STATE_0;-- return 0;-}--static struct sock *rose_make_new(struct sock *osk)-{- struct sock *sk;- struct rose_sock *rose, *orose;-- if (osk->sk_type != SOCK_SEQPACKET)- return NULL;-- sk = sk_alloc(sock_net(osk), PF_ROSE, GFP_ATOMIC, &rose_proto, 0);- if (sk == NULL)- return NULL;-- rose = rose_sk(sk);-- sock_init_data(NULL, sk);-- skb_queue_head_init(&rose->ack_queue);-#ifdef M_BIT- skb_queue_head_init(&rose->frag_queue);- rose->fraglen = 0;-#endif-- sk->sk_type = osk->sk_type;- sk->sk_priority = READ_ONCE(osk->sk_priority);- sk->sk_protocol = osk->sk_protocol;- sk->sk_rcvbuf = osk->sk_rcvbuf;- sk->sk_sndbuf = osk->sk_sndbuf;- sk->sk_state = TCP_ESTABLISHED;- sock_copy_flags(sk, osk);-- timer_setup(&rose->timer, NULL, 0);- timer_setup(&rose->idletimer, NULL, 0);-- orose = rose_sk(osk);- rose->t1 = orose->t1;- rose->t2 = orose->t2;- rose->t3 = orose->t3;- rose->hb = orose->hb;- rose->idle = orose->idle;- rose->defer = orose->defer;- rose->device = orose->device;- if (rose->device)- netdev_hold(rose->device, &rose->dev_tracker, GFP_ATOMIC);- rose->qbitincl = orose->qbitincl;-- return sk;-}--static int rose_release(struct socket *sock)-{- struct sock *sk = sock->sk;- struct rose_sock *rose;-- if (sk == NULL) return 0;-- sock_hold(sk);- sock_orphan(sk);- lock_sock(sk);- rose = rose_sk(sk);-- switch (rose->state) {- case ROSE_STATE_0:- release_sock(sk);- rose_disconnect(sk, 0, -1, -1);- lock_sock(sk);- rose_destroy_socket(sk);- break;-- case ROSE_STATE_2:- rose_neigh_put(rose->neighbour);- release_sock(sk);- rose_disconnect(sk, 0, -1, -1);- lock_sock(sk);- rose_destroy_socket(sk);- break;-- case ROSE_STATE_1:- case ROSE_STATE_3:- case ROSE_STATE_4:- case ROSE_STATE_5:- rose_clear_queues(sk);- rose_stop_idletimer(sk);- rose_write_internal(sk, ROSE_CLEAR_REQUEST);- rose_start_t3timer(sk);- rose->state = ROSE_STATE_2;- sk->sk_state = TCP_CLOSE;- sk->sk_shutdown |= SEND_SHUTDOWN;- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DEAD);- sock_set_flag(sk, SOCK_DESTROY);- break;-- default:- break;- }-- spin_lock_bh(&rose_list_lock);- netdev_put(rose->device, &rose->dev_tracker);- rose->device = NULL;- spin_unlock_bh(&rose_list_lock);- sock->sk = NULL;- release_sock(sk);- sock_put(sk);-- return 0;-}--static int rose_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int addr_len)-{- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;- struct net_device *dev;- ax25_address *source;- ax25_uid_assoc *user;- int err = -EINVAL;- int n;-- if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))- return -EINVAL;-- if (addr->srose_family != AF_ROSE)- return -EINVAL;-- if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)- return -EINVAL;-- if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)- return -EINVAL;-- lock_sock(sk);-- if (!sock_flag(sk, SOCK_ZAPPED))- goto out_release;-- err = -EADDRNOTAVAIL;- dev = rose_dev_get(&addr->srose_addr);- if (!dev)- goto out_release;-- source = &addr->srose_call;-- user = ax25_findbyuid(current_euid());- if (user) {- rose->source_call = user->call;- ax25_uid_put(user);- } else {- if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {- dev_put(dev);- err = -EACCES;- goto out_release;- }- rose->source_call = *source;- }-- rose->source_addr = addr->srose_addr;- rose->device = dev;- netdev_tracker_alloc(rose->device, &rose->dev_tracker, GFP_KERNEL);- rose->source_ndigis = addr->srose_ndigis;-- if (addr_len == sizeof(struct full_sockaddr_rose)) {- struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr;- for (n = 0 ; n < addr->srose_ndigis ; n++)- rose->source_digis[n] = full_addr->srose_digis[n];- } else {- if (rose->source_ndigis == 1) {- rose->source_digis[0] = addr->srose_digi;- }- }-- rose_insert_socket(sk);-- sock_reset_flag(sk, SOCK_ZAPPED);- err = 0;-out_release:- release_sock(sk);- return err;-}--static int rose_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int addr_len,- int flags)-{- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;- unsigned char cause, diagnostic;- ax25_uid_assoc *user;- int n, err = 0;-- if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))- return -EINVAL;-- if (addr->srose_family != AF_ROSE)- return -EINVAL;-- if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)- return -EINVAL;-- if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)- return -EINVAL;-- /* Source + Destination digis should not exceed ROSE_MAX_DIGIS */- if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS)- return -EINVAL;-- lock_sock(sk);-- if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {- /* Connect completed during a ERESTARTSYS event */- sock->state = SS_CONNECTED;- goto out_release;- }-- if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {- sock->state = SS_UNCONNECTED;- err = -ECONNREFUSED;- goto out_release;- }-- if (sk->sk_state == TCP_ESTABLISHED) {- /* No reconnect on a seqpacket socket */- err = -EISCONN;- goto out_release;- }-- if (sk->sk_state == TCP_SYN_SENT) {- err = -EALREADY;- goto out_release;- }-- sk->sk_state = TCP_CLOSE;- sock->state = SS_UNCONNECTED;-- rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,- &diagnostic, 0);- if (!rose->neighbour) {- err = -ENETUNREACH;- goto out_release;- }-- rose->lci = rose_new_lci(rose->neighbour);- if (!rose->lci) {- err = -ENETUNREACH;- rose_neigh_put(rose->neighbour);- goto out_release;- }-- if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */- struct net_device *dev;-- sock_reset_flag(sk, SOCK_ZAPPED);-- dev = rose_dev_first();- if (!dev) {- err = -ENETUNREACH;- rose_neigh_put(rose->neighbour);- goto out_release;- }-- user = ax25_findbyuid(current_euid());- if (!user) {- err = -EINVAL;- rose_neigh_put(rose->neighbour);- dev_put(dev);- goto out_release;- }-- memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);- rose->source_call = user->call;- rose->device = dev;- netdev_tracker_alloc(rose->device, &rose->dev_tracker,- GFP_KERNEL);- ax25_uid_put(user);-- rose_insert_socket(sk); /* Finish the bind */- }- rose->dest_addr = addr->srose_addr;- rose->dest_call = addr->srose_call;- rose->rand = ((long)rose & 0xFFFF) + rose->lci;- rose->dest_ndigis = addr->srose_ndigis;-- if (addr_len == sizeof(struct full_sockaddr_rose)) {- struct full_sockaddr_rose *full_addr = (struct full_sockaddr_rose *)uaddr;- for (n = 0 ; n < addr->srose_ndigis ; n++)- rose->dest_digis[n] = full_addr->srose_digis[n];- } else {- if (rose->dest_ndigis == 1) {- rose->dest_digis[0] = addr->srose_digi;- }- }-- /* Move to connecting socket, start sending Connect Requests */- sock->state = SS_CONNECTING;- sk->sk_state = TCP_SYN_SENT;-- rose->state = ROSE_STATE_1;-- rose_write_internal(sk, ROSE_CALL_REQUEST);- rose_start_heartbeat(sk);- rose_start_t1timer(sk);-- /* Now the loop */- if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {- err = -EINPROGRESS;- goto out_release;- }-- /*- * A Connect Ack with Choke or timeout or failed routing will go to- * closed.- */- if (sk->sk_state == TCP_SYN_SENT) {- DEFINE_WAIT(wait);-- for (;;) {- prepare_to_wait(sk_sleep(sk), &wait,- TASK_INTERRUPTIBLE);- if (sk->sk_state != TCP_SYN_SENT)- break;- if (!signal_pending(current)) {- release_sock(sk);- schedule();- lock_sock(sk);- continue;- }- err = -ERESTARTSYS;- break;- }- finish_wait(sk_sleep(sk), &wait);-- if (err)- goto out_release;- }-- if (sk->sk_state != TCP_ESTABLISHED) {- sock->state = SS_UNCONNECTED;- err = sock_error(sk); /* Always set at this point */- goto out_release;- }-- sock->state = SS_CONNECTED;--out_release:- release_sock(sk);-- return err;-}--static int rose_accept(struct socket *sock, struct socket *newsock,- struct proto_accept_arg *arg)-{- struct sk_buff *skb;- struct sock *newsk;- DEFINE_WAIT(wait);- struct sock *sk;- int err = 0;-- if ((sk = sock->sk) == NULL)- return -EINVAL;-- lock_sock(sk);- if (sk->sk_type != SOCK_SEQPACKET) {- err = -EOPNOTSUPP;- goto out_release;- }-- if (sk->sk_state != TCP_LISTEN) {- err = -EINVAL;- goto out_release;- }-- /*- * The write queue this time is holding sockets ready to use- * hooked into the SABM we saved- */- for (;;) {- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);-- skb = skb_dequeue(&sk->sk_receive_queue);- if (skb)- break;-- if (arg->flags & O_NONBLOCK) {- err = -EWOULDBLOCK;- break;- }- if (!signal_pending(current)) {- release_sock(sk);- schedule();- lock_sock(sk);- continue;- }- err = -ERESTARTSYS;- break;- }- finish_wait(sk_sleep(sk), &wait);- if (err)- goto out_release;-- newsk = skb->sk;- sock_graft(newsk, newsock);-- /* Now attach up the new socket */- skb->sk = NULL;- kfree_skb(skb);- sk_acceptq_removed(sk);--out_release:- release_sock(sk);-- return err;-}--static int rose_getname(struct socket *sock, struct sockaddr *uaddr,- int peer)-{- struct full_sockaddr_rose *srose = (struct full_sockaddr_rose *)uaddr;- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- int n;-- memset(srose, 0, sizeof(*srose));- if (peer != 0) {- if (sk->sk_state != TCP_ESTABLISHED)- return -ENOTCONN;- srose->srose_family = AF_ROSE;- srose->srose_addr = rose->dest_addr;- srose->srose_call = rose->dest_call;- srose->srose_ndigis = rose->dest_ndigis;- for (n = 0; n < rose->dest_ndigis; n++)- srose->srose_digis[n] = rose->dest_digis[n];- } else {- srose->srose_family = AF_ROSE;- srose->srose_addr = rose->source_addr;- srose->srose_call = rose->source_call;- srose->srose_ndigis = rose->source_ndigis;- for (n = 0; n < rose->source_ndigis; n++)- srose->srose_digis[n] = rose->source_digis[n];- }-- return sizeof(struct full_sockaddr_rose);-}--int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct rose_neigh *neigh, unsigned int lci)-{- struct sock *sk;- struct sock *make;- struct rose_sock *make_rose;- struct rose_facilities_struct facilities;- int n;-- skb->sk = NULL; /* Initially we don't know who it's for */-- /*- * skb->data points to the rose frame start- */- memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));-- if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,- skb->len - ROSE_CALL_REQ_FACILITIES_OFF,- &facilities)) {- rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76);- return 0;- }-- sk = rose_find_listener(&facilities.source_addr, &facilities.source_call);-- /*- * We can't accept the Call Request.- */- if (sk == NULL || sk_acceptq_is_full(sk) ||- (make = rose_make_new(sk)) == NULL) {- rose_transmit_clear_request(neigh, lci, ROSE_NETWORK_CONGESTION, 120);- return 0;- }-- skb->sk = make;- make->sk_state = TCP_ESTABLISHED;- make_rose = rose_sk(make);-- make_rose->lci = lci;- make_rose->dest_addr = facilities.dest_addr;- make_rose->dest_call = facilities.dest_call;- make_rose->dest_ndigis = facilities.dest_ndigis;- for (n = 0 ; n < facilities.dest_ndigis ; n++)- make_rose->dest_digis[n] = facilities.dest_digis[n];- make_rose->source_addr = facilities.source_addr;- make_rose->source_call = facilities.source_call;- make_rose->source_ndigis = facilities.source_ndigis;- for (n = 0 ; n < facilities.source_ndigis ; n++)- make_rose->source_digis[n] = facilities.source_digis[n];- make_rose->neighbour = neigh;- make_rose->device = dev;- /* Caller got a reference for us. */- netdev_tracker_alloc(make_rose->device, &make_rose->dev_tracker,- GFP_ATOMIC);- make_rose->facilities = facilities;-- rose_neigh_hold(make_rose->neighbour);-- if (rose_sk(sk)->defer) {- make_rose->state = ROSE_STATE_5;- } else {- rose_write_internal(make, ROSE_CALL_ACCEPTED);- make_rose->state = ROSE_STATE_3;- rose_start_idletimer(make);- }-- make_rose->condition = 0x00;- make_rose->vs = 0;- make_rose->va = 0;- make_rose->vr = 0;- make_rose->vl = 0;- sk_acceptq_added(sk);-- rose_insert_socket(make);-- skb_queue_head(&sk->sk_receive_queue, skb);-- rose_start_heartbeat(make);-- if (!sock_flag(sk, SOCK_DEAD))- sk->sk_data_ready(sk);-- return 1;-}--static int rose_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)-{- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- DECLARE_SOCKADDR(struct sockaddr_rose *, usrose, msg->msg_name);- int err;- struct full_sockaddr_rose srose;- struct sk_buff *skb;- unsigned char *asmptr;- int n, size, qbit = 0;-- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))- return -EINVAL;-- if (sock_flag(sk, SOCK_ZAPPED))- return -EADDRNOTAVAIL;-- if (sk->sk_shutdown & SEND_SHUTDOWN) {- send_sig(SIGPIPE, current, 0);- return -EPIPE;- }-- if (rose->neighbour == NULL || rose->device == NULL)- return -ENETUNREACH;-- if (usrose != NULL) {- if (msg->msg_namelen != sizeof(struct sockaddr_rose) && msg->msg_namelen != sizeof(struct full_sockaddr_rose))- return -EINVAL;- memset(&srose, 0, sizeof(struct full_sockaddr_rose));- memcpy(&srose, usrose, msg->msg_namelen);- if (rosecmp(&rose->dest_addr, &srose.srose_addr) != 0 ||- ax25cmp(&rose->dest_call, &srose.srose_call) != 0)- return -EISCONN;- if (srose.srose_ndigis != rose->dest_ndigis)- return -EISCONN;- if (srose.srose_ndigis == rose->dest_ndigis) {- for (n = 0 ; n < srose.srose_ndigis ; n++)- if (ax25cmp(&rose->dest_digis[n],- &srose.srose_digis[n]))- return -EISCONN;- }- if (srose.srose_family != AF_ROSE)- return -EINVAL;- } else {- if (sk->sk_state != TCP_ESTABLISHED)- return -ENOTCONN;-- srose.srose_family = AF_ROSE;- srose.srose_addr = rose->dest_addr;- srose.srose_call = rose->dest_call;- srose.srose_ndigis = rose->dest_ndigis;- for (n = 0 ; n < rose->dest_ndigis ; n++)- srose.srose_digis[n] = rose->dest_digis[n];- }-- /* Build a packet */- /* Sanity check the packet size */- if (len > 65535)- return -EMSGSIZE;-- size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;-- if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)- return err;-- skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN);-- /*- * Put the data on the end- */-- skb_reset_transport_header(skb);- skb_put(skb, len);-- err = memcpy_from_msg(skb_transport_header(skb), msg, len);- if (err) {- kfree_skb(skb);- return err;- }-- /*- * If the Q BIT Include socket option is in force, the first- * byte of the user data is the logical value of the Q Bit.- */- if (rose->qbitincl) {- qbit = skb->data[0];- skb_pull(skb, 1);- }-- /*- * Push down the ROSE header- */- asmptr = skb_push(skb, ROSE_MIN_LEN);-- /* Build a ROSE Network header */- asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI;- asmptr[1] = (rose->lci >> 0) & 0xFF;- asmptr[2] = ROSE_DATA;-- if (qbit)- asmptr[0] |= ROSE_Q_BIT;-- if (sk->sk_state != TCP_ESTABLISHED) {- kfree_skb(skb);- return -ENOTCONN;- }--#ifdef M_BIT-#define ROSE_PACLEN (256-ROSE_MIN_LEN)- if (skb->len - ROSE_MIN_LEN > ROSE_PACLEN) {- unsigned char header[ROSE_MIN_LEN];- struct sk_buff *skbn;- int frontlen;- int lg;-- /* Save a copy of the Header */- skb_copy_from_linear_data(skb, header, ROSE_MIN_LEN);- skb_pull(skb, ROSE_MIN_LEN);-- frontlen = skb_headroom(skb);-- while (skb->len > 0) {- if ((skbn = sock_alloc_send_skb(sk, frontlen + ROSE_PACLEN, 0, &err)) == NULL) {- kfree_skb(skb);- return err;- }-- skbn->sk = sk;- skbn->free = 1;- skbn->arp = 1;-- skb_reserve(skbn, frontlen);-- lg = (ROSE_PACLEN > skb->len) ? skb->len : ROSE_PACLEN;-- /* Copy the user data */- skb_copy_from_linear_data(skb, skb_put(skbn, lg), lg);- skb_pull(skb, lg);-- /* Duplicate the Header */- skb_push(skbn, ROSE_MIN_LEN);- skb_copy_to_linear_data(skbn, header, ROSE_MIN_LEN);-- if (skb->len > 0)- skbn->data[2] |= M_BIT;-- skb_queue_tail(&sk->sk_write_queue, skbn); /* Throw it on the queue */- }-- skb->free = 1;- kfree_skb(skb);- } else {- skb_queue_tail(&sk->sk_write_queue, skb); /* Throw it on the queue */- }-#else- skb_queue_tail(&sk->sk_write_queue, skb); /* Shove it onto the queue */-#endif-- rose_kick(sk);-- return len;-}---static int rose_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,- int flags)-{- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- size_t copied;- unsigned char *asmptr;- struct sk_buff *skb;- int n, er, qbit;-- /*- * This works for seqpacket too. The receiver has ordered the queue for- * us! We do one quick check first though- */- if (sk->sk_state != TCP_ESTABLISHED)- return -ENOTCONN;-- /* Now we can treat all alike */- skb = skb_recv_datagram(sk, flags, &er);- if (!skb)- return er;-- qbit = (skb->data[0] & ROSE_Q_BIT) == ROSE_Q_BIT;-- skb_pull(skb, ROSE_MIN_LEN);-- if (rose->qbitincl) {- asmptr = skb_push(skb, 1);- *asmptr = qbit;- }-- skb_reset_transport_header(skb);- copied = skb->len;-- if (copied > size) {- copied = size;- msg->msg_flags |= MSG_TRUNC;- }-- skb_copy_datagram_msg(skb, 0, msg, copied);-- if (msg->msg_name) {- struct sockaddr_rose *srose;- DECLARE_SOCKADDR(struct full_sockaddr_rose *, full_srose,- msg->msg_name);-- memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));- srose = msg->msg_name;- srose->srose_family = AF_ROSE;- srose->srose_addr = rose->dest_addr;- srose->srose_call = rose->dest_call;- srose->srose_ndigis = rose->dest_ndigis;- for (n = 0 ; n < rose->dest_ndigis ; n++)- full_srose->srose_digis[n] = rose->dest_digis[n];- msg->msg_namelen = sizeof(struct full_sockaddr_rose);- }-- skb_free_datagram(sk, skb);-- return copied;-}---static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)-{- struct sock *sk = sock->sk;- struct rose_sock *rose = rose_sk(sk);- void __user *argp = (void __user *)arg;-- switch (cmd) {- case TIOCOUTQ: {- long amount;-- amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);- if (amount < 0)- amount = 0;- return put_user(amount, (unsigned int __user *) argp);- }-- case TIOCINQ: {- struct sk_buff *skb;- long amount = 0L;-- spin_lock_irq(&sk->sk_receive_queue.lock);- if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)- amount = skb->len;- spin_unlock_irq(&sk->sk_receive_queue.lock);- return put_user(amount, (unsigned int __user *) argp);- }-- case SIOCGIFADDR:- case SIOCSIFADDR:- case SIOCGIFDSTADDR:- case SIOCSIFDSTADDR:- case SIOCGIFBRDADDR:- case SIOCSIFBRDADDR:- case SIOCGIFNETMASK:- case SIOCSIFNETMASK:- case SIOCGIFMETRIC:- case SIOCSIFMETRIC:- return -EINVAL;-- case SIOCADDRT:- case SIOCDELRT:- case SIOCRSCLRRT:- if (!capable(CAP_NET_ADMIN))- return -EPERM;- return rose_rt_ioctl(cmd, argp);-- case SIOCRSGCAUSE: {- struct rose_cause_struct rose_cause;- rose_cause.cause = rose->cause;- rose_cause.diagnostic = rose->diagnostic;- return copy_to_user(argp, &rose_cause, sizeof(struct rose_cause_struct)) ? -EFAULT : 0;- }-- case SIOCRSSCAUSE: {- struct rose_cause_struct rose_cause;- if (copy_from_user(&rose_cause, argp, sizeof(struct rose_cause_struct)))- return -EFAULT;- rose->cause = rose_cause.cause;- rose->diagnostic = rose_cause.diagnostic;- return 0;- }-- case SIOCRSSL2CALL:- if (!capable(CAP_NET_ADMIN)) return -EPERM;- if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)- ax25_listen_release(&rose_callsign, NULL);- if (copy_from_user(&rose_callsign, argp, sizeof(ax25_address)))- return -EFAULT;- if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)- return ax25_listen_register(&rose_callsign, NULL);-- return 0;-- case SIOCRSGL2CALL:- return copy_to_user(argp, &rose_callsign, sizeof(ax25_address)) ? -EFAULT : 0;-- case SIOCRSACCEPT:- if (rose->state == ROSE_STATE_5) {- rose_write_internal(sk, ROSE_CALL_ACCEPTED);- rose_start_idletimer(sk);- rose->condition = 0x00;- rose->vs = 0;- rose->va = 0;- rose->vr = 0;- rose->vl = 0;- rose->state = ROSE_STATE_3;- }- return 0;-- default:- return -ENOIOCTLCMD;- }-- return 0;-}--#ifdef CONFIG_PROC_FS-static void *rose_info_start(struct seq_file *seq, loff_t *pos)- __acquires(rose_list_lock)-{- spin_lock_bh(&rose_list_lock);- return seq_hlist_start_head(&rose_list, *pos);-}--static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos)-{- return seq_hlist_next(v, &rose_list, pos);-}--static void rose_info_stop(struct seq_file *seq, void *v)- __releases(rose_list_lock)-{- spin_unlock_bh(&rose_list_lock);-}--static int rose_info_show(struct seq_file *seq, void *v)-{- char buf[11], rsbuf[11];-- if (v == SEQ_START_TOKEN)- seq_puts(seq,- "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n");-- else {- struct sock *s = sk_entry(v);- struct rose_sock *rose = rose_sk(s);- const char *devname, *callsign;- const struct net_device *dev = rose->device;-- if (!dev)- devname = "???";- else- devname = dev->name;-- seq_printf(seq, "%-10s %-9s ",- rose2asc(rsbuf, &rose->dest_addr),- ax2asc(buf, &rose->dest_call));-- if (ax25cmp(&rose->source_call, &null_ax25_address) == 0)- callsign = "??????-?";- else- callsign = ax2asc(buf, &rose->source_call);-- seq_printf(seq,- "%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %llu\n",- rose2asc(rsbuf, &rose->source_addr),- callsign,- devname,- rose->lci & 0x0FFF,- (rose->neighbour) ? rose->neighbour->number : 0,- rose->state,- rose->vs,- rose->vr,- rose->va,- ax25_display_timer(&rose->timer) / HZ,- rose->t1 / HZ,- rose->t2 / HZ,- rose->t3 / HZ,- rose->hb / HZ,- ax25_display_timer(&rose->idletimer) / (60 * HZ),- rose->idle / (60 * HZ),- sk_wmem_alloc_get(s),- sk_rmem_alloc_get(s),- s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : (u64)0);- }-- return 0;-}--static const struct seq_operations rose_info_seqops = {- .start = rose_info_start,- .next = rose_info_next,- .stop = rose_info_stop,- .show = rose_info_show,-};-#endif /* CONFIG_PROC_FS */--static const struct net_proto_family rose_family_ops = {- .family = PF_ROSE,- .create = rose_create,- .owner = THIS_MODULE,-};--static const struct proto_ops rose_proto_ops = {- .family = PF_ROSE,- .owner = THIS_MODULE,- .release = rose_release,- .bind = rose_bind,- .connect = rose_connect,- .socketpair = sock_no_socketpair,- .accept = rose_accept,- .getname = rose_getname,- .poll = datagram_poll,- .ioctl = rose_ioctl,- .gettstamp = sock_gettstamp,- .listen = rose_listen,- .shutdown = sock_no_shutdown,- .setsockopt = rose_setsockopt,- .getsockopt = rose_getsockopt,- .sendmsg = rose_sendmsg,- .recvmsg = rose_recvmsg,- .mmap = sock_no_mmap,-};--static struct notifier_block rose_dev_notifier = {- .notifier_call = rose_device_event,-};--static struct net_device **dev_rose;--static struct ax25_protocol rose_pid = {- .pid = AX25_P_ROSE,- .func = rose_route_frame-};--static struct ax25_linkfail rose_linkfail_notifier = {- .func = rose_link_failed-};--static int __init rose_proto_init(void)-{- int i;- int rc;-- if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) {- printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter too large\n");- rc = -EINVAL;- goto out;- }-- rc = proto_register(&rose_proto, 0);- if (rc != 0)- goto out;-- rose_callsign = null_ax25_address;-- dev_rose = kzalloc_objs(struct net_device *, rose_ndevs);- if (dev_rose == NULL) {- printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");- rc = -ENOMEM;- goto out_proto_unregister;- }-- for (i = 0; i < rose_ndevs; i++) {- struct net_device *dev;- char name[IFNAMSIZ];-- sprintf(name, "rose%d", i);- dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, rose_setup);- if (!dev) {- printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");- rc = -ENOMEM;- goto fail;- }- rc = register_netdev(dev);- if (rc) {- printk(KERN_ERR "ROSE: netdevice registration failed\n");- free_netdev(dev);- goto fail;- }- rose_set_lockdep_key(dev);- dev_rose[i] = dev;- }-- sock_register(&rose_family_ops);- register_netdevice_notifier(&rose_dev_notifier);-- ax25_register_pid(&rose_pid);- ax25_linkfail_register(&rose_linkfail_notifier);--#ifdef CONFIG_SYSCTL- rose_register_sysctl();-#endif- rose_loopback_init();-- rose_add_loopback_neigh();-- proc_create_seq("rose", 0444, init_net.proc_net, &rose_info_seqops);- proc_create_seq("rose_neigh", 0444, init_net.proc_net,- &rose_neigh_seqops);- proc_create_seq("rose_nodes", 0444, init_net.proc_net,- &rose_node_seqops);- proc_create_seq("rose_routes", 0444, init_net.proc_net,- &rose_route_seqops);-out:- return rc;-fail:- while (--i >= 0) {- unregister_netdev(dev_rose[i]);- free_netdev(dev_rose[i]);- }- kfree(dev_rose);-out_proto_unregister:- proto_unregister(&rose_proto);- goto out;-}-module_init(rose_proto_init);--module_param(rose_ndevs, int, 0);-MODULE_PARM_DESC(rose_ndevs, "number of ROSE devices");--MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");-MODULE_DESCRIPTION("The amateur radio ROSE network layer protocol");-MODULE_LICENSE("GPL");-MODULE_ALIAS_NETPROTO(PF_ROSE);--static void __exit rose_exit(void)-{- int i;-- remove_proc_entry("rose", init_net.proc_net);- remove_proc_entry("rose_neigh", init_net.proc_net);- remove_proc_entry("rose_nodes", init_net.proc_net);- remove_proc_entry("rose_routes", init_net.proc_net);- rose_loopback_clear();-- rose_rt_free();-- ax25_protocol_release(AX25_P_ROSE);- ax25_linkfail_release(&rose_linkfail_notifier);-- if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)- ax25_listen_release(&rose_callsign, NULL);--#ifdef CONFIG_SYSCTL- rose_unregister_sysctl();-#endif- unregister_netdevice_notifier(&rose_dev_notifier);-- sock_unregister(PF_ROSE);-- for (i = 0; i < rose_ndevs; i++) {- struct net_device *dev = dev_rose[i];-- if (dev) {- unregister_netdev(dev);- free_netdev(dev);- }- }-- kfree(dev_rose);- proto_unregister(&rose_proto);-}--module_exit(rose_exit);diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.cdeleted file mode 100644index f1a76a5820f1..000000000000--- a/net/rose/rose_dev.c+++ /dev/null@@ -1,141 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/module.h>-#include <linux/proc_fs.h>-#include <linux/kernel.h>-#include <linux/interrupt.h>-#include <linux/fs.h>-#include <linux/types.h>-#include <linux/sysctl.h>-#include <linux/string.h>-#include <linux/socket.h>-#include <linux/errno.h>-#include <linux/fcntl.h>-#include <linux/in.h>-#include <linux/if_ether.h>-#include <linux/slab.h>--#include <asm/io.h>--#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/etherdevice.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>--#include <net/ip.h>-#include <net/arp.h>--#include <net/ax25.h>-#include <net/rose.h>--static int rose_header(struct sk_buff *skb, struct net_device *dev,- unsigned short type,- const void *daddr, const void *saddr, unsigned int len)-{- unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2);-- if (daddr)- memcpy(buff + 7, daddr, dev->addr_len);-- *buff++ = ROSE_GFI | ROSE_Q_BIT;- *buff++ = 0x00;- *buff++ = ROSE_DATA;- *buff++ = 0x7F;- *buff++ = AX25_P_IP;-- if (daddr != NULL)- return 37;-- return -37;-}--static int rose_set_mac_address(struct net_device *dev, void *addr)-{- struct sockaddr *sa = addr;- int err;-- if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))- return 0;-- if (dev->flags & IFF_UP) {- err = rose_add_loopback_node((rose_address *)sa->sa_data);- if (err)- return err;-- rose_del_loopback_node((const rose_address *)dev->dev_addr);- }-- dev_addr_set(dev, sa->sa_data);-- return 0;-}--static int rose_open(struct net_device *dev)-{- int err;-- err = rose_add_loopback_node((const rose_address *)dev->dev_addr);- if (err)- return err;-- netif_start_queue(dev);-- return 0;-}--static int rose_close(struct net_device *dev)-{- netif_stop_queue(dev);- rose_del_loopback_node((const rose_address *)dev->dev_addr);- return 0;-}--static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev)-{- struct net_device_stats *stats = &dev->stats;- unsigned int len = skb->len;-- if (!netif_running(dev)) {- printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");- return NETDEV_TX_BUSY;- }-- if (!rose_route_frame(skb, NULL)) {- dev_kfree_skb(skb);- stats->tx_errors++;- return NETDEV_TX_OK;- }-- stats->tx_packets++;- stats->tx_bytes += len;- return NETDEV_TX_OK;-}--static const struct header_ops rose_header_ops = {- .create = rose_header,-};--static const struct net_device_ops rose_netdev_ops = {- .ndo_open = rose_open,- .ndo_stop = rose_close,- .ndo_start_xmit = rose_xmit,- .ndo_set_mac_address = rose_set_mac_address,-};--void rose_setup(struct net_device *dev)-{- dev->mtu = ROSE_MAX_PACKET_SIZE - 2;- dev->netdev_ops = &rose_netdev_ops;-- dev->header_ops = &rose_header_ops;- dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;- dev->addr_len = ROSE_ADDR_LEN;- dev->type = ARPHRD_ROSE;-- /* New-style flags. */- dev->flags = IFF_NOARP;-}diff --git a/net/rose/rose_in.c b/net/rose/rose_in.cdeleted file mode 100644index ca4f217ef3d3..000000000000--- a/net/rose/rose_in.c+++ /dev/null@@ -1,301 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- *- * Most of this code is based on the SDL diagrams published in the 7th ARRL- * Computer Networking Conference papers. The diagrams have mistakes in them,- * but are mostly correct. Before you modify the code could you read the SDL- * diagrams as the code is not obvious and probably very easy to break.- */-#include <linux/errno.h>-#include <linux/filter.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/rose.h>--/*- * State machine for state 1, Awaiting Call Accepted State.- * The handling of the timer(s) is in file rose_timer.c.- * Handling of state 0 and connection release is in af_rose.c.- */-static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)-{- struct rose_sock *rose = rose_sk(sk);-- switch (frametype) {- case ROSE_CALL_ACCEPTED:- rose_stop_timer(sk);- rose_start_idletimer(sk);- rose->condition = 0x00;- rose->vs = 0;- rose->va = 0;- rose->vr = 0;- rose->vl = 0;- rose->state = ROSE_STATE_3;- sk->sk_state = TCP_ESTABLISHED;- if (!sock_flag(sk, SOCK_DEAD))- sk->sk_state_change(sk);- break;-- case ROSE_CLEAR_REQUEST:- rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);- rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);- rose_neigh_put(rose->neighbour);- break;-- default:- break;- }-- return 0;-}--/*- * State machine for state 2, Awaiting Clear Confirmation State.- * The handling of the timer(s) is in file rose_timer.c- * Handling of state 0 and connection release is in af_rose.c.- */-static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)-{- struct rose_sock *rose = rose_sk(sk);-- switch (frametype) {- case ROSE_CLEAR_REQUEST:- rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);- rose_disconnect(sk, 0, skb->data[3], skb->data[4]);- rose_neigh_put(rose->neighbour);- break;-- case ROSE_CLEAR_CONFIRMATION:- rose_disconnect(sk, 0, -1, -1);- rose_neigh_put(rose->neighbour);- break;-- default:- break;- }-- return 0;-}--/*- * State machine for state 3, Connected State.- * The handling of the timer(s) is in file rose_timer.c- * Handling of state 0 and connection release is in af_rose.c.- */-static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)-{- struct rose_sock *rose = rose_sk(sk);- int queued = 0;-- switch (frametype) {- case ROSE_RESET_REQUEST:- rose_stop_timer(sk);- rose_start_idletimer(sk);- rose_write_internal(sk, ROSE_RESET_CONFIRMATION);- rose->condition = 0x00;- rose->vs = 0;- rose->vr = 0;- rose->va = 0;- rose->vl = 0;- rose_requeue_frames(sk);- break;-- case ROSE_CLEAR_REQUEST:- rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);- rose_disconnect(sk, 0, skb->data[3], skb->data[4]);- rose_neigh_put(rose->neighbour);- break;-- case ROSE_RR:- case ROSE_RNR:- if (!rose_validate_nr(sk, nr)) {- rose_write_internal(sk, ROSE_RESET_REQUEST);- rose->condition = 0x00;- rose->vs = 0;- rose->vr = 0;- rose->va = 0;- rose->vl = 0;- rose->state = ROSE_STATE_4;- rose_start_t2timer(sk);- rose_stop_idletimer(sk);- } else {- rose_frames_acked(sk, nr);- if (frametype == ROSE_RNR) {- rose->condition |= ROSE_COND_PEER_RX_BUSY;- } else {- rose->condition &= ~ROSE_COND_PEER_RX_BUSY;- }- }- break;-- case ROSE_DATA: /* XXX */- rose->condition &= ~ROSE_COND_PEER_RX_BUSY;- if (!rose_validate_nr(sk, nr)) {- rose_write_internal(sk, ROSE_RESET_REQUEST);- rose->condition = 0x00;- rose->vs = 0;- rose->vr = 0;- rose->va = 0;- rose->vl = 0;- rose->state = ROSE_STATE_4;- rose_start_t2timer(sk);- rose_stop_idletimer(sk);- break;- }- rose_frames_acked(sk, nr);- if (ns == rose->vr) {- rose_start_idletimer(sk);- if (!sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN) &&- __sock_queue_rcv_skb(sk, skb) == 0) {- rose->vr = (rose->vr + 1) % ROSE_MODULUS;- queued = 1;- } else {- /* Should never happen ! */- rose_write_internal(sk, ROSE_RESET_REQUEST);- rose->condition = 0x00;- rose->vs = 0;- rose->vr = 0;- rose->va = 0;- rose->vl = 0;- rose->state = ROSE_STATE_4;- rose_start_t2timer(sk);- rose_stop_idletimer(sk);- break;- }- if (atomic_read(&sk->sk_rmem_alloc) >- (sk->sk_rcvbuf >> 1))- rose->condition |= ROSE_COND_OWN_RX_BUSY;- }- /*- * If the window is full, ack the frame, else start the- * acknowledge hold back timer.- */- if (((rose->vl + sysctl_rose_window_size) % ROSE_MODULUS) == rose->vr) {- rose->condition &= ~ROSE_COND_ACK_PENDING;- rose_stop_timer(sk);- rose_enquiry_response(sk);- } else {- rose->condition |= ROSE_COND_ACK_PENDING;- rose_start_hbtimer(sk);- }- break;-- default:- printk(KERN_WARNING "ROSE: unknown %02X in state 3\n", frametype);- break;- }-- return queued;-}--/*- * State machine for state 4, Awaiting Reset Confirmation State.- * The handling of the timer(s) is in file rose_timer.c- * Handling of state 0 and connection release is in af_rose.c.- */-static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype)-{- struct rose_sock *rose = rose_sk(sk);-- switch (frametype) {- case ROSE_RESET_REQUEST:- rose_write_internal(sk, ROSE_RESET_CONFIRMATION);- fallthrough;- case ROSE_RESET_CONFIRMATION:- rose_stop_timer(sk);- rose_start_idletimer(sk);- rose->condition = 0x00;- rose->va = 0;- rose->vr = 0;- rose->vs = 0;- rose->vl = 0;- rose->state = ROSE_STATE_3;- rose_requeue_frames(sk);- break;-- case ROSE_CLEAR_REQUEST:- rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);- rose_disconnect(sk, 0, skb->data[3], skb->data[4]);- rose_neigh_put(rose->neighbour);- break;-- default:- break;- }-- return 0;-}--/*- * State machine for state 5, Awaiting Call Acceptance State.- * The handling of the timer(s) is in file rose_timer.c- * Handling of state 0 and connection release is in af_rose.c.- */-static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int frametype)-{- if (frametype == ROSE_CLEAR_REQUEST) {- rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);- rose_disconnect(sk, 0, skb->data[3], skb->data[4]);- rose_neigh_put(rose_sk(sk)->neighbour);- }-- return 0;-}--/* Higher level upcall for a LAPB frame */-int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb)-{- struct rose_sock *rose = rose_sk(sk);- int queued = 0, frametype, ns, nr, q, d, m;-- if (rose->state == ROSE_STATE_0)- return 0;-- frametype = rose_decode(skb, &ns, &nr, &q, &d, &m);-- /*- * ROSE_CLEAR_REQUEST carries cause and diagnostic in bytes 3..4.- * Reject a malformed frame that is too short to contain them.- */- if (frametype == ROSE_CLEAR_REQUEST && skb->len < 5)- return 0;-- switch (rose->state) {- case ROSE_STATE_1:- queued = rose_state1_machine(sk, skb, frametype);- break;- case ROSE_STATE_2:- queued = rose_state2_machine(sk, skb, frametype);- break;- case ROSE_STATE_3:- queued = rose_state3_machine(sk, skb, frametype, ns, nr, q, d, m);- break;- case ROSE_STATE_4:- queued = rose_state4_machine(sk, skb, frametype);- break;- case ROSE_STATE_5:- queued = rose_state5_machine(sk, skb, frametype);- break;- }-- rose_kick(sk);-- return queued;-}diff --git a/net/rose/rose_link.c b/net/rose/rose_link.cdeleted file mode 100644index 7746229fdc8c..000000000000--- a/net/rose/rose_link.c+++ /dev/null@@ -1,289 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/jiffies.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/rose.h>--static void rose_ftimer_expiry(struct timer_list *);-static void rose_t0timer_expiry(struct timer_list *);--static void rose_transmit_restart_confirmation(struct rose_neigh *neigh);-static void rose_transmit_restart_request(struct rose_neigh *neigh);--void rose_start_ftimer(struct rose_neigh *neigh)-{- timer_delete(&neigh->ftimer);-- neigh->ftimer.function = rose_ftimer_expiry;- neigh->ftimer.expires =- jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout);-- add_timer(&neigh->ftimer);-}--static void rose_start_t0timer(struct rose_neigh *neigh)-{- timer_delete(&neigh->t0timer);-- neigh->t0timer.function = rose_t0timer_expiry;- neigh->t0timer.expires =- jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout);-- add_timer(&neigh->t0timer);-}--void rose_stop_ftimer(struct rose_neigh *neigh)-{- timer_delete(&neigh->ftimer);-}--void rose_stop_t0timer(struct rose_neigh *neigh)-{- timer_delete(&neigh->t0timer);-}--int rose_ftimer_running(struct rose_neigh *neigh)-{- return timer_pending(&neigh->ftimer);-}--static int rose_t0timer_running(struct rose_neigh *neigh)-{- return timer_pending(&neigh->t0timer);-}--static void rose_ftimer_expiry(struct timer_list *t)-{-}--static void rose_t0timer_expiry(struct timer_list *t)-{- struct rose_neigh *neigh = timer_container_of(neigh, t, t0timer);-- rose_transmit_restart_request(neigh);-- neigh->dce_mode = 0;-- rose_start_t0timer(neigh);-}--/*- * Interface to ax25_send_frame. Changes my level 2 callsign depending- * on whether we have a global ROSE callsign or use the default port- * callsign.- */-static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh)-{- const ax25_address *rose_call;- ax25_cb *ax25s;-- if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)- rose_call = (const ax25_address *)neigh->dev->dev_addr;- else- rose_call = &rose_callsign;-- ax25s = neigh->ax25;- neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);- if (ax25s)- ax25_cb_put(ax25s);-- return neigh->ax25 != NULL;-}--/*- * Interface to ax25_link_up. Changes my level 2 callsign depending- * on whether we have a global ROSE callsign or use the default port- * callsign.- */-static int rose_link_up(struct rose_neigh *neigh)-{- const ax25_address *rose_call;- ax25_cb *ax25s;-- if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)- rose_call = (const ax25_address *)neigh->dev->dev_addr;- else- rose_call = &rose_callsign;-- ax25s = neigh->ax25;- neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);- if (ax25s)- ax25_cb_put(ax25s);-- return neigh->ax25 != NULL;-}--/*- * This handles all restart and diagnostic frames.- */-void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigned short frametype)-{- struct sk_buff *skbn;-- switch (frametype) {- case ROSE_RESTART_REQUEST:- rose_stop_t0timer(neigh);- neigh->restarted = 1;- neigh->dce_mode = (skb->data[3] == ROSE_DTE_ORIGINATED);- rose_transmit_restart_confirmation(neigh);- break;-- case ROSE_RESTART_CONFIRMATION:- rose_stop_t0timer(neigh);- neigh->restarted = 1;- break;-- case ROSE_DIAGNOSTIC:- pr_warn("ROSE: received diagnostic #%d - %3ph\n", skb->data[3],- skb->data + 4);- break;-- default:- printk(KERN_WARNING "ROSE: received unknown %02X with LCI 000\n", frametype);- break;- }-- if (neigh->restarted) {- while ((skbn = skb_dequeue(&neigh->queue)) != NULL)- if (!rose_send_frame(skbn, neigh))- kfree_skb(skbn);- }-}--/*- * This routine is called when a Restart Request is needed- */-static void rose_transmit_restart_request(struct rose_neigh *neigh)-{- struct sk_buff *skb;- unsigned char *dptr;- int len;-- len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;-- if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)- return;-- skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);-- dptr = skb_put(skb, ROSE_MIN_LEN + 3);-- *dptr++ = AX25_P_ROSE;- *dptr++ = ROSE_GFI;- *dptr++ = 0x00;- *dptr++ = ROSE_RESTART_REQUEST;- *dptr++ = ROSE_DTE_ORIGINATED;- *dptr++ = 0;-- if (!rose_send_frame(skb, neigh))- kfree_skb(skb);-}--/*- * This routine is called when a Restart Confirmation is needed- */-static void rose_transmit_restart_confirmation(struct rose_neigh *neigh)-{- struct sk_buff *skb;- unsigned char *dptr;- int len;-- len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 1;-- if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)- return;-- skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);-- dptr = skb_put(skb, ROSE_MIN_LEN + 1);-- *dptr++ = AX25_P_ROSE;- *dptr++ = ROSE_GFI;- *dptr++ = 0x00;- *dptr++ = ROSE_RESTART_CONFIRMATION;-- if (!rose_send_frame(skb, neigh))- kfree_skb(skb);-}--/*- * This routine is called when a Clear Request is needed outside of the context- * of a connected socket.- */-void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, unsigned char cause, unsigned char diagnostic)-{- struct sk_buff *skb;- unsigned char *dptr;- int len;-- if (!neigh->dev)- return;-- len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;-- if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)- return;-- skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);-- dptr = skb_put(skb, ROSE_MIN_LEN + 3);-- *dptr++ = AX25_P_ROSE;- *dptr++ = ((lci >> 8) & 0x0F) | ROSE_GFI;- *dptr++ = ((lci >> 0) & 0xFF);- *dptr++ = ROSE_CLEAR_REQUEST;- *dptr++ = cause;- *dptr++ = diagnostic;-- if (!rose_send_frame(skb, neigh))- kfree_skb(skb);-}--void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)-{- unsigned char *dptr;-- if (neigh->loopback) {- rose_loopback_queue(skb, neigh);- return;- }-- if (!rose_link_up(neigh))- neigh->restarted = 0;-- dptr = skb_push(skb, 1);- *dptr++ = AX25_P_ROSE;-- if (neigh->restarted) {- if (!rose_send_frame(skb, neigh))- kfree_skb(skb);- } else {- skb_queue_tail(&neigh->queue, skb);-- if (!rose_t0timer_running(neigh)) {- rose_transmit_restart_request(neigh);- neigh->dce_mode = 0;- rose_start_t0timer(neigh);- }- }-}diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.cdeleted file mode 100644index b538e39b3df5..000000000000--- a/net/rose/rose_loopback.c+++ /dev/null@@ -1,133 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/types.h>-#include <linux/slab.h>-#include <linux/socket.h>-#include <linux/timer.h>-#include <net/ax25.h>-#include <linux/skbuff.h>-#include <net/rose.h>-#include <linux/init.h>--static struct sk_buff_head loopback_queue;-#define ROSE_LOOPBACK_LIMIT 1000-static struct timer_list loopback_timer;--static void rose_set_loopback_timer(void);-static void rose_loopback_timer(struct timer_list *unused);--void rose_loopback_init(void)-{- skb_queue_head_init(&loopback_queue);-- timer_setup(&loopback_timer, rose_loopback_timer, 0);-}--static int rose_loopback_running(void)-{- return timer_pending(&loopback_timer);-}--int rose_loopback_queue(struct sk_buff *skb, struct rose_neigh *neigh)-{- struct sk_buff *skbn = NULL;-- if (skb_queue_len(&loopback_queue) < ROSE_LOOPBACK_LIMIT)- skbn = skb_clone(skb, GFP_ATOMIC);-- if (skbn) {- consume_skb(skb);- skb_queue_tail(&loopback_queue, skbn);-- if (!rose_loopback_running())- rose_set_loopback_timer();- } else {- kfree_skb(skb);- }-- return 1;-}--static void rose_set_loopback_timer(void)-{- mod_timer(&loopback_timer, jiffies + 10);-}--static void rose_loopback_timer(struct timer_list *unused)-{- struct sk_buff *skb;- struct net_device *dev;- rose_address *dest;- struct sock *sk;- unsigned short frametype;- unsigned int lci_i, lci_o;- int count;-- for (count = 0; count < ROSE_LOOPBACK_LIMIT; count++) {- skb = skb_dequeue(&loopback_queue);- if (!skb)- return;- if (skb->len < ROSE_MIN_LEN) {- kfree_skb(skb);- continue;- }- lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);- frametype = skb->data[2];- if (frametype == ROSE_CALL_REQUEST &&- (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF ||- skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] !=- ROSE_CALL_REQ_ADDR_LEN_VAL)) {- kfree_skb(skb);- continue;- }- dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF);- lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i;-- skb_reset_transport_header(skb);-- sk = rose_find_socket(lci_o, rose_loopback_neigh);- if (sk) {- if (rose_process_rx_frame(sk, skb) == 0)- kfree_skb(skb);- continue;- }-- if (frametype == ROSE_CALL_REQUEST) {- if (!rose_loopback_neigh->dev &&- !rose_loopback_neigh->loopback) {- kfree_skb(skb);- continue;- }-- dev = rose_dev_get(dest);- if (!dev) {- kfree_skb(skb);- continue;- }-- if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) {- dev_put(dev);- kfree_skb(skb);- }- } else {- kfree_skb(skb);- }- }- if (!skb_queue_empty(&loopback_queue))- mod_timer(&loopback_timer, jiffies + 1);-}--void __exit rose_loopback_clear(void)-{- struct sk_buff *skb;-- timer_delete(&loopback_timer);-- while ((skb = skb_dequeue(&loopback_queue)) != NULL) {- skb->sk = NULL;- kfree_skb(skb);- }-}diff --git a/net/rose/rose_out.c b/net/rose/rose_out.cdeleted file mode 100644index 9050e33c9604..000000000000--- a/net/rose/rose_out.c+++ /dev/null@@ -1,122 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/gfp.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/rose.h>--/*- * This procedure is passed a buffer descriptor for an iframe. It builds- * the rest of the control part of the frame and then writes it out.- */-static void rose_send_iframe(struct sock *sk, struct sk_buff *skb)-{- struct rose_sock *rose = rose_sk(sk);-- if (skb == NULL)- return;-- skb->data[2] |= (rose->vr << 5) & 0xE0;- skb->data[2] |= (rose->vs << 1) & 0x0E;-- rose_start_idletimer(sk);-- rose_transmit_link(skb, rose->neighbour);-}--void rose_kick(struct sock *sk)-{- struct rose_sock *rose = rose_sk(sk);- struct sk_buff *skb, *skbn;- unsigned short start, end;-- if (rose->state != ROSE_STATE_3)- return;-- if (rose->condition & ROSE_COND_PEER_RX_BUSY)- return;-- if (!skb_peek(&sk->sk_write_queue))- return;-- start = (skb_peek(&rose->ack_queue) == NULL) ? rose->va : rose->vs;- end = (rose->va + sysctl_rose_window_size) % ROSE_MODULUS;-- if (start == end)- return;-- rose->vs = start;-- /*- * Transmit data until either we're out of data to send or- * the window is full.- */-- skb = skb_dequeue(&sk->sk_write_queue);-- do {- if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {- skb_queue_head(&sk->sk_write_queue, skb);- break;- }-- skb_set_owner_w(skbn, sk);-- /*- * Transmit the frame copy.- */- rose_send_iframe(sk, skbn);-- rose->vs = (rose->vs + 1) % ROSE_MODULUS;-- /*- * Requeue the original data frame.- */- skb_queue_tail(&rose->ack_queue, skb);-- } while (rose->vs != end &&- (skb = skb_dequeue(&sk->sk_write_queue)) != NULL);-- rose->vl = rose->vr;- rose->condition &= ~ROSE_COND_ACK_PENDING;-- rose_stop_timer(sk);-}--/*- * The following routines are taken from page 170 of the 7th ARRL Computer- * Networking Conference paper, as is the whole state machine.- */--void rose_enquiry_response(struct sock *sk)-{- struct rose_sock *rose = rose_sk(sk);-- if (rose->condition & ROSE_COND_OWN_RX_BUSY)- rose_write_internal(sk, ROSE_RNR);- else- rose_write_internal(sk, ROSE_RR);-- rose->vl = rose->vr;- rose->condition &= ~ROSE_COND_ACK_PENDING;-- rose_stop_timer(sk);-}diff --git a/net/rose/rose_route.c b/net/rose/rose_route.cdeleted file mode 100644index e31842e6b3c8..000000000000--- a/net/rose/rose_route.c+++ /dev/null@@ -1,1333 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) Terry Dawson VK2KTJ (terry@animats.net)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <net/arp.h>-#include <linux/if_arp.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/uaccess.h>-#include <linux/fcntl.h>-#include <linux/termios.h> /* For TIOCINQ/OUTQ */-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <linux/notifier.h>-#include <linux/init.h>-#include <net/rose.h>-#include <linux/seq_file.h>-#include <linux/export.h>--static unsigned int rose_neigh_no = 1;--static struct rose_node *rose_node_list;-static DEFINE_SPINLOCK(rose_node_list_lock);-static struct rose_neigh *rose_neigh_list;-static DEFINE_SPINLOCK(rose_neigh_list_lock);-static struct rose_route *rose_route_list;-static DEFINE_SPINLOCK(rose_route_list_lock);--struct rose_neigh *rose_loopback_neigh;--/*- * Add a new route to a node, and in the process add the node and the- * neighbour if it is new.- */-static int __must_check rose_add_node(struct rose_route_struct *rose_route,- struct net_device *dev)-{- struct rose_node *rose_node, *rose_tmpn, *rose_tmpp;- struct rose_neigh *rose_neigh;- int i, res = 0;-- spin_lock_bh(&rose_node_list_lock);- spin_lock_bh(&rose_neigh_list_lock);-- rose_node = rose_node_list;- while (rose_node != NULL) {- if ((rose_node->mask == rose_route->mask) &&- (rosecmpm(&rose_route->address, &rose_node->address,- rose_route->mask) == 0))- break;- rose_node = rose_node->next;- }-- if (rose_node != NULL && rose_node->loopback) {- res = -EINVAL;- goto out;- }-- rose_neigh = rose_neigh_list;- while (rose_neigh != NULL) {- if (ax25cmp(&rose_route->neighbour,- &rose_neigh->callsign) == 0 &&- rose_neigh->dev == dev)- break;- rose_neigh = rose_neigh->next;- }-- if (rose_neigh == NULL) {- rose_neigh = kmalloc_obj(*rose_neigh, GFP_ATOMIC);- if (rose_neigh == NULL) {- res = -ENOMEM;- goto out;- }-- rose_neigh->callsign = rose_route->neighbour;- rose_neigh->digipeat = NULL;- rose_neigh->ax25 = NULL;- rose_neigh->dev = dev;- rose_neigh->count = 0;- rose_neigh->dce_mode = 0;- rose_neigh->loopback = 0;- rose_neigh->number = rose_neigh_no++;- rose_neigh->restarted = 0;- refcount_set(&rose_neigh->use, 1);-- skb_queue_head_init(&rose_neigh->queue);-- timer_setup(&rose_neigh->ftimer, NULL, 0);- timer_setup(&rose_neigh->t0timer, NULL, 0);-- if (rose_route->ndigis != 0) {- rose_neigh->digipeat =- kmalloc_obj(ax25_digi, GFP_ATOMIC);- if (rose_neigh->digipeat == NULL) {- kfree(rose_neigh);- res = -ENOMEM;- goto out;- }-- rose_neigh->digipeat->ndigi = rose_route->ndigis;- rose_neigh->digipeat->lastrepeat = -1;-- for (i = 0; i < rose_route->ndigis; i++) {- rose_neigh->digipeat->calls[i] =- rose_route->digipeaters[i];- rose_neigh->digipeat->repeated[i] = 0;- }- }-- rose_neigh->next = rose_neigh_list;- rose_neigh_list = rose_neigh;- }-- /*- * This is a new node to be inserted into the list. Find where it needs- * to be inserted into the list, and insert it. We want to be sure- * to order the list in descending order of mask size to ensure that- * later when we are searching this list the first match will be the- * best match.- */- if (rose_node == NULL) {- rose_tmpn = rose_node_list;- rose_tmpp = NULL;-- while (rose_tmpn != NULL) {- if (rose_tmpn->mask > rose_route->mask) {- rose_tmpp = rose_tmpn;- rose_tmpn = rose_tmpn->next;- } else {- break;- }- }-- /* create new node */- rose_node = kmalloc_obj(*rose_node, GFP_ATOMIC);- if (rose_node == NULL) {- res = -ENOMEM;- goto out;- }-- rose_node->address = rose_route->address;- rose_node->mask = rose_route->mask;- rose_node->count = 1;- rose_node->loopback = 0;- rose_node->neighbour[0] = rose_neigh;-- if (rose_tmpn == NULL) {- if (rose_tmpp == NULL) { /* Empty list */- rose_node_list = rose_node;- rose_node->next = NULL;- } else {- rose_tmpp->next = rose_node;- rose_node->next = NULL;- }- } else {- if (rose_tmpp == NULL) { /* 1st node */- rose_node->next = rose_node_list;- rose_node_list = rose_node;- } else {- rose_tmpp->next = rose_node;- rose_node->next = rose_tmpn;- }- }- rose_neigh->count++;- rose_neigh_hold(rose_neigh);-- goto out;- }-- /* We have space, slot it in */- if (rose_node->count < 3) {- rose_node->neighbour[rose_node->count] = rose_neigh;- rose_node->count++;- rose_neigh->count++;- rose_neigh_hold(rose_neigh);- }--out:- spin_unlock_bh(&rose_neigh_list_lock);- spin_unlock_bh(&rose_node_list_lock);-- return res;-}--/*- * Caller is holding rose_node_list_lock.- */-static void rose_remove_node(struct rose_node *rose_node)-{- struct rose_node *s;-- if ((s = rose_node_list) == rose_node) {- rose_node_list = rose_node->next;- kfree(rose_node);- return;- }-- while (s != NULL && s->next != NULL) {- if (s->next == rose_node) {- s->next = rose_node->next;- kfree(rose_node);- return;- }-- s = s->next;- }-}--/*- * Caller is holding rose_neigh_list_lock.- */-static void rose_remove_neigh(struct rose_neigh *rose_neigh)-{- struct rose_neigh *s;-- timer_delete_sync(&rose_neigh->ftimer);- timer_delete_sync(&rose_neigh->t0timer);-- skb_queue_purge(&rose_neigh->queue);-- if ((s = rose_neigh_list) == rose_neigh) {- rose_neigh_list = rose_neigh->next;- return;- }-- while (s != NULL && s->next != NULL) {- if (s->next == rose_neigh) {- s->next = rose_neigh->next;- return;- }-- s = s->next;- }-}--/*- * Caller is holding rose_route_list_lock.- */-static void rose_remove_route(struct rose_route *rose_route)-{- struct rose_route *s;-- if (rose_route->neigh1 != NULL)- rose_neigh_put(rose_route->neigh1);-- if (rose_route->neigh2 != NULL)- rose_neigh_put(rose_route->neigh2);-- if ((s = rose_route_list) == rose_route) {- rose_route_list = rose_route->next;- kfree(rose_route);- return;- }-- while (s != NULL && s->next != NULL) {- if (s->next == rose_route) {- s->next = rose_route->next;- kfree(rose_route);- return;- }-- s = s->next;- }-}--/*- * "Delete" a node. Strictly speaking remove a route to a node. The node- * is only deleted if no routes are left to it.- */-static int rose_del_node(struct rose_route_struct *rose_route,- struct net_device *dev)-{- struct rose_node *rose_node;- struct rose_neigh *rose_neigh;- int i, err = 0;-- spin_lock_bh(&rose_node_list_lock);- spin_lock_bh(&rose_neigh_list_lock);-- rose_node = rose_node_list;- while (rose_node != NULL) {- if ((rose_node->mask == rose_route->mask) &&- (rosecmpm(&rose_route->address, &rose_node->address,- rose_route->mask) == 0))- break;- rose_node = rose_node->next;- }-- if (rose_node == NULL || rose_node->loopback) {- err = -EINVAL;- goto out;- }-- rose_neigh = rose_neigh_list;- while (rose_neigh != NULL) {- if (ax25cmp(&rose_route->neighbour,- &rose_neigh->callsign) == 0 &&- rose_neigh->dev == dev)- break;- rose_neigh = rose_neigh->next;- }-- if (rose_neigh == NULL) {- err = -EINVAL;- goto out;- }-- for (i = 0; i < rose_node->count; i++) {- if (rose_node->neighbour[i] == rose_neigh) {- rose_neigh->count--;- rose_neigh_put(rose_neigh);-- if (rose_neigh->count == 0) {- rose_remove_neigh(rose_neigh);- rose_neigh_put(rose_neigh);- }-- rose_node->count--;-- if (rose_node->count == 0) {- rose_remove_node(rose_node);- } else {- switch (i) {- case 0:- rose_node->neighbour[0] =- rose_node->neighbour[1];- fallthrough;- case 1:- rose_node->neighbour[1] =- rose_node->neighbour[2];- break;- case 2:- break;- }- }- goto out;- }- }- err = -EINVAL;--out:- spin_unlock_bh(&rose_neigh_list_lock);- spin_unlock_bh(&rose_node_list_lock);-- return err;-}--/*- * Add the loopback neighbour.- */-void rose_add_loopback_neigh(void)-{- struct rose_neigh *sn;-- rose_loopback_neigh = kmalloc_obj(struct rose_neigh);- if (!rose_loopback_neigh)- return;- sn = rose_loopback_neigh;-- sn->callsign = null_ax25_address;- sn->digipeat = NULL;- sn->ax25 = NULL;- sn->dev = NULL;- sn->count = 0;- sn->dce_mode = 1;- sn->loopback = 1;- sn->number = rose_neigh_no++;- sn->restarted = 1;- refcount_set(&sn->use, 1);-- skb_queue_head_init(&sn->queue);-- timer_setup(&sn->ftimer, NULL, 0);- timer_setup(&sn->t0timer, NULL, 0);-- spin_lock_bh(&rose_neigh_list_lock);- sn->next = rose_neigh_list;- rose_neigh_list = sn;- spin_unlock_bh(&rose_neigh_list_lock);-}--/*- * Add a loopback node.- */-int rose_add_loopback_node(const rose_address *address)-{- struct rose_node *rose_node;- int err = 0;-- spin_lock_bh(&rose_node_list_lock);-- rose_node = rose_node_list;- while (rose_node != NULL) {- if ((rose_node->mask == 10) &&- (rosecmpm(address, &rose_node->address, 10) == 0) &&- rose_node->loopback)- break;- rose_node = rose_node->next;- }-- if (rose_node != NULL)- goto out;-- if ((rose_node = kmalloc_obj(*rose_node, GFP_ATOMIC)) == NULL) {- err = -ENOMEM;- goto out;- }-- rose_node->address = *address;- rose_node->mask = 10;- rose_node->count = 1;- rose_node->loopback = 1;- rose_node->neighbour[0] = rose_loopback_neigh;-- /* Insert at the head of list. Address is always mask=10 */- rose_node->next = rose_node_list;- rose_node_list = rose_node;-- rose_loopback_neigh->count++;- rose_neigh_hold(rose_loopback_neigh);--out:- spin_unlock_bh(&rose_node_list_lock);-- return err;-}--/*- * Delete a loopback node.- */-void rose_del_loopback_node(const rose_address *address)-{- struct rose_node *rose_node;-- spin_lock_bh(&rose_node_list_lock);-- rose_node = rose_node_list;- while (rose_node != NULL) {- if ((rose_node->mask == 10) &&- (rosecmpm(address, &rose_node->address, 10) == 0) &&- rose_node->loopback)- break;- rose_node = rose_node->next;- }-- if (rose_node == NULL)- goto out;-- rose_remove_node(rose_node);-- rose_loopback_neigh->count--;- rose_neigh_put(rose_loopback_neigh);--out:- spin_unlock_bh(&rose_node_list_lock);-}--/*- * A device has been removed. Remove its routes and neighbours.- */-void rose_rt_device_down(struct net_device *dev)-{- struct rose_neigh *s, *rose_neigh;- struct rose_node *t, *rose_node;- int i;-- spin_lock_bh(&rose_node_list_lock);- spin_lock_bh(&rose_neigh_list_lock);- rose_neigh = rose_neigh_list;- while (rose_neigh != NULL) {- s = rose_neigh;- rose_neigh = rose_neigh->next;-- if (s->dev != dev)- continue;-- rose_node = rose_node_list;-- while (rose_node != NULL) {- t = rose_node;- rose_node = rose_node->next;-- for (i = t->count - 1; i >= 0; i--) {- if (t->neighbour[i] != s)- continue;-- t->count--;-- memmove(&t->neighbour[i], &t->neighbour[i + 1],- sizeof(t->neighbour[0]) *- (t->count - i));- rose_neigh_put(s);- }-- if (t->count <= 0)- rose_remove_node(t);- }-- rose_remove_neigh(s);- rose_neigh_put(s);- }- spin_unlock_bh(&rose_neigh_list_lock);- spin_unlock_bh(&rose_node_list_lock);-}--#if 0 /* Currently unused */-/*- * A device has been removed. Remove its links.- */-void rose_route_device_down(struct net_device *dev)-{- struct rose_route *s, *rose_route;-- spin_lock_bh(&rose_route_list_lock);- rose_route = rose_route_list;- while (rose_route != NULL) {- s = rose_route;- rose_route = rose_route->next;-- if (s->neigh1->dev == dev || s->neigh2->dev == dev)- rose_remove_route(s);- }- spin_unlock_bh(&rose_route_list_lock);-}-#endif--/*- * Clear all nodes and neighbours out, except for neighbours with- * active connections going through them.- * Do not clear loopback neighbour and nodes.- */-static int rose_clear_routes(void)-{- struct rose_neigh *s, *rose_neigh;- struct rose_node *t, *rose_node;- int i;-- spin_lock_bh(&rose_node_list_lock);- spin_lock_bh(&rose_neigh_list_lock);-- rose_neigh = rose_neigh_list;- rose_node = rose_node_list;-- while (rose_node != NULL) {- t = rose_node;- rose_node = rose_node->next;-- if (!t->loopback) {- for (i = 0; i < t->count; i++)- rose_neigh_put(t->neighbour[i]);- rose_remove_node(t);- }- }-- while (rose_neigh != NULL) {- s = rose_neigh;- rose_neigh = rose_neigh->next;-- if (!s->loopback) {- rose_remove_neigh(s);- rose_neigh_put(s);- }- }-- spin_unlock_bh(&rose_neigh_list_lock);- spin_unlock_bh(&rose_node_list_lock);-- return 0;-}--/*- * Check that the device given is a valid AX.25 interface that is "up".- * called with RTNL- */-static struct net_device *rose_ax25_dev_find(char *devname)-{- struct net_device *dev;-- if ((dev = __dev_get_by_name(&init_net, devname)) == NULL)- return NULL;-- if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)- return dev;-- return NULL;-}--/*- * Find the first active ROSE device, usually "rose0".- */-struct net_device *rose_dev_first(void)-{- struct net_device *dev, *first = NULL;-- rcu_read_lock();- for_each_netdev_rcu(&init_net, dev) {- if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)- if (first == NULL || strncmp(dev->name, first->name, 3) < 0)- first = dev;- }- if (first)- dev_hold(first);- rcu_read_unlock();-- return first;-}--/*- * Find the ROSE device for the given address.- */-struct net_device *rose_dev_get(rose_address *addr)-{- struct net_device *dev;-- rcu_read_lock();- for_each_netdev_rcu(&init_net, dev) {- if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE &&- rosecmp(addr, (const rose_address *)dev->dev_addr) == 0) {- dev_hold(dev);- goto out;- }- }- dev = NULL;-out:- rcu_read_unlock();- return dev;-}--static int rose_dev_exists(rose_address *addr)-{- struct net_device *dev;-- rcu_read_lock();- for_each_netdev_rcu(&init_net, dev) {- if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE &&- rosecmp(addr, (const rose_address *)dev->dev_addr) == 0)- goto out;- }- dev = NULL;-out:- rcu_read_unlock();- return dev != NULL;-}-----struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neigh)-{- struct rose_route *rose_route;-- for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next)- if ((rose_route->neigh1 == neigh && rose_route->lci1 == lci) ||- (rose_route->neigh2 == neigh && rose_route->lci2 == lci))- return rose_route;-- return NULL;-}--/*- * Find a neighbour or a route given a ROSE address.- */-struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,- unsigned char *diagnostic, int route_frame)-{- struct rose_neigh *res = NULL;- struct rose_node *node;- int failed = 0;- int i;-- if (!route_frame) spin_lock_bh(&rose_node_list_lock);- for (node = rose_node_list; node != NULL; node = node->next) {- if (rosecmpm(addr, &node->address, node->mask) == 0) {- for (i = 0; i < node->count; i++) {- if (node->neighbour[i]->restarted) {- res = node->neighbour[i];- rose_neigh_hold(node->neighbour[i]);- goto out;- }- }- }- }- if (!route_frame) { /* connect request */- for (node = rose_node_list; node != NULL; node = node->next) {- if (rosecmpm(addr, &node->address, node->mask) == 0) {- for (i = 0; i < node->count; i++) {- if (!rose_ftimer_running(node->neighbour[i])) {- res = node->neighbour[i];- rose_neigh_hold(node->neighbour[i]);- goto out;- }- failed = 1;- }- }- }- }-- if (failed) {- *cause = ROSE_OUT_OF_ORDER;- *diagnostic = 0;- } else {- *cause = ROSE_NOT_OBTAINABLE;- *diagnostic = 0;- }--out:- if (!route_frame) spin_unlock_bh(&rose_node_list_lock);- return res;-}--/*- * Handle the ioctls that control the routing functions.- */-int rose_rt_ioctl(unsigned int cmd, void __user *arg)-{- struct rose_route_struct rose_route;- struct net_device *dev;- int err;-- switch (cmd) {- case SIOCADDRT:- if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))- return -EFAULT;- if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL)- return -EINVAL;- if (rose_dev_exists(&rose_route.address)) /* Can't add routes to ourself */- return -EINVAL;- if (rose_route.mask > 10) /* Mask can't be more than 10 digits */- return -EINVAL;- if (rose_route.ndigis > AX25_MAX_DIGIS)- return -EINVAL;- err = rose_add_node(&rose_route, dev);- return err;-- case SIOCDELRT:- if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))- return -EFAULT;- if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL)- return -EINVAL;- err = rose_del_node(&rose_route, dev);- return err;-- case SIOCRSCLRRT:- return rose_clear_routes();-- default:- return -EINVAL;- }-- return 0;-}--static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh)-{- struct rose_route *rose_route, *s;-- rose_neigh->restarted = 0;-- rose_stop_t0timer(rose_neigh);- rose_start_ftimer(rose_neigh);-- skb_queue_purge(&rose_neigh->queue);-- spin_lock_bh(&rose_route_list_lock);-- rose_route = rose_route_list;-- while (rose_route != NULL) {- if ((rose_route->neigh1 == rose_neigh && rose_route->neigh2 == rose_neigh) ||- (rose_route->neigh1 == rose_neigh && rose_route->neigh2 == NULL) ||- (rose_route->neigh2 == rose_neigh && rose_route->neigh1 == NULL)) {- s = rose_route->next;- rose_remove_route(rose_route);- rose_route = s;- continue;- }-- if (rose_route->neigh1 == rose_neigh) {- rose_neigh_put(rose_route->neigh1);- rose_route->neigh1 = NULL;- rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0);- }-- if (rose_route->neigh2 == rose_neigh) {- rose_neigh_put(rose_route->neigh2);- rose_route->neigh2 = NULL;- rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0);- }-- rose_route = rose_route->next;- }- spin_unlock_bh(&rose_route_list_lock);-}--/*- * A level 2 link has timed out, therefore it appears to be a poor link,- * then don't use that neighbour until it is reset. Blow away all through- * routes and connections using this route.- */-void rose_link_failed(ax25_cb *ax25, int reason)-{- struct rose_neigh *rose_neigh;-- spin_lock_bh(&rose_neigh_list_lock);- rose_neigh = rose_neigh_list;- while (rose_neigh != NULL) {- if (rose_neigh->ax25 == ax25)- break;- rose_neigh = rose_neigh->next;- }-- if (rose_neigh != NULL) {- rose_neigh->ax25 = NULL;- ax25_cb_put(ax25);-- rose_del_route_by_neigh(rose_neigh);- rose_kill_by_neigh(rose_neigh);- }- spin_unlock_bh(&rose_neigh_list_lock);-}--/*- * A device has been "downed" remove its link status. Blow away all- * through routes and connections that use this device.- */-void rose_link_device_down(struct net_device *dev)-{- struct rose_neigh *rose_neigh;-- for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) {- if (rose_neigh->dev == dev) {- rose_del_route_by_neigh(rose_neigh);- rose_kill_by_neigh(rose_neigh);- }- }-}--/*- * Route a frame to an appropriate AX.25 connection.- * A NULL ax25_cb indicates an internally generated frame.- */-int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)-{- struct rose_neigh *rose_neigh, *new_neigh;- struct rose_route *rose_route;- struct rose_facilities_struct facilities;- rose_address *src_addr, *dest_addr;- struct sock *sk;- unsigned short frametype;- unsigned int lci, new_lci;- unsigned char cause, diagnostic;- struct net_device *dev;- int res = 0;- char buf[11];-- if (skb->len < ROSE_MIN_LEN)- return res;-- if (!ax25)- return rose_loopback_queue(skb, NULL);-- frametype = skb->data[2];- lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);- if (frametype == ROSE_CALL_REQUEST &&- (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF ||- skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] !=- ROSE_CALL_REQ_ADDR_LEN_VAL))- return res;- src_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF);- dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF);-- spin_lock_bh(&rose_neigh_list_lock);- spin_lock_bh(&rose_route_list_lock);-- rose_neigh = rose_neigh_list;- while (rose_neigh != NULL) {- if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 &&- ax25->ax25_dev->dev == rose_neigh->dev)- break;- rose_neigh = rose_neigh->next;- }-- if (rose_neigh == NULL) {- printk("rose_route : unknown neighbour or device %s\n",- ax2asc(buf, &ax25->dest_addr));- goto out;- }-- /*- * Obviously the link is working, halt the ftimer.- */- rose_stop_ftimer(rose_neigh);-- /*- * LCI of zero is always for us, and its always a restart- * frame.- */- if (lci == 0) {- rose_link_rx_restart(skb, rose_neigh, frametype);- goto out;- }-- /*- * Find an existing socket.- */- if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) {- if (frametype == ROSE_CALL_REQUEST) {- struct rose_sock *rose = rose_sk(sk);-- /* Remove an existing unused socket */- rose_clear_queues(sk);- rose->cause = ROSE_NETWORK_CONGESTION;- rose->diagnostic = 0;- rose_neigh_put(rose->neighbour);- rose->neighbour = NULL;- rose->lci = 0;- rose->state = ROSE_STATE_0;- sk->sk_state = TCP_CLOSE;- sk->sk_err = 0;- sk->sk_shutdown |= SEND_SHUTDOWN;- if (!sock_flag(sk, SOCK_DEAD)) {- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DEAD);- }- }- else {- skb_reset_transport_header(skb);- res = rose_process_rx_frame(sk, skb);- goto out;- }- }-- /*- * Is is a Call Request and is it for us ?- */- if (frametype == ROSE_CALL_REQUEST)- if ((dev = rose_dev_get(dest_addr)) != NULL) {- res = rose_rx_call_request(skb, dev, rose_neigh, lci);- dev_put(dev);- goto out;- }-- if (!sysctl_rose_routing_control) {- rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 0);- goto out;- }-- /*- * Route it to the next in line if we have an entry for it.- */- rose_route = rose_route_list;- while (rose_route != NULL) {- if (rose_route->lci1 == lci &&- rose_route->neigh1 == rose_neigh) {- if (frametype == ROSE_CALL_REQUEST) {- /* F6FBB - Remove an existing unused route */- rose_remove_route(rose_route);- break;- } else if (rose_route->neigh2 != NULL) {- skb->data[0] &= 0xF0;- skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;- skb->data[1] = (rose_route->lci2 >> 0) & 0xFF;- rose_transmit_link(skb, rose_route->neigh2);- if (frametype == ROSE_CLEAR_CONFIRMATION)- rose_remove_route(rose_route);- res = 1;- goto out;- } else {- if (frametype == ROSE_CLEAR_CONFIRMATION)- rose_remove_route(rose_route);- goto out;- }- }- if (rose_route->lci2 == lci &&- rose_route->neigh2 == rose_neigh) {- if (frametype == ROSE_CALL_REQUEST) {- /* F6FBB - Remove an existing unused route */- rose_remove_route(rose_route);- break;- } else if (rose_route->neigh1 != NULL) {- skb->data[0] &= 0xF0;- skb->data[0] |= (rose_route->lci1 >> 8) & 0x0F;- skb->data[1] = (rose_route->lci1 >> 0) & 0xFF;- rose_transmit_link(skb, rose_route->neigh1);- if (frametype == ROSE_CLEAR_CONFIRMATION)- rose_remove_route(rose_route);- res = 1;- goto out;- } else {- if (frametype == ROSE_CLEAR_CONFIRMATION)- rose_remove_route(rose_route);- goto out;- }- }- rose_route = rose_route->next;- }-- /*- * We know that:- * 1. The frame isn't for us,- * 2. It isn't "owned" by any existing route.- */- if (frametype != ROSE_CALL_REQUEST) { /* XXX */- res = 0;- goto out;- }-- memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));-- if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,- skb->len - ROSE_CALL_REQ_FACILITIES_OFF,- &facilities)) {- rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);- goto out;- }-- /*- * Check for routing loops.- */- rose_route = rose_route_list;- while (rose_route != NULL) {- if (rose_route->rand == facilities.rand &&- rosecmp(src_addr, &rose_route->src_addr) == 0 &&- ax25cmp(&facilities.dest_call, &rose_route->src_call) == 0 &&- ax25cmp(&facilities.source_call, &rose_route->dest_call) == 0) {- rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 120);- goto out;- }- rose_route = rose_route->next;- }-- if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic, 1)) == NULL) {- rose_transmit_clear_request(rose_neigh, lci, cause, diagnostic);- goto out;- }-- if ((new_lci = rose_new_lci(new_neigh)) == 0) {- rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71);- goto put_neigh;- }-- if ((rose_route = kmalloc_obj(*rose_route, GFP_ATOMIC)) == NULL) {- rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120);- goto put_neigh;- }-- rose_route->lci1 = lci;- rose_route->src_addr = *src_addr;- rose_route->dest_addr = *dest_addr;- rose_route->src_call = facilities.dest_call;- rose_route->dest_call = facilities.source_call;- rose_route->rand = facilities.rand;- rose_route->neigh1 = rose_neigh;- rose_route->lci2 = new_lci;- rose_route->neigh2 = new_neigh;-- rose_neigh_hold(rose_route->neigh1);- rose_neigh_hold(rose_route->neigh2);-- rose_route->next = rose_route_list;- rose_route_list = rose_route;-- skb->data[0] &= 0xF0;- skb->data[0] |= (rose_route->lci2 >> 8) & 0x0F;- skb->data[1] = (rose_route->lci2 >> 0) & 0xFF;-- rose_transmit_link(skb, rose_route->neigh2);- res = 1;--put_neigh:- rose_neigh_put(new_neigh);-out:- spin_unlock_bh(&rose_route_list_lock);- spin_unlock_bh(&rose_neigh_list_lock);-- return res;-}--#ifdef CONFIG_PROC_FS--static void *rose_node_start(struct seq_file *seq, loff_t *pos)- __acquires(rose_node_list_lock)-{- struct rose_node *rose_node;- int i = 1;-- spin_lock_bh(&rose_node_list_lock);- if (*pos == 0)- return SEQ_START_TOKEN;-- for (rose_node = rose_node_list; rose_node && i < *pos;- rose_node = rose_node->next, ++i);-- return (i == *pos) ? rose_node : NULL;-}--static void *rose_node_next(struct seq_file *seq, void *v, loff_t *pos)-{- ++*pos;-- return (v == SEQ_START_TOKEN) ? rose_node_list- : ((struct rose_node *)v)->next;-}--static void rose_node_stop(struct seq_file *seq, void *v)- __releases(rose_node_list_lock)-{- spin_unlock_bh(&rose_node_list_lock);-}--static int rose_node_show(struct seq_file *seq, void *v)-{- char rsbuf[11];- int i;-- if (v == SEQ_START_TOKEN)- seq_puts(seq, "address mask n neigh neigh neigh\n");- else {- const struct rose_node *rose_node = v;- seq_printf(seq, "%-10s %04d %d",- rose2asc(rsbuf, &rose_node->address),- rose_node->mask,- rose_node->count);-- for (i = 0; i < rose_node->count; i++)- seq_printf(seq, " %05d", rose_node->neighbour[i]->number);-- seq_puts(seq, "\n");- }- return 0;-}--const struct seq_operations rose_node_seqops = {- .start = rose_node_start,- .next = rose_node_next,- .stop = rose_node_stop,- .show = rose_node_show,-};--static void *rose_neigh_start(struct seq_file *seq, loff_t *pos)- __acquires(rose_neigh_list_lock)-{- struct rose_neigh *rose_neigh;- int i = 1;-- spin_lock_bh(&rose_neigh_list_lock);- if (*pos == 0)- return SEQ_START_TOKEN;-- for (rose_neigh = rose_neigh_list; rose_neigh && i < *pos;- rose_neigh = rose_neigh->next, ++i);-- return (i == *pos) ? rose_neigh : NULL;-}--static void *rose_neigh_next(struct seq_file *seq, void *v, loff_t *pos)-{- ++*pos;-- return (v == SEQ_START_TOKEN) ? rose_neigh_list- : ((struct rose_neigh *)v)->next;-}--static void rose_neigh_stop(struct seq_file *seq, void *v)- __releases(rose_neigh_list_lock)-{- spin_unlock_bh(&rose_neigh_list_lock);-}--static int rose_neigh_show(struct seq_file *seq, void *v)-{- char buf[11];- int i;-- if (v == SEQ_START_TOKEN)- seq_puts(seq,- "addr callsign dev count use mode restart t0 tf digipeaters\n");- else {- struct rose_neigh *rose_neigh = v;-- /* if (!rose_neigh->loopback) { */- seq_printf(seq, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu",- rose_neigh->number,- (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign),- rose_neigh->dev ? rose_neigh->dev->name : "???",- rose_neigh->count,- refcount_read(&rose_neigh->use) - rose_neigh->count - 1,- (rose_neigh->dce_mode) ? "DCE" : "DTE",- (rose_neigh->restarted) ? "yes" : "no",- ax25_display_timer(&rose_neigh->t0timer) / HZ,- ax25_display_timer(&rose_neigh->ftimer) / HZ);-- if (rose_neigh->digipeat != NULL) {- for (i = 0; i < rose_neigh->digipeat->ndigi; i++)- seq_printf(seq, " %s", ax2asc(buf, &rose_neigh->digipeat->calls[i]));- }-- seq_puts(seq, "\n");- }- return 0;-}---const struct seq_operations rose_neigh_seqops = {- .start = rose_neigh_start,- .next = rose_neigh_next,- .stop = rose_neigh_stop,- .show = rose_neigh_show,-};--static void *rose_route_start(struct seq_file *seq, loff_t *pos)- __acquires(rose_route_list_lock)-{- struct rose_route *rose_route;- int i = 1;-- spin_lock_bh(&rose_route_list_lock);- if (*pos == 0)- return SEQ_START_TOKEN;-- for (rose_route = rose_route_list; rose_route && i < *pos;- rose_route = rose_route->next, ++i);-- return (i == *pos) ? rose_route : NULL;-}--static void *rose_route_next(struct seq_file *seq, void *v, loff_t *pos)-{- ++*pos;-- return (v == SEQ_START_TOKEN) ? rose_route_list- : ((struct rose_route *)v)->next;-}--static void rose_route_stop(struct seq_file *seq, void *v)- __releases(rose_route_list_lock)-{- spin_unlock_bh(&rose_route_list_lock);-}--static int rose_route_show(struct seq_file *seq, void *v)-{- char buf[11], rsbuf[11];-- if (v == SEQ_START_TOKEN)- seq_puts(seq,- "lci address callsign neigh <-> lci address callsign neigh\n");- else {- struct rose_route *rose_route = v;-- if (rose_route->neigh1)- seq_printf(seq,- "%3.3X %-10s %-9s %05d ",- rose_route->lci1,- rose2asc(rsbuf, &rose_route->src_addr),- ax2asc(buf, &rose_route->src_call),- rose_route->neigh1->number);- else- seq_puts(seq,- "000 * * 00000 ");-- if (rose_route->neigh2)- seq_printf(seq,- "%3.3X %-10s %-9s %05d\n",- rose_route->lci2,- rose2asc(rsbuf, &rose_route->dest_addr),- ax2asc(buf, &rose_route->dest_call),- rose_route->neigh2->number);- else- seq_puts(seq,- "000 * * 00000\n");- }- return 0;-}--struct seq_operations rose_route_seqops = {- .start = rose_route_start,- .next = rose_route_next,- .stop = rose_route_stop,- .show = rose_route_show,-};-#endif /* CONFIG_PROC_FS */--/*- * Release all memory associated with ROSE routing structures.- */-void __exit rose_rt_free(void)-{- struct rose_neigh *s, *rose_neigh = rose_neigh_list;- struct rose_node *t, *rose_node = rose_node_list;- struct rose_route *u, *rose_route = rose_route_list;- int i;-- while (rose_neigh != NULL) {- s = rose_neigh;- rose_neigh = rose_neigh->next;-- rose_remove_neigh(s);- rose_neigh_put(s);- }-- while (rose_node != NULL) {- t = rose_node;- rose_node = rose_node->next;-- for (i = 0; i < t->count; i++)- rose_neigh_put(t->neighbour[i]);- rose_remove_node(t);- }-- while (rose_route != NULL) {- u = rose_route;- rose_route = rose_route->next;-- rose_remove_route(u);- }-}diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.cdeleted file mode 100644index 4dbc437a9e22..000000000000--- a/net/rose/rose_subr.c+++ /dev/null@@ -1,556 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <linux/slab.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/rose.h>--static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose);--/*- * This routine purges all of the queues of frames.- */-void rose_clear_queues(struct sock *sk)-{- skb_queue_purge(&sk->sk_write_queue);- skb_queue_purge(&rose_sk(sk)->ack_queue);-}--/*- * This routine purges the input queue of those frames that have been- * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the- * SDL diagram.- */-void rose_frames_acked(struct sock *sk, unsigned short nr)-{- struct sk_buff *skb;- struct rose_sock *rose = rose_sk(sk);-- /*- * Remove all the ack-ed frames from the ack queue.- */- if (rose->va != nr) {- while (skb_peek(&rose->ack_queue) != NULL && rose->va != nr) {- skb = skb_dequeue(&rose->ack_queue);- kfree_skb(skb);- rose->va = (rose->va + 1) % ROSE_MODULUS;- }- }-}--void rose_requeue_frames(struct sock *sk)-{- struct sk_buff *skb, *skb_prev = NULL;-- /*- * Requeue all the un-ack-ed frames on the output queue to be picked- * up by rose_kick. This arrangement handles the possibility of an- * empty output queue.- */- while ((skb = skb_dequeue(&rose_sk(sk)->ack_queue)) != NULL) {- if (skb_prev == NULL)- skb_queue_head(&sk->sk_write_queue, skb);- else- skb_append(skb_prev, skb, &sk->sk_write_queue);- skb_prev = skb;- }-}--/*- * Validate that the value of nr is between va and vs. Return true or- * false for testing.- */-int rose_validate_nr(struct sock *sk, unsigned short nr)-{- struct rose_sock *rose = rose_sk(sk);- unsigned short vc = rose->va;-- while (vc != rose->vs) {- if (nr == vc) return 1;- vc = (vc + 1) % ROSE_MODULUS;- }-- return nr == rose->vs;-}--/*- * This routine is called when the packet layer internally generates a- * control frame.- */-void rose_write_internal(struct sock *sk, int frametype)-{- struct rose_sock *rose = rose_sk(sk);- struct sk_buff *skb;- unsigned char *dptr;- unsigned char lci1, lci2;- int maxfaclen = 0;- int len, faclen;- int reserve;-- reserve = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 1;- len = ROSE_MIN_LEN;-- switch (frametype) {- case ROSE_CALL_REQUEST:- len += 1 + ROSE_ADDR_LEN + ROSE_ADDR_LEN;- maxfaclen = 256;- break;- case ROSE_CALL_ACCEPTED:- case ROSE_CLEAR_REQUEST:- case ROSE_RESET_REQUEST:- len += 2;- break;- }-- skb = alloc_skb(reserve + len + maxfaclen, GFP_ATOMIC);- if (!skb)- return;-- /*- * Space for AX.25 header and PID.- */- skb_reserve(skb, reserve);-- dptr = skb_put(skb, len);-- lci1 = (rose->lci >> 8) & 0x0F;- lci2 = (rose->lci >> 0) & 0xFF;-- switch (frametype) {- case ROSE_CALL_REQUEST:- *dptr++ = ROSE_GFI | lci1;- *dptr++ = lci2;- *dptr++ = frametype;- *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL;- memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN);- dptr += ROSE_ADDR_LEN;- memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN);- dptr += ROSE_ADDR_LEN;- faclen = rose_create_facilities(dptr, rose);- skb_put(skb, faclen);- dptr += faclen;- break;-- case ROSE_CALL_ACCEPTED:- *dptr++ = ROSE_GFI | lci1;- *dptr++ = lci2;- *dptr++ = frametype;- *dptr++ = 0x00; /* Address length */- *dptr++ = 0; /* Facilities length */- break;-- case ROSE_CLEAR_REQUEST:- *dptr++ = ROSE_GFI | lci1;- *dptr++ = lci2;- *dptr++ = frametype;- *dptr++ = rose->cause;- *dptr++ = rose->diagnostic;- break;-- case ROSE_RESET_REQUEST:- *dptr++ = ROSE_GFI | lci1;- *dptr++ = lci2;- *dptr++ = frametype;- *dptr++ = ROSE_DTE_ORIGINATED;- *dptr++ = 0;- break;-- case ROSE_RR:- case ROSE_RNR:- *dptr++ = ROSE_GFI | lci1;- *dptr++ = lci2;- *dptr = frametype;- *dptr++ |= (rose->vr << 5) & 0xE0;- break;-- case ROSE_CLEAR_CONFIRMATION:- case ROSE_RESET_CONFIRMATION:- *dptr++ = ROSE_GFI | lci1;- *dptr++ = lci2;- *dptr++ = frametype;- break;-- default:- printk(KERN_ERR "ROSE: rose_write_internal - invalid frametype %02X\n", frametype);- kfree_skb(skb);- return;- }-- rose_transmit_link(skb, rose->neighbour);-}--int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m)-{- unsigned char *frame;-- frame = skb->data;-- *ns = *nr = *q = *d = *m = 0;-- switch (frame[2]) {- case ROSE_CALL_REQUEST:- case ROSE_CALL_ACCEPTED:- case ROSE_CLEAR_REQUEST:- case ROSE_CLEAR_CONFIRMATION:- case ROSE_RESET_REQUEST:- case ROSE_RESET_CONFIRMATION:- return frame[2];- default:- break;- }-- if ((frame[2] & 0x1F) == ROSE_RR ||- (frame[2] & 0x1F) == ROSE_RNR) {- *nr = (frame[2] >> 5) & 0x07;- return frame[2] & 0x1F;- }-- if ((frame[2] & 0x01) == ROSE_DATA) {- *q = (frame[0] & ROSE_Q_BIT) == ROSE_Q_BIT;- *d = (frame[0] & ROSE_D_BIT) == ROSE_D_BIT;- *m = (frame[2] & ROSE_M_BIT) == ROSE_M_BIT;- *nr = (frame[2] >> 5) & 0x07;- *ns = (frame[2] >> 1) & 0x07;- return ROSE_DATA;- }-- return ROSE_ILLEGAL;-}--static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *facilities, int len)-{- unsigned char *pt;- unsigned char l, lg, n = 0;- int fac_national_digis_received = 0;-- do {- switch (*p & 0xC0) {- case 0x00:- if (len < 2)- return -1;- p += 2;- n += 2;- len -= 2;- break;-- case 0x40:- if (len < 3)- return -1;- if (*p == FAC_NATIONAL_RAND)- facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF);- p += 3;- n += 3;- len -= 3;- break;-- case 0x80:- if (len < 4)- return -1;- p += 4;- n += 4;- len -= 4;- break;-- case 0xC0:- if (len < 2)- return -1;- l = p[1];- if (len < 2 + l)- return -1;- if (*p == FAC_NATIONAL_DEST_DIGI) {- if (!fac_national_digis_received) {- if (l < AX25_ADDR_LEN)- return -1;- memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN);- facilities->source_ndigis = 1;- }- }- else if (*p == FAC_NATIONAL_SRC_DIGI) {- if (!fac_national_digis_received) {- if (l < AX25_ADDR_LEN)- return -1;- memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN);- facilities->dest_ndigis = 1;- }- }- else if (*p == FAC_NATIONAL_FAIL_CALL) {- if (l < AX25_ADDR_LEN)- return -1;- memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN);- }- else if (*p == FAC_NATIONAL_FAIL_ADD) {- if (l < 1 + ROSE_ADDR_LEN)- return -1;- memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN);- }- else if (*p == FAC_NATIONAL_DIGIS) {- if (l % AX25_ADDR_LEN)- return -1;- fac_national_digis_received = 1;- facilities->source_ndigis = 0;- facilities->dest_ndigis = 0;- for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) {- if (pt[6] & AX25_HBIT) {- if (facilities->dest_ndigis >= ROSE_MAX_DIGIS)- return -1;- memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN);- } else {- if (facilities->source_ndigis >= ROSE_MAX_DIGIS)- return -1;- memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);- }- }- }- p += l + 2;- n += l + 2;- len -= l + 2;- break;- }- } while (*p != 0x00 && len > 0);-- return n;-}--static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *facilities, int len)-{- unsigned char l, n = 0;- char callsign[11];-- do {- switch (*p & 0xC0) {- case 0x00:- if (len < 2)- return -1;- p += 2;- n += 2;- len -= 2;- break;-- case 0x40:- if (len < 3)- return -1;- p += 3;- n += 3;- len -= 3;- break;-- case 0x80:- if (len < 4)- return -1;- p += 4;- n += 4;- len -= 4;- break;-- case 0xC0:- if (len < 2)- return -1;- l = p[1];-- /* Prevent overflows*/- if (l < 10 || l > 20)- return -1;-- if (*p == FAC_CCITT_DEST_NSAP) {- memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);- memcpy(callsign, p + 12, l - 10);- callsign[l - 10] = '\0';- asc2ax(&facilities->source_call, callsign);- }- if (*p == FAC_CCITT_SRC_NSAP) {- memcpy(&facilities->dest_addr, p + 7, ROSE_ADDR_LEN);- memcpy(callsign, p + 12, l - 10);- callsign[l - 10] = '\0';- asc2ax(&facilities->dest_call, callsign);- }- p += l + 2;- n += l + 2;- len -= l + 2;- break;- }- } while (*p != 0x00 && len > 0);-- return n;-}--int rose_parse_facilities(unsigned char *p, unsigned packet_len,- struct rose_facilities_struct *facilities)-{- int facilities_len, len;-- facilities_len = *p++;-- if (facilities_len == 0 || (unsigned int)facilities_len > packet_len)- return 0;-- while (facilities_len >= 3 && *p == 0x00) {- facilities_len--;- p++;-- switch (*p) {- case FAC_NATIONAL: /* National */- len = rose_parse_national(p + 1, facilities, facilities_len - 1);- break;-- case FAC_CCITT: /* CCITT */- len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);- break;-- default:- printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);- len = 1;- break;- }-- if (len < 0)- return 0;- if (WARN_ON(len >= facilities_len))- return 0;- facilities_len -= len + 1;- p += len + 1;- }-- return facilities_len == 0;-}--static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)-{- unsigned char *p = buffer + 1;- char *callsign;- char buf[11];- int len, nb;-- /* National Facilities */- if (rose->rand != 0 || rose->source_ndigis == 1 || rose->dest_ndigis == 1) {- *p++ = 0x00;- *p++ = FAC_NATIONAL;-- if (rose->rand != 0) {- *p++ = FAC_NATIONAL_RAND;- *p++ = (rose->rand >> 8) & 0xFF;- *p++ = (rose->rand >> 0) & 0xFF;- }-- /* Sent before older facilities */- if ((rose->source_ndigis > 0) || (rose->dest_ndigis > 0)) {- int maxdigi = 0;- *p++ = FAC_NATIONAL_DIGIS;- *p++ = AX25_ADDR_LEN * (rose->source_ndigis + rose->dest_ndigis);- for (nb = 0 ; nb < rose->source_ndigis ; nb++) {- if (++maxdigi >= ROSE_MAX_DIGIS)- break;- memcpy(p, &rose->source_digis[nb], AX25_ADDR_LEN);- p[6] |= AX25_HBIT;- p += AX25_ADDR_LEN;- }- for (nb = 0 ; nb < rose->dest_ndigis ; nb++) {- if (++maxdigi >= ROSE_MAX_DIGIS)- break;- memcpy(p, &rose->dest_digis[nb], AX25_ADDR_LEN);- p[6] &= ~AX25_HBIT;- p += AX25_ADDR_LEN;- }- }-- /* For compatibility */- if (rose->source_ndigis > 0) {- *p++ = FAC_NATIONAL_SRC_DIGI;- *p++ = AX25_ADDR_LEN;- memcpy(p, &rose->source_digis[0], AX25_ADDR_LEN);- p += AX25_ADDR_LEN;- }-- /* For compatibility */- if (rose->dest_ndigis > 0) {- *p++ = FAC_NATIONAL_DEST_DIGI;- *p++ = AX25_ADDR_LEN;- memcpy(p, &rose->dest_digis[0], AX25_ADDR_LEN);- p += AX25_ADDR_LEN;- }- }-- *p++ = 0x00;- *p++ = FAC_CCITT;-- *p++ = FAC_CCITT_DEST_NSAP;-- callsign = ax2asc(buf, &rose->dest_call);-- *p++ = strlen(callsign) + 10;- *p++ = (strlen(callsign) + 9) * 2; /* ??? */-- *p++ = 0x47; *p++ = 0x00; *p++ = 0x11;- *p++ = ROSE_ADDR_LEN * 2;- memcpy(p, &rose->dest_addr, ROSE_ADDR_LEN);- p += ROSE_ADDR_LEN;-- memcpy(p, callsign, strlen(callsign));- p += strlen(callsign);-- *p++ = FAC_CCITT_SRC_NSAP;-- callsign = ax2asc(buf, &rose->source_call);-- *p++ = strlen(callsign) + 10;- *p++ = (strlen(callsign) + 9) * 2; /* ??? */-- *p++ = 0x47; *p++ = 0x00; *p++ = 0x11;- *p++ = ROSE_ADDR_LEN * 2;- memcpy(p, &rose->source_addr, ROSE_ADDR_LEN);- p += ROSE_ADDR_LEN;-- memcpy(p, callsign, strlen(callsign));- p += strlen(callsign);-- len = p - buffer;- buffer[0] = len - 1;-- return len;-}--void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic)-{- struct rose_sock *rose = rose_sk(sk);-- rose_stop_timer(sk);- rose_stop_idletimer(sk);-- rose_clear_queues(sk);-- rose->lci = 0;- rose->state = ROSE_STATE_0;-- if (cause != -1)- rose->cause = cause;-- if (diagnostic != -1)- rose->diagnostic = diagnostic;-- sk->sk_state = TCP_CLOSE;- sk->sk_err = reason;- sk->sk_shutdown |= SEND_SHUTDOWN;-- if (!sock_flag(sk, SOCK_DEAD)) {- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DEAD);- }-}diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.cdeleted file mode 100644index bb60a1654d61..000000000000--- a/net/rose/rose_timer.c+++ /dev/null@@ -1,227 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)- * Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org)- */-#include <linux/errno.h>-#include <linux/types.h>-#include <linux/socket.h>-#include <linux/in.h>-#include <linux/kernel.h>-#include <linux/jiffies.h>-#include <linux/timer.h>-#include <linux/string.h>-#include <linux/sockios.h>-#include <linux/net.h>-#include <net/ax25.h>-#include <linux/inet.h>-#include <linux/netdevice.h>-#include <linux/skbuff.h>-#include <net/sock.h>-#include <net/tcp_states.h>-#include <linux/fcntl.h>-#include <linux/mm.h>-#include <linux/interrupt.h>-#include <net/rose.h>--static void rose_heartbeat_expiry(struct timer_list *t);-static void rose_timer_expiry(struct timer_list *);-static void rose_idletimer_expiry(struct timer_list *);--void rose_start_heartbeat(struct sock *sk)-{- sk_stop_timer(sk, &sk->sk_timer);-- sk->sk_timer.function = rose_heartbeat_expiry;- sk->sk_timer.expires = jiffies + 5 * HZ;-- sk_reset_timer(sk, &sk->sk_timer, sk->sk_timer.expires);-}--void rose_start_t1timer(struct sock *sk)-{- struct rose_sock *rose = rose_sk(sk);-- sk_stop_timer(sk, &rose->timer);-- rose->timer.function = rose_timer_expiry;- rose->timer.expires = jiffies + rose->t1;-- sk_reset_timer(sk, &rose->timer, rose->timer.expires);-}--void rose_start_t2timer(struct sock *sk)-{- struct rose_sock *rose = rose_sk(sk);-- sk_stop_timer(sk, &rose->timer);-- rose->timer.function = rose_timer_expiry;- rose->timer.expires = jiffies + rose->t2;-- sk_reset_timer(sk, &rose->timer, rose->timer.expires);-}--void rose_start_t3timer(struct sock *sk)-{- struct rose_sock *rose = rose_sk(sk);-- sk_stop_timer(sk, &rose->timer);-- rose->timer.function = rose_timer_expiry;- rose->timer.expires = jiffies + rose->t3;-- sk_reset_timer(sk, &rose->timer, rose->timer.expires);-}--void rose_start_hbtimer(struct sock *sk)-{- struct rose_sock *rose = rose_sk(sk);-- sk_stop_timer(sk, &rose->timer);-- rose->timer.function = rose_timer_expiry;- rose->timer.expires = jiffies + rose->hb;-- sk_reset_timer(sk, &rose->timer, rose->timer.expires);-}--void rose_start_idletimer(struct sock *sk)-{- struct rose_sock *rose = rose_sk(sk);-- sk_stop_timer(sk, &rose->idletimer);-- if (rose->idle > 0) {- rose->idletimer.function = rose_idletimer_expiry;- rose->idletimer.expires = jiffies + rose->idle;-- sk_reset_timer(sk, &rose->idletimer, rose->idletimer.expires);- }-}--void rose_stop_heartbeat(struct sock *sk)-{- sk_stop_timer(sk, &sk->sk_timer);-}--void rose_stop_timer(struct sock *sk)-{- sk_stop_timer(sk, &rose_sk(sk)->timer);-}--void rose_stop_idletimer(struct sock *sk)-{- sk_stop_timer(sk, &rose_sk(sk)->idletimer);-}--static void rose_heartbeat_expiry(struct timer_list *t)-{- struct sock *sk = timer_container_of(sk, t, sk_timer);- struct rose_sock *rose = rose_sk(sk);-- bh_lock_sock(sk);- if (sock_owned_by_user(sk)) {- sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ/20);- goto out;- }- switch (rose->state) {- case ROSE_STATE_0:- /* Magic here: If we listen() and a new link dies before it- is accepted() it isn't 'dead' so doesn't get removed. */- if (sock_flag(sk, SOCK_DESTROY) ||- (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {- bh_unlock_sock(sk);- rose_destroy_socket(sk);- sock_put(sk);- return;- }- break;-- case ROSE_STATE_3:- /*- * Check for the state of the receive buffer.- */- if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) &&- (rose->condition & ROSE_COND_OWN_RX_BUSY)) {- rose->condition &= ~ROSE_COND_OWN_RX_BUSY;- rose->condition &= ~ROSE_COND_ACK_PENDING;- rose->vl = rose->vr;- rose_write_internal(sk, ROSE_RR);- rose_stop_timer(sk); /* HB */- break;- }- break;- }-- rose_start_heartbeat(sk);-out:- bh_unlock_sock(sk);- sock_put(sk);-}--static void rose_timer_expiry(struct timer_list *t)-{- struct rose_sock *rose = timer_container_of(rose, t, timer);- struct sock *sk = &rose->sock;-- bh_lock_sock(sk);- if (sock_owned_by_user(sk)) {- sk_reset_timer(sk, &rose->timer, jiffies + HZ/20);- goto out;- }- switch (rose->state) {- case ROSE_STATE_1: /* T1 */- case ROSE_STATE_4: /* T2 */- rose_write_internal(sk, ROSE_CLEAR_REQUEST);- rose->state = ROSE_STATE_2;- rose_start_t3timer(sk);- break;-- case ROSE_STATE_2: /* T3 */- rose_neigh_put(rose->neighbour);- rose_disconnect(sk, ETIMEDOUT, -1, -1);- break;-- case ROSE_STATE_3: /* HB */- if (rose->condition & ROSE_COND_ACK_PENDING) {- rose->condition &= ~ROSE_COND_ACK_PENDING;- rose_enquiry_response(sk);- }- break;- }-out:- bh_unlock_sock(sk);- sock_put(sk);-}--static void rose_idletimer_expiry(struct timer_list *t)-{- struct rose_sock *rose = timer_container_of(rose, t, idletimer);- struct sock *sk = &rose->sock;-- bh_lock_sock(sk);- if (sock_owned_by_user(sk)) {- sk_reset_timer(sk, &rose->idletimer, jiffies + HZ/20);- goto out;- }- rose_clear_queues(sk);-- rose_write_internal(sk, ROSE_CLEAR_REQUEST);- rose_sk(sk)->state = ROSE_STATE_2;-- rose_start_t3timer(sk);-- sk->sk_state = TCP_CLOSE;- sk->sk_err = 0;- sk->sk_shutdown |= SEND_SHUTDOWN;-- if (!sock_flag(sk, SOCK_DEAD)) {- sk->sk_state_change(sk);- sock_set_flag(sk, SOCK_DEAD);- }-out:- bh_unlock_sock(sk);- sock_put(sk);-}diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.cdeleted file mode 100644index d801315b7083..000000000000--- a/net/rose/sysctl_net_rose.c+++ /dev/null@@ -1,125 +0,0 @@-// SPDX-License-Identifier: GPL-2.0-or-later-/*- *- * Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)- */-#include <linux/mm.h>-#include <linux/sysctl.h>-#include <linux/init.h>-#include <net/ax25.h>-#include <net/rose.h>--static int min_timer[] = {1 * HZ};-static int max_timer[] = {300 * HZ};-static int min_idle[] = {0 * HZ};-static int max_idle[] = {65535 * HZ};-static int min_route[1], max_route[] = {1};-static int min_ftimer[] = {60 * HZ};-static int max_ftimer[] = {600 * HZ};-static int min_maxvcs[] = {1}, max_maxvcs[] = {254};-static int min_window[] = {1}, max_window[] = {7};--static struct ctl_table_header *rose_table_header;--static struct ctl_table rose_table[] = {- {- .procname = "restart_request_timeout",- .data = &sysctl_rose_restart_request_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_timer,- .extra2 = &max_timer- },- {- .procname = "call_request_timeout",- .data = &sysctl_rose_call_request_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_timer,- .extra2 = &max_timer- },- {- .procname = "reset_request_timeout",- .data = &sysctl_rose_reset_request_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_timer,- .extra2 = &max_timer- },- {- .procname = "clear_request_timeout",- .data = &sysctl_rose_clear_request_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_timer,- .extra2 = &max_timer- },- {- .procname = "no_activity_timeout",- .data = &sysctl_rose_no_activity_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_idle,- .extra2 = &max_idle- },- {- .procname = "acknowledge_hold_back_timeout",- .data = &sysctl_rose_ack_hold_back_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_timer,- .extra2 = &max_timer- },- {- .procname = "routing_control",- .data = &sysctl_rose_routing_control,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_route,- .extra2 = &max_route- },- {- .procname = "link_fail_timeout",- .data = &sysctl_rose_link_fail_timeout,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_ftimer,- .extra2 = &max_ftimer- },- {- .procname = "maximum_virtual_circuits",- .data = &sysctl_rose_maximum_vcs,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_maxvcs,- .extra2 = &max_maxvcs- },- {- .procname = "window_size",- .data = &sysctl_rose_window_size,- .maxlen = sizeof(int),- .mode = 0644,- .proc_handler = proc_dointvec_minmax,- .extra1 = &min_window,- .extra2 = &max_window- },-};--void __init rose_register_sysctl(void)-{- rose_table_header = register_net_sysctl(&init_net, "net/rose", rose_table);-}--void rose_unregister_sysctl(void)-{- unregister_net_sysctl_table(rose_table_header);-}diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfigindex d10b3d4adbd1..acbab8dae53f 100644--- a/arch/mips/configs/bcm47xx_defconfig+++ b/arch/mips/configs/bcm47xx_defconfig@@ -28,7 +28,6 @@ CONFIG_NETFILTER=y CONFIG_VLAN_8021Q=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_FQ_CODEL=y-CONFIG_HAMRADIO=y CONFIG_CFG80211=y CONFIG_MAC80211=y CONFIG_MTD=ydiff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfigindex 3b64e151e187..aa63ada62e28 100644--- a/arch/mips/configs/bigsur_defconfig+++ b/arch/mips/configs/bigsur_defconfig@@ -84,16 +84,6 @@ CONFIG_IP_VS_FTP=m CONFIG_BRIDGE=m CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y-CONFIG_HAMRADIO=y-CONFIG_AX25=m-CONFIG_NETROM=m-CONFIG_ROSE=m-CONFIG_MKISS=m-CONFIG_6PACK=m-CONFIG_BPQETHER=m-CONFIG_BAYCOM_SER_FDX=m-CONFIG_BAYCOM_SER_HDX=m-CONFIG_YAM=m CONFIG_FW_LOADER=m CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=mdiff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfigindex 8097974489e3..ad80ad2eae6b 100644--- a/arch/mips/configs/gpr_defconfig+++ b/arch/mips/configs/gpr_defconfig@@ -126,17 +126,6 @@ CONFIG_NET_EMATCH_TEXT=m CONFIG_NET_CLS_ACT=y CONFIG_NET_ACT_POLICE=y CONFIG_NET_PKTGEN=m-CONFIG_HAMRADIO=y-CONFIG_AX25=m-# CONFIG_AX25_DAMA_SLAVE is not set-CONFIG_NETROM=m-CONFIG_ROSE=m-CONFIG_MKISS=m-CONFIG_6PACK=m-CONFIG_BPQETHER=m-CONFIG_BAYCOM_SER_FDX=m-CONFIG_BAYCOM_SER_HDX=m-CONFIG_YAM=m CONFIG_CFG80211=y CONFIG_MAC80211=y CONFIG_MTD=ydiff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfigindex 63787b8b733e..1295164af08e 100644--- a/arch/mips/configs/mtx1_defconfig+++ b/arch/mips/configs/mtx1_defconfig@@ -172,17 +172,6 @@ CONFIG_NET_EMATCH_TEXT=m CONFIG_NET_CLS_ACT=y CONFIG_NET_ACT_POLICE=y CONFIG_NET_PKTGEN=m-CONFIG_HAMRADIO=y-CONFIG_AX25=m-# CONFIG_AX25_DAMA_SLAVE is not set-CONFIG_NETROM=m-CONFIG_ROSE=m-CONFIG_MKISS=m-CONFIG_6PACK=m-CONFIG_BPQETHER=m-CONFIG_BAYCOM_SER_FDX=m-CONFIG_BAYCOM_SER_HDX=m-CONFIG_YAM=m CONFIG_BT=m CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=ydiff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfigindex 30d18b084cda..a88322fe3935 100644--- a/arch/mips/configs/rb532_defconfig+++ b/arch/mips/configs/rb532_defconfig@@ -95,7 +95,6 @@ CONFIG_NET_ACT_GACT=m CONFIG_GACT_PROB=y CONFIG_NET_ACT_MIRRED=m CONFIG_NET_ACT_PEDIT=m-CONFIG_HAMRADIO=y CONFIG_MTD=y CONFIG_MTD_BLOCK=y CONFIG_MTD_BLOCK2MTD=ydiff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfigindex b1e67ff0c4f0..ad9fbd0cbb38 100644--- a/arch/mips/configs/rm200_defconfig+++ b/arch/mips/configs/rm200_defconfig@@ -147,13 +147,6 @@ CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m-CONFIG_HAMRADIO=y-CONFIG_AX25=m-CONFIG_NETROM=m-CONFIG_ROSE=m-CONFIG_MKISS=m-CONFIG_6PACK=m-CONFIG_BPQETHER=m CONFIG_CONNECTOR=m CONFIG_PARPORT=m CONFIG_PARPORT_PC=mdiff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfigindex 8f9701efef19..c920976bedd0 100644--- a/arch/mips/configs/rt305x_defconfig+++ b/arch/mips/configs/rt305x_defconfig@@ -64,7 +64,6 @@ CONFIG_BRIDGE=y # CONFIG_BRIDGE_IGMP_SNOOPING is not set CONFIG_VLAN_8021Q=y CONFIG_NET_SCHED=y-CONFIG_HAMRADIO=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=ydiff --git a/arch/mips/configs/xway_defconfig b/arch/mips/configs/xway_defconfigindex aae8497b6872..f1c53bbb72e9 100644--- a/arch/mips/configs/xway_defconfig+++ b/arch/mips/configs/xway_defconfig@@ -66,7 +66,6 @@ CONFIG_BRIDGE=y # CONFIG_BRIDGE_IGMP_SNOOPING is not set CONFIG_VLAN_8021Q=y CONFIG_NET_SCHED=y-CONFIG_HAMRADIO=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=y-- 2.53.0