From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-dy1-f170.google.com (mail-dy1-f170.google.com [74.125.82.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4BC0F3009D4 for ; Wed, 22 Apr 2026 01:56:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.170 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776823042; cv=none; b=r2I9WqFGxwf/+3w+C2VHU8rO9am06vxkAhMBorQY1Uksi2t6kQkFxOQBnOJyJMLfhcQ+lDSHHehiUDeukBEIG2MPkHbcFMOQov8w/7EPhv7PxZd44GSKhpcT4l0YT12FOF8p2Uk7czVo5CXtA2dWyffrQkjetVYIapxrYIkcIZQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776823042; c=relaxed/simple; bh=Tehc36RW9TrLyQSOWa2CDpgHTG6XoSG/npaJpLAHl1A=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=AaLYpho+1QnHxoFelHmFvcpxAeEfW5apGUmxGQibwCV8Oaffq2vMJvaZ7EQao5i2tT162wJHczFa5MScM81l7KDrVD+Mna/eOtEpbjxRkpt9icCaY+pgk4NpItR2GZWmnSvH5nk6NVRWhEgvlaLdTZBWN7QMRXsuo+zyGOl80mQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Ou4Sfg0q; arc=none smtp.client-ip=74.125.82.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ou4Sfg0q" Received: by mail-dy1-f170.google.com with SMTP id 5a478bee46e88-2c15849aa2cso6644582eec.0 for ; Tue, 21 Apr 2026 18:56:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776823009; x=1777427809; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=IyIQY/Q5seRRlJCaaQrUIlnTajmFOgTGoVqpOjVhF0g=; b=Ou4Sfg0qQ8cIP1duDN4fB4SL7/rABcVopCRzFIiyWpqsHVvCs4Nihf/buc/FI0MnHv EDAvCbfRzGFsLUGNqhyMRQJ/PWfCQcZfnRTDMFFITm675vRB/aapNvzRkjiEQRc2nn4b oKi61qwEqAyzJ/DazS9BWJw0voA4yHZkjjNfp1Lry7aKqQnUdqtWUGrBUnKk7OWk4GTS f6lUj6Xo4EzJcImOIZ+bjacIOrWov7dKJ3dDE4lafnrC5kjJzH1WXS1Cz2PN8jclwXQe KVfMFIVXVtsc7TiOoEYS0cviHC02PEYwYcsP64pVouu01WgVuk6RPQq2C6X8MLPTqRSD WS/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776823009; x=1777427809; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=IyIQY/Q5seRRlJCaaQrUIlnTajmFOgTGoVqpOjVhF0g=; b=gpFtDMfIKiVwFKwe4D9sbn84q0Xviqi+XOW6351vq1AwgMSwCvhAGqwEEkEEzgIOft /3XbkbXXoXW+CL4NIpDkf4SonlDEfwUMpehS3kni1xVq3EjG/gTNoIlERF+wT3odeblT 7BDoVrpzEBAJdWTcOJmwJUpzvx9+/9cEG52yQ81YViu2pCqKNgodc+QY0fpnbFivDilN Ef9PyAejTbpiNE/p62H7fvqYGQDl8LKciRu1xFN3IQrQz1ps6U+ZzLHp3PSlOyRUhJz6 YNKyDUw8OfCxfUT8lp4nz3+s0pdwbRrHiBUR+uriEzCMDrsVc11SO0sW1MMuCWcBqwhs SIXw== X-Gm-Message-State: AOJu0YxATF93kSmpEm8rsVeaidPN2/48DNzeJIo940k7K9TMhj9Ix71w uRsT8B2aHqXFo2HXLMuVADQbJ+eCymjnV4MVGC9apCWTnQqSsd5j/09i X-Gm-Gg: AeBDieudqcllSMfbb/koavAc9kjheenOuLGs6S1r7Z2DL2bWTH0iNteGlmmu+nl81Vz VpLIyuJJHxKEpGOW0OLbNEJ7Pwf2GNfRQagZB0FEiRWm9C0LTM5hjw3kOV2TbSu6m3kgWRV64DK eu6KgdUMyvDdeg+KGRvTrdoI+PIYJKuTJIdlOo+7frVyPlDRDs/3xkc+Qqwe1/w4jNNdAOVzP0z vHFss+n/liaeM3wiWeD1tpynLaXn3tYMG6i+eyfFiqugpKfbANy5K5slKLPQR2ro1El8txUPFJD SZk3agZQ9xIrysyKP7hwb9pq5WSLOzdFJj5xJfkFWkE0JC1UBEYrzqOwtgSDN1p2nk/XprX4goX 2xYvIvftYrMXle7BEBK4/TG//wU1kCF7NlOWkrN9Mc+XyRDJpfEkAPC3gAVAQ428k/Wf6F/INpM X2Tzeo7jXmprjMvdm/Tm8Saf8glS/3pSs4kKiN/TDanlk0c9JZzKg= X-Received: by 2002:a05:7300:fd09:b0:2da:d4b4:c85a with SMTP id 5a478bee46e88-2e464dad10cmr9508648eec.11.1776823008218; Tue, 21 Apr 2026 18:56:48 -0700 (PDT) Received: from [192.168.86.23] ([136.25.189.61]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2e53d2cfc1dsm20747864eec.22.2026.04.21.18.56.44 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 21 Apr 2026 18:56:46 -0700 (PDT) Message-ID: <3e6a83f8-0070-4dce-8b91-5e28204739f6@gmail.com> Date: Tue, 21 Apr 2026 18:56:44 -0700 Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH net-deletions] net: remove ax25 and amateur radio (hamradio) subsystem To: Jakub Kicinski , davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org, federico.vaga@vaga.pv.it, carlos.bilbao@kernel.org, avadhut.naik@amd.com, alexs@kernel.org, si.yanteng@linux.dev, dzm91@hust.edu.cn, 2023002089@link.tyut.edu.cn, tsbogend@alpha.franken.de, dsahern@kernel.org, jani.nikula@intel.com, mchehab+huawei@kernel.org, gregkh@linuxfoundation.org, jirislaby@kernel.org, tytso@mit.edu, herbert@gondor.apana.org.au, ebiggers@kernel.org, johannes.berg@intel.com, geert@linux-m68k.org, pablo@netfilter.org, tglx@kernel.org, mashiro.chen@mailbox.org, mingo@kernel.org, dqfext@gmail.com, jreuter@yaina.de, sdf@fomichev.me, pkshih@realtek.com, enelsonmoore@gmail.com, mkl@pengutronix.de, toke@toke.dk, kees@kernel.org, crossd@gmail.com, jlayton@kernel.org, wangliang74@huawei.com, aha310510@gmail.com, takamitz@amazon.co.jp, kuniyu@google.com, linux-doc@vger.kernel.org, linux-mips@vger.kernel.org References: <20260421021824.1293976-1-kuba@kernel.org> Content-Language: en-US From: Carlos Bilbao In-Reply-To: <20260421021824.1293976-1-kuba@kernel.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 4/20/26 19:18, Jakub Kicinski wrote: > Remove the amateur radio (AX.25, NET/ROM, ROSE) protocol implementation > and 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 influx > of the AI-generated bug reports we need to move it out of tree > to protect our sanity. > > The code is moved to an out-of-tree repo: > https://github.com/linux-netdev/mod-orphan > if 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 continues > to compile and work when the out-of-tree modules are loaded. > > Signed-off-by: Jakub Kicinski Acked-by: Carlos Bilbao > --- > CC: corbet@lwn.net > CC: skhan@linuxfoundation.org > CC: federico.vaga@vaga.pv.it > CC: carlos.bilbao@kernel.org > CC: avadhut.naik@amd.com > CC: alexs@kernel.org > CC: si.yanteng@linux.dev > CC: dzm91@hust.edu.cn > CC: 2023002089@link.tyut.edu.cn > CC: tsbogend@alpha.franken.de > CC: dsahern@kernel.org > CC: jani.nikula@intel.com > CC: mchehab+huawei@kernel.org > CC: gregkh@linuxfoundation.org > CC: jirislaby@kernel.org > CC: tytso@mit.edu > CC: herbert@gondor.apana.org.au > CC: ebiggers@kernel.org > CC: johannes.berg@intel.com > CC: geert@linux-m68k.org > CC: pablo@netfilter.org > CC: tglx@kernel.org > CC: mashiro.chen@mailbox.org > CC: mingo@kernel.org > CC: dqfext@gmail.com > CC: jreuter@yaina.de > CC: sdf@fomichev.me > CC: pkshih@realtek.com > CC: enelsonmoore@gmail.com > CC: mkl@pengutronix.de > CC: toke@toke.dk > CC: kees@kernel.org > CC: crossd@gmail.com > CC: jlayton@kernel.org > CC: wangliang74@huawei.com > CC: aha310510@gmail.com > CC: takamitz@amazon.co.jp > CC: kuniyu@google.com > CC: linux-doc@vger.kernel.org > CC: 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/MAINTAINERS > index 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 > -L: linux-hams@vger.kernel.org > -S: Maintained > -F: drivers/net/hamradio/6pack.c > - > 802.11 (including CFG80211/NL80211) > M: Johannes Berg > 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 > 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 > -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 > M: Kent Overstreet > @@ -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 > -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ć > 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 > 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 > 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 > 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 > -L: linux-hams@vger.kernel.org > -S: Maintained > -F: drivers/net/hamradio/yam* > -F: include/linux/yam.h > - > YAMA SECURITY MODULE > M: Kees Cook > 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 > -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: Orphan > diff --git a/Documentation/.renames.txt b/Documentation/.renames.txt > index 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-pn544 > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > index 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: , > - > - baycom_par= [HW,AX25] BayCom Parallel Port AX.25 Modem > - Format: , > - See header of drivers/net/hamradio/baycom_par.c. > - > - baycom_ser_fdx= [HW,AX25] > - BayCom Serial Port AX.25 Modem (Full Duplex Mode) > - Format: ,,[,] > - 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: ,, > - See header of drivers/net/hamradio/baycom_ser_hdx.c. > - > bdev_allow_write_mounted= > Format: > Control the ability to open a mounted block device > diff --git a/Documentation/networking/6pack.rst b/Documentation/networking/6pack.rst > deleted file mode 100644 > index 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! > - > -Andreas > diff --git a/Documentation/networking/ax25.rst b/Documentation/networking/ax25.rst > deleted file mode 100644 > index 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.rst > deleted file mode 100644 > index 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, > - > -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.org > diff --git a/Documentation/networking/device_drivers/hamradio/index.rst b/Documentation/networking/device_drivers/hamradio/index.rst > deleted file mode 100644 > index 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 > - z8530drv > diff --git a/Documentation/networking/device_drivers/hamradio/z8530drv.rst b/Documentation/networking/device_drivers/hamradio/z8530drv.rst > deleted file mode 100644 > index d2942760f167..000000000000 > --- a/Documentation/networking/device_drivers/hamradio/z8530drv.rst > +++ /dev/null > @@ -1,686 +0,0 @@ > -.. SPDX-License-Identifier: GPL-2.0 > -.. include:: > - > -========================================================= > -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 > - > -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 > - > -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 group " command. This will only work when > - you are using CSMA mode (parameter full = 0). > - > - The number must be 0 if you want no group restrictions, and > - can be computed as follows to create restricted groups: > - 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/jreuter > diff --git a/Documentation/networking/device_drivers/index.rst b/Documentation/networking/device_drivers/index.rst > index 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/index > diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst > index 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 > dctcp > diff --git a/Documentation/staging/magic-number.rst b/Documentation/staging/magic-number.rst > index 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.rst > index 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.rst > index 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.rst > index 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.rst > index 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/Kconfig > deleted file mode 100644 > index 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 . > - > - 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 > - > - and the AX25-HOWTO, available from > - . 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 > - > - 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 > - . > - > - 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 > - . > - > - 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 > - . > - > - 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 > - . > - > - 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/Kconfig > index 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/Kconfig > deleted file mode 100644 > index 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 > - and more specifically about AX.25 on Linux > - . > - > - 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 > - . You might also want to > - check out the file in the > - kernel source. More information about digital amateur radio in > - general is on the WWW at > - . > - > - 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 > - . 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 > - . You also might want to check out > - the file . More information > - about digital amateur radio in general is on the WWW at > - . > - > - 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 > - . You also might want to check out > - the file . More information > - about digital amateur radio in general is on the WWW at > - . > - > - 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" > - > -endmenu > diff --git a/drivers/net/Makefile b/drivers/net/Makefile > index 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/Makefile > deleted file mode 100644 > index 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 > -# > -# 20000806 Rewritten to use lists instead of if-statements. > -# Christoph Hellwig > -# > - > -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.o > diff --git a/net/Makefile b/net/Makefile > index 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/Makefile > deleted file mode 100644 > index 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.o > diff --git a/net/netrom/Makefile b/net/netrom/Makefile > deleted file mode 100644 > index 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.o > diff --git a/net/rose/Makefile b/net/rose/Makefile > deleted file mode 100644 > index 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.o > diff --git a/drivers/net/hamradio/z8530.h b/drivers/net/hamradio/z8530.h > deleted file mode 100644 > index 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.h > deleted file mode 100644 > index 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 > -#include > -#include > -#include > - > -#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.h > index 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; > #endif > diff --git a/include/linux/scc.h b/include/linux/scc.h > deleted file mode 100644 > index 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 > - > - > -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.h > deleted file mode 100644 > index 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.h > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > > -#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 > -#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 > > #endif > diff --git a/include/net/netrom.h b/include/net/netrom.h > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > - > -#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); > - > -#endif > diff --git a/include/net/rose.h b/include/net/rose.h > index 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 > -#include > -#include > -#include > - > -#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 > > #endif > diff --git a/include/uapi/linux/baycom.h b/include/uapi/linux/baycom.h > deleted file mode 100644 > index 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.h > deleted file mode 100644 > index 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.h > deleted file mode 100644 > index 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 > - > -#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]; > -}; > - > -#endif > diff --git a/include/uapi/linux/rose.h b/include/uapi/linux/rose.h > deleted file mode 100644 > index 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 > -#include > - > -#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; > -}; > - > -#endif > diff --git a/include/uapi/linux/scc.h b/include/uapi/linux/scc.h > deleted file mode 100644 > index 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 > - > -/* 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.c > deleted file mode 100644 > index 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 > - * Ralf Baechle DL5RB > - * > - * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by > - * > - * Laurence Culhane, > - * Fred N. van Kempen, > - */ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* 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 "); > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* --------------------------------------------------------------------- */ > - > -#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< -#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< -#define LPTDATA_TCK 0x02 > -#define LPTDATA_TMS (1< -#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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > - > -/* --------------------------------------------------------------------- */ > - > -#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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > -#include > - > -/* --------------------------------------------------------------------- */ > - > -#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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* --------------------------------------------------------------------- */ > - > -#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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > -#include > -#include > - > -#include > - > -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 "); > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > - > -/* --------------------------------------------------------------------- */ > - > -#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.c > deleted file mode 100644 > index 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 > - * Copyright (C) 2004, 05 Ralf Baechle DL5RB > - * Copyright (C) 2004, 05 Thomas Osterried DL9SAU > - */ > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > - > -#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 "); > -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.c > deleted file mode 100644 > index 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. > - > - . > - . > - . > - > - 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > - > -#include > -#include > -#include > - > -#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 "); > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > -#include > -#include > - > -#include > -#include > - > -#include > - > -/* --------------------------------------------------------------------- */ > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include /* For TIOCINQ/OUTQ */ > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > - > - > -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 "); > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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 [DAMA] > - * DL1BKE->DB0ACH > - * DL1BKE-7->DB0PRA-6 DB0ACH > - * DL1BKE->DB0ACH > - * > - * The Flexnet DAMA Master implementation apparently > - * insists on the "proper" AX.25 behaviour: > - * > - * DB0ACH->DL1BKE [DAMA] > - * DL1BKE->DB0ACH > - * DL1BKE->DB0ACH > - * DL1BKE-7->DB0PRA-6 DB0ACH > - * > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include /* For TIOCINQ/OUTQ */ > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > - > -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.c > index 51d70180e1cc..d409f606aec0 100644 > --- a/net/ipv4/arp.c > +++ b/net/ipv4/arp.c > @@ -109,7 +109,6 @@ > #include > #include > #include > -#include > #include > #include > > diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include /* For TIOCINQ/OUTQ */ > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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 "); > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include /* For the statistics structure. */ > -#include > -#include > - > -#include > - > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > - > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include /* For TIOCINQ/OUTQ */ > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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 "); > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > - > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > - > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* > - * 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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include /* For TIOCINQ/OUTQ */ > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -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.c > deleted file mode 100644 > index 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 > -#include > -#include > -#include > -#include > - > -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_defconfig > index 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=y > diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig > index 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=m > diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig > index 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=y > diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig > index 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=y > diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig > index 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=y > diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig > index 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=m > diff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfig > index 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=y > diff --git a/arch/mips/configs/xway_defconfig b/arch/mips/configs/xway_defconfig > index 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