* [PATCH net-deletions] net: remove unused ATM protocols and legacy ATM device drivers
@ 2026-04-21 2:19 Jakub Kicinski
2026-04-21 9:26 ` David Woodhouse
0 siblings, 1 reply; 5+ messages in thread
From: Jakub Kicinski @ 2026-04-21 2:19 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, Jakub Kicinski,
corbet, skhan, linux, tsbogend, maddy, mpe, npiggin, chleroy,
3chas3, razor, idosch, jani.nikula, mchehab+huawei, tytso,
herbert, geert, ebiggers, johannes.berg, jonathan.cameron, kees,
kuniyu, fourier.thomas, andriy.shevchenko, rdunlap, akpm,
linux-doc, linux-mips, linuxppc-dev, bridge
Remove the ATM protocol modules and PCI/SBUS ATM device drivers
that are no longer in active use.
The ATM core protocol stack, PPPoATM, and USB DSL modem drivers
(drivers/usb/atm/) are retained in-tree to maintain PPP over ATM
(PPPoA) support for DSL connections.
Removed ATM protocol modules:
- net/atm/clip.c - Classical IP over ATM (RFC 2225)
- net/atm/br2684.c - RFC 2684 bridged protocols
- net/atm/lec.c - LAN Emulation Client (LANE)
- net/atm/mpc.c, mpoa_caches.c, mpoa_proc.c - Multi-Protocol Over ATM
Removed PCI/SBUS ATM device drivers (drivers/atm/):
- adummy, atmtcp - software/testing ATM devices
- eni - Efficient Networks ENI155P (OC-3, ~1995)
- fore200e - FORE Systems 200E PCI/SBUS (OC-3, ~1999)
- he - ForeRunner HE (OC-3/OC-12, ~2000)
- idt77105 - IDT 77105 25 Mbps ATM PHY
- idt77252 - IDT 77252 NICStAR II (OC-3, ~2000)
- iphase - Interphase ATM PCI (OC-3/DS3/E3)
- lanai - Efficient Networks Speedstream 3010
- nicstar - IDT 77201 NICStAR (155/25 Mbps, ~1999)
- solos-pci - Traverse Technologies ADSL2+ PCI (defunct vendor)
- suni - PMC S/UNI SONET PHY library
Also clean up references in:
- net/bridge/ - remove ATM LANE hook (br_fdb_test_addr_hook,
br_fdb_test_addr)
- net/core/dev.c - remove br_fdb_test_addr_hook export
- defconfig files - remove ATM driver config options
The removed code is moved to an out-of-tree module package (mod-orphan).
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: corbet@lwn.net
CC: skhan@linuxfoundation.org
CC: linux@armlinux.org.uk
CC: tsbogend@alpha.franken.de
CC: maddy@linux.ibm.com
CC: mpe@ellerman.id.au
CC: npiggin@gmail.com
CC: chleroy@kernel.org
CC: 3chas3@gmail.com
CC: razor@blackwall.org
CC: idosch@nvidia.com
CC: jani.nikula@intel.com
CC: mchehab+huawei@kernel.org
CC: tytso@mit.edu
CC: herbert@gondor.apana.org.au
CC: geert@linux-m68k.org
CC: ebiggers@kernel.org
CC: johannes.berg@intel.com
CC: jonathan.cameron@huawei.com
CC: kees@kernel.org
CC: kuniyu@google.com
CC: fourier.thomas@gmail.com
CC: andriy.shevchenko@intel.com
CC: rdunlap@infradead.org
CC: akpm@linux-foundation.org
CC: linux-doc@vger.kernel.org
CC: linux-mips@vger.kernel.org
CC: linuxppc-dev@lists.ozlabs.org
CC: bridge@lists.linux.dev
---
MAINTAINERS | 3 +-
Documentation/.renames.txt | 2 -
.../device_drivers/atm/fore200e.rst | 66 -
.../networking/device_drivers/atm/index.rst | 2 -
.../networking/device_drivers/atm/iphase.rst | 193 -
drivers/atm/Kconfig | 325 --
drivers/net/Kconfig | 2 -
net/atm/Kconfig | 58 -
drivers/Makefile | 1 -
drivers/atm/Makefile | 32 -
net/atm/Makefile | 8 +-
drivers/atm/eni.h | 136 -
drivers/atm/fore200e.h | 973 -----
drivers/atm/he.h | 845 ----
drivers/atm/idt77105.h | 92 -
drivers/atm/idt77252.h | 816 ----
drivers/atm/idt77252_tables.h | 781 ----
drivers/atm/iphase.h | 1452 -------
drivers/atm/midway.h | 266 --
drivers/atm/nicstar.h | 759 ----
drivers/atm/suni.h | 242 --
drivers/atm/tonga.h | 21 -
drivers/atm/zeprom.h | 35 -
net/atm/lec.h | 155 -
net/atm/lec_arpc.h | 97 -
net/atm/mpc.h | 65 -
net/atm/mpoa_caches.h | 99 -
net/bridge/br_private.h | 4 -
drivers/atm/adummy.c | 202 -
drivers/atm/atmtcp.c | 513 ---
drivers/atm/eni.c | 2321 ----------
drivers/atm/fore200e.c | 3012 -------------
drivers/atm/he.c | 2861 -------------
drivers/atm/idt77105.c | 376 --
drivers/atm/idt77252.c | 3797 -----------------
drivers/atm/iphase.c | 3283 --------------
drivers/atm/lanai.c | 2603 -----------
drivers/atm/nicstar.c | 2759 ------------
drivers/atm/nicstarmac.c | 244 --
drivers/atm/solos-attrlist.c | 83 -
drivers/atm/solos-pci.c | 1496 -------
drivers/atm/suni.c | 391 --
net/atm/br2684.c | 872 ----
net/atm/clip.c | 960 -----
net/atm/lec.c | 2274 ----------
net/atm/mpc.c | 1538 -------
net/atm/mpoa_caches.c | 565 ---
net/atm/mpoa_proc.c | 307 --
net/bridge/br.c | 7 -
net/bridge/br_fdb.c | 29 -
net/core/dev.c | 7 -
arch/arm/configs/ixp4xx_defconfig | 5 -
arch/mips/configs/gpr_defconfig | 13 -
arch/mips/configs/mtx1_defconfig | 13 -
arch/powerpc/configs/ppc6xx_defconfig | 9 -
drivers/atm/.gitignore | 5 -
drivers/atm/nicstarmac.copyright | 61 -
57 files changed, 3 insertions(+), 38133 deletions(-)
delete mode 100644 Documentation/networking/device_drivers/atm/fore200e.rst
delete mode 100644 Documentation/networking/device_drivers/atm/iphase.rst
delete mode 100644 drivers/atm/Kconfig
delete mode 100644 drivers/atm/Makefile
delete mode 100644 drivers/atm/eni.h
delete mode 100644 drivers/atm/fore200e.h
delete mode 100644 drivers/atm/he.h
delete mode 100644 drivers/atm/idt77105.h
delete mode 100644 drivers/atm/idt77252.h
delete mode 100644 drivers/atm/idt77252_tables.h
delete mode 100644 drivers/atm/iphase.h
delete mode 100644 drivers/atm/midway.h
delete mode 100644 drivers/atm/nicstar.h
delete mode 100644 drivers/atm/suni.h
delete mode 100644 drivers/atm/tonga.h
delete mode 100644 drivers/atm/zeprom.h
delete mode 100644 net/atm/lec.h
delete mode 100644 net/atm/lec_arpc.h
delete mode 100644 net/atm/mpc.h
delete mode 100644 net/atm/mpoa_caches.h
delete mode 100644 drivers/atm/adummy.c
delete mode 100644 drivers/atm/atmtcp.c
delete mode 100644 drivers/atm/eni.c
delete mode 100644 drivers/atm/fore200e.c
delete mode 100644 drivers/atm/he.c
delete mode 100644 drivers/atm/idt77105.c
delete mode 100644 drivers/atm/idt77252.c
delete mode 100644 drivers/atm/iphase.c
delete mode 100644 drivers/atm/lanai.c
delete mode 100644 drivers/atm/nicstar.c
delete mode 100644 drivers/atm/nicstarmac.c
delete mode 100644 drivers/atm/solos-attrlist.c
delete mode 100644 drivers/atm/solos-pci.c
delete mode 100644 drivers/atm/suni.c
delete mode 100644 net/atm/br2684.c
delete mode 100644 net/atm/clip.c
delete mode 100644 net/atm/lec.c
delete mode 100644 net/atm/mpc.c
delete mode 100644 net/atm/mpoa_caches.c
delete mode 100644 net/atm/mpoa_proc.c
delete mode 100644 drivers/atm/.gitignore
delete mode 100644 drivers/atm/nicstarmac.copyright
diff --git a/MAINTAINERS b/MAINTAINERS
index 867ca44422d8..cfcf422dd40a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4150,11 +4150,12 @@ L: linux-atm-general@lists.sourceforge.net (moderated for non-subscribers)
L: netdev@vger.kernel.org
S: Maintained
W: http://linux-atm.sourceforge.net
-F: drivers/atm/
+F: drivers/usb/atm/
F: include/linux/atm*
F: include/linux/sonet.h
F: include/uapi/linux/atm*
F: include/uapi/linux/sonet.h
+F: net/atm/
ATMEL MACB ETHERNET DRIVER
M: Nicolas Ferre <nicolas.ferre@microchip.com>
diff --git a/Documentation/.renames.txt b/Documentation/.renames.txt
index e5f2f7447914..df4db1121995 100644
--- a/Documentation/.renames.txt
+++ b/Documentation/.renames.txt
@@ -835,14 +835,12 @@ networking/e100 networking/device_drivers/ethernet/intel/e100
networking/e1000 networking/device_drivers/ethernet/intel/e1000
networking/e1000e networking/device_drivers/ethernet/intel/e1000e
networking/fm10k networking/device_drivers/ethernet/intel/fm10k
-networking/fore200e networking/device_drivers/atm/fore200e
networking/hinic networking/device_drivers/ethernet/huawei/hinic
networking/i40e networking/device_drivers/ethernet/intel/i40e
networking/iavf networking/device_drivers/ethernet/intel/iavf
networking/ice networking/device_drivers/ethernet/intel/ice
networking/igb networking/device_drivers/ethernet/intel/igb
networking/igbvf networking/device_drivers/ethernet/intel/igbvf
-networking/iphase networking/device_drivers/atm/iphase
networking/ixgbe networking/device_drivers/ethernet/intel/ixgbe
networking/ixgbevf networking/device_drivers/ethernet/intel/ixgbevf
networking/netdev-FAQ process/maintainer-netdev
diff --git a/Documentation/networking/device_drivers/atm/fore200e.rst b/Documentation/networking/device_drivers/atm/fore200e.rst
deleted file mode 100644
index 55df9ec09ac8..000000000000
--- a/Documentation/networking/device_drivers/atm/fore200e.rst
+++ /dev/null
@@ -1,66 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=============================================
-FORE Systems PCA-200E/SBA-200E ATM NIC driver
-=============================================
-
-This driver adds support for the FORE Systems 200E-series ATM adapters
-to the Linux operating system. It is based on the earlier PCA-200E driver
-written by Uwe Dannowski.
-
-The driver simultaneously supports PCA-200E and SBA-200E adapters on
-i386, alpha (untested), powerpc, sparc and sparc64 archs.
-
-The intent is to enable the use of different models of FORE adapters at the
-same time, by hosts that have several bus interfaces (such as PCI+SBUS,
-or PCI+EISA).
-
-Only PCI and SBUS devices are currently supported by the driver, but support
-for other bus interfaces such as EISA should not be too hard to add.
-
-
-Firmware Copyright Notice
--------------------------
-
-Please read the fore200e_firmware_copyright file present
-in the linux/drivers/atm directory for details and restrictions.
-
-
-Firmware Updates
-----------------
-
-The FORE Systems 200E-series driver is shipped with firmware data being
-uploaded to the ATM adapters at system boot time or at module loading time.
-The supplied firmware images should work with all adapters.
-
-However, if you encounter problems (the firmware doesn't start or the driver
-is unable to read the PROM data), you may consider trying another firmware
-version. Alternative binary firmware images can be found somewhere on the
-ForeThought CD-ROM supplied with your adapter by FORE Systems.
-
-You can also get the latest firmware images from FORE Systems at
-https://en.wikipedia.org/wiki/FORE_Systems. Register TACTics Online and go to
-the 'software updates' pages. The firmware binaries are part of
-the various ForeThought software distributions.
-
-Notice that different versions of the PCA-200E firmware exist, depending
-on the endianness of the host architecture. The driver is shipped with
-both little and big endian PCA firmware images.
-
-Name and location of the new firmware images can be set at kernel
-configuration time:
-
-1. Copy the new firmware binary files (with .bin, .bin1 or .bin2 suffix)
- to some directory, such as linux/drivers/atm.
-
-2. Reconfigure your kernel to set the new firmware name and location.
- Expected pathnames are absolute or relative to the drivers/atm directory.
-
-3. Rebuild and re-install your kernel or your module.
-
-
-Feedback
---------
-
-Feedback is welcome. Please send success stories/bug reports/
-patches/improvement/comments/flames to <lizzi@cnam.fr>.
diff --git a/Documentation/networking/device_drivers/atm/index.rst b/Documentation/networking/device_drivers/atm/index.rst
index 724552ca0be4..9392c86f48bc 100644
--- a/Documentation/networking/device_drivers/atm/index.rst
+++ b/Documentation/networking/device_drivers/atm/index.rst
@@ -9,5 +9,3 @@ Asynchronous Transfer Mode (ATM) Device Drivers
:maxdepth: 2
cxacru
- fore200e
- iphase
diff --git a/Documentation/networking/device_drivers/atm/iphase.rst b/Documentation/networking/device_drivers/atm/iphase.rst
deleted file mode 100644
index 388c7101e2cb..000000000000
--- a/Documentation/networking/device_drivers/atm/iphase.rst
+++ /dev/null
@@ -1,193 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==================================
-ATM (i)Chip IA Linux Driver Source
-==================================
-
- READ ME FIRST
-
---------------------------------------------------------------------------------
-
- Read This Before You Begin!
-
---------------------------------------------------------------------------------
-
-Description
-===========
-
-This is the README file for the Interphase PCI ATM (i)Chip IA Linux driver
-source release.
-
-The features and limitations of this driver are as follows:
-
- - A single VPI (VPI value of 0) is supported.
- - Supports 4K VCs for the server board (with 512K control memory) and 1K
- VCs for the client board (with 128K control memory).
- - UBR, ABR and CBR service categories are supported.
- - Only AAL5 is supported.
- - Supports setting of PCR on the VCs.
- - Multiple adapters in a system are supported.
- - All variants of Interphase ATM PCI (i)Chip adapter cards are supported,
- including x575 (OC3, control memory 128K , 512K and packet memory 128K,
- 512K and 1M), x525 (UTP25) and x531 (DS3 and E3). See
- http://www.iphase.com/
- for details.
- - Only x86 platforms are supported.
- - SMP is supported.
-
-
-Before You Start
-================
-
-
-Installation
-------------
-
-1. Installing the adapters in the system
-
- To install the ATM adapters in the system, follow the steps below.
-
- a. Login as root.
- b. Shut down the system and power off the system.
- c. Install one or more ATM adapters in the system.
- d. Connect each adapter to a port on an ATM switch. The green 'Link'
- LED on the front panel of the adapter will be on if the adapter is
- connected to the switch properly when the system is powered up.
- e. Power on and boot the system.
-
-2. [ Removed ]
-
-3. Rebuild kernel with ABR support
-
- [ a. and b. removed ]
-
- c. Reconfigure the kernel, choose the Interphase ia driver through "make
- menuconfig" or "make xconfig".
- d. Rebuild the kernel, loadable modules and the atm tools.
- e. Install the new built kernel and modules and reboot.
-
-4. Load the adapter hardware driver (ia driver) if it is built as a module
-
- a. Login as root.
- b. Change directory to /lib/modules/<kernel-version>/atm.
- c. Run "insmod suni.o;insmod iphase.o"
- The yellow 'status' LED on the front panel of the adapter will blink
- while the driver is loaded in the system.
- d. To verify that the 'ia' driver is loaded successfully, run the
- following command::
-
- cat /proc/atm/devices
-
- If the driver is loaded successfully, the output of the command will
- be similar to the following lines::
-
- Itf Type ESI/"MAC"addr AAL(TX,err,RX,err,drop) ...
- 0 ia xxxxxxxxx 0 ( 0 0 0 0 0 ) 5 ( 0 0 0 0 0 )
-
- You can also check the system log file /var/log/messages for messages
- related to the ATM driver.
-
-5. Ia Driver Configuration
-
-5.1 Configuration of adapter buffers
- The (i)Chip boards have 3 different packet RAM size variants: 128K, 512K and
- 1M. The RAM size decides the number of buffers and buffer size. The default
- size and number of buffers are set as following:
-
- ========= ======= ====== ====== ====== ====== ======
- Total Rx RAM Tx RAM Rx Buf Tx Buf Rx buf Tx buf
- RAM size size size size size cnt cnt
- ========= ======= ====== ====== ====== ====== ======
- 128K 64K 64K 10K 10K 6 6
- 512K 256K 256K 10K 10K 25 25
- 1M 512K 512K 10K 10K 51 51
- ========= ======= ====== ====== ====== ====== ======
-
- These setting should work well in most environments, but can be
- changed by typing the following command::
-
- insmod <IA_DIR>/ia.o IA_RX_BUF=<RX_CNT> IA_RX_BUF_SZ=<RX_SIZE> \
- IA_TX_BUF=<TX_CNT> IA_TX_BUF_SZ=<TX_SIZE>
-
- Where:
-
- - RX_CNT = number of receive buffers in the range (1-128)
- - RX_SIZE = size of receive buffers in the range (48-64K)
- - TX_CNT = number of transmit buffers in the range (1-128)
- - TX_SIZE = size of transmit buffers in the range (48-64K)
-
- 1. Transmit and receive buffer size must be a multiple of 4.
- 2. Care should be taken so that the memory required for the
- transmit and receive buffers is less than or equal to the
- total adapter packet memory.
-
-5.2 Turn on ia debug trace
-
- When the ia driver is built with the CONFIG_ATM_IA_DEBUG flag, the driver
- can provide more debug trace if needed. There is a bit mask variable,
- IADebugFlag, which controls the output of the traces. You can find the bit
- map of the IADebugFlag in iphase.h.
- The debug trace can be turn on through the insmod command line option, for
- example, "insmod iphase.o IADebugFlag=0xffffffff" can turn on all the debug
- traces together with loading the driver.
-
-6. Ia Driver Test Using ttcp_atm and PVC
-
- For the PVC setup, the test machines can either be connected back-to-back or
- through a switch. If connected through the switch, the switch must be
- configured for the PVC(s).
-
- a. For UBR test:
-
- At the test machine intended to receive data, type::
-
- ttcp_atm -r -a -s 0.100
-
- At the other test machine, type::
-
- ttcp_atm -t -a -s 0.100 -n 10000
-
- Run "ttcp_atm -h" to display more options of the ttcp_atm tool.
- b. For ABR test:
-
- It is the same as the UBR testing, but with an extra command option::
-
- -Pabr:max_pcr=<xxx>
-
- where:
-
- xxx = the maximum peak cell rate, from 170 - 353207.
-
- This option must be set on both the machines.
-
- c. For CBR test:
-
- It is the same as the UBR testing, but with an extra command option::
-
- -Pcbr:max_pcr=<xxx>
-
- where:
-
- xxx = the maximum peak cell rate, from 170 - 353207.
-
- This option may only be set on the transmit machine.
-
-
-Outstanding Issues
-==================
-
-
-
-Contact Information
--------------------
-
-::
-
- Customer Support:
- United States: Telephone: (214) 654-5555
- Fax: (214) 654-5500
- E-Mail: intouch@iphase.com
- Europe: Telephone: 33 (0)1 41 15 44 00
- Fax: 33 (0)1 41 15 12 13
- World Wide Web: http://www.iphase.com
- Anonymous FTP: ftp.iphase.com
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
deleted file mode 100644
index 63cdb46a3439..000000000000
--- a/drivers/atm/Kconfig
+++ /dev/null
@@ -1,325 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# ATM device configuration
-#
-
-menuconfig ATM_DRIVERS
- bool "ATM drivers"
- depends on NETDEVICES && ATM
- default y
- help
- Say Y here to get to see options for Asynchronous Transfer Mode
- device drivers. This option alone does not add any kernel code.
-
- If you say N, all options in this submenu will be skipped and disabled.
-
-if ATM_DRIVERS && NETDEVICES && ATM
-
-config ATM_DUMMY
- tristate "Dummy ATM driver"
- help
- Dummy ATM driver. Useful for proxy signalling, testing,
- and development. If unsure, say N.
-
-config ATM_TCP
- tristate "ATM over TCP"
- depends on INET
- help
- ATM over TCP driver. Useful mainly for development and for
- experiments. If unsure, say N.
-
-config ATM_LANAI
- tristate "Efficient Networks Speedstream 3010"
- depends on PCI && ATM
- help
- Supports ATM cards based on the Efficient Networks "Lanai"
- chipset such as the Speedstream 3010 and the ENI-25p. The
- Speedstream 3060 is currently not supported since we don't
- have the code to drive the on-board Alcatel DSL chipset (yet).
-
-config ATM_ENI
- tristate "Efficient Networks ENI155P"
- depends on PCI
- help
- Driver for the Efficient Networks ENI155p series and SMC ATM
- Power155 155 Mbps ATM adapters. Both, the versions with 512KB and
- 2MB on-board RAM (Efficient calls them "C" and "S", respectively),
- and the FPGA and the ASIC Tonga versions of the board are supported.
- The driver works with MMF (-MF or ...F) and UTP-5 (-U5 or ...D)
- adapters.
-
- To compile this driver as a module, choose M here: the module will
- be called eni.
-
-config ATM_ENI_DEBUG
- bool "Enable extended debugging"
- depends on ATM_ENI
- help
- Extended debugging records various events and displays that list
- when an inconsistency is detected. This mechanism is faster than
- generally using printks, but still has some impact on performance.
- Note that extended debugging may create certain race conditions
- itself. Enable this ONLY if you suspect problems with the driver.
-
-config ATM_ENI_TUNE_BURST
- bool "Fine-tune burst settings"
- depends on ATM_ENI
- help
- In order to obtain good throughput, the ENI NIC can transfer
- multiple words of data per PCI bus access cycle. Such a multi-word
- transfer is called a burst.
-
- The default settings for the burst sizes are suitable for most PCI
- chipsets. However, in some cases, large bursts may overrun buffers
- in the PCI chipset and cause data corruption. In such cases, large
- bursts must be disabled and only (slower) small bursts can be used.
- The burst sizes can be set independently in the send (TX) and
- receive (RX) direction.
-
- Note that enabling many different burst sizes in the same direction
- may increase the cost of setting up a transfer such that the
- resulting throughput is lower than when using only the largest
- available burst size.
-
- Also, sometimes larger bursts lead to lower throughput, e.g. on an
- Intel 440FX board, a drop from 135 Mbps to 103 Mbps was observed
- when going from 8W to 16W bursts.
-
-config ATM_ENI_BURST_TX_16W
- bool "Enable 16W TX bursts (discouraged)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst sixteen words at once in the send direction. This may work
- with recent PCI chipsets, but is known to fail with older chipsets.
-
-config ATM_ENI_BURST_TX_8W
- bool "Enable 8W TX bursts (recommended)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst eight words at once in the send direction. This is the default
- setting.
-
-config ATM_ENI_BURST_TX_4W
- bool "Enable 4W TX bursts (optional)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst four words at once in the send direction. You may want to try
- this if you have disabled 8W bursts. Enabling 4W if 8W is also set
- may or may not improve throughput.
-
-config ATM_ENI_BURST_TX_2W
- bool "Enable 2W TX bursts (optional)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst two words at once in the send direction. You may want to try
- this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or 8W
- are also set may or may not improve throughput.
-
-config ATM_ENI_BURST_RX_16W
- bool "Enable 16W RX bursts (discouraged)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst sixteen words at once in the receive direction. This may work
- with recent PCI chipsets, but is known to fail with older chipsets.
-
-config ATM_ENI_BURST_RX_8W
- bool "Enable 8W RX bursts (discouraged)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst eight words at once in the receive direction. This may work
- with recent PCI chipsets, but is known to fail with older chipsets,
- such as the Intel Neptune series.
-
-config ATM_ENI_BURST_RX_4W
- bool "Enable 4W RX bursts (recommended)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst four words at once in the receive direction. This is the
- default setting. Enabling 4W if 8W is also set may or may not
- improve throughput.
-
-config ATM_ENI_BURST_RX_2W
- bool "Enable 2W RX bursts (optional)"
- depends on ATM_ENI_TUNE_BURST
- help
- Burst two words at once in the receive direction. You may want to
- try this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or
- 8W are also set may or may not improve throughput.
-
-config ATM_NICSTAR
- tristate "IDT 77201 (NICStAR) (ForeRunnerLE)"
- depends on PCI
- help
- The NICStAR chipset family is used in a large number of ATM NICs for
- 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE
- series. Say Y if you have one of those.
-
- To compile this driver as a module, choose M here: the module will
- be called nicstar.
-
-config ATM_NICSTAR_USE_SUNI
- bool "Use suni PHY driver (155Mbps)"
- depends on ATM_NICSTAR
- help
- Support for the S-UNI and compatible PHYsical layer chips. These are
- found in most 155Mbps NICStAR based ATM cards, namely in the
- ForeRunner LE155 cards. This driver provides detection of cable~
- removal and reinsertion and provides some statistics. This driver
- doesn't have removal capability when compiled as a module, so if you
- need that capability don't include S-UNI support (it's not needed to
- make the card work).
-
-config ATM_NICSTAR_USE_IDT77105
- bool "Use IDT77105 PHY driver (25Mbps)"
- depends on ATM_NICSTAR
- help
- Support for the PHYsical layer chip in ForeRunner LE25 cards. In
- addition to cable removal/reinsertion detection, this driver allows
- you to control the loopback mode of the chip via a dedicated IOCTL.
- This driver is required for proper handling of temporary carrier
- loss, so if you have a 25Mbps NICStAR based ATM card you must say Y.
-
-config ATM_IDT77252
- tristate "IDT 77252 (NICStAR II)"
- depends on PCI
- help
- Driver for the IDT 77252 ATM PCI chips.
-
- To compile this driver as a module, choose M here: the module will
- be called idt77252.
-
-config ATM_IDT77252_DEBUG
- bool "Enable debugging messages"
- depends on ATM_IDT77252
- help
- Somewhat useful debugging messages are available. The choice of
- messages is controlled by a bitmap. This may be specified as a
- module argument. See the file <file:drivers/atm/idt77252.h> for
- the meanings of the bits in the mask.
-
- When active, these messages can have a significant impact on the
- speed of the driver, and the size of your syslog files! When
- inactive, they will have only a modest impact on performance.
-
-config ATM_IDT77252_RCV_ALL
- bool "Receive ALL cells in raw queue"
- depends on ATM_IDT77252
- help
- Enable receiving of all cells on the ATM link, that do not match
- an open connection in the raw cell queue of the driver. Useful
- for debugging or special applications only, so the safe answer is N.
-
-config ATM_IDT77252_USE_SUNI
- bool
- depends on ATM_IDT77252
- default y
-
-config ATM_IA
- tristate "Interphase ATM PCI x575/x525/x531"
- depends on PCI
- help
- This is a driver for the Interphase (i)ChipSAR adapter cards
- which include a variety of variants in term of the size of the
- control memory (128K-1KVC, 512K-4KVC), the size of the packet
- memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3,
- UTP155, UTP25, DS3 and E3). Go to:
- <http://www.iphase.com/>
- for more info about the cards. Say Y (or M to compile as a module
- named iphase) here if you have one of these cards.
-
- See the file
- <file:Documentation/networking/device_drivers/atm/iphase.rst>
- for further details.
-
-config ATM_IA_DEBUG
- bool "Enable debugging messages"
- depends on ATM_IA
- help
- Somewhat useful debugging messages are available. The choice of
- messages is controlled by a bitmap. This may be specified as a
- module argument (kernel command line argument as well?), changed
- dynamically using an ioctl (Get the debug utility, iadbg, from
- <ftp://ftp.iphase.com/pub/atm/pci/>).
-
- See the file <file:drivers/atm/iphase.h> for the meanings of the
- bits in the mask.
-
- When active, these messages can have a significant impact on the
- speed of the driver, and the size of your syslog files! When
- inactive, they will have only a modest impact on performance.
-
-config ATM_FORE200E
- tristate "FORE Systems 200E-series"
- depends on (PCI || SBUS)
- select FW_LOADER
- help
- This is a driver for the FORE Systems 200E-series ATM adapter
- cards. It simultaneously supports PCA-200E and SBA-200E models
- on PCI and SBUS hosts. Say Y (or M to compile as a module
- named fore_200e) here if you have one of these ATM adapters.
-
- See the file
- <file:Documentation/networking/device_drivers/atm/fore200e.rst> for
- further details.
-
-config ATM_FORE200E_USE_TASKLET
- bool "Defer interrupt work to a tasklet"
- depends on ATM_FORE200E
- default n
- help
- This defers work to be done by the interrupt handler to a
- tasklet instead of handling everything at interrupt time. This
- may improve the responsive of the host.
-
-config ATM_FORE200E_TX_RETRY
- int "Maximum number of tx retries"
- depends on ATM_FORE200E
- default "16"
- help
- Specifies the number of times the driver attempts to transmit
- a message before giving up, if the transmit queue of the ATM card
- is transiently saturated.
-
- Saturation of the transmit queue may occur only under extreme
- conditions, e.g. when a fast host continuously submits very small
- frames (<64 bytes) or raw AAL0 cells (48 bytes) to the ATM adapter.
-
- Note that under common conditions, it is unlikely that you encounter
- a saturation of the transmit queue, so the retry mechanism never
- comes into play.
-
-config ATM_FORE200E_DEBUG
- int "Debugging level (0-3)"
- depends on ATM_FORE200E
- default "0"
- help
- Specifies the level of debugging messages issued by the driver.
- The verbosity of the driver increases with the value of this
- parameter.
-
- When active, these messages can have a significant impact on
- the performances of the driver, and the size of your syslog files!
- Keep the debugging level to 0 during normal operations.
-
-config ATM_HE
- tristate "ForeRunner HE Series"
- depends on PCI
- help
- This is a driver for the Marconi ForeRunner HE-series ATM adapter
- cards. It simultaneously supports the 155 and 622 versions.
-
-config ATM_HE_USE_SUNI
- bool "Use S/UNI PHY driver"
- depends on ATM_HE
- help
- Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner
- HE cards. This driver provides carrier detection some statistics.
-
-config ATM_SOLOS
- tristate "Solos ADSL2+ PCI Multiport card driver"
- depends on PCI
- select FW_LOADER
- help
- Support for the Solos multiport ADSL2+ card.
-
-endif # ATM
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8ec98f6dfef9..19cc389028ba 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -501,8 +501,6 @@ config SUNGEM_PHY
source "drivers/net/arcnet/Kconfig"
-source "drivers/atm/Kconfig"
-
source "drivers/net/dsa/Kconfig"
source "drivers/net/ethernet/Kconfig"
diff --git a/net/atm/Kconfig b/net/atm/Kconfig
index 77343d57ff2a..9a2f376d3d2b 100644
--- a/net/atm/Kconfig
+++ b/net/atm/Kconfig
@@ -14,61 +14,3 @@ config ATM
In order to participate in an ATM network, your Linux box needs an
ATM networking card. If you have that, say Y here and to the driver
of your ATM card below.
-
- Note that you need a set of user-space programs to actually make use
- of ATM. See the file <file:Documentation/networking/atm.rst> for
- further details.
-
-config ATM_CLIP
- tristate "Classical IP over ATM"
- depends on ATM && INET
- help
- Classical IP over ATM for PVCs and SVCs, supporting InARP and
- ATMARP. If you want to communication with other IP hosts on your ATM
- network, you will typically either say Y here or to "LAN Emulation
- (LANE)" below.
-
-config ATM_CLIP_NO_ICMP
- bool "Do NOT send ICMP if no neighbour"
- depends on ATM_CLIP
- help
- Normally, an "ICMP host unreachable" message is sent if a neighbour
- cannot be reached because there is no VC to it in the kernel's
- ATMARP table. This may cause problems when ATMARP table entries are
- briefly removed during revalidation. If you say Y here, packets to
- such neighbours are silently discarded instead.
-
-config ATM_LANE
- tristate "LAN Emulation (LANE) support"
- depends on ATM
- help
- LAN Emulation emulates services of existing LANs across an ATM
- network. Besides operating as a normal ATM end station client, Linux
- LANE client can also act as an proxy client bridging packets between
- ELAN and Ethernet segments. You need LANE if you want to try MPOA.
-
-config ATM_MPOA
- tristate "Multi-Protocol Over ATM (MPOA) support"
- depends on ATM && INET && ATM_LANE!=n
- help
- Multi-Protocol Over ATM allows ATM edge devices such as routers,
- bridges and ATM attached hosts establish direct ATM VCs across
- subnetwork boundaries. These shortcut connections bypass routers
- enhancing overall network performance.
-
-config ATM_BR2684
- tristate "RFC1483/2684 Bridged protocols"
- depends on ATM && INET
- help
- ATM PVCs can carry ethernet PDUs according to RFC2684 (formerly 1483)
- This device will act like an ethernet from the kernels point of view,
- with the traffic being carried by ATM PVCs (currently 1 PVC/device).
- This is sometimes used over DSL lines. If in doubt, say N.
-
-config ATM_BR2684_IPFILTER
- bool "Per-VC IP filter kludge"
- depends on ATM_BR2684
- help
- This is an experimental mechanism for users who need to terminate a
- large number of IP-only vcc's. Do not enable this unless you are sure
- you know what you are doing.
diff --git a/drivers/Makefile b/drivers/Makefile
index 0841ea851847..cc5fdb1ef79f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -90,7 +90,6 @@ obj-$(CONFIG_SPMI) += spmi/
obj-$(CONFIG_HSI) += hsi/
obj-$(CONFIG_SLIMBUS) += slimbus/
obj-y += net/
-obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
obj-y += firewire/
obj-$(CONFIG_UIO) += uio/
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
deleted file mode 100644
index c9eade92019b..000000000000
--- a/drivers/atm/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the Linux network (ATM) device drivers.
-#
-
-fore_200e-y := fore200e.o
-
-obj-$(CONFIG_ATM_NICSTAR) += nicstar.o
-obj-$(CONFIG_ATM_IA) += iphase.o suni.o
-obj-$(CONFIG_ATM_FORE200E) += fore_200e.o
-obj-$(CONFIG_ATM_ENI) += eni.o suni.o
-obj-$(CONFIG_ATM_IDT77252) += idt77252.o
-obj-$(CONFIG_ATM_SOLOS) += solos-pci.o
-
-ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
- obj-$(CONFIG_ATM_NICSTAR) += suni.o
-endif
-ifeq ($(CONFIG_ATM_NICSTAR_USE_IDT77105),y)
- obj-$(CONFIG_ATM_NICSTAR) += idt77105.o
-endif
-ifeq ($(CONFIG_ATM_IDT77252_USE_SUNI),y)
- obj-$(CONFIG_ATM_IDT77252) += suni.o
-endif
-
-obj-$(CONFIG_ATM_DUMMY) += adummy.o
-obj-$(CONFIG_ATM_TCP) += atmtcp.o
-obj-$(CONFIG_ATM_LANAI) += lanai.o
-
-obj-$(CONFIG_ATM_HE) += he.o
-ifeq ($(CONFIG_ATM_HE_USE_SUNI),y)
- obj-$(CONFIG_ATM_HE) += suni.o
-endif
diff --git a/net/atm/Makefile b/net/atm/Makefile
index bfec0f2d83b5..226eecbe3825 100644
--- a/net/atm/Makefile
+++ b/net/atm/Makefile
@@ -4,13 +4,7 @@
#
atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
-mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o
-
-obj-$(CONFIG_ATM) += atm.o
-obj-$(CONFIG_ATM_CLIP) += clip.o
-obj-$(CONFIG_ATM_BR2684) += br2684.o
atm-$(CONFIG_PROC_FS) += proc.o
-obj-$(CONFIG_ATM_LANE) += lec.o
-obj-$(CONFIG_ATM_MPOA) += mpoa.o
+obj-$(CONFIG_ATM) += atm.o
obj-$(CONFIG_PPPOATM) += pppoatm.o
diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h
deleted file mode 100644
index de1ed802cbf8..000000000000
--- a/drivers/atm/eni.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef DRIVER_ATM_ENI_H
-#define DRIVER_ATM_ENI_H
-
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/interrupt.h>
-#include <linux/sonet.h>
-#include <linux/skbuff.h>
-#include <linux/time.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-
-#include "midway.h"
-
-
-#define DEV_LABEL "eni"
-
-#define UBR_BUFFER (128*1024) /* UBR buffer size */
-
-#define RX_DMA_BUF 8 /* burst and skip a few things */
-#define TX_DMA_BUF 100 /* should be enough for 64 kB */
-
-#define DEFAULT_RX_MULT 300 /* max_sdu*3 */
-#define DEFAULT_TX_MULT 300 /* max_sdu*3 */
-
-#define ENI_ZEROES_SIZE 4 /* need that many DMA-able zero bytes */
-
-
-struct eni_free {
- void __iomem *start; /* counting in bytes */
- int order;
-};
-
-struct eni_tx {
- void __iomem *send; /* base, 0 if unused */
- int prescaler; /* shaping prescaler */
- int resolution; /* shaping divider */
- unsigned long tx_pos; /* current TX write position */
- unsigned long words; /* size of TX queue */
- int index; /* TX channel number */
- int reserved; /* reserved peak cell rate */
- int shaping; /* shaped peak cell rate */
- struct sk_buff_head backlog; /* queue of waiting TX buffers */
-};
-
-struct eni_vcc {
- int (*rx)(struct atm_vcc *vcc); /* RX function, NULL if none */
- void __iomem *recv; /* receive buffer */
- unsigned long words; /* its size in words */
- unsigned long descr; /* next descriptor (RX) */
- unsigned long rx_pos; /* current RX descriptor pos */
- struct eni_tx *tx; /* TXer, NULL if none */
- int rxing; /* number of pending PDUs */
- int servicing; /* number of waiting VCs (0 or 1) */
- int txing; /* number of pending TX bytes */
- ktime_t timestamp; /* for RX timing */
- struct atm_vcc *next; /* next pending RX */
- struct sk_buff *last; /* last PDU being DMAed (used to carry
- discard information) */
-};
-
-struct eni_dev {
- /*-------------------------------- spinlock */
- spinlock_t lock; /* sync with interrupt */
- struct tasklet_struct task; /* tasklet for interrupt work */
- u32 events; /* pending events */
- /*-------------------------------- base pointers into Midway address
- space */
- void __iomem *ioaddr;
- void __iomem *phy; /* PHY interface chip registers */
- void __iomem *reg; /* register base */
- void __iomem *ram; /* RAM base */
- void __iomem *vci; /* VCI table */
- void __iomem *rx_dma; /* RX DMA queue */
- void __iomem *tx_dma; /* TX DMA queue */
- void __iomem *service; /* service list */
- /*-------------------------------- TX part */
- struct eni_tx tx[NR_CHAN]; /* TX channels */
- struct eni_tx *ubr; /* UBR channel */
- struct sk_buff_head tx_queue; /* PDUs currently being TX DMAed*/
- wait_queue_head_t tx_wait; /* for close */
- int tx_bw; /* remaining bandwidth */
- u32 dma[TX_DMA_BUF*2]; /* DMA request scratch area */
- struct eni_zero { /* aligned "magic" zeroes */
- u32 *addr;
- dma_addr_t dma;
- } zero;
- int tx_mult; /* buffer size multiplier (percent) */
- /*-------------------------------- RX part */
- u32 serv_read; /* host service read index */
- struct atm_vcc *fast,*last_fast;/* queues of VCCs with pending PDUs */
- struct atm_vcc *slow,*last_slow;
- struct atm_vcc **rx_map; /* for fast lookups */
- struct sk_buff_head rx_queue; /* PDUs currently being RX-DMAed */
- wait_queue_head_t rx_wait; /* for close */
- int rx_mult; /* buffer size multiplier (percent) */
- /*-------------------------------- statistics */
- unsigned long lost; /* number of lost cells (RX) */
- /*-------------------------------- memory management */
- unsigned long base_diff; /* virtual-real base address */
- int free_len; /* free list length */
- struct eni_free *free_list; /* free list */
- int free_list_size; /* maximum size of free list */
- /*-------------------------------- ENI links */
- struct atm_dev *more; /* other ENI devices */
- /*-------------------------------- general information */
- int mem; /* RAM on board (in bytes) */
- int asic; /* PCI interface type, 0 for FPGA */
- unsigned int irq; /* IRQ */
- struct pci_dev *pci_dev; /* PCI stuff */
-};
-
-
-#define ENI_DEV(d) ((struct eni_dev *) (d)->dev_data)
-#define ENI_VCC(d) ((struct eni_vcc *) (d)->dev_data)
-
-
-struct eni_skb_prv {
- struct atm_skb_data _; /* reserved */
- unsigned long pos; /* position of next descriptor */
- int size; /* PDU size in reassembly buffer */
- dma_addr_t paddr; /* DMA handle */
-};
-
-#define ENI_PRV_SIZE(skb) (((struct eni_skb_prv *) (skb)->cb)->size)
-#define ENI_PRV_POS(skb) (((struct eni_skb_prv *) (skb)->cb)->pos)
-#define ENI_PRV_PADDR(skb) (((struct eni_skb_prv *) (skb)->cb)->paddr)
-
-#endif
diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h
deleted file mode 100644
index 5d95fe9fd836..000000000000
--- a/drivers/atm/fore200e.h
+++ /dev/null
@@ -1,973 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _FORE200E_H
-#define _FORE200E_H
-
-#ifdef __KERNEL__
-
-/* rx buffer sizes */
-
-#define SMALL_BUFFER_SIZE 384 /* size of small buffers (multiple of 48 (PCA) and 64 (SBA) bytes) */
-#define LARGE_BUFFER_SIZE 4032 /* size of large buffers (multiple of 48 (PCA) and 64 (SBA) bytes) */
-
-
-#define RBD_BLK_SIZE 32 /* nbr of supplied rx buffers per rbd */
-
-
-#define MAX_PDU_SIZE 65535 /* maximum PDU size supported by AALs */
-
-
-#define BUFFER_S1_SIZE SMALL_BUFFER_SIZE /* size of small buffers, scheme 1 */
-#define BUFFER_L1_SIZE LARGE_BUFFER_SIZE /* size of large buffers, scheme 1 */
-
-#define BUFFER_S2_SIZE SMALL_BUFFER_SIZE /* size of small buffers, scheme 2 */
-#define BUFFER_L2_SIZE LARGE_BUFFER_SIZE /* size of large buffers, scheme 2 */
-
-#define BUFFER_S1_NBR (RBD_BLK_SIZE * 6)
-#define BUFFER_L1_NBR (RBD_BLK_SIZE * 4)
-
-#define BUFFER_S2_NBR (RBD_BLK_SIZE * 6)
-#define BUFFER_L2_NBR (RBD_BLK_SIZE * 4)
-
-
-#define QUEUE_SIZE_CMD 16 /* command queue capacity */
-#define QUEUE_SIZE_RX 64 /* receive queue capacity */
-#define QUEUE_SIZE_TX 256 /* transmit queue capacity */
-#define QUEUE_SIZE_BS 32 /* buffer supply queue capacity */
-
-#define FORE200E_VPI_BITS 0
-#define FORE200E_VCI_BITS 10
-#define NBR_CONNECT (1 << (FORE200E_VPI_BITS + FORE200E_VCI_BITS)) /* number of connections */
-
-
-#define TSD_FIXED 2
-#define TSD_EXTENSION 0
-#define TSD_NBR (TSD_FIXED + TSD_EXTENSION)
-
-
-/* the cp starts putting a received PDU into one *small* buffer,
- then it uses a number of *large* buffers for the trailing data.
- we compute here the total number of receive segment descriptors
- required to hold the largest possible PDU */
-
-#define RSD_REQUIRED (((MAX_PDU_SIZE - SMALL_BUFFER_SIZE + LARGE_BUFFER_SIZE) / LARGE_BUFFER_SIZE) + 1)
-
-#define RSD_FIXED 3
-
-/* RSD_REQUIRED receive segment descriptors are enough to describe a max-sized PDU,
- but we have to keep the size of the receive PDU descriptor multiple of 32 bytes,
- so we add one extra RSD to RSD_EXTENSION
- (WARNING: THIS MAY CHANGE IF BUFFER SIZES ARE MODIFIED) */
-
-#define RSD_EXTENSION ((RSD_REQUIRED - RSD_FIXED) + 1)
-#define RSD_NBR (RSD_FIXED + RSD_EXTENSION)
-
-
-#define FORE200E_DEV(d) ((struct fore200e*)((d)->dev_data))
-#define FORE200E_VCC(d) ((struct fore200e_vcc*)((d)->dev_data))
-
-/* bitfields endian games */
-
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-#define BITFIELD2(b1, b2) b1; b2;
-#define BITFIELD3(b1, b2, b3) b1; b2; b3;
-#define BITFIELD4(b1, b2, b3, b4) b1; b2; b3; b4;
-#define BITFIELD5(b1, b2, b3, b4, b5) b1; b2; b3; b4; b5;
-#define BITFIELD6(b1, b2, b3, b4, b5, b6) b1; b2; b3; b4; b5; b6;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-#define BITFIELD2(b1, b2) b2; b1;
-#define BITFIELD3(b1, b2, b3) b3; b2; b1;
-#define BITFIELD4(b1, b2, b3, b4) b4; b3; b2; b1;
-#define BITFIELD5(b1, b2, b3, b4, b5) b5; b4; b3; b2; b1;
-#define BITFIELD6(b1, b2, b3, b4, b5, b6) b6; b5; b4; b3; b2; b1;
-#else
-#error unknown bitfield endianess
-#endif
-
-
-/* ATM cell header (minus HEC byte) */
-
-typedef struct atm_header {
- BITFIELD5(
- u32 clp : 1, /* cell loss priority */
- u32 plt : 3, /* payload type */
- u32 vci : 16, /* virtual channel identifier */
- u32 vpi : 8, /* virtual path identifier */
- u32 gfc : 4 /* generic flow control */
- )
-} atm_header_t;
-
-
-/* ATM adaptation layer id */
-
-typedef enum fore200e_aal {
- FORE200E_AAL0 = 0,
- FORE200E_AAL34 = 4,
- FORE200E_AAL5 = 5,
-} fore200e_aal_t;
-
-
-/* transmit PDU descriptor specification */
-
-typedef struct tpd_spec {
- BITFIELD4(
- u32 length : 16, /* total PDU length */
- u32 nseg : 8, /* number of transmit segments */
- enum fore200e_aal aal : 4, /* adaptation layer */
- u32 intr : 4 /* interrupt requested */
- )
-} tpd_spec_t;
-
-
-/* transmit PDU rate control */
-
-typedef struct tpd_rate
-{
- BITFIELD2(
- u32 idle_cells : 16, /* number of idle cells to insert */
- u32 data_cells : 16 /* number of data cells to transmit */
- )
-} tpd_rate_t;
-
-
-/* transmit segment descriptor */
-
-typedef struct tsd {
- u32 buffer; /* transmit buffer DMA address */
- u32 length; /* number of bytes in buffer */
-} tsd_t;
-
-
-/* transmit PDU descriptor */
-
-typedef struct tpd {
- struct atm_header atm_header; /* ATM header minus HEC byte */
- struct tpd_spec spec; /* tpd specification */
- struct tpd_rate rate; /* tpd rate control */
- u32 pad; /* reserved */
- struct tsd tsd[ TSD_NBR ]; /* transmit segment descriptors */
-} tpd_t;
-
-
-/* receive segment descriptor */
-
-typedef struct rsd {
- u32 handle; /* host supplied receive buffer handle */
- u32 length; /* number of bytes in buffer */
-} rsd_t;
-
-
-/* receive PDU descriptor */
-
-typedef struct rpd {
- struct atm_header atm_header; /* ATM header minus HEC byte */
- u32 nseg; /* number of receive segments */
- struct rsd rsd[ RSD_NBR ]; /* receive segment descriptors */
-} rpd_t;
-
-
-/* buffer scheme */
-
-typedef enum buffer_scheme {
- BUFFER_SCHEME_ONE,
- BUFFER_SCHEME_TWO,
- BUFFER_SCHEME_NBR /* always last */
-} buffer_scheme_t;
-
-
-/* buffer magnitude */
-
-typedef enum buffer_magn {
- BUFFER_MAGN_SMALL,
- BUFFER_MAGN_LARGE,
- BUFFER_MAGN_NBR /* always last */
-} buffer_magn_t;
-
-
-/* receive buffer descriptor */
-
-typedef struct rbd {
- u32 handle; /* host supplied handle */
- u32 buffer_haddr; /* host DMA address of host buffer */
-} rbd_t;
-
-
-/* receive buffer descriptor block */
-
-typedef struct rbd_block {
- struct rbd rbd[ RBD_BLK_SIZE ]; /* receive buffer descriptor */
-} rbd_block_t;
-
-
-/* tpd DMA address */
-
-typedef struct tpd_haddr {
- BITFIELD3(
- u32 size : 4, /* tpd size expressed in 32 byte blocks */
- u32 pad : 1, /* reserved */
- u32 haddr : 27 /* tpd DMA addr aligned on 32 byte boundary */
- )
-} tpd_haddr_t;
-
-#define TPD_HADDR_SHIFT 5 /* addr aligned on 32 byte boundary */
-
-/* cp resident transmit queue entry */
-
-typedef struct cp_txq_entry {
- struct tpd_haddr tpd_haddr; /* host DMA address of tpd */
- u32 status_haddr; /* host DMA address of completion status */
-} cp_txq_entry_t;
-
-
-/* cp resident receive queue entry */
-
-typedef struct cp_rxq_entry {
- u32 rpd_haddr; /* host DMA address of rpd */
- u32 status_haddr; /* host DMA address of completion status */
-} cp_rxq_entry_t;
-
-
-/* cp resident buffer supply queue entry */
-
-typedef struct cp_bsq_entry {
- u32 rbd_block_haddr; /* host DMA address of rbd block */
- u32 status_haddr; /* host DMA address of completion status */
-} cp_bsq_entry_t;
-
-
-/* completion status */
-
-typedef volatile enum status {
- STATUS_PENDING = (1<<0), /* initial status (written by host) */
- STATUS_COMPLETE = (1<<1), /* completion status (written by cp) */
- STATUS_FREE = (1<<2), /* initial status (written by host) */
- STATUS_ERROR = (1<<3) /* completion status (written by cp) */
-} status_t;
-
-
-/* cp operation code */
-
-typedef enum opcode {
- OPCODE_INITIALIZE = 1, /* initialize board */
- OPCODE_ACTIVATE_VCIN, /* activate incoming VCI */
- OPCODE_ACTIVATE_VCOUT, /* activate outgoing VCI */
- OPCODE_DEACTIVATE_VCIN, /* deactivate incoming VCI */
- OPCODE_DEACTIVATE_VCOUT, /* deactivate incoing VCI */
- OPCODE_GET_STATS, /* get board statistics */
- OPCODE_SET_OC3, /* set OC-3 registers */
- OPCODE_GET_OC3, /* get OC-3 registers */
- OPCODE_RESET_STATS, /* reset board statistics */
- OPCODE_GET_PROM, /* get expansion PROM data (PCI specific) */
- OPCODE_SET_VPI_BITS, /* set x bits of those decoded by the
- firmware to be low order bits from
- the VPI field of the ATM cell header */
- OPCODE_REQUEST_INTR = (1<<7) /* request interrupt */
-} opcode_t;
-
-
-/* virtual path / virtual channel identifiers */
-
-typedef struct vpvc {
- BITFIELD3(
- u32 vci : 16, /* virtual channel identifier */
- u32 vpi : 8, /* virtual path identifier */
- u32 pad : 8 /* reserved */
- )
-} vpvc_t;
-
-
-/* activate VC command opcode */
-
-typedef struct activate_opcode {
- BITFIELD4(
- enum opcode opcode : 8, /* cp opcode */
- enum fore200e_aal aal : 8, /* adaptation layer */
- enum buffer_scheme scheme : 8, /* buffer scheme */
- u32 pad : 8 /* reserved */
- )
-} activate_opcode_t;
-
-
-/* activate VC command block */
-
-typedef struct activate_block {
- struct activate_opcode opcode; /* activate VC command opcode */
- struct vpvc vpvc; /* VPI/VCI */
- u32 mtu; /* for AAL0 only */
-
-} activate_block_t;
-
-
-/* deactivate VC command opcode */
-
-typedef struct deactivate_opcode {
- BITFIELD2(
- enum opcode opcode : 8, /* cp opcode */
- u32 pad : 24 /* reserved */
- )
-} deactivate_opcode_t;
-
-
-/* deactivate VC command block */
-
-typedef struct deactivate_block {
- struct deactivate_opcode opcode; /* deactivate VC command opcode */
- struct vpvc vpvc; /* VPI/VCI */
-} deactivate_block_t;
-
-
-/* OC-3 registers */
-
-typedef struct oc3_regs {
- u32 reg[ 128 ]; /* see the PMC Sierra PC5346 S/UNI-155-Lite
- Saturn User Network Interface documentation
- for a description of the OC-3 chip registers */
-} oc3_regs_t;
-
-
-/* set/get OC-3 regs command opcode */
-
-typedef struct oc3_opcode {
- BITFIELD4(
- enum opcode opcode : 8, /* cp opcode */
- u32 reg : 8, /* register index */
- u32 value : 8, /* register value */
- u32 mask : 8 /* register mask that specifies which
- bits of the register value field
- are significant */
- )
-} oc3_opcode_t;
-
-
-/* set/get OC-3 regs command block */
-
-typedef struct oc3_block {
- struct oc3_opcode opcode; /* set/get OC-3 regs command opcode */
- u32 regs_haddr; /* host DMA address of OC-3 regs buffer */
-} oc3_block_t;
-
-
-/* physical encoding statistics */
-
-typedef struct stats_phy {
- __be32 crc_header_errors; /* cells received with bad header CRC */
- __be32 framing_errors; /* cells received with bad framing */
- __be32 pad[ 2 ]; /* i960 padding */
-} stats_phy_t;
-
-
-/* OC-3 statistics */
-
-typedef struct stats_oc3 {
- __be32 section_bip8_errors; /* section 8 bit interleaved parity */
- __be32 path_bip8_errors; /* path 8 bit interleaved parity */
- __be32 line_bip24_errors; /* line 24 bit interleaved parity */
- __be32 line_febe_errors; /* line far end block errors */
- __be32 path_febe_errors; /* path far end block errors */
- __be32 corr_hcs_errors; /* correctable header check sequence */
- __be32 ucorr_hcs_errors; /* uncorrectable header check sequence */
- __be32 pad[ 1 ]; /* i960 padding */
-} stats_oc3_t;
-
-
-/* ATM statistics */
-
-typedef struct stats_atm {
- __be32 cells_transmitted; /* cells transmitted */
- __be32 cells_received; /* cells received */
- __be32 vpi_bad_range; /* cell drops: VPI out of range */
- __be32 vpi_no_conn; /* cell drops: no connection for VPI */
- __be32 vci_bad_range; /* cell drops: VCI out of range */
- __be32 vci_no_conn; /* cell drops: no connection for VCI */
- __be32 pad[ 2 ]; /* i960 padding */
-} stats_atm_t;
-
-/* AAL0 statistics */
-
-typedef struct stats_aal0 {
- __be32 cells_transmitted; /* cells transmitted */
- __be32 cells_received; /* cells received */
- __be32 cells_dropped; /* cells dropped */
- __be32 pad[ 1 ]; /* i960 padding */
-} stats_aal0_t;
-
-
-/* AAL3/4 statistics */
-
-typedef struct stats_aal34 {
- __be32 cells_transmitted; /* cells transmitted from segmented PDUs */
- __be32 cells_received; /* cells reassembled into PDUs */
- __be32 cells_crc_errors; /* payload CRC error count */
- __be32 cells_protocol_errors; /* SAR or CS layer protocol errors */
- __be32 cells_dropped; /* cells dropped: partial reassembly */
- __be32 cspdus_transmitted; /* CS PDUs transmitted */
- __be32 cspdus_received; /* CS PDUs received */
- __be32 cspdus_protocol_errors; /* CS layer protocol errors */
- __be32 cspdus_dropped; /* reassembled PDUs drop'd (in cells) */
- __be32 pad[ 3 ]; /* i960 padding */
-} stats_aal34_t;
-
-
-/* AAL5 statistics */
-
-typedef struct stats_aal5 {
- __be32 cells_transmitted; /* cells transmitted from segmented SDUs */
- __be32 cells_received; /* cells reassembled into SDUs */
- __be32 cells_dropped; /* reassembled PDUs dropped (in cells) */
- __be32 congestion_experienced; /* CRC error and length wrong */
- __be32 cspdus_transmitted; /* CS PDUs transmitted */
- __be32 cspdus_received; /* CS PDUs received */
- __be32 cspdus_crc_errors; /* CS PDUs CRC errors */
- __be32 cspdus_protocol_errors; /* CS layer protocol errors */
- __be32 cspdus_dropped; /* reassembled PDUs dropped */
- __be32 pad[ 3 ]; /* i960 padding */
-} stats_aal5_t;
-
-
-/* auxiliary statistics */
-
-typedef struct stats_aux {
- __be32 small_b1_failed; /* receive BD allocation failures */
- __be32 large_b1_failed; /* receive BD allocation failures */
- __be32 small_b2_failed; /* receive BD allocation failures */
- __be32 large_b2_failed; /* receive BD allocation failures */
- __be32 rpd_alloc_failed; /* receive PDU allocation failures */
- __be32 receive_carrier; /* no carrier = 0, carrier = 1 */
- __be32 pad[ 2 ]; /* i960 padding */
-} stats_aux_t;
-
-
-/* whole statistics buffer */
-
-typedef struct stats {
- struct stats_phy phy; /* physical encoding statistics */
- struct stats_oc3 oc3; /* OC-3 statistics */
- struct stats_atm atm; /* ATM statistics */
- struct stats_aal0 aal0; /* AAL0 statistics */
- struct stats_aal34 aal34; /* AAL3/4 statistics */
- struct stats_aal5 aal5; /* AAL5 statistics */
- struct stats_aux aux; /* auxiliary statistics */
-} stats_t;
-
-
-/* get statistics command opcode */
-
-typedef struct stats_opcode {
- BITFIELD2(
- enum opcode opcode : 8, /* cp opcode */
- u32 pad : 24 /* reserved */
- )
-} stats_opcode_t;
-
-
-/* get statistics command block */
-
-typedef struct stats_block {
- struct stats_opcode opcode; /* get statistics command opcode */
- u32 stats_haddr; /* host DMA address of stats buffer */
-} stats_block_t;
-
-
-/* expansion PROM data (PCI specific) */
-
-typedef struct prom_data {
- u32 hw_revision; /* hardware revision */
- u32 serial_number; /* board serial number */
- u8 mac_addr[ 8 ]; /* board MAC address */
-} prom_data_t;
-
-
-/* get expansion PROM data command opcode */
-
-typedef struct prom_opcode {
- BITFIELD2(
- enum opcode opcode : 8, /* cp opcode */
- u32 pad : 24 /* reserved */
- )
-} prom_opcode_t;
-
-
-/* get expansion PROM data command block */
-
-typedef struct prom_block {
- struct prom_opcode opcode; /* get PROM data command opcode */
- u32 prom_haddr; /* host DMA address of PROM buffer */
-} prom_block_t;
-
-
-/* cp command */
-
-typedef union cmd {
- enum opcode opcode; /* operation code */
- struct activate_block activate_block; /* activate VC */
- struct deactivate_block deactivate_block; /* deactivate VC */
- struct stats_block stats_block; /* get statistics */
- struct prom_block prom_block; /* get expansion PROM data */
- struct oc3_block oc3_block; /* get/set OC-3 registers */
- u32 pad[ 4 ]; /* i960 padding */
-} cmd_t;
-
-
-/* cp resident command queue */
-
-typedef struct cp_cmdq_entry {
- union cmd cmd; /* command */
- u32 status_haddr; /* host DMA address of completion status */
- u32 pad[ 3 ]; /* i960 padding */
-} cp_cmdq_entry_t;
-
-
-/* host resident transmit queue entry */
-
-typedef struct host_txq_entry {
- struct cp_txq_entry __iomem *cp_entry; /* addr of cp resident tx queue entry */
- enum status* status; /* addr of host resident status */
- struct tpd* tpd; /* addr of transmit PDU descriptor */
- u32 tpd_dma; /* DMA address of tpd */
- struct sk_buff* skb; /* related skb */
- void* data; /* copy of misaligned data */
- unsigned long incarn; /* vc_map incarnation when submitted for tx */
- struct fore200e_vc_map* vc_map;
-
-} host_txq_entry_t;
-
-
-/* host resident receive queue entry */
-
-typedef struct host_rxq_entry {
- struct cp_rxq_entry __iomem *cp_entry; /* addr of cp resident rx queue entry */
- enum status* status; /* addr of host resident status */
- struct rpd* rpd; /* addr of receive PDU descriptor */
- u32 rpd_dma; /* DMA address of rpd */
-} host_rxq_entry_t;
-
-
-/* host resident buffer supply queue entry */
-
-typedef struct host_bsq_entry {
- struct cp_bsq_entry __iomem *cp_entry; /* addr of cp resident buffer supply queue entry */
- enum status* status; /* addr of host resident status */
- struct rbd_block* rbd_block; /* addr of receive buffer descriptor block */
- u32 rbd_block_dma; /* DMA address od rdb */
-} host_bsq_entry_t;
-
-
-/* host resident command queue entry */
-
-typedef struct host_cmdq_entry {
- struct cp_cmdq_entry __iomem *cp_entry; /* addr of cp resident cmd queue entry */
- enum status *status; /* addr of host resident status */
-} host_cmdq_entry_t;
-
-
-/* chunk of memory */
-
-typedef struct chunk {
- void* alloc_addr; /* base address of allocated chunk */
- void* align_addr; /* base address of aligned chunk */
- dma_addr_t dma_addr; /* DMA address of aligned chunk */
- int direction; /* direction of DMA mapping */
- u32 alloc_size; /* length of allocated chunk */
- u32 align_size; /* length of aligned chunk */
-} chunk_t;
-
-#define dma_size align_size /* DMA useable size */
-
-
-/* host resident receive buffer */
-
-typedef struct buffer {
- struct buffer* next; /* next receive buffer */
- enum buffer_scheme scheme; /* buffer scheme */
- enum buffer_magn magn; /* buffer magnitude */
- struct chunk data; /* data buffer */
-#ifdef FORE200E_BSQ_DEBUG
- unsigned long index; /* buffer # in queue */
- int supplied; /* 'buffer supplied' flag */
-#endif
-} buffer_t;
-
-
-#if (BITS_PER_LONG == 32)
-#define FORE200E_BUF2HDL(buffer) ((u32)(buffer))
-#define FORE200E_HDL2BUF(handle) ((struct buffer*)(handle))
-#else /* deal with 64 bit pointers */
-#define FORE200E_BUF2HDL(buffer) ((u32)((u64)(buffer)))
-#define FORE200E_HDL2BUF(handle) ((struct buffer*)(((u64)(handle)) | PAGE_OFFSET))
-#endif
-
-
-/* host resident command queue */
-
-typedef struct host_cmdq {
- struct host_cmdq_entry host_entry[ QUEUE_SIZE_CMD ]; /* host resident cmd queue entries */
- int head; /* head of cmd queue */
- struct chunk status; /* array of completion status */
-} host_cmdq_t;
-
-
-/* host resident transmit queue */
-
-typedef struct host_txq {
- struct host_txq_entry host_entry[ QUEUE_SIZE_TX ]; /* host resident tx queue entries */
- int head; /* head of tx queue */
- int tail; /* tail of tx queue */
- struct chunk tpd; /* array of tpds */
- struct chunk status; /* arry of completion status */
- int txing; /* number of pending PDUs in tx queue */
-} host_txq_t;
-
-
-/* host resident receive queue */
-
-typedef struct host_rxq {
- struct host_rxq_entry host_entry[ QUEUE_SIZE_RX ]; /* host resident rx queue entries */
- int head; /* head of rx queue */
- struct chunk rpd; /* array of rpds */
- struct chunk status; /* array of completion status */
-} host_rxq_t;
-
-
-/* host resident buffer supply queues */
-
-typedef struct host_bsq {
- struct host_bsq_entry host_entry[ QUEUE_SIZE_BS ]; /* host resident buffer supply queue entries */
- int head; /* head of buffer supply queue */
- struct chunk rbd_block; /* array of rbds */
- struct chunk status; /* array of completion status */
- struct buffer* buffer; /* array of rx buffers */
- struct buffer* freebuf; /* list of free rx buffers */
- volatile int freebuf_count; /* count of free rx buffers */
-} host_bsq_t;
-
-
-/* header of the firmware image */
-
-typedef struct fw_header {
- __le32 magic; /* magic number */
- __le32 version; /* firmware version id */
- __le32 load_offset; /* fw load offset in board memory */
- __le32 start_offset; /* fw execution start address in board memory */
-} fw_header_t;
-
-#define FW_HEADER_MAGIC 0x65726f66 /* 'fore' */
-
-
-/* receive buffer supply queues scheme specification */
-
-typedef struct bs_spec {
- u32 queue_length; /* queue capacity */
- u32 buffer_size; /* host buffer size */
- u32 pool_size; /* number of rbds */
- u32 supply_blksize; /* num of rbds in I/O block (multiple
- of 4 between 4 and 124 inclusive) */
-} bs_spec_t;
-
-
-/* initialization command block (one-time command, not in cmd queue) */
-
-typedef struct init_block {
- enum opcode opcode; /* initialize command */
- enum status status; /* related status word */
- u32 receive_threshold; /* not used */
- u32 num_connect; /* ATM connections */
- u32 cmd_queue_len; /* length of command queue */
- u32 tx_queue_len; /* length of transmit queue */
- u32 rx_queue_len; /* length of receive queue */
- u32 rsd_extension; /* number of extra 32 byte blocks */
- u32 tsd_extension; /* number of extra 32 byte blocks */
- u32 conless_vpvc; /* not used */
- u32 pad[ 2 ]; /* force quad alignment */
- struct bs_spec bs_spec[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ]; /* buffer supply queues spec */
-} init_block_t;
-
-
-typedef enum media_type {
- MEDIA_TYPE_CAT5_UTP = 0x06, /* unshielded twisted pair */
- MEDIA_TYPE_MM_OC3_ST = 0x16, /* multimode fiber ST */
- MEDIA_TYPE_MM_OC3_SC = 0x26, /* multimode fiber SC */
- MEDIA_TYPE_SM_OC3_ST = 0x36, /* single-mode fiber ST */
- MEDIA_TYPE_SM_OC3_SC = 0x46 /* single-mode fiber SC */
-} media_type_t;
-
-#define FORE200E_MEDIA_INDEX(media_type) ((media_type)>>4)
-
-
-/* cp resident queues */
-
-typedef struct cp_queues {
- u32 cp_cmdq; /* command queue */
- u32 cp_txq; /* transmit queue */
- u32 cp_rxq; /* receive queue */
- u32 cp_bsq[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ]; /* buffer supply queues */
- u32 imask; /* 1 enables cp to host interrupts */
- u32 istat; /* 1 for interrupt posted */
- u32 heap_base; /* offset form beginning of ram */
- u32 heap_size; /* space available for queues */
- u32 hlogger; /* non zero for host logging */
- u32 heartbeat; /* cp heartbeat */
- u32 fw_release; /* firmware version */
- u32 mon960_release; /* i960 monitor version */
- u32 tq_plen; /* transmit throughput measurements */
- /* make sure the init block remains on a quad word boundary */
- struct init_block init; /* one time cmd, not in cmd queue */
- enum media_type media_type; /* media type id */
- u32 oc3_revision; /* OC-3 revision number */
-} cp_queues_t;
-
-
-/* boot status */
-
-typedef enum boot_status {
- BSTAT_COLD_START = (u32) 0xc01dc01d, /* cold start */
- BSTAT_SELFTEST_OK = (u32) 0x02201958, /* self-test ok */
- BSTAT_SELFTEST_FAIL = (u32) 0xadbadbad, /* self-test failed */
- BSTAT_CP_RUNNING = (u32) 0xce11feed, /* cp is running */
- BSTAT_MON_TOO_BIG = (u32) 0x10aded00 /* i960 monitor is too big */
-} boot_status_t;
-
-
-/* software UART */
-
-typedef struct soft_uart {
- u32 send; /* write register */
- u32 recv; /* read register */
-} soft_uart_t;
-
-#define FORE200E_CP_MONITOR_UART_FREE 0x00000000
-#define FORE200E_CP_MONITOR_UART_AVAIL 0x01000000
-
-
-/* i960 monitor */
-
-typedef struct cp_monitor {
- struct soft_uart soft_uart; /* software UART */
- enum boot_status bstat; /* boot status */
- u32 app_base; /* application base offset */
- u32 mon_version; /* i960 monitor version */
-} cp_monitor_t;
-
-
-/* device state */
-
-typedef enum fore200e_state {
- FORE200E_STATE_BLANK, /* initial state */
- FORE200E_STATE_REGISTER, /* device registered */
- FORE200E_STATE_CONFIGURE, /* bus interface configured */
- FORE200E_STATE_MAP, /* board space mapped in host memory */
- FORE200E_STATE_RESET, /* board resetted */
- FORE200E_STATE_START_FW, /* firmware started */
- FORE200E_STATE_INITIALIZE, /* initialize command successful */
- FORE200E_STATE_INIT_CMDQ, /* command queue initialized */
- FORE200E_STATE_INIT_TXQ, /* transmit queue initialized */
- FORE200E_STATE_INIT_RXQ, /* receive queue initialized */
- FORE200E_STATE_INIT_BSQ, /* buffer supply queue initialized */
- FORE200E_STATE_ALLOC_BUF, /* receive buffers allocated */
- FORE200E_STATE_IRQ, /* host interrupt requested */
- FORE200E_STATE_COMPLETE /* initialization completed */
-} fore200e_state;
-
-
-/* PCA-200E registers */
-
-typedef struct fore200e_pca_regs {
- volatile u32 __iomem * hcr; /* address of host control register */
- volatile u32 __iomem * imr; /* address of host interrupt mask register */
- volatile u32 __iomem * psr; /* address of PCI specific register */
-} fore200e_pca_regs_t;
-
-
-/* SBA-200E registers */
-
-typedef struct fore200e_sba_regs {
- u32 __iomem *hcr; /* address of host control register */
- u32 __iomem *bsr; /* address of burst transfer size register */
- u32 __iomem *isr; /* address of interrupt level selection register */
-} fore200e_sba_regs_t;
-
-
-/* model-specific registers */
-
-typedef union fore200e_regs {
- struct fore200e_pca_regs pca; /* PCA-200E registers */
- struct fore200e_sba_regs sba; /* SBA-200E registers */
-} fore200e_regs;
-
-
-struct fore200e;
-
-/* bus-dependent data */
-
-typedef struct fore200e_bus {
- char* model_name; /* board model name */
- char* proc_name; /* board name under /proc/atm */
- int descr_alignment; /* tpd/rpd/rbd DMA alignment requirement */
- int buffer_alignment; /* rx buffers DMA alignment requirement */
- int status_alignment; /* status words DMA alignment requirement */
- u32 (*read)(volatile u32 __iomem *);
- void (*write)(u32, volatile u32 __iomem *);
- int (*configure)(struct fore200e*);
- int (*map)(struct fore200e*);
- void (*reset)(struct fore200e*);
- int (*prom_read)(struct fore200e*, struct prom_data*);
- void (*unmap)(struct fore200e*);
- void (*irq_enable)(struct fore200e*);
- int (*irq_check)(struct fore200e*);
- void (*irq_ack)(struct fore200e*);
- int (*proc_read)(struct fore200e*, char*);
-} fore200e_bus_t;
-
-/* vc mapping */
-
-typedef struct fore200e_vc_map {
- struct atm_vcc* vcc; /* vcc entry */
- unsigned long incarn; /* vcc incarnation number */
-} fore200e_vc_map_t;
-
-#define FORE200E_VC_MAP(fore200e, vpi, vci) \
- (& (fore200e)->vc_map[ ((vpi) << FORE200E_VCI_BITS) | (vci) ])
-
-
-/* per-device data */
-
-typedef struct fore200e {
- const struct fore200e_bus* bus; /* bus-dependent code and data */
- union fore200e_regs regs; /* bus-dependent registers */
- struct atm_dev* atm_dev; /* ATM device */
-
- enum fore200e_state state; /* device state */
-
- char name[16]; /* device name */
- struct device *dev;
- int irq; /* irq number */
- unsigned long phys_base; /* physical base address */
- void __iomem * virt_base; /* virtual base address */
-
- unsigned char esi[ ESI_LEN ]; /* end system identifier */
-
- struct cp_monitor __iomem * cp_monitor; /* i960 monitor address */
- struct cp_queues __iomem * cp_queues; /* cp resident queues */
- struct host_cmdq host_cmdq; /* host resident cmd queue */
- struct host_txq host_txq; /* host resident tx queue */
- struct host_rxq host_rxq; /* host resident rx queue */
- /* host resident buffer supply queues */
- struct host_bsq host_bsq[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ];
-
- u32 available_cell_rate; /* remaining pseudo-CBR bw on link */
-
- int loop_mode; /* S/UNI loopback mode */
-
- struct stats* stats; /* last snapshot of the stats */
-
- struct mutex rate_mtx; /* protects rate reservation ops */
- spinlock_t q_lock; /* protects queue ops */
-#ifdef FORE200E_USE_TASKLET
- struct tasklet_struct tx_tasklet; /* performs tx interrupt work */
- struct tasklet_struct rx_tasklet; /* performs rx interrupt work */
-#endif
- unsigned long tx_sat; /* tx queue saturation count */
-
- unsigned long incarn_count;
- struct fore200e_vc_map vc_map[ NBR_CONNECT ]; /* vc mapping */
-} fore200e_t;
-
-
-/* per-vcc data */
-
-typedef struct fore200e_vcc {
- enum buffer_scheme scheme; /* rx buffer scheme */
- struct tpd_rate rate; /* tx rate control data */
- int rx_min_pdu; /* size of smallest PDU received */
- int rx_max_pdu; /* size of largest PDU received */
- int tx_min_pdu; /* size of smallest PDU transmitted */
- int tx_max_pdu; /* size of largest PDU transmitted */
- unsigned long tx_pdu; /* nbr of tx pdus */
- unsigned long rx_pdu; /* nbr of rx pdus */
-} fore200e_vcc_t;
-
-
-
-/* 200E-series common memory layout */
-
-#define FORE200E_CP_MONITOR_OFFSET 0x00000400 /* i960 monitor interface */
-#define FORE200E_CP_QUEUES_OFFSET 0x00004d40 /* cp resident queues */
-
-
-/* PCA-200E memory layout */
-
-#define PCA200E_IOSPACE_LENGTH 0x00200000
-
-#define PCA200E_HCR_OFFSET 0x00100000 /* board control register */
-#define PCA200E_IMR_OFFSET 0x00100004 /* host IRQ mask register */
-#define PCA200E_PSR_OFFSET 0x00100008 /* PCI specific register */
-
-
-/* PCA-200E host control register */
-
-#define PCA200E_HCR_RESET (1<<0) /* read / write */
-#define PCA200E_HCR_HOLD_LOCK (1<<1) /* read / write */
-#define PCA200E_HCR_I960FAIL (1<<2) /* read */
-#define PCA200E_HCR_INTRB (1<<2) /* write */
-#define PCA200E_HCR_HOLD_ACK (1<<3) /* read */
-#define PCA200E_HCR_INTRA (1<<3) /* write */
-#define PCA200E_HCR_OUTFULL (1<<4) /* read */
-#define PCA200E_HCR_CLRINTR (1<<4) /* write */
-#define PCA200E_HCR_ESPHOLD (1<<5) /* read */
-#define PCA200E_HCR_INFULL (1<<6) /* read */
-#define PCA200E_HCR_TESTMODE (1<<7) /* read */
-
-
-/* PCA-200E PCI bus interface regs (offsets in PCI config space) */
-
-#define PCA200E_PCI_LATENCY 0x40 /* maximum slave latenty */
-#define PCA200E_PCI_MASTER_CTRL 0x41 /* master control */
-#define PCA200E_PCI_THRESHOLD 0x42 /* burst / continuous req threshold */
-
-/* PBI master control register */
-
-#define PCA200E_CTRL_DIS_CACHE_RD (1<<0) /* disable cache-line reads */
-#define PCA200E_CTRL_DIS_WRT_INVAL (1<<1) /* disable writes and invalidates */
-#define PCA200E_CTRL_2_CACHE_WRT_INVAL (1<<2) /* require 2 cache-lines for writes and invalidates */
-#define PCA200E_CTRL_IGN_LAT_TIMER (1<<3) /* ignore the latency timer */
-#define PCA200E_CTRL_ENA_CONT_REQ_MODE (1<<4) /* enable continuous request mode */
-#define PCA200E_CTRL_LARGE_PCI_BURSTS (1<<5) /* force large PCI bus bursts */
-#define PCA200E_CTRL_CONVERT_ENDIAN (1<<6) /* convert endianess of slave RAM accesses */
-
-
-
-#define SBA200E_PROM_NAME "FORE,sba-200e" /* device name in openprom tree */
-
-
-/* size of SBA-200E registers */
-
-#define SBA200E_HCR_LENGTH 4
-#define SBA200E_BSR_LENGTH 4
-#define SBA200E_ISR_LENGTH 4
-#define SBA200E_RAM_LENGTH 0x40000
-
-
-/* SBA-200E SBUS burst transfer size register */
-
-#define SBA200E_BSR_BURST4 0x04
-#define SBA200E_BSR_BURST8 0x08
-#define SBA200E_BSR_BURST16 0x10
-
-
-/* SBA-200E host control register */
-
-#define SBA200E_HCR_RESET (1<<0) /* read / write (sticky) */
-#define SBA200E_HCR_HOLD_LOCK (1<<1) /* read / write (sticky) */
-#define SBA200E_HCR_I960FAIL (1<<2) /* read */
-#define SBA200E_HCR_I960SETINTR (1<<2) /* write */
-#define SBA200E_HCR_OUTFULL (1<<3) /* read */
-#define SBA200E_HCR_INTR_CLR (1<<3) /* write */
-#define SBA200E_HCR_INTR_ENA (1<<4) /* read / write (sticky) */
-#define SBA200E_HCR_ESPHOLD (1<<5) /* read */
-#define SBA200E_HCR_INFULL (1<<6) /* read */
-#define SBA200E_HCR_TESTMODE (1<<7) /* read */
-#define SBA200E_HCR_INTR_REQ (1<<8) /* read */
-
-#define SBA200E_HCR_STICKY (SBA200E_HCR_RESET | SBA200E_HCR_HOLD_LOCK | SBA200E_HCR_INTR_ENA)
-
-
-#endif /* __KERNEL__ */
-#endif /* _FORE200E_H */
diff --git a/drivers/atm/he.h b/drivers/atm/he.h
deleted file mode 100644
index f3f53674ef3f..000000000000
--- a/drivers/atm/he.h
+++ /dev/null
@@ -1,845 +0,0 @@
-/*
-
- he.h
-
- ForeRunnerHE ATM Adapter driver for ATM on Linux
- Copyright (C) 1999-2001 Naval Research Laboratory
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-/*
-
- he.h
-
- ForeRunnerHE ATM Adapter driver for ATM on Linux
- Copyright (C) 1999-2000 Naval Research Laboratory
-
- Permission to use, copy, modify and distribute this software and its
- documentation is hereby granted, provided that both the copyright
- notice and this permission notice appear in all copies of the software,
- derivative works or modified versions, and any portions thereof, and
- that both notices appear in supporting documentation.
-
- NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
- DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
- RESULTING FROM THE USE OF THIS SOFTWARE.
-
- */
-
-#ifndef _HE_H_
-#define _HE_H_
-
-#define DEV_LABEL "he"
-
-#define CONFIG_DEFAULT_VCIBITS 12
-#define CONFIG_DEFAULT_VPIBITS 0
-
-#define CONFIG_IRQ_SIZE 128
-#define CONFIG_IRQ_THRESH (CONFIG_IRQ_SIZE/2)
-
-#define CONFIG_TPDRQ_SIZE 512
-#define TPDRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1))
-
-#define CONFIG_RBRQ_SIZE 512
-#define CONFIG_RBRQ_THRESH 400
-#define RBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1))
-
-#define CONFIG_TBRQ_SIZE 512
-#define CONFIG_TBRQ_THRESH 400
-#define TBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1))
-
-#define CONFIG_RBPL_SIZE 512
-#define CONFIG_RBPL_THRESH 64
-#define CONFIG_RBPL_BUFSIZE 4096
-#define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1))
-
-/* 5.1.3 initialize connection memory */
-
-#define CONFIG_RSRA 0x00000
-#define CONFIG_RCMLBM 0x08000
-#define CONFIG_RCMABR 0x0d800
-#define CONFIG_RSRB 0x0e000
-
-#define CONFIG_TSRA 0x00000
-#define CONFIG_TSRB 0x08000
-#define CONFIG_TSRC 0x0c000
-#define CONFIG_TSRD 0x0e000
-#define CONFIG_TMABR 0x0f000
-#define CONFIG_TPDBA 0x10000
-
-#define HE_MAXCIDBITS 12
-
-/* 2.9.3.3 interrupt encodings */
-
-struct he_irq {
- volatile u32 isw;
-};
-
-#define IRQ_ALIGNMENT 0x1000
-
-#define NEXT_ENTRY(base, tail, mask) \
- (((unsigned long)base)|(((unsigned long)(tail+1))&mask))
-
-#define ITYPE_INVALID 0xffffffff
-#define ITYPE_TBRQ_THRESH (0<<3)
-#define ITYPE_TPD_COMPLETE (1<<3)
-#define ITYPE_RBPS_THRESH (2<<3)
-#define ITYPE_RBPL_THRESH (3<<3)
-#define ITYPE_RBRQ_THRESH (4<<3)
-#define ITYPE_RBRQ_TIMER (5<<3)
-#define ITYPE_PHY (6<<3)
-#define ITYPE_OTHER 0x80
-#define ITYPE_PARITY 0x81
-#define ITYPE_ABORT 0x82
-
-#define ITYPE_GROUP(x) (x & 0x7)
-#define ITYPE_TYPE(x) (x & 0xf8)
-
-#define HE_NUM_GROUPS 8
-
-/* 2.1.4 transmit packet descriptor */
-
-struct he_tpd {
-
- /* read by the adapter */
-
- volatile u32 status;
- volatile u32 reserved;
-
-#define TPD_MAXIOV 3
- struct {
- u32 addr, len;
- } iovec[TPD_MAXIOV];
-
-#define address0 iovec[0].addr
-#define length0 iovec[0].len
-
- /* linux-atm extensions */
-
- struct sk_buff *skb;
- struct atm_vcc *vcc;
-
- struct list_head entry;
-};
-
-#define TPD_ALIGNMENT 64
-#define TPD_LEN_MASK 0xffff
-
-#define TPD_ADDR_SHIFT 6
-#define TPD_MASK 0xffffffc0
-#define TPD_ADDR(x) ((x) & TPD_MASK)
-#define TPD_INDEX(x) (TPD_ADDR(x) >> TPD_ADDR_SHIFT)
-
-
-/* table 2.3 transmit buffer return elements */
-
-struct he_tbrq {
- volatile u32 tbre;
-};
-
-#define TBRQ_ALIGNMENT CONFIG_TBRQ_SIZE
-
-#define TBRQ_TPD(tbrq) ((tbrq)->tbre & 0xffffffc0)
-#define TBRQ_EOS(tbrq) ((tbrq)->tbre & (1<<3))
-#define TBRQ_MULTIPLE(tbrq) ((tbrq)->tbre & (1))
-
-/* table 2.21 receive buffer return queue element field organization */
-
-struct he_rbrq {
- volatile u32 addr;
- volatile u32 cidlen;
-};
-
-#define RBRQ_ALIGNMENT CONFIG_RBRQ_SIZE
-
-#define RBRQ_ADDR(rbrq) ((rbrq)->addr & 0xffffffc0)
-#define RBRQ_CRC_ERR(rbrq) ((rbrq)->addr & (1<<5))
-#define RBRQ_LEN_ERR(rbrq) ((rbrq)->addr & (1<<4))
-#define RBRQ_END_PDU(rbrq) ((rbrq)->addr & (1<<3))
-#define RBRQ_AAL5_PROT(rbrq) ((rbrq)->addr & (1<<2))
-#define RBRQ_CON_CLOSED(rbrq) ((rbrq)->addr & (1<<1))
-#define RBRQ_HBUF_ERR(rbrq) ((rbrq)->addr & 1)
-#define RBRQ_CID(rbrq) (((rbrq)->cidlen >> 16) & 0x1fff)
-#define RBRQ_BUFLEN(rbrq) ((rbrq)->cidlen & 0xffff)
-
-/* figure 2.3 transmit packet descriptor ready queue */
-
-struct he_tpdrq {
- volatile u32 tpd;
- volatile u32 cid;
-};
-
-#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE
-
-/* table 2.30 host status page detail */
-
-#define HSP_ALIGNMENT 0x400 /* must align on 1k boundary */
-
-struct he_hsp {
- struct he_hsp_entry {
- volatile u32 tbrq_tail;
- volatile u32 reserved1[15];
- volatile u32 rbrq_tail;
- volatile u32 reserved2[15];
- } group[HE_NUM_GROUPS];
-};
-
-/*
- * figure 2.9 receive buffer pools
- *
- * since a virtual address might be more than 32 bits, we store an index
- * in the virt member of he_rbp. NOTE: the lower six bits in the rbrq
- * addr member are used for buffer status further limiting us to 26 bits.
- */
-
-struct he_rbp {
- volatile u32 phys;
- volatile u32 idx; /* virt */
-};
-
-#define RBP_IDX_OFFSET 6
-
-/*
- * the he dma engine will try to hold an extra 16 buffers in its local
- * caches. and add a couple buffers for safety.
- */
-
-#define RBPL_TABLE_SIZE (CONFIG_RBPL_SIZE + 16 + 2)
-
-struct he_buff {
- struct list_head entry;
- dma_addr_t mapping;
- unsigned long len;
- u8 data[];
-};
-
-#ifdef notyet
-struct he_group {
- u32 rpbl_size, rpbl_qsize;
- struct he_rpb_entry *rbpl_ba;
-};
-#endif
-
-#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc)
-
-struct he_vcc_table
-{
- struct atm_vcc *vcc;
-};
-
-struct he_cs_stper
-{
- long pcr;
- int inuse;
-};
-
-#define HE_NUM_CS_STPER 16
-
-struct he_dev {
- unsigned int number;
- unsigned int irq;
- void __iomem *membase;
-
- char prod_id[30];
- char mac_addr[6];
- int media;
-
- unsigned int vcibits, vpibits;
- unsigned int cells_per_row;
- unsigned int bytes_per_row;
- unsigned int cells_per_lbuf;
- unsigned int r0_numrows, r0_startrow, r0_numbuffs;
- unsigned int r1_numrows, r1_startrow, r1_numbuffs;
- unsigned int tx_numrows, tx_startrow, tx_numbuffs;
- unsigned int buffer_limit;
-
- struct he_vcc_table *he_vcc_table;
-
-#ifdef notyet
- struct he_group group[HE_NUM_GROUPS];
-#endif
- struct he_cs_stper cs_stper[HE_NUM_CS_STPER];
- unsigned total_bw;
-
- dma_addr_t irq_phys;
- struct he_irq *irq_base, *irq_head, *irq_tail;
- volatile unsigned *irq_tailoffset;
- int irq_peak;
-
- struct tasklet_struct tasklet;
- struct dma_pool *tpd_pool;
- struct list_head outstanding_tpds;
-
- dma_addr_t tpdrq_phys;
- struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head;
-
- spinlock_t global_lock; /* 8.1.5 pci transaction ordering
- error problem */
- dma_addr_t rbrq_phys;
- struct he_rbrq *rbrq_base, *rbrq_head;
- int rbrq_peak;
-
- struct he_buff **rbpl_virt;
- unsigned long *rbpl_table;
- unsigned long rbpl_hint;
- struct dma_pool *rbpl_pool;
- dma_addr_t rbpl_phys;
- struct he_rbp *rbpl_base, *rbpl_tail;
- struct list_head rbpl_outstanding;
- int rbpl_peak;
-
- dma_addr_t tbrq_phys;
- struct he_tbrq *tbrq_base, *tbrq_head;
- int tbrq_peak;
-
- dma_addr_t hsp_phys;
- struct he_hsp *hsp;
-
- struct pci_dev *pci_dev;
- struct atm_dev *atm_dev;
- struct he_dev *next;
-};
-
-#define HE_MAXIOV 20
-
-struct he_vcc
-{
- struct list_head buffers;
- int pdu_len;
- int rc_index;
-
- wait_queue_head_t rx_waitq;
- wait_queue_head_t tx_waitq;
-};
-
-#define HE_VCC(vcc) ((struct he_vcc *)(vcc->dev_data))
-
-#define PCI_VENDOR_ID_FORE 0x1127
-#define PCI_DEVICE_ID_FORE_HE 0x400
-
-#define GEN_CNTL_0 0x40
-#define INT_PROC_ENBL (1<<25)
-#define SLAVE_ENDIAN_MODE (1<<16)
-#define MRL_ENB (1<<5)
-#define MRM_ENB (1<<4)
-#define INIT_ENB (1<<2)
-#define IGNORE_TIMEOUT (1<<1)
-#define ENBL_64 (1<<0)
-
-#define MIN_PCI_LATENCY 32 /* errata 8.1.3 */
-
-#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data)
-
-#define he_is622(dev) ((dev)->media & 0x1)
-#define he_isMM(dev) ((dev)->media & 0x20)
-
-#define HE_REGMAP_SIZE 0x100000
-
-#define RESET_CNTL 0x80000
-#define BOARD_RST_STATUS (1<<6)
-
-#define HOST_CNTL 0x80004
-#define PCI_BUS_SIZE64 (1<<27)
-#define DESC_RD_STATIC_64 (1<<26)
-#define DATA_RD_STATIC_64 (1<<25)
-#define DATA_WR_STATIC_64 (1<<24)
-#define ID_CS (1<<12)
-#define ID_WREN (1<<11)
-#define ID_DOUT (1<<10)
-#define ID_DOFFSET 10
-#define ID_DIN (1<<9)
-#define ID_CLOCK (1<<8)
-#define QUICK_RD_RETRY (1<<7)
-#define QUICK_WR_RETRY (1<<6)
-#define OUTFF_ENB (1<<5)
-#define CMDFF_ENB (1<<4)
-#define PERR_INT_ENB (1<<2)
-#define IGNORE_INTR (1<<0)
-
-#define LB_SWAP 0x80008
-#define SWAP_RNUM_MAX(x) (x<<27)
-#define DATA_WR_SWAP (1<<20)
-#define DESC_RD_SWAP (1<<19)
-#define DATA_RD_SWAP (1<<18)
-#define INTR_SWAP (1<<17)
-#define DESC_WR_SWAP (1<<16)
-#define SDRAM_INIT (1<<15)
-#define BIG_ENDIAN_HOST (1<<14)
-#define XFER_SIZE (1<<7)
-
-#define LB_MEM_ADDR 0x8000c
-#define LB_MEM_DATA 0x80010
-
-#define LB_MEM_ACCESS 0x80014
-#define LB_MEM_HNDSHK (1<<30)
-#define LM_MEM_WRITE (0x7)
-#define LM_MEM_READ (0x3)
-
-#define SDRAM_CTL 0x80018
-#define LB_64_ENB (1<<3)
-#define LB_TWR (1<<2)
-#define LB_TRP (1<<1)
-#define LB_TRAS (1<<0)
-
-#define INT_FIFO 0x8001c
-#define INT_MASK_D (1<<15)
-#define INT_MASK_C (1<<14)
-#define INT_MASK_B (1<<13)
-#define INT_MASK_A (1<<12)
-#define INT_CLEAR_D (1<<11)
-#define INT_CLEAR_C (1<<10)
-#define INT_CLEAR_B (1<<9)
-#define INT_CLEAR_A (1<<8)
-
-#define ABORT_ADDR 0x80020
-
-#define IRQ0_BASE 0x80080
-#define IRQ_BASE(x) (x<<12)
-#define IRQ_MASK ((CONFIG_IRQ_SIZE<<2)-1) /* was 0x3ff */
-#define IRQ_TAIL(x) (((unsigned long)(x)) & IRQ_MASK)
-#define IRQ0_HEAD 0x80084
-#define IRQ_SIZE(x) (x<<22)
-#define IRQ_THRESH(x) (x<<12)
-#define IRQ_HEAD(x) (x<<2)
-/* #define IRQ_PENDING (1) conflict with linux/irq.h */
-#define IRQ0_CNTL 0x80088
-#define IRQ_ADDRSEL(x) (x<<2)
-#define IRQ_INT_A (0<<2)
-#define IRQ_INT_B (1<<2)
-#define IRQ_INT_C (2<<2)
-#define IRQ_INT_D (3<<2)
-#define IRQ_TYPE_ADDR 0x1
-#define IRQ_TYPE_LINE 0x0
-#define IRQ0_DATA 0x8008c
-
-#define IRQ1_BASE 0x80090
-#define IRQ1_HEAD 0x80094
-#define IRQ1_CNTL 0x80098
-#define IRQ1_DATA 0x8009c
-
-#define IRQ2_BASE 0x800a0
-#define IRQ2_HEAD 0x800a4
-#define IRQ2_CNTL 0x800a8
-#define IRQ2_DATA 0x800ac
-
-#define IRQ3_BASE 0x800b0
-#define IRQ3_HEAD 0x800b4
-#define IRQ3_CNTL 0x800b8
-#define IRQ3_DATA 0x800bc
-
-#define GRP_10_MAP 0x800c0
-#define GRP_32_MAP 0x800c4
-#define GRP_54_MAP 0x800c8
-#define GRP_76_MAP 0x800cc
-
-#define G0_RBPS_S 0x80400
-#define G0_RBPS_T 0x80404
-#define RBP_TAIL(x) ((x)<<3)
-#define RBP_MASK(x) ((x)|0x1fff)
-#define G0_RBPS_QI 0x80408
-#define RBP_QSIZE(x) ((x)<<14)
-#define RBP_INT_ENB (1<<13)
-#define RBP_THRESH(x) (x)
-#define G0_RBPS_BS 0x8040c
-#define G0_RBPL_S 0x80410
-#define G0_RBPL_T 0x80414
-#define G0_RBPL_QI 0x80418
-#define G0_RBPL_BS 0x8041c
-
-#define G1_RBPS_S 0x80420
-#define G1_RBPS_T 0x80424
-#define G1_RBPS_QI 0x80428
-#define G1_RBPS_BS 0x8042c
-#define G1_RBPL_S 0x80430
-#define G1_RBPL_T 0x80434
-#define G1_RBPL_QI 0x80438
-#define G1_RBPL_BS 0x8043c
-
-#define G2_RBPS_S 0x80440
-#define G2_RBPS_T 0x80444
-#define G2_RBPS_QI 0x80448
-#define G2_RBPS_BS 0x8044c
-#define G2_RBPL_S 0x80450
-#define G2_RBPL_T 0x80454
-#define G2_RBPL_QI 0x80458
-#define G2_RBPL_BS 0x8045c
-
-#define G3_RBPS_S 0x80460
-#define G3_RBPS_T 0x80464
-#define G3_RBPS_QI 0x80468
-#define G3_RBPS_BS 0x8046c
-#define G3_RBPL_S 0x80470
-#define G3_RBPL_T 0x80474
-#define G3_RBPL_QI 0x80478
-#define G3_RBPL_BS 0x8047c
-
-#define G4_RBPS_S 0x80480
-#define G4_RBPS_T 0x80484
-#define G4_RBPS_QI 0x80488
-#define G4_RBPS_BS 0x8048c
-#define G4_RBPL_S 0x80490
-#define G4_RBPL_T 0x80494
-#define G4_RBPL_QI 0x80498
-#define G4_RBPL_BS 0x8049c
-
-#define G5_RBPS_S 0x804a0
-#define G5_RBPS_T 0x804a4
-#define G5_RBPS_QI 0x804a8
-#define G5_RBPS_BS 0x804ac
-#define G5_RBPL_S 0x804b0
-#define G5_RBPL_T 0x804b4
-#define G5_RBPL_QI 0x804b8
-#define G5_RBPL_BS 0x804bc
-
-#define G6_RBPS_S 0x804c0
-#define G6_RBPS_T 0x804c4
-#define G6_RBPS_QI 0x804c8
-#define G6_RBPS_BS 0x804cc
-#define G6_RBPL_S 0x804d0
-#define G6_RBPL_T 0x804d4
-#define G6_RBPL_QI 0x804d8
-#define G6_RBPL_BS 0x804dc
-
-#define G7_RBPS_S 0x804e0
-#define G7_RBPS_T 0x804e4
-#define G7_RBPS_QI 0x804e8
-#define G7_RBPS_BS 0x804ec
-
-#define G7_RBPL_S 0x804f0
-#define G7_RBPL_T 0x804f4
-#define G7_RBPL_QI 0x804f8
-#define G7_RBPL_BS 0x804fc
-
-#define G0_RBRQ_ST 0x80500
-#define G0_RBRQ_H 0x80504
-#define G0_RBRQ_Q 0x80508
-#define RBRQ_THRESH(x) ((x)<<13)
-#define RBRQ_SIZE(x) (x)
-#define G0_RBRQ_I 0x8050c
-#define RBRQ_TIME(x) ((x)<<8)
-#define RBRQ_COUNT(x) (x)
-
-/* fill in 1 ... 7 later */
-
-#define G0_TBRQ_B_T 0x80600
-#define G0_TBRQ_H 0x80604
-#define G0_TBRQ_S 0x80608
-#define G0_TBRQ_THRESH 0x8060c
-#define TBRQ_THRESH(x) (x)
-
-/* fill in 1 ... 7 later */
-
-#define RH_CONFIG 0x805c0
-#define PHY_INT_ENB (1<<10)
-#define OAM_GID(x) (x<<7)
-#define PTMR_PRE(x) (x)
-
-#define G0_INMQ_S 0x80580
-#define G0_INMQ_L 0x80584
-#define G1_INMQ_S 0x80588
-#define G1_INMQ_L 0x8058c
-#define G2_INMQ_S 0x80590
-#define G2_INMQ_L 0x80594
-#define G3_INMQ_S 0x80598
-#define G3_INMQ_L 0x8059c
-#define G4_INMQ_S 0x805a0
-#define G4_INMQ_L 0x805a4
-#define G5_INMQ_S 0x805a8
-#define G5_INMQ_L 0x805ac
-#define G6_INMQ_S 0x805b0
-#define G6_INMQ_L 0x805b4
-#define G7_INMQ_S 0x805b8
-#define G7_INMQ_L 0x805bc
-
-#define TPDRQ_B_H 0x80680
-#define TPDRQ_T 0x80684
-#define TPDRQ_S 0x80688
-
-#define UBUFF_BA 0x8068c
-
-#define RLBF0_H 0x806c0
-#define RLBF0_T 0x806c4
-#define RLBF1_H 0x806c8
-#define RLBF1_T 0x806cc
-#define RLBC_H 0x806d0
-#define RLBC_T 0x806d4
-#define RLBC_H2 0x806d8
-#define TLBF_H 0x806e0
-#define TLBF_T 0x806e4
-#define RLBF0_C 0x806e8
-#define RLBF1_C 0x806ec
-#define RXTHRSH 0x806f0
-#define LITHRSH 0x806f4
-
-#define LBARB 0x80700
-#define SLICE_X(x) (x<<28)
-#define ARB_RNUM_MAX(x) (x<<23)
-#define TH_PRTY(x) (x<<21)
-#define RH_PRTY(x) (x<<19)
-#define TL_PRTY(x) (x<<17)
-#define RL_PRTY(x) (x<<15)
-#define BUS_MULTI(x) (x<<8)
-#define NET_PREF(x) (x)
-
-#define SDRAMCON 0x80704
-#define BANK_ON (1<<14)
-#define WIDE_DATA (1<<13)
-#define TWR_WAIT (1<<12)
-#define TRP_WAIT (1<<11)
-#define TRAS_WAIT (1<<10)
-#define REF_RATE(x) (x)
-
-#define LBSTAT 0x80708
-
-#define RCC_STAT 0x8070c
-#define RCC_BUSY (1)
-
-#define TCMCONFIG 0x80740
-#define TM_DESL2 (1<<10)
-#define TM_BANK_WAIT(x) (x<<6)
-#define TM_ADD_BANK4(x) (x<<4)
-#define TM_PAR_CHECK(x) (x<<3)
-#define TM_RW_WAIT(x) (x<<2)
-#define TM_SRAM_TYPE(x) (x)
-
-#define TSRB_BA 0x80744
-#define TSRC_BA 0x80748
-#define TMABR_BA 0x8074c
-#define TPD_BA 0x80750
-#define TSRD_BA 0x80758
-
-#define TX_CONFIG 0x80760
-#define DRF_THRESH(x) (x<<22)
-#define TX_UT_MODE(x) (x<<21)
-#define TX_VCI_MASK(x) (x<<17)
-#define LBFREE_CNT(x) (x)
-
-#define TXAAL5_PROTO 0x80764
-#define CPCS_UU(x) (x<<8)
-#define CPI(x) (x)
-
-#define RCMCONFIG 0x80780
-#define RM_DESL2(x) (x<<10)
-#define RM_BANK_WAIT(x) (x<<6)
-#define RM_ADD_BANK(x) (x<<4)
-#define RM_PAR_CHECK(x) (x<<3)
-#define RM_RW_WAIT(x) (x<<2)
-#define RM_SRAM_TYPE(x) (x)
-
-#define RCMRSRB_BA 0x80784
-#define RCMLBM_BA 0x80788
-#define RCMABR_BA 0x8078c
-
-#define RC_CONFIG 0x807c0
-#define UT_RD_DELAY(x) (x<<11)
-#define WRAP_MODE(x) (x<<10)
-#define RC_UT_MODE(x) (x<<9)
-#define RX_ENABLE (1<<8)
-#define RX_VALVP(x) (x<<4)
-#define RX_VALVC(x) (x)
-
-#define MCC 0x807c4
-#define OEC 0x807c8
-#define DCC 0x807cc
-#define CEC 0x807d0
-
-#define HSP_BA 0x807f0
-
-#define LB_CONFIG 0x807f4
-#define LB_SIZE(x) (x)
-
-#define CON_DAT 0x807f8
-#define CON_CTL 0x807fc
-#define CON_CTL_MBOX (2<<30)
-#define CON_CTL_TCM (1<<30)
-#define CON_CTL_RCM (0<<30)
-#define CON_CTL_WRITE (1<<29)
-#define CON_CTL_READ (0<<29)
-#define CON_CTL_BUSY (1<<28)
-#define CON_BYTE_DISABLE_3 (1<<22) /* 24..31 */
-#define CON_BYTE_DISABLE_2 (1<<21) /* 16..23 */
-#define CON_BYTE_DISABLE_1 (1<<20) /* 8..15 */
-#define CON_BYTE_DISABLE_0 (1<<19) /* 0..7 */
-#define CON_CTL_ADDR(x) (x)
-
-#define FRAMER 0x80800 /* to 0x80bfc */
-
-/* 3.3 network controller (internal) mailbox registers */
-
-#define CS_STPER0 0x0
- /* ... */
-#define CS_STPER31 0x01f
-
-#define CS_STTIM0 0x020
- /* ... */
-#define CS_STTIM31 0x03f
-
-#define CS_TGRLD0 0x040
- /* ... */
-#define CS_TGRLD15 0x04f
-
-#define CS_ERTHR0 0x050
-#define CS_ERTHR1 0x051
-#define CS_ERTHR2 0x052
-#define CS_ERTHR3 0x053
-#define CS_ERTHR4 0x054
-#define CS_ERCTL0 0x055
-#define TX_ENABLE (1<<28)
-#define ER_ENABLE (1<<27)
-#define CS_ERCTL1 0x056
-#define CS_ERCTL2 0x057
-#define CS_ERSTAT0 0x058
-#define CS_ERSTAT1 0x059
-
-#define CS_RTCCT 0x060
-#define CS_RTFWC 0x061
-#define CS_RTFWR 0x062
-#define CS_RTFTC 0x063
-#define CS_RTATR 0x064
-
-#define CS_TFBSET 0x070
-#define CS_TFBADD 0x071
-#define CS_TFBSUB 0x072
-#define CS_WCRMAX 0x073
-#define CS_WCRMIN 0x074
-#define CS_WCRINC 0x075
-#define CS_WCRDEC 0x076
-#define CS_WCRCEIL 0x077
-#define CS_BWDCNT 0x078
-
-#define CS_OTPPER 0x080
-#define CS_OTWPER 0x081
-#define CS_OTTLIM 0x082
-#define CS_OTTCNT 0x083
-
-#define CS_HGRRT0 0x090
- /* ... */
-#define CS_HGRRT7 0x097
-
-#define CS_ORPTRS 0x0a0
-
-#define RXCON_CLOSE 0x100
-
-
-#define RCM_MEM_SIZE 0x10000 /* 1M of 32-bit registers */
-#define TCM_MEM_SIZE 0x20000 /* 2M of 32-bit registers */
-
-/* 2.5 transmit connection memory registers */
-
-#define TSR0_CONN_STATE(x) ((x>>28) & 0x7)
-#define TSR0_USE_WMIN (1<<23)
-#define TSR0_GROUP(x) ((x & 0x7)<<18)
-#define TSR0_ABR (2<<16)
-#define TSR0_UBR (1<<16)
-#define TSR0_CBR (0<<16)
-#define TSR0_PROT (1<<15)
-#define TSR0_AAL0_SDU (2<<12)
-#define TSR0_AAL0 (1<<12)
-#define TSR0_AAL5 (0<<12)
-#define TSR0_HALT_ER (1<<11)
-#define TSR0_MARK_CI (1<<10)
-#define TSR0_MARK_ER (1<<9)
-#define TSR0_UPDATE_GER (1<<8)
-#define TSR0_RC_INDEX(x) (x & 0x1F)
-
-#define TSR1_PCR(x) ((x & 0x7FFF)<<16)
-#define TSR1_MCR(x) (x & 0x7FFF)
-
-#define TSR2_ACR(x) ((x & 0x7FFF)<<16)
-
-#define TSR3_NRM_CNT(x) ((x & 0xFF)<<24)
-#define TSR3_CRM_CNT(x) (x & 0xFFFF)
-
-#define TSR4_FLUSH_CONN (1<<31)
-#define TSR4_SESSION_ENDED (1<<30)
-#define TSR4_CRC10 (1<<28)
-#define TSR4_NULL_CRC10 (1<<27)
-#define TSR4_PROT (1<<26)
-#define TSR4_AAL0_SDU (2<<23)
-#define TSR4_AAL0 (1<<23)
-#define TSR4_AAL5 (0<<23)
-
-#define TSR9_OPEN_CONN (1<<20)
-
-#define TSR11_ICR(x) ((x & 0x7FFF)<<16)
-#define TSR11_TRM(x) ((x & 0x7)<<13)
-#define TSR11_NRM(x) ((x & 0x7)<<10)
-#define TSR11_ADTF(x) (x & 0x3FF)
-
-#define TSR13_RDF(x) ((x & 0xF)<<23)
-#define TSR13_RIF(x) ((x & 0xF)<<19)
-#define TSR13_CDF(x) ((x & 0x7)<<16)
-#define TSR13_CRM(x) (x & 0xFFFF)
-
-#define TSR14_DELETE (1<<31)
-#define TSR14_ABR_CLOSE (1<<16)
-
-/* 2.7.1 per connection receieve state registers */
-
-#define RSR0_START_PDU (1<<10)
-#define RSR0_OPEN_CONN (1<<6)
-#define RSR0_CLOSE_CONN (0<<6)
-#define RSR0_PPD_ENABLE (1<<5)
-#define RSR0_EPD_ENABLE (1<<4)
-#define RSR0_TCP_CKSUM (1<<3)
-#define RSR0_AAL5 (0)
-#define RSR0_AAL0 (1)
-#define RSR0_AAL0_SDU (2)
-#define RSR0_RAWCELL (3)
-#define RSR0_RAWCELL_CRC10 (4)
-
-#define RSR1_AQI_ENABLE (1<<20)
-#define RSR1_RBPL_ONLY (1<<19)
-#define RSR1_GROUP(x) ((x)<<16)
-
-#define RSR4_AQI_ENABLE (1<<30)
-#define RSR4_GROUP(x) ((x)<<27)
-#define RSR4_RBPL_ONLY (1<<26)
-
-/* 2.1.4 transmit packet descriptor */
-
-#define TPD_USERCELL 0x0
-#define TPD_SEGMENT_OAMF5 0x4
-#define TPD_END2END_OAMF5 0x5
-#define TPD_RMCELL 0x6
-#define TPD_CELLTYPE(x) (x<<3)
-#define TPD_EOS (1<<2)
-#define TPD_CLP (1<<1)
-#define TPD_INT (1<<0)
-#define TPD_LST (1<<31)
-
-/* table 4.3 serial eeprom information */
-
-#define PROD_ID 0x08 /* char[] */
-#define PROD_ID_LEN 30
-#define HW_REV 0x26 /* char[] */
-#define M_SN 0x3a /* integer */
-#define MEDIA 0x3e /* integer */
-#define HE155MM 0x26
-#define HE622MM 0x27
-#define HE155SM 0x46
-#define HE622SM 0x47
-#define MAC_ADDR 0x42 /* char[] */
-
-#define CS_LOW 0x0
-#define CS_HIGH ID_CS /* HOST_CNTL_ID_PROM_SEL */
-#define CLK_LOW 0x0
-#define CLK_HIGH ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */
-#define SI_HIGH ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */
-#define EEPROM_DELAY 400 /* microseconds */
-
-#endif /* _HE_H_ */
diff --git a/drivers/atm/idt77105.h b/drivers/atm/idt77105.h
deleted file mode 100644
index 8dfea9e361de..000000000000
--- a/drivers/atm/idt77105.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* drivers/atm/idt77105.h - IDT77105 (PHY) declarations */
-
-/* Written 1999 by Greg Banks, NEC Australia <gnb@linuxfan.com>. Based on suni.h */
-
-
-#ifndef DRIVER_ATM_IDT77105_H
-#define DRIVER_ATM_IDT77105_H
-
-#include <linux/atmdev.h>
-#include <linux/atmioc.h>
-
-
-/* IDT77105 registers */
-
-#define IDT77105_MCR 0x0 /* Master Control Register */
-#define IDT77105_ISTAT 0x1 /* Interrupt Status */
-#define IDT77105_DIAG 0x2 /* Diagnostic Control */
-#define IDT77105_LEDHEC 0x3 /* LED Driver & HEC Status/Control */
-#define IDT77105_CTRLO 0x4 /* Low Byte Counter Register */
-#define IDT77105_CTRHI 0x5 /* High Byte Counter Register */
-#define IDT77105_CTRSEL 0x6 /* Counter Register Read Select */
-
-/* IDT77105 register values */
-
-/* MCR */
-#define IDT77105_MCR_UPLO 0x80 /* R/W, User Prog'le Output Latch */
-#define IDT77105_MCR_DREC 0x40 /* R/W, Discard Receive Error Cells */
-#define IDT77105_MCR_ECEIO 0x20 /* R/W, Enable Cell Error Interrupts
- * Only */
-#define IDT77105_MCR_TDPC 0x10 /* R/W, Transmit Data Parity Check */
-#define IDT77105_MCR_DRIC 0x08 /* R/W, Discard Received Idle Cells */
-#define IDT77105_MCR_HALTTX 0x04 /* R/W, Halt Tx */
-#define IDT77105_MCR_UMODE 0x02 /* R/W, Utopia (cell/byte) Mode */
-#define IDT77105_MCR_EIP 0x01 /* R/W, Enable Interrupt Pin */
-
-/* ISTAT */
-#define IDT77105_ISTAT_GOODSIG 0x40 /* R, Good Signal Bit */
-#define IDT77105_ISTAT_HECERR 0x20 /* sticky, HEC Error*/
-#define IDT77105_ISTAT_SCR 0x10 /* sticky, Short Cell Received */
-#define IDT77105_ISTAT_TPE 0x08 /* sticky, Transmit Parity Error */
-#define IDT77105_ISTAT_RSCC 0x04 /* sticky, Rx Signal Condition Change */
-#define IDT77105_ISTAT_RSE 0x02 /* sticky, Rx Symbol Error */
-#define IDT77105_ISTAT_RFO 0x01 /* sticky, Rx FIFO Overrun */
-
-/* DIAG */
-#define IDT77105_DIAG_FTD 0x80 /* R/W, Force TxClav deassert */
-#define IDT77105_DIAG_ROS 0x40 /* R/W, RxClav operation select */
-#define IDT77105_DIAG_MPCS 0x20 /* R/W, Multi-PHY config'n select */
-#define IDT77105_DIAG_RFLUSH 0x10 /* R/W, clear receive FIFO */
-#define IDT77105_DIAG_ITPE 0x08 /* R/W, Insert Tx payload error */
-#define IDT77105_DIAG_ITHE 0x04 /* R/W, Insert Tx HEC error */
-#define IDT77105_DIAG_UMODE 0x02 /* R/W, Utopia (cell/byte) Mode */
-#define IDT77105_DIAG_LCMASK 0x03 /* R/W, Loopback Control */
-
-#define IDT77105_DIAG_LC_NORMAL 0x00 /* Receive from network */
-#define IDT77105_DIAG_LC_PHY_LOOPBACK 0x02
-#define IDT77105_DIAG_LC_LINE_LOOPBACK 0x03
-
-/* LEDHEC */
-#define IDT77105_LEDHEC_DRHC 0x40 /* R/W, Disable Rx HEC check */
-#define IDT77105_LEDHEC_DTHC 0x20 /* R/W, Disable Tx HEC calculation */
-#define IDT77105_LEDHEC_RPWMASK 0x18 /* R/W, RxRef pulse width select */
-#define IDT77105_LEDHEC_TFS 0x04 /* R, Tx FIFO Status (1=empty) */
-#define IDT77105_LEDHEC_TLS 0x02 /* R, Tx LED Status (1=lit) */
-#define IDT77105_LEDHEC_RLS 0x01 /* R, Rx LED Status (1=lit) */
-
-#define IDT77105_LEDHEC_RPW_1 0x00 /* RxRef active for 1 RxClk cycle */
-#define IDT77105_LEDHEC_RPW_2 0x08 /* RxRef active for 2 RxClk cycle */
-#define IDT77105_LEDHEC_RPW_4 0x10 /* RxRef active for 4 RxClk cycle */
-#define IDT77105_LEDHEC_RPW_8 0x18 /* RxRef active for 8 RxClk cycle */
-
-/* CTRSEL */
-#define IDT77105_CTRSEL_SEC 0x08 /* W, Symbol Error Counter */
-#define IDT77105_CTRSEL_TCC 0x04 /* W, Tx Cell Counter */
-#define IDT77105_CTRSEL_RCC 0x02 /* W, Rx Cell Counter */
-#define IDT77105_CTRSEL_RHEC 0x01 /* W, Rx HEC Error Counter */
-
-#ifdef __KERNEL__
-int idt77105_init(struct atm_dev *dev);
-#endif
-
-/*
- * Tunable parameters
- */
-
-/* Time between samples of the hardware cell counters. Should be <= 1 sec */
-#define IDT77105_STATS_TIMER_PERIOD (HZ)
-/* Time between checks to see if the signal has been found again */
-#define IDT77105_RESTART_TIMER_PERIOD (5 * HZ)
-
-#endif
diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h
deleted file mode 100644
index b059d31364dd..000000000000
--- a/drivers/atm/idt77252.h
+++ /dev/null
@@ -1,816 +0,0 @@
-/*******************************************************************
- *
- * Copyright (c) 2000 ATecoM GmbH
- *
- * The author may be reached at ecd@atecom.com.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *******************************************************************/
-
-#ifndef _IDT77252_H
-#define _IDT77252_H 1
-
-
-#include <linux/ptrace.h>
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-
-/*****************************************************************************/
-/* */
-/* Makros */
-/* */
-/*****************************************************************************/
-#define VPCI2VC(card, vpi, vci) \
- (((vpi) << card->vcibits) | ((vci) & card->vcimask))
-
-/*****************************************************************************/
-/* */
-/* DEBUGGING definitions */
-/* */
-/*****************************************************************************/
-
-#define DBG_RAW_CELL 0x00000400
-#define DBG_TINY 0x00000200
-#define DBG_GENERAL 0x00000100
-#define DBG_XGENERAL 0x00000080
-#define DBG_INIT 0x00000040
-#define DBG_DEINIT 0x00000020
-#define DBG_INTERRUPT 0x00000010
-#define DBG_OPEN_CONN 0x00000008
-#define DBG_CLOSE_CONN 0x00000004
-#define DBG_RX_DATA 0x00000002
-#define DBG_TX_DATA 0x00000001
-
-#ifdef CONFIG_ATM_IDT77252_DEBUG
-
-#define CPRINTK(args...) do { if (debug & DBG_CLOSE_CONN) printk(args); } while(0)
-#define OPRINTK(args...) do { if (debug & DBG_OPEN_CONN) printk(args); } while(0)
-#define IPRINTK(args...) do { if (debug & DBG_INIT) printk(args); } while(0)
-#define INTPRINTK(args...) do { if (debug & DBG_INTERRUPT) printk(args); } while(0)
-#define DIPRINTK(args...) do { if (debug & DBG_DEINIT) printk(args); } while(0)
-#define TXPRINTK(args...) do { if (debug & DBG_TX_DATA) printk(args); } while(0)
-#define RXPRINTK(args...) do { if (debug & DBG_RX_DATA) printk(args); } while(0)
-#define XPRINTK(args...) do { if (debug & DBG_XGENERAL) printk(args); } while(0)
-#define DPRINTK(args...) do { if (debug & DBG_GENERAL) printk(args); } while(0)
-#define NPRINTK(args...) do { if (debug & DBG_TINY) printk(args); } while(0)
-#define RPRINTK(args...) do { if (debug & DBG_RAW_CELL) printk(args); } while(0)
-
-#else
-
-#define CPRINTK(args...) do { } while(0)
-#define OPRINTK(args...) do { } while(0)
-#define IPRINTK(args...) do { } while(0)
-#define INTPRINTK(args...) do { } while(0)
-#define DIPRINTK(args...) do { } while(0)
-#define TXPRINTK(args...) do { } while(0)
-#define RXPRINTK(args...) do { } while(0)
-#define XPRINTK(args...) do { } while(0)
-#define DPRINTK(args...) do { } while(0)
-#define NPRINTK(args...) do { } while(0)
-#define RPRINTK(args...) do { } while(0)
-
-#endif
-
-#define SCHED_UBR0 0
-#define SCHED_UBR 1
-#define SCHED_VBR 2
-#define SCHED_ABR 3
-#define SCHED_CBR 4
-
-#define SCQFULL_TIMEOUT HZ
-
-/*****************************************************************************/
-/* */
-/* Free Buffer Queue Layout */
-/* */
-/*****************************************************************************/
-#define SAR_FB_SIZE_0 (2048 - 256)
-#define SAR_FB_SIZE_1 (4096 - 256)
-#define SAR_FB_SIZE_2 (8192 - 256)
-#define SAR_FB_SIZE_3 (16384 - 256)
-
-#define SAR_FBQ0_LOW 4
-#define SAR_FBQ0_HIGH 8
-#define SAR_FBQ1_LOW 2
-#define SAR_FBQ1_HIGH 4
-#define SAR_FBQ2_LOW 1
-#define SAR_FBQ2_HIGH 2
-#define SAR_FBQ3_LOW 1
-#define SAR_FBQ3_HIGH 2
-
-#if 0
-#define SAR_TST_RESERVED 44 /* Num TST reserved for UBR/ABR/VBR */
-#else
-#define SAR_TST_RESERVED 0 /* Num TST reserved for UBR/ABR/VBR */
-#endif
-
-#define TCT_CBR 0x00000000
-#define TCT_UBR 0x00000000
-#define TCT_VBR 0x40000000
-#define TCT_ABR 0x80000000
-#define TCT_TYPE 0xc0000000
-
-#define TCT_RR 0x20000000
-#define TCT_LMCR 0x08000000
-#define TCT_SCD_MASK 0x0007ffff
-
-#define TCT_TSIF 0x00004000
-#define TCT_HALT 0x80000000
-#define TCT_IDLE 0x40000000
-#define TCT_FLAG_UBR 0x80000000
-
-/*****************************************************************************/
-/* */
-/* Structure describing an IDT77252 */
-/* */
-/*****************************************************************************/
-
-struct scqe
-{
- u32 word_1;
- u32 word_2;
- u32 word_3;
- u32 word_4;
-};
-
-#define SCQ_ENTRIES 64
-#define SCQ_SIZE (SCQ_ENTRIES * sizeof(struct scqe))
-#define SCQ_MASK (SCQ_SIZE - 1)
-
-struct scq_info
-{
- struct scqe *base;
- struct scqe *next;
- struct scqe *last;
- dma_addr_t paddr;
- spinlock_t lock;
- atomic_t used;
- unsigned long trans_start;
- unsigned long scd;
- spinlock_t skblock;
- struct sk_buff_head transmit;
- struct sk_buff_head pending;
-};
-
-struct rx_pool {
- struct sk_buff_head queue;
- unsigned int len;
-};
-
-struct aal1 {
- unsigned int total;
- unsigned int count;
- struct sk_buff *data;
- unsigned char sequence;
-};
-
-struct vc_map;
-
-struct rate_estimator {
- struct timer_list timer;
- unsigned int interval;
- unsigned int ewma_log;
- u64 cells;
- u64 last_cells;
- long avcps;
- u32 cps;
- u32 maxcps;
- struct vc_map *vc;
-};
-
-struct vc_map {
- unsigned int index;
- unsigned long flags;
-#define VCF_TX 0
-#define VCF_RX 1
-#define VCF_IDLE 2
-#define VCF_RSV 3
- unsigned int class;
- u8 init_er;
- u8 lacr;
- u8 max_er;
- unsigned int ntste;
- spinlock_t lock;
- struct atm_vcc *tx_vcc;
- struct atm_vcc *rx_vcc;
- struct idt77252_dev *card;
- struct scq_info *scq; /* To keep track of the SCQ */
- struct rate_estimator *estimator;
- int scd_index;
- union {
- struct rx_pool rx_pool;
- struct aal1 aal1;
- } rcv;
-};
-
-/*****************************************************************************/
-/* */
-/* RCTE - Receive Connection Table Entry */
-/* */
-/*****************************************************************************/
-
-struct rct_entry
-{
- u32 word_1;
- u32 buffer_handle;
- u32 dma_address;
- u32 aal5_crc32;
-};
-
-/*****************************************************************************/
-/* */
-/* RSQ - Receive Status Queue */
-/* */
-/*****************************************************************************/
-
-#define SAR_RSQE_VALID 0x80000000
-#define SAR_RSQE_IDLE 0x40000000
-#define SAR_RSQE_BUF_MASK 0x00030000
-#define SAR_RSQE_BUF_ASGN 0x00008000
-#define SAR_RSQE_NZGFC 0x00004000
-#define SAR_RSQE_EPDU 0x00002000
-#define SAR_RSQE_BUF_CONT 0x00001000
-#define SAR_RSQE_EFCIE 0x00000800
-#define SAR_RSQE_CLP 0x00000400
-#define SAR_RSQE_CRC 0x00000200
-#define SAR_RSQE_CELLCNT 0x000001FF
-
-
-#define RSQSIZE 8192
-#define RSQ_NUM_ENTRIES (RSQSIZE / 16)
-#define RSQ_ALIGNMENT 8192
-
-struct rsq_entry {
- u32 word_1;
- u32 word_2;
- u32 word_3;
- u32 word_4;
-};
-
-struct rsq_info {
- struct rsq_entry *base;
- struct rsq_entry *next;
- struct rsq_entry *last;
- dma_addr_t paddr;
-};
-
-
-/*****************************************************************************/
-/* */
-/* TSQ - Transmit Status Queue */
-/* */
-/*****************************************************************************/
-
-#define SAR_TSQE_INVALID 0x80000000
-#define SAR_TSQE_TIMESTAMP 0x00FFFFFF
-#define SAR_TSQE_TYPE 0x60000000
-#define SAR_TSQE_TYPE_TIMER 0x00000000
-#define SAR_TSQE_TYPE_TSR 0x20000000
-#define SAR_TSQE_TYPE_IDLE 0x40000000
-#define SAR_TSQE_TYPE_TBD_COMP 0x60000000
-
-#define SAR_TSQE_TAG(stat) (((stat) >> 24) & 0x1f)
-
-#define TSQSIZE 8192
-#define TSQ_NUM_ENTRIES 1024
-#define TSQ_ALIGNMENT 8192
-
-struct tsq_entry
-{
- u32 word_1;
- u32 word_2;
-};
-
-struct tsq_info
-{
- struct tsq_entry *base;
- struct tsq_entry *next;
- struct tsq_entry *last;
- dma_addr_t paddr;
-};
-
-struct tst_info
-{
- struct vc_map *vc;
- u32 tste;
-};
-
-#define TSTE_MASK 0x601fffff
-
-#define TSTE_OPC_MASK 0x60000000
-#define TSTE_OPC_NULL 0x00000000
-#define TSTE_OPC_CBR 0x20000000
-#define TSTE_OPC_VAR 0x40000000
-#define TSTE_OPC_JMP 0x60000000
-
-#define TSTE_PUSH_IDLE 0x01000000
-#define TSTE_PUSH_ACTIVE 0x02000000
-
-#define TST_SWITCH_DONE 0
-#define TST_SWITCH_PENDING 1
-#define TST_SWITCH_WAIT 2
-
-#define FBQ_SHIFT 9
-#define FBQ_SIZE (1 << FBQ_SHIFT)
-#define FBQ_MASK (FBQ_SIZE - 1)
-
-struct sb_pool
-{
- unsigned int index;
- struct sk_buff *skb[FBQ_SIZE];
-};
-
-#define POOL_HANDLE(queue, index) (((queue + 1) << 16) | (index))
-#define POOL_QUEUE(handle) (((handle) >> 16) - 1)
-#define POOL_INDEX(handle) ((handle) & 0xffff)
-
-struct idt77252_dev
-{
- struct tsq_info tsq; /* Transmit Status Queue */
- struct rsq_info rsq; /* Receive Status Queue */
-
- struct pci_dev *pcidev; /* PCI handle (desriptor) */
- struct atm_dev *atmdev; /* ATM device desriptor */
-
- void __iomem *membase; /* SAR's memory base address */
- unsigned long srambase; /* SAR's sram base address */
- void __iomem *fbq[4]; /* FBQ fill addresses */
-
- struct mutex mutex;
- spinlock_t cmd_lock; /* for r/w utility/sram */
-
- unsigned long softstat;
- unsigned long flags; /* see blow */
-
- struct work_struct tqueue;
-
- unsigned long tct_base; /* TCT base address in SRAM */
- unsigned long rct_base; /* RCT base address in SRAM */
- unsigned long rt_base; /* Rate Table base in SRAM */
- unsigned long scd_base; /* SCD base address in SRAM */
- unsigned long tst[2]; /* TST base address in SRAM */
- unsigned long abrst_base; /* ABRST base address in SRAM */
- unsigned long fifo_base; /* RX FIFO base in SRAM */
-
- unsigned long irqstat[16];
-
- unsigned int sramsize; /* SAR's sram size */
-
- unsigned int tct_size; /* total TCT entries */
- unsigned int rct_size; /* total RCT entries */
- unsigned int scd_size; /* length of SCD */
- unsigned int tst_size; /* total TST entries */
- unsigned int tst_free; /* free TSTEs in TST */
- unsigned int abrst_size; /* size of ABRST in words */
- unsigned int fifo_size; /* size of RX FIFO in words */
-
- unsigned int vpibits; /* Bits used for VPI index */
- unsigned int vcibits; /* Bits used for VCI index */
- unsigned int vcimask; /* Mask for VCI index */
-
- unsigned int utopia_pcr; /* Utopia Itf's Cell Rate */
- unsigned int link_pcr; /* PHY's Peek Cell Rate */
-
- struct vc_map **vcs; /* Open Connections */
- struct vc_map **scd2vc; /* SCD to Connection map */
-
- struct tst_info *soft_tst; /* TST to Connection map */
- unsigned int tst_index; /* Current TST in use */
- struct timer_list tst_timer;
- spinlock_t tst_lock;
- unsigned long tst_state;
-
- struct sb_pool sbpool[4]; /* Pool of RX skbuffs */
- struct sk_buff *raw_cell_head; /* Pointer to raw cell queue */
- u32 *raw_cell_hnd; /* Pointer to RCQ handle */
- dma_addr_t raw_cell_paddr;
-
- int index; /* SAR's ID */
- int revision; /* chip revision */
-
- char name[16]; /* Device name */
-
- struct idt77252_dev *next;
-};
-
-
-/* definition for flag field above */
-#define IDT77252_BIT_INIT 1
-#define IDT77252_BIT_INTERRUPT 2
-
-
-#define ATM_CELL_PAYLOAD 48
-
-#define FREEBUF_ALIGNMENT 16
-
-/*****************************************************************************/
-/* */
-/* Makros */
-/* */
-/*****************************************************************************/
-#define ALIGN_ADDRESS(addr, alignment) \
- ((((u32)(addr)) + (((u32)(alignment))-1)) & ~(((u32)(alignment)) - 1))
-
-
-/*****************************************************************************/
-/* */
-/* ABR SAR Network operation Register */
-/* */
-/*****************************************************************************/
-
-#define SAR_REG_DR0 (card->membase + 0x00)
-#define SAR_REG_DR1 (card->membase + 0x04)
-#define SAR_REG_DR2 (card->membase + 0x08)
-#define SAR_REG_DR3 (card->membase + 0x0C)
-#define SAR_REG_CMD (card->membase + 0x10)
-#define SAR_REG_CFG (card->membase + 0x14)
-#define SAR_REG_STAT (card->membase + 0x18)
-#define SAR_REG_RSQB (card->membase + 0x1C)
-#define SAR_REG_RSQT (card->membase + 0x20)
-#define SAR_REG_RSQH (card->membase + 0x24)
-#define SAR_REG_CDC (card->membase + 0x28)
-#define SAR_REG_VPEC (card->membase + 0x2C)
-#define SAR_REG_ICC (card->membase + 0x30)
-#define SAR_REG_RAWCT (card->membase + 0x34)
-#define SAR_REG_TMR (card->membase + 0x38)
-#define SAR_REG_TSTB (card->membase + 0x3C)
-#define SAR_REG_TSQB (card->membase + 0x40)
-#define SAR_REG_TSQT (card->membase + 0x44)
-#define SAR_REG_TSQH (card->membase + 0x48)
-#define SAR_REG_GP (card->membase + 0x4C)
-#define SAR_REG_VPM (card->membase + 0x50)
-#define SAR_REG_RXFD (card->membase + 0x54)
-#define SAR_REG_RXFT (card->membase + 0x58)
-#define SAR_REG_RXFH (card->membase + 0x5C)
-#define SAR_REG_RAWHND (card->membase + 0x60)
-#define SAR_REG_RXSTAT (card->membase + 0x64)
-#define SAR_REG_ABRSTD (card->membase + 0x68)
-#define SAR_REG_ABRRQ (card->membase + 0x6C)
-#define SAR_REG_VBRRQ (card->membase + 0x70)
-#define SAR_REG_RTBL (card->membase + 0x74)
-#define SAR_REG_MDFCT (card->membase + 0x78)
-#define SAR_REG_TXSTAT (card->membase + 0x7C)
-#define SAR_REG_TCMDQ (card->membase + 0x80)
-#define SAR_REG_IRCP (card->membase + 0x84)
-#define SAR_REG_FBQP0 (card->membase + 0x88)
-#define SAR_REG_FBQP1 (card->membase + 0x8C)
-#define SAR_REG_FBQP2 (card->membase + 0x90)
-#define SAR_REG_FBQP3 (card->membase + 0x94)
-#define SAR_REG_FBQS0 (card->membase + 0x98)
-#define SAR_REG_FBQS1 (card->membase + 0x9C)
-#define SAR_REG_FBQS2 (card->membase + 0xA0)
-#define SAR_REG_FBQS3 (card->membase + 0xA4)
-#define SAR_REG_FBQWP0 (card->membase + 0xA8)
-#define SAR_REG_FBQWP1 (card->membase + 0xAC)
-#define SAR_REG_FBQWP2 (card->membase + 0xB0)
-#define SAR_REG_FBQWP3 (card->membase + 0xB4)
-#define SAR_REG_NOW (card->membase + 0xB8)
-
-
-/*****************************************************************************/
-/* */
-/* Commands */
-/* */
-/*****************************************************************************/
-
-#define SAR_CMD_NO_OPERATION 0x00000000
-#define SAR_CMD_OPENCLOSE_CONNECTION 0x20000000
-#define SAR_CMD_WRITE_SRAM 0x40000000
-#define SAR_CMD_READ_SRAM 0x50000000
-#define SAR_CMD_READ_UTILITY 0x80000000
-#define SAR_CMD_WRITE_UTILITY 0x90000000
-
-#define SAR_CMD_OPEN_CONNECTION (SAR_CMD_OPENCLOSE_CONNECTION | 0x00080000)
-#define SAR_CMD_CLOSE_CONNECTION SAR_CMD_OPENCLOSE_CONNECTION
-
-
-/*****************************************************************************/
-/* */
-/* Configuration Register bits */
-/* */
-/*****************************************************************************/
-
-#define SAR_CFG_SWRST 0x80000000 /* Software reset */
-#define SAR_CFG_LOOP 0x40000000 /* Internal Loopback */
-#define SAR_CFG_RXPTH 0x20000000 /* Receive Path Enable */
-#define SAR_CFG_IDLE_CLP 0x10000000 /* SAR set CLP Bits of Null Cells */
-#define SAR_CFG_TX_FIFO_SIZE_1 0x04000000 /* TX FIFO Size = 1 cell */
-#define SAR_CFG_TX_FIFO_SIZE_2 0x08000000 /* TX FIFO Size = 2 cells */
-#define SAR_CFG_TX_FIFO_SIZE_4 0x0C000000 /* TX FIFO Size = 4 cells */
-#define SAR_CFG_TX_FIFO_SIZE_9 0x00000000 /* TX FIFO Size = 9 cells (full) */
-#define SAR_CFG_NO_IDLE 0x02000000 /* SAR sends no Null Cells */
-#define SAR_CFG_RSVD1 0x01000000 /* Reserved */
-#define SAR_CFG_RXSTQ_SIZE_2k 0x00000000 /* RX Stat Queue Size = 2048 byte */
-#define SAR_CFG_RXSTQ_SIZE_4k 0x00400000 /* RX Stat Queue Size = 4096 byte */
-#define SAR_CFG_RXSTQ_SIZE_8k 0x00800000 /* RX Stat Queue Size = 8192 byte */
-#define SAR_CFG_RXSTQ_SIZE_R 0x00C00000 /* RX Stat Queue Size = reserved */
-#define SAR_CFG_ICAPT 0x00200000 /* accept Invalid Cells */
-#define SAR_CFG_IGGFC 0x00100000 /* Ignore GFC */
-#define SAR_CFG_VPVCS_0 0x00000000 /* VPI/VCI Select bit range */
-#define SAR_CFG_VPVCS_1 0x00040000 /* VPI/VCI Select bit range */
-#define SAR_CFG_VPVCS_2 0x00080000 /* VPI/VCI Select bit range */
-#define SAR_CFG_VPVCS_8 0x000C0000 /* VPI/VCI Select bit range */
-#define SAR_CFG_CNTBL_1k 0x00000000 /* Connection Table Size */
-#define SAR_CFG_CNTBL_4k 0x00010000 /* Connection Table Size */
-#define SAR_CFG_CNTBL_16k 0x00020000 /* Connection Table Size */
-#define SAR_CFG_CNTBL_512 0x00030000 /* Connection Table Size */
-#define SAR_CFG_VPECA 0x00008000 /* VPI/VCI Error Cell Accept */
-#define SAR_CFG_RXINT_NOINT 0x00000000 /* No Interrupt on PDU received */
-#define SAR_CFG_RXINT_NODELAY 0x00001000 /* Interrupt without delay to host*/
-#define SAR_CFG_RXINT_256US 0x00002000 /* Interrupt with delay 256 usec */
-#define SAR_CFG_RXINT_505US 0x00003000 /* Interrupt with delay 505 usec */
-#define SAR_CFG_RXINT_742US 0x00004000 /* Interrupt with delay 742 usec */
-#define SAR_CFG_RAWIE 0x00000800 /* Raw Cell Queue Interrupt Enable*/
-#define SAR_CFG_RQFIE 0x00000400 /* RSQ Almost Full Int Enable */
-#define SAR_CFG_RSVD2 0x00000200 /* Reserved */
-#define SAR_CFG_CACHE 0x00000100 /* DMA on Cache Line Boundary */
-#define SAR_CFG_TMOIE 0x00000080 /* Timer Roll Over Int Enable */
-#define SAR_CFG_FBIE 0x00000040 /* Free Buffer Queue Int Enable */
-#define SAR_CFG_TXEN 0x00000020 /* Transmit Operation Enable */
-#define SAR_CFG_TXINT 0x00000010 /* Transmit status Int Enable */
-#define SAR_CFG_TXUIE 0x00000008 /* Transmit underrun Int Enable */
-#define SAR_CFG_UMODE 0x00000004 /* Utopia Mode Select */
-#define SAR_CFG_TXSFI 0x00000002 /* Transmit status Full Int Enable*/
-#define SAR_CFG_PHYIE 0x00000001 /* PHY Interrupt Enable */
-
-#define SAR_CFG_TX_FIFO_SIZE_MASK 0x0C000000 /* TX FIFO Size Mask */
-#define SAR_CFG_RXSTQSIZE_MASK 0x00C00000
-#define SAR_CFG_CNTBL_MASK 0x00030000
-#define SAR_CFG_RXINT_MASK 0x00007000
-
-
-/*****************************************************************************/
-/* */
-/* Status Register bits */
-/* */
-/*****************************************************************************/
-
-#define SAR_STAT_FRAC_3 0xF0000000 /* Fraction of Free Buffer Queue 3 */
-#define SAR_STAT_FRAC_2 0x0F000000 /* Fraction of Free Buffer Queue 2 */
-#define SAR_STAT_FRAC_1 0x00F00000 /* Fraction of Free Buffer Queue 1 */
-#define SAR_STAT_FRAC_0 0x000F0000 /* Fraction of Free Buffer Queue 0 */
-#define SAR_STAT_TSIF 0x00008000 /* Transmit Status Indicator */
-#define SAR_STAT_TXICP 0x00004000 /* Transmit Status Indicator */
-#define SAR_STAT_RSVD1 0x00002000 /* Reserved */
-#define SAR_STAT_TSQF 0x00001000 /* Transmit Status Queue full */
-#define SAR_STAT_TMROF 0x00000800 /* Timer overflow */
-#define SAR_STAT_PHYI 0x00000400 /* PHY device Interrupt flag */
-#define SAR_STAT_CMDBZ 0x00000200 /* ABR SAR Command Busy Flag */
-#define SAR_STAT_FBQ3A 0x00000100 /* Free Buffer Queue 3 Attention */
-#define SAR_STAT_FBQ2A 0x00000080 /* Free Buffer Queue 2 Attention */
-#define SAR_STAT_RSQF 0x00000040 /* Receive Status Queue full */
-#define SAR_STAT_EPDU 0x00000020 /* End Of PDU Flag */
-#define SAR_STAT_RAWCF 0x00000010 /* Raw Cell Flag */
-#define SAR_STAT_FBQ1A 0x00000008 /* Free Buffer Queue 1 Attention */
-#define SAR_STAT_FBQ0A 0x00000004 /* Free Buffer Queue 0 Attention */
-#define SAR_STAT_RSQAF 0x00000002 /* Receive Status Queue almost full*/
-#define SAR_STAT_RSVD2 0x00000001 /* Reserved */
-
-
-/*****************************************************************************/
-/* */
-/* General Purpose Register bits */
-/* */
-/*****************************************************************************/
-
-#define SAR_GP_TXNCC_MASK 0xff000000 /* Transmit Negative Credit Count */
-#define SAR_GP_EEDI 0x00010000 /* EEPROM Data In */
-#define SAR_GP_BIGE 0x00008000 /* Big Endian Operation */
-#define SAR_GP_RM_NORMAL 0x00000000 /* Normal handling of RM cells */
-#define SAR_GP_RM_TO_RCQ 0x00002000 /* put RM cells into Raw Cell Queue */
-#define SAR_GP_RM_RSVD 0x00004000 /* Reserved */
-#define SAR_GP_RM_INHIBIT 0x00006000 /* Inhibit update of Connection tab */
-#define SAR_GP_PHY_RESET 0x00000008 /* PHY Reset */
-#define SAR_GP_EESCLK 0x00000004 /* EEPROM SCLK */
-#define SAR_GP_EECS 0x00000002 /* EEPROM Chip Select */
-#define SAR_GP_EEDO 0x00000001 /* EEPROM Data Out */
-
-
-/*****************************************************************************/
-/* */
-/* SAR local SRAM layout for 128k work SRAM */
-/* */
-/*****************************************************************************/
-
-#define SAR_SRAM_SCD_SIZE 12
-#define SAR_SRAM_TCT_SIZE 8
-#define SAR_SRAM_RCT_SIZE 4
-
-#define SAR_SRAM_TCT_128_BASE 0x00000
-#define SAR_SRAM_TCT_128_TOP 0x01fff
-#define SAR_SRAM_RCT_128_BASE 0x02000
-#define SAR_SRAM_RCT_128_TOP 0x02fff
-#define SAR_SRAM_FB0_128_BASE 0x03000
-#define SAR_SRAM_FB0_128_TOP 0x033ff
-#define SAR_SRAM_FB1_128_BASE 0x03400
-#define SAR_SRAM_FB1_128_TOP 0x037ff
-#define SAR_SRAM_FB2_128_BASE 0x03800
-#define SAR_SRAM_FB2_128_TOP 0x03bff
-#define SAR_SRAM_FB3_128_BASE 0x03c00
-#define SAR_SRAM_FB3_128_TOP 0x03fff
-#define SAR_SRAM_SCD_128_BASE 0x04000
-#define SAR_SRAM_SCD_128_TOP 0x07fff
-#define SAR_SRAM_TST1_128_BASE 0x08000
-#define SAR_SRAM_TST1_128_TOP 0x0bfff
-#define SAR_SRAM_TST2_128_BASE 0x0c000
-#define SAR_SRAM_TST2_128_TOP 0x0ffff
-#define SAR_SRAM_ABRSTD_128_BASE 0x10000
-#define SAR_SRAM_ABRSTD_128_TOP 0x13fff
-#define SAR_SRAM_RT_128_BASE 0x14000
-#define SAR_SRAM_RT_128_TOP 0x15fff
-
-#define SAR_SRAM_FIFO_128_BASE 0x18000
-#define SAR_SRAM_FIFO_128_TOP 0x1ffff
-
-
-/*****************************************************************************/
-/* */
-/* SAR local SRAM layout for 32k work SRAM */
-/* */
-/*****************************************************************************/
-
-#define SAR_SRAM_TCT_32_BASE 0x00000
-#define SAR_SRAM_TCT_32_TOP 0x00fff
-#define SAR_SRAM_RCT_32_BASE 0x01000
-#define SAR_SRAM_RCT_32_TOP 0x017ff
-#define SAR_SRAM_FB0_32_BASE 0x01800
-#define SAR_SRAM_FB0_32_TOP 0x01bff
-#define SAR_SRAM_FB1_32_BASE 0x01c00
-#define SAR_SRAM_FB1_32_TOP 0x01fff
-#define SAR_SRAM_FB2_32_BASE 0x02000
-#define SAR_SRAM_FB2_32_TOP 0x023ff
-#define SAR_SRAM_FB3_32_BASE 0x02400
-#define SAR_SRAM_FB3_32_TOP 0x027ff
-#define SAR_SRAM_SCD_32_BASE 0x02800
-#define SAR_SRAM_SCD_32_TOP 0x03fff
-#define SAR_SRAM_TST1_32_BASE 0x04000
-#define SAR_SRAM_TST1_32_TOP 0x04fff
-#define SAR_SRAM_TST2_32_BASE 0x05000
-#define SAR_SRAM_TST2_32_TOP 0x05fff
-#define SAR_SRAM_ABRSTD_32_BASE 0x06000
-#define SAR_SRAM_ABRSTD_32_TOP 0x067ff
-#define SAR_SRAM_RT_32_BASE 0x06800
-#define SAR_SRAM_RT_32_TOP 0x06fff
-#define SAR_SRAM_FIFO_32_BASE 0x07000
-#define SAR_SRAM_FIFO_32_TOP 0x07fff
-
-
-/*****************************************************************************/
-/* */
-/* TSR - Transmit Status Request */
-/* */
-/*****************************************************************************/
-
-#define SAR_TSR_TYPE_TSR 0x80000000
-#define SAR_TSR_TYPE_TBD 0x00000000
-#define SAR_TSR_TSIF 0x20000000
-#define SAR_TSR_TAG_MASK 0x01F00000
-
-
-/*****************************************************************************/
-/* */
-/* TBD - Transmit Buffer Descriptor */
-/* */
-/*****************************************************************************/
-
-#define SAR_TBD_EPDU 0x40000000
-#define SAR_TBD_TSIF 0x20000000
-#define SAR_TBD_OAM 0x10000000
-#define SAR_TBD_AAL0 0x00000000
-#define SAR_TBD_AAL34 0x04000000
-#define SAR_TBD_AAL5 0x08000000
-#define SAR_TBD_GTSI 0x02000000
-#define SAR_TBD_TAG_MASK 0x01F00000
-
-#define SAR_TBD_VPI_MASK 0x0FF00000
-#define SAR_TBD_VCI_MASK 0x000FFFF0
-#define SAR_TBD_VC_MASK (SAR_TBD_VPI_MASK | SAR_TBD_VCI_MASK)
-
-#define SAR_TBD_VPI_SHIFT 20
-#define SAR_TBD_VCI_SHIFT 4
-
-
-/*****************************************************************************/
-/* */
-/* RXFD - Receive FIFO Descriptor */
-/* */
-/*****************************************************************************/
-
-#define SAR_RXFD_SIZE_MASK 0x0F000000
-#define SAR_RXFD_SIZE_512 0x00000000 /* 512 words */
-#define SAR_RXFD_SIZE_1K 0x01000000 /* 1k words */
-#define SAR_RXFD_SIZE_2K 0x02000000 /* 2k words */
-#define SAR_RXFD_SIZE_4K 0x03000000 /* 4k words */
-#define SAR_RXFD_SIZE_8K 0x04000000 /* 8k words */
-#define SAR_RXFD_SIZE_16K 0x05000000 /* 16k words */
-#define SAR_RXFD_SIZE_32K 0x06000000 /* 32k words */
-#define SAR_RXFD_SIZE_64K 0x07000000 /* 64k words */
-#define SAR_RXFD_SIZE_128K 0x08000000 /* 128k words */
-#define SAR_RXFD_SIZE_256K 0x09000000 /* 256k words */
-#define SAR_RXFD_ADDR_MASK 0x001ffc00
-
-
-/*****************************************************************************/
-/* */
-/* ABRSTD - ABR + VBR Schedule Tables */
-/* */
-/*****************************************************************************/
-
-#define SAR_ABRSTD_SIZE_MASK 0x07000000
-#define SAR_ABRSTD_SIZE_512 0x00000000 /* 512 words */
-#define SAR_ABRSTD_SIZE_1K 0x01000000 /* 1k words */
-#define SAR_ABRSTD_SIZE_2K 0x02000000 /* 2k words */
-#define SAR_ABRSTD_SIZE_4K 0x03000000 /* 4k words */
-#define SAR_ABRSTD_SIZE_8K 0x04000000 /* 8k words */
-#define SAR_ABRSTD_SIZE_16K 0x05000000 /* 16k words */
-#define SAR_ABRSTD_ADDR_MASK 0x001ffc00
-
-
-/*****************************************************************************/
-/* */
-/* RCTE - Receive Connection Table Entry */
-/* */
-/*****************************************************************************/
-
-#define SAR_RCTE_IL_MASK 0xE0000000 /* inactivity limit */
-#define SAR_RCTE_IC_MASK 0x1C000000 /* inactivity count */
-#define SAR_RCTE_RSVD 0x02000000 /* reserved */
-#define SAR_RCTE_LCD 0x01000000 /* last cell data */
-#define SAR_RCTE_CI_VC 0x00800000 /* EFCI in previous cell of VC */
-#define SAR_RCTE_FBP_01 0x00000000 /* 1. cell->FBQ0, others->FBQ1 */
-#define SAR_RCTE_FBP_1 0x00200000 /* use FBQ 1 for all cells */
-#define SAR_RCTE_FBP_2 0x00400000 /* use FBQ 2 for all cells */
-#define SAR_RCTE_FBP_3 0x00600000 /* use FBQ 3 for all cells */
-#define SAR_RCTE_NZ_GFC 0x00100000 /* non zero GFC in all cell of VC */
-#define SAR_RCTE_CONNECTOPEN 0x00080000 /* VC is open */
-#define SAR_RCTE_AAL_MASK 0x00070000 /* mask for AAL type field s.b. */
-#define SAR_RCTE_RAWCELLINTEN 0x00008000 /* raw cell interrupt enable */
-#define SAR_RCTE_RXCONCELLADDR 0x00004000 /* RX constant cell address */
-#define SAR_RCTE_BUFFSTAT_MASK 0x00003000 /* buffer status */
-#define SAR_RCTE_EFCI 0x00000800 /* EFCI Congestion flag */
-#define SAR_RCTE_CLP 0x00000400 /* Cell Loss Priority flag */
-#define SAR_RCTE_CRC 0x00000200 /* Received CRC Error */
-#define SAR_RCTE_CELLCNT_MASK 0x000001FF /* cell Count */
-
-#define SAR_RCTE_AAL0 0x00000000 /* AAL types for ALL field */
-#define SAR_RCTE_AAL34 0x00010000
-#define SAR_RCTE_AAL5 0x00020000
-#define SAR_RCTE_RCQ 0x00030000
-#define SAR_RCTE_OAM 0x00040000
-
-#define TCMDQ_START 0x01000000
-#define TCMDQ_LACR 0x02000000
-#define TCMDQ_START_LACR 0x03000000
-#define TCMDQ_INIT_ER 0x04000000
-#define TCMDQ_HALT 0x05000000
-
-
-struct idt77252_skb_prv {
- struct scqe tbd; /* Transmit Buffer Descriptor */
- dma_addr_t paddr; /* DMA handle */
- u32 pool; /* sb_pool handle */
-} __packed;
-
-#define IDT77252_PRV_TBD(skb) \
- (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->tbd)
-#define IDT77252_PRV_PADDR(skb) \
- (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->paddr)
-#define IDT77252_PRV_POOL(skb) \
- (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->pool)
-
-/*****************************************************************************/
-/* */
-/* PCI related items */
-/* */
-/*****************************************************************************/
-
-#ifndef PCI_VENDOR_ID_IDT
-#define PCI_VENDOR_ID_IDT 0x111D
-#endif /* PCI_VENDOR_ID_IDT */
-
-#ifndef PCI_DEVICE_ID_IDT_IDT77252
-#define PCI_DEVICE_ID_IDT_IDT77252 0x0003
-#endif /* PCI_DEVICE_ID_IDT_IDT772052 */
-
-
-#endif /* !(_IDT77252_H) */
diff --git a/drivers/atm/idt77252_tables.h b/drivers/atm/idt77252_tables.h
deleted file mode 100644
index 12b81e046a7b..000000000000
--- a/drivers/atm/idt77252_tables.h
+++ /dev/null
@@ -1,781 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Do not edit, automatically generated by `./genrtbl'.
- *
- * Cell Line Rate: 353207.55 (155520000 bps)
- */
-
-static unsigned int log_to_rate[] =
-{
-/* 000 */ 0x8d022e27, /* cps = 10.02, nrm = 3, interval = 35264.00 */
-/* 001 */ 0x8d362e11, /* cps = 10.42, nrm = 3, interval = 33856.00 */
-/* 002 */ 0x8d6e2bf8, /* cps = 10.86, nrm = 3, interval = 32512.00 */
-/* 003 */ 0x8da82bcf, /* cps = 11.31, nrm = 3, interval = 31200.00 */
-/* 004 */ 0x8de42ba8, /* cps = 11.78, nrm = 3, interval = 29952.00 */
-/* 005 */ 0x8e242b82, /* cps = 12.28, nrm = 3, interval = 28736.00 */
-/* 006 */ 0x8e662b5e, /* cps = 12.80, nrm = 3, interval = 27584.00 */
-/* 007 */ 0x8eaa2b3c, /* cps = 13.33, nrm = 3, interval = 26496.00 */
-/* 008 */ 0x8ef22b1a, /* cps = 13.89, nrm = 3, interval = 25408.00 */
-/* 009 */ 0x8f3e2afa, /* cps = 14.48, nrm = 3, interval = 24384.00 */
-/* 010 */ 0x8f8a2adc, /* cps = 15.08, nrm = 3, interval = 23424.00 */
-/* 011 */ 0x8fdc2abe, /* cps = 15.72, nrm = 3, interval = 22464.00 */
-/* 012 */ 0x90182aa2, /* cps = 16.38, nrm = 3, interval = 21568.00 */
-/* 013 */ 0x90422a87, /* cps = 17.03, nrm = 3, interval = 20704.00 */
-/* 014 */ 0x90702a6d, /* cps = 17.75, nrm = 3, interval = 19872.00 */
-/* 015 */ 0x90a02a54, /* cps = 18.50, nrm = 3, interval = 19072.00 */
-/* 016 */ 0x90d22a3c, /* cps = 19.28, nrm = 3, interval = 18304.00 */
-/* 017 */ 0x91062a25, /* cps = 20.09, nrm = 3, interval = 17568.00 */
-/* 018 */ 0x913c2a0f, /* cps = 20.94, nrm = 3, interval = 16864.00 */
-/* 019 */ 0x917427f3, /* cps = 21.81, nrm = 3, interval = 16176.00 */
-/* 020 */ 0x91b027ca, /* cps = 22.75, nrm = 3, interval = 15520.00 */
-/* 021 */ 0x91ec27a3, /* cps = 23.69, nrm = 3, interval = 14896.00 */
-/* 022 */ 0x922c277e, /* cps = 24.69, nrm = 3, interval = 14304.00 */
-/* 023 */ 0x926e275a, /* cps = 25.72, nrm = 3, interval = 13728.00 */
-/* 024 */ 0x92b42737, /* cps = 26.81, nrm = 3, interval = 13168.00 */
-/* 025 */ 0x92fc2716, /* cps = 27.94, nrm = 3, interval = 12640.00 */
-/* 026 */ 0x934626f6, /* cps = 29.09, nrm = 3, interval = 12128.00 */
-/* 027 */ 0x939426d8, /* cps = 30.31, nrm = 3, interval = 11648.00 */
-/* 028 */ 0x93e426bb, /* cps = 31.56, nrm = 3, interval = 11184.00 */
-/* 029 */ 0x941e269e, /* cps = 32.94, nrm = 3, interval = 10720.00 */
-/* 030 */ 0x944a2683, /* cps = 34.31, nrm = 3, interval = 10288.00 */
-/* 031 */ 0x9476266a, /* cps = 35.69, nrm = 3, interval = 9888.00 */
-/* 032 */ 0x94a62651, /* cps = 37.19, nrm = 3, interval = 9488.00 */
-/* 033 */ 0x94d82639, /* cps = 38.75, nrm = 3, interval = 9104.00 */
-/* 034 */ 0x950c6622, /* cps = 40.38, nrm = 4, interval = 8736.00 */
-/* 035 */ 0x9544660c, /* cps = 42.12, nrm = 4, interval = 8384.00 */
-/* 036 */ 0x957c63ee, /* cps = 43.88, nrm = 4, interval = 8048.00 */
-/* 037 */ 0x95b663c6, /* cps = 45.69, nrm = 4, interval = 7728.00 */
-/* 038 */ 0x95f4639f, /* cps = 47.62, nrm = 4, interval = 7416.00 */
-/* 039 */ 0x96346379, /* cps = 49.62, nrm = 4, interval = 7112.00 */
-/* 040 */ 0x96766356, /* cps = 51.69, nrm = 4, interval = 6832.00 */
-/* 041 */ 0x96bc6333, /* cps = 53.88, nrm = 4, interval = 6552.00 */
-/* 042 */ 0x97046312, /* cps = 56.12, nrm = 4, interval = 6288.00 */
-/* 043 */ 0x974e62f3, /* cps = 58.44, nrm = 4, interval = 6040.00 */
-/* 044 */ 0x979e62d4, /* cps = 60.94, nrm = 4, interval = 5792.00 */
-/* 045 */ 0x97f062b7, /* cps = 63.50, nrm = 4, interval = 5560.00 */
-/* 046 */ 0x9822629b, /* cps = 66.12, nrm = 4, interval = 5336.00 */
-/* 047 */ 0x984e6280, /* cps = 68.88, nrm = 4, interval = 5120.00 */
-/* 048 */ 0x987e6266, /* cps = 71.88, nrm = 4, interval = 4912.00 */
-/* 049 */ 0x98ac624e, /* cps = 74.75, nrm = 4, interval = 4720.00 */
-/* 050 */ 0x98e06236, /* cps = 78.00, nrm = 4, interval = 4528.00 */
-/* 051 */ 0x9914a21f, /* cps = 81.25, nrm = 8, interval = 4344.00 */
-/* 052 */ 0x994aa209, /* cps = 84.62, nrm = 8, interval = 4168.00 */
-/* 053 */ 0x99829fe9, /* cps = 88.12, nrm = 8, interval = 4004.00 */
-/* 054 */ 0x99be9fc1, /* cps = 91.88, nrm = 8, interval = 3844.00 */
-/* 055 */ 0x99fc9f9a, /* cps = 95.75, nrm = 8, interval = 3688.00 */
-/* 056 */ 0x9a3c9f75, /* cps = 99.75, nrm = 8, interval = 3540.00 */
-/* 057 */ 0x9a809f51, /* cps = 104.00, nrm = 8, interval = 3396.00 */
-/* 058 */ 0x9ac49f2f, /* cps = 108.25, nrm = 8, interval = 3260.00 */
-/* 059 */ 0x9b0e9f0e, /* cps = 112.88, nrm = 8, interval = 3128.00 */
-/* 060 */ 0x9b589eef, /* cps = 117.50, nrm = 8, interval = 3004.00 */
-/* 061 */ 0x9ba69ed1, /* cps = 122.38, nrm = 8, interval = 2884.00 */
-/* 062 */ 0x9bf89eb4, /* cps = 127.50, nrm = 8, interval = 2768.00 */
-/* 063 */ 0x9c269e98, /* cps = 132.75, nrm = 8, interval = 2656.00 */
-/* 064 */ 0x9c549e7d, /* cps = 138.50, nrm = 8, interval = 2548.00 */
-/* 065 */ 0x9c849e63, /* cps = 144.50, nrm = 8, interval = 2444.00 */
-/* 066 */ 0x9cb29e4b, /* cps = 150.25, nrm = 8, interval = 2348.00 */
-/* 067 */ 0x9ce69e33, /* cps = 156.75, nrm = 8, interval = 2252.00 */
-/* 068 */ 0x9d1cde1c, /* cps = 163.50, nrm = 16, interval = 2160.00 */
-/* 069 */ 0x9d50de07, /* cps = 170.00, nrm = 16, interval = 2076.00 */
-/* 070 */ 0x9d8adbe4, /* cps = 177.25, nrm = 16, interval = 1992.00 */
-/* 071 */ 0x9dc4dbbc, /* cps = 184.50, nrm = 16, interval = 1912.00 */
-/* 072 */ 0x9e02db96, /* cps = 192.25, nrm = 16, interval = 1836.00 */
-/* 073 */ 0x9e42db71, /* cps = 200.25, nrm = 16, interval = 1762.00 */
-/* 074 */ 0x9e86db4d, /* cps = 208.75, nrm = 16, interval = 1690.00 */
-/* 075 */ 0x9ecedb2b, /* cps = 217.75, nrm = 16, interval = 1622.00 */
-/* 076 */ 0x9f16db0a, /* cps = 226.75, nrm = 16, interval = 1556.00 */
-/* 077 */ 0x9f62daeb, /* cps = 236.25, nrm = 16, interval = 1494.00 */
-/* 078 */ 0x9fb2dacd, /* cps = 246.25, nrm = 16, interval = 1434.00 */
-/* 079 */ 0xa002dab0, /* cps = 256.50, nrm = 16, interval = 1376.00 */
-/* 080 */ 0xa02eda94, /* cps = 267.50, nrm = 16, interval = 1320.00 */
-/* 081 */ 0xa05ada7a, /* cps = 278.50, nrm = 16, interval = 1268.00 */
-/* 082 */ 0xa088da60, /* cps = 290.00, nrm = 16, interval = 1216.00 */
-/* 083 */ 0xa0b8da48, /* cps = 302.00, nrm = 16, interval = 1168.00 */
-/* 084 */ 0xa0ecda30, /* cps = 315.00, nrm = 16, interval = 1120.00 */
-/* 085 */ 0xa1211a1a, /* cps = 328.00, nrm = 32, interval = 1076.00 */
-/* 086 */ 0xa1591a04, /* cps = 342.00, nrm = 32, interval = 1032.00 */
-/* 087 */ 0xa19117df, /* cps = 356.00, nrm = 32, interval = 991.00 */
-/* 088 */ 0xa1cd17b7, /* cps = 371.00, nrm = 32, interval = 951.00 */
-/* 089 */ 0xa20b1791, /* cps = 386.50, nrm = 32, interval = 913.00 */
-/* 090 */ 0xa24d176c, /* cps = 403.00, nrm = 32, interval = 876.00 */
-/* 091 */ 0xa28f1749, /* cps = 419.50, nrm = 32, interval = 841.00 */
-/* 092 */ 0xa2d71727, /* cps = 437.50, nrm = 32, interval = 807.00 */
-/* 093 */ 0xa31f1707, /* cps = 455.50, nrm = 32, interval = 775.00 */
-/* 094 */ 0xa36d16e7, /* cps = 475.00, nrm = 32, interval = 743.00 */
-/* 095 */ 0xa3bd16c9, /* cps = 495.00, nrm = 32, interval = 713.00 */
-/* 096 */ 0xa40716ad, /* cps = 515.00, nrm = 32, interval = 685.00 */
-/* 097 */ 0xa4331691, /* cps = 537.00, nrm = 32, interval = 657.00 */
-/* 098 */ 0xa45f1677, /* cps = 559.00, nrm = 32, interval = 631.00 */
-/* 099 */ 0xa48f165d, /* cps = 583.00, nrm = 32, interval = 605.00 */
-/* 100 */ 0xa4bf1645, /* cps = 607.00, nrm = 32, interval = 581.00 */
-/* 101 */ 0xa4f1162e, /* cps = 632.00, nrm = 32, interval = 558.00 */
-/* 102 */ 0xa5291617, /* cps = 660.00, nrm = 32, interval = 535.00 */
-/* 103 */ 0xa55f1602, /* cps = 687.00, nrm = 32, interval = 514.00 */
-/* 104 */ 0xa59913da, /* cps = 716.00, nrm = 32, interval = 493.00 */
-/* 105 */ 0xa5d513b2, /* cps = 746.00, nrm = 32, interval = 473.00 */
-/* 106 */ 0xa613138c, /* cps = 777.00, nrm = 32, interval = 454.00 */
-/* 107 */ 0xa6551368, /* cps = 810.00, nrm = 32, interval = 436.00 */
-/* 108 */ 0xa6971345, /* cps = 843.00, nrm = 32, interval = 418.50 */
-/* 109 */ 0xa6df1323, /* cps = 879.00, nrm = 32, interval = 401.50 */
-/* 110 */ 0xa7291303, /* cps = 916.00, nrm = 32, interval = 385.50 */
-/* 111 */ 0xa77512e4, /* cps = 954.00, nrm = 32, interval = 370.00 */
-/* 112 */ 0xa7c512c6, /* cps = 994.00, nrm = 32, interval = 355.00 */
-/* 113 */ 0xa80d12a9, /* cps = 1036.00, nrm = 32, interval = 340.50 */
-/* 114 */ 0xa839128e, /* cps = 1080.00, nrm = 32, interval = 327.00 */
-/* 115 */ 0xa8651274, /* cps = 1124.00, nrm = 32, interval = 314.00 */
-/* 116 */ 0xa895125a, /* cps = 1172.00, nrm = 32, interval = 301.00 */
-/* 117 */ 0xa8c71242, /* cps = 1222.00, nrm = 32, interval = 289.00 */
-/* 118 */ 0xa8f9122b, /* cps = 1272.00, nrm = 32, interval = 277.50 */
-/* 119 */ 0xa92f1214, /* cps = 1326.00, nrm = 32, interval = 266.00 */
-/* 120 */ 0xa9670ffe, /* cps = 1382.00, nrm = 32, interval = 255.50 */
-/* 121 */ 0xa9a10fd5, /* cps = 1440.00, nrm = 32, interval = 245.25 */
-/* 122 */ 0xa9db0fae, /* cps = 1498.00, nrm = 32, interval = 235.50 */
-/* 123 */ 0xaa1b0f88, /* cps = 1562.00, nrm = 32, interval = 226.00 */
-/* 124 */ 0xaa5d0f63, /* cps = 1628.00, nrm = 32, interval = 216.75 */
-/* 125 */ 0xaaa10f41, /* cps = 1696.00, nrm = 32, interval = 208.25 */
-/* 126 */ 0xaae90f1f, /* cps = 1768.00, nrm = 32, interval = 199.75 */
-/* 127 */ 0xab330eff, /* cps = 1842.00, nrm = 32, interval = 191.75 */
-/* 128 */ 0xab7f0ee0, /* cps = 1918.00, nrm = 32, interval = 184.00 */
-/* 129 */ 0xabd10ec2, /* cps = 2000.00, nrm = 32, interval = 176.50 */
-/* 130 */ 0xac110ea6, /* cps = 2080.00, nrm = 32, interval = 169.50 */
-/* 131 */ 0xac3d0e8b, /* cps = 2168.00, nrm = 32, interval = 162.75 */
-/* 132 */ 0xac6d0e70, /* cps = 2264.00, nrm = 32, interval = 156.00 */
-/* 133 */ 0xac9b0e57, /* cps = 2356.00, nrm = 32, interval = 149.75 */
-/* 134 */ 0xaccd0e3f, /* cps = 2456.00, nrm = 32, interval = 143.75 */
-/* 135 */ 0xacff0e28, /* cps = 2556.00, nrm = 32, interval = 138.00 */
-/* 136 */ 0xad350e12, /* cps = 2664.00, nrm = 32, interval = 132.50 */
-/* 137 */ 0xad6d0bf9, /* cps = 2776.00, nrm = 32, interval = 127.12 */
-/* 138 */ 0xada70bd0, /* cps = 2892.00, nrm = 32, interval = 122.00 */
-/* 139 */ 0xade30ba9, /* cps = 3012.00, nrm = 32, interval = 117.12 */
-/* 140 */ 0xae230b83, /* cps = 3140.00, nrm = 32, interval = 112.38 */
-/* 141 */ 0xae650b5f, /* cps = 3272.00, nrm = 32, interval = 107.88 */
-/* 142 */ 0xaeab0b3c, /* cps = 3412.00, nrm = 32, interval = 103.50 */
-/* 143 */ 0xaef10b1b, /* cps = 3552.00, nrm = 32, interval = 99.38 */
-/* 144 */ 0xaf3b0afb, /* cps = 3700.00, nrm = 32, interval = 95.38 */
-/* 145 */ 0xaf8b0adc, /* cps = 3860.00, nrm = 32, interval = 91.50 */
-/* 146 */ 0xafd90abf, /* cps = 4016.00, nrm = 32, interval = 87.88 */
-/* 147 */ 0xb0170aa3, /* cps = 4184.00, nrm = 32, interval = 84.38 */
-/* 148 */ 0xb0430a87, /* cps = 4360.00, nrm = 32, interval = 80.88 */
-/* 149 */ 0xb0710a6d, /* cps = 4544.00, nrm = 32, interval = 77.62 */
-/* 150 */ 0xb0a10a54, /* cps = 4736.00, nrm = 32, interval = 74.50 */
-/* 151 */ 0xb0d30a3c, /* cps = 4936.00, nrm = 32, interval = 71.50 */
-/* 152 */ 0xb1070a25, /* cps = 5144.00, nrm = 32, interval = 68.62 */
-/* 153 */ 0xb13d0a0f, /* cps = 5360.00, nrm = 32, interval = 65.88 */
-/* 154 */ 0xb17507f4, /* cps = 5584.00, nrm = 32, interval = 63.25 */
-/* 155 */ 0xb1af07cb, /* cps = 5816.00, nrm = 32, interval = 60.69 */
-/* 156 */ 0xb1eb07a4, /* cps = 6056.00, nrm = 32, interval = 58.25 */
-/* 157 */ 0xb22b077f, /* cps = 6312.00, nrm = 32, interval = 55.94 */
-/* 158 */ 0xb26d075b, /* cps = 6576.00, nrm = 32, interval = 53.69 */
-/* 159 */ 0xb2b30738, /* cps = 6856.00, nrm = 32, interval = 51.50 */
-/* 160 */ 0xb2fb0717, /* cps = 7144.00, nrm = 32, interval = 49.44 */
-/* 161 */ 0xb34506f7, /* cps = 7440.00, nrm = 32, interval = 47.44 */
-/* 162 */ 0xb39306d9, /* cps = 7752.00, nrm = 32, interval = 45.56 */
-/* 163 */ 0xb3e506bb, /* cps = 8080.00, nrm = 32, interval = 43.69 */
-/* 164 */ 0xb41d069f, /* cps = 8416.00, nrm = 32, interval = 41.94 */
-/* 165 */ 0xb4490684, /* cps = 8768.00, nrm = 32, interval = 40.25 */
-/* 166 */ 0xb477066a, /* cps = 9136.00, nrm = 32, interval = 38.62 */
-/* 167 */ 0xb4a70651, /* cps = 9520.00, nrm = 32, interval = 37.06 */
-/* 168 */ 0xb4d90639, /* cps = 9920.00, nrm = 32, interval = 35.56 */
-/* 169 */ 0xb50d0622, /* cps = 10336.00, nrm = 32, interval = 34.12 */
-/* 170 */ 0xb545060c, /* cps = 10784.00, nrm = 32, interval = 32.75 */
-/* 171 */ 0xb57b03ef, /* cps = 11216.00, nrm = 32, interval = 31.47 */
-/* 172 */ 0xb5b503c7, /* cps = 11680.00, nrm = 32, interval = 30.22 */
-/* 173 */ 0xb5f303a0, /* cps = 12176.00, nrm = 32, interval = 29.00 */
-/* 174 */ 0xb633037a, /* cps = 12688.00, nrm = 32, interval = 27.81 */
-/* 175 */ 0xb6750357, /* cps = 13216.00, nrm = 32, interval = 26.72 */
-/* 176 */ 0xb6bb0334, /* cps = 13776.00, nrm = 32, interval = 25.62 */
-/* 177 */ 0xb7030313, /* cps = 14352.00, nrm = 32, interval = 24.59 */
-/* 178 */ 0xb74f02f3, /* cps = 14960.00, nrm = 32, interval = 23.59 */
-/* 179 */ 0xb79d02d5, /* cps = 15584.00, nrm = 32, interval = 22.66 */
-/* 180 */ 0xb7ed02b8, /* cps = 16224.00, nrm = 32, interval = 21.75 */
-/* 181 */ 0xb821029c, /* cps = 16896.00, nrm = 32, interval = 20.88 */
-/* 182 */ 0xb84f0281, /* cps = 17632.00, nrm = 32, interval = 20.03 */
-/* 183 */ 0xb87d0267, /* cps = 18368.00, nrm = 32, interval = 19.22 */
-/* 184 */ 0xb8ad024e, /* cps = 19136.00, nrm = 32, interval = 18.44 */
-/* 185 */ 0xb8dd0237, /* cps = 19904.00, nrm = 32, interval = 17.72 */
-/* 186 */ 0xb9130220, /* cps = 20768.00, nrm = 32, interval = 17.00 */
-/* 187 */ 0xb949020a, /* cps = 21632.00, nrm = 32, interval = 16.31 */
-/* 188 */ 0xb98301f5, /* cps = 22560.00, nrm = 32, interval = 15.66 */
-/* 189 */ 0xb9bd01e1, /* cps = 23488.00, nrm = 32, interval = 15.03 */
-/* 190 */ 0xb9fd01cd, /* cps = 24512.00, nrm = 32, interval = 14.41 */
-/* 191 */ 0xba3b01bb, /* cps = 25504.00, nrm = 32, interval = 13.84 */
-/* 192 */ 0xba7f01a9, /* cps = 26592.00, nrm = 32, interval = 13.28 */
-/* 193 */ 0xbac30198, /* cps = 27680.00, nrm = 32, interval = 12.75 */
-/* 194 */ 0xbb0f0187, /* cps = 28896.00, nrm = 32, interval = 12.22 */
-/* 195 */ 0xbb570178, /* cps = 30048.00, nrm = 32, interval = 11.75 */
-/* 196 */ 0xbbab0168, /* cps = 31392.00, nrm = 32, interval = 11.25 */
-/* 197 */ 0xbbf9015a, /* cps = 32640.00, nrm = 32, interval = 10.81 */
-/* 198 */ 0xbc27014c, /* cps = 33984.00, nrm = 32, interval = 10.38 */
-/* 199 */ 0xbc53013f, /* cps = 35392.00, nrm = 32, interval = 9.97 */
-/* 200 */ 0xbc830132, /* cps = 36928.00, nrm = 32, interval = 9.56 */
-/* 201 */ 0xbcb50125, /* cps = 38528.00, nrm = 32, interval = 9.16 */
-/* 202 */ 0xbce5011a, /* cps = 40064.00, nrm = 32, interval = 8.81 */
-/* 203 */ 0xbd1d010e, /* cps = 41856.00, nrm = 32, interval = 8.44 */
-/* 204 */ 0xbd530103, /* cps = 43584.00, nrm = 32, interval = 8.09 */
-/* 205 */ 0xbd8b00f9, /* cps = 45376.00, nrm = 32, interval = 7.78 */
-/* 206 */ 0xbdc500ef, /* cps = 47232.00, nrm = 32, interval = 7.47 */
-/* 207 */ 0xbe0700e5, /* cps = 49344.00, nrm = 32, interval = 7.16 */
-/* 208 */ 0xbe4500dc, /* cps = 51328.00, nrm = 32, interval = 6.88 */
-/* 209 */ 0xbe8900d3, /* cps = 53504.00, nrm = 32, interval = 6.59 */
-/* 210 */ 0xbecb00cb, /* cps = 55616.00, nrm = 32, interval = 6.34 */
-/* 211 */ 0xbf1d00c2, /* cps = 58240.00, nrm = 32, interval = 6.06 */
-/* 212 */ 0xbf6100bb, /* cps = 60416.00, nrm = 32, interval = 5.84 */
-/* 213 */ 0xbfb500b3, /* cps = 63104.00, nrm = 32, interval = 5.59 */
-/* 214 */ 0xc00300ac, /* cps = 65664.00, nrm = 32, interval = 5.38 */
-/* 215 */ 0xc02f00a5, /* cps = 68480.00, nrm = 32, interval = 5.16 */
-/* 216 */ 0xc05d009e, /* cps = 71424.00, nrm = 32, interval = 4.94 */
-/* 217 */ 0xc0890098, /* cps = 74240.00, nrm = 32, interval = 4.75 */
-/* 218 */ 0xc0b90092, /* cps = 77312.00, nrm = 32, interval = 4.56 */
-/* 219 */ 0xc0ed008c, /* cps = 80640.00, nrm = 32, interval = 4.38 */
-/* 220 */ 0xc1250086, /* cps = 84224.00, nrm = 32, interval = 4.19 */
-/* 221 */ 0xc1590081, /* cps = 87552.00, nrm = 32, interval = 4.03 */
-/* 222 */ 0xc191007c, /* cps = 91136.00, nrm = 32, interval = 3.88 */
-/* 223 */ 0xc1cd0077, /* cps = 94976.00, nrm = 32, interval = 3.72 */
-/* 224 */ 0xc20d0072, /* cps = 99072.00, nrm = 32, interval = 3.56 */
-/* 225 */ 0xc255006d, /* cps = 103680.00, nrm = 32, interval = 3.41 */
-/* 226 */ 0xc2910069, /* cps = 107520.00, nrm = 32, interval = 3.28 */
-/* 227 */ 0xc2d50065, /* cps = 111872.00, nrm = 32, interval = 3.16 */
-/* 228 */ 0xc32f0060, /* cps = 117632.00, nrm = 32, interval = 3.00 */
-/* 229 */ 0xc36b005d, /* cps = 121472.00, nrm = 32, interval = 2.91 */
-/* 230 */ 0xc3c10059, /* cps = 126976.00, nrm = 32, interval = 2.78 */
-/* 231 */ 0xc40f0055, /* cps = 132864.00, nrm = 32, interval = 2.66 */
-/* 232 */ 0xc4350052, /* cps = 137728.00, nrm = 32, interval = 2.56 */
-/* 233 */ 0xc46d004e, /* cps = 144896.00, nrm = 32, interval = 2.44 */
-/* 234 */ 0xc499004b, /* cps = 150528.00, nrm = 32, interval = 2.34 */
-/* 235 */ 0xc4cb0048, /* cps = 156928.00, nrm = 32, interval = 2.25 */
-/* 236 */ 0xc4ff0045, /* cps = 163584.00, nrm = 32, interval = 2.16 */
-/* 237 */ 0xc5250043, /* cps = 168448.00, nrm = 32, interval = 2.09 */
-/* 238 */ 0xc5630040, /* cps = 176384.00, nrm = 32, interval = 2.00 */
-/* 239 */ 0xc5a7003d, /* cps = 185088.00, nrm = 32, interval = 1.91 */
-/* 240 */ 0xc5d9003b, /* cps = 191488.00, nrm = 32, interval = 1.84 */
-/* 241 */ 0xc6290038, /* cps = 201728.00, nrm = 32, interval = 1.75 */
-/* 242 */ 0xc6630036, /* cps = 209152.00, nrm = 32, interval = 1.69 */
-/* 243 */ 0xc6a30034, /* cps = 217344.00, nrm = 32, interval = 1.62 */
-/* 244 */ 0xc6e70032, /* cps = 226048.00, nrm = 32, interval = 1.56 */
-/* 245 */ 0xc72f0030, /* cps = 235264.00, nrm = 32, interval = 1.50 */
-/* 246 */ 0xc77f002e, /* cps = 245504.00, nrm = 32, interval = 1.44 */
-/* 247 */ 0xc7d7002c, /* cps = 256768.00, nrm = 32, interval = 1.38 */
-/* 248 */ 0xc81b002a, /* cps = 268800.00, nrm = 32, interval = 1.31 */
-/* 249 */ 0xc84f0028, /* cps = 282112.00, nrm = 32, interval = 1.25 */
-/* 250 */ 0xc86d0027, /* cps = 289792.00, nrm = 32, interval = 1.22 */
-/* 251 */ 0xc8a90025, /* cps = 305152.00, nrm = 32, interval = 1.16 */
-/* 252 */ 0xc8cb0024, /* cps = 313856.00, nrm = 32, interval = 1.12 */
-/* 253 */ 0xc9130022, /* cps = 332288.00, nrm = 32, interval = 1.06 */
-/* 254 */ 0xc9390021, /* cps = 342016.00, nrm = 32, interval = 1.03 */
-/* 255 */ 0xc9630020, /* cps = 352768.00, nrm = 32, interval = 1.00 */
-};
-
-static unsigned char rate_to_log[] =
-{
-/* 1.00 => 0 */ 0x00, /* => 10.02 */
-/* 1.06 => 0 */ 0x00, /* => 10.02 */
-/* 1.12 => 0 */ 0x00, /* => 10.02 */
-/* 1.19 => 0 */ 0x00, /* => 10.02 */
-/* 1.25 => 0 */ 0x00, /* => 10.02 */
-/* 1.31 => 0 */ 0x00, /* => 10.02 */
-/* 1.38 => 0 */ 0x00, /* => 10.02 */
-/* 1.44 => 0 */ 0x00, /* => 10.02 */
-/* 1.50 => 0 */ 0x00, /* => 10.02 */
-/* 1.56 => 0 */ 0x00, /* => 10.02 */
-/* 1.62 => 0 */ 0x00, /* => 10.02 */
-/* 1.69 => 0 */ 0x00, /* => 10.02 */
-/* 1.75 => 0 */ 0x00, /* => 10.02 */
-/* 1.81 => 0 */ 0x00, /* => 10.02 */
-/* 1.88 => 0 */ 0x00, /* => 10.02 */
-/* 1.94 => 0 */ 0x00, /* => 10.02 */
-/* 2.00 => 0 */ 0x00, /* => 10.02 */
-/* 2.12 => 0 */ 0x00, /* => 10.02 */
-/* 2.25 => 0 */ 0x00, /* => 10.02 */
-/* 2.38 => 0 */ 0x00, /* => 10.02 */
-/* 2.50 => 0 */ 0x00, /* => 10.02 */
-/* 2.62 => 0 */ 0x00, /* => 10.02 */
-/* 2.75 => 0 */ 0x00, /* => 10.02 */
-/* 2.88 => 0 */ 0x00, /* => 10.02 */
-/* 3.00 => 0 */ 0x00, /* => 10.02 */
-/* 3.12 => 0 */ 0x00, /* => 10.02 */
-/* 3.25 => 0 */ 0x00, /* => 10.02 */
-/* 3.38 => 0 */ 0x00, /* => 10.02 */
-/* 3.50 => 0 */ 0x00, /* => 10.02 */
-/* 3.62 => 0 */ 0x00, /* => 10.02 */
-/* 3.75 => 0 */ 0x00, /* => 10.02 */
-/* 3.88 => 0 */ 0x00, /* => 10.02 */
-/* 4.00 => 0 */ 0x00, /* => 10.02 */
-/* 4.25 => 0 */ 0x00, /* => 10.02 */
-/* 4.50 => 0 */ 0x00, /* => 10.02 */
-/* 4.75 => 0 */ 0x00, /* => 10.02 */
-/* 5.00 => 0 */ 0x00, /* => 10.02 */
-/* 5.25 => 0 */ 0x00, /* => 10.02 */
-/* 5.50 => 0 */ 0x00, /* => 10.02 */
-/* 5.75 => 0 */ 0x00, /* => 10.02 */
-/* 6.00 => 0 */ 0x00, /* => 10.02 */
-/* 6.25 => 0 */ 0x00, /* => 10.02 */
-/* 6.50 => 0 */ 0x00, /* => 10.02 */
-/* 6.75 => 0 */ 0x00, /* => 10.02 */
-/* 7.00 => 0 */ 0x00, /* => 10.02 */
-/* 7.25 => 0 */ 0x00, /* => 10.02 */
-/* 7.50 => 0 */ 0x00, /* => 10.02 */
-/* 7.75 => 0 */ 0x00, /* => 10.02 */
-/* 8.00 => 0 */ 0x00, /* => 10.02 */
-/* 8.50 => 0 */ 0x00, /* => 10.02 */
-/* 9.00 => 0 */ 0x00, /* => 10.02 */
-/* 9.50 => 0 */ 0x00, /* => 10.02 */
-/* 10.00 => 0 */ 0x00, /* => 10.02 */
-/* 10.50 => 1 */ 0x01, /* => 10.42 */
-/* 11.00 => 2 */ 0x02, /* => 10.86 */
-/* 11.50 => 3 */ 0x03, /* => 11.31 */
-/* 12.00 => 4 */ 0x04, /* => 11.78 */
-/* 12.50 => 5 */ 0x05, /* => 12.28 */
-/* 13.00 => 6 */ 0x06, /* => 12.80 */
-/* 13.50 => 7 */ 0x07, /* => 13.33 */
-/* 14.00 => 8 */ 0x08, /* => 13.89 */
-/* 14.50 => 9 */ 0x09, /* => 14.48 */
-/* 15.00 => 9 */ 0x09, /* => 14.48 */
-/* 15.50 => 10 */ 0x0a, /* => 15.08 */
-/* 16.00 => 11 */ 0x0b, /* => 15.72 */
-/* 17.00 => 12 */ 0x0c, /* => 16.38 */
-/* 18.00 => 14 */ 0x0e, /* => 17.75 */
-/* 19.00 => 15 */ 0x0f, /* => 18.50 */
-/* 20.00 => 16 */ 0x10, /* => 19.28 */
-/* 21.00 => 18 */ 0x12, /* => 20.94 */
-/* 22.00 => 19 */ 0x13, /* => 21.81 */
-/* 23.00 => 20 */ 0x14, /* => 22.75 */
-/* 24.00 => 21 */ 0x15, /* => 23.69 */
-/* 25.00 => 22 */ 0x16, /* => 24.69 */
-/* 26.00 => 23 */ 0x17, /* => 25.72 */
-/* 27.00 => 24 */ 0x18, /* => 26.81 */
-/* 28.00 => 25 */ 0x19, /* => 27.94 */
-/* 29.00 => 25 */ 0x19, /* => 27.94 */
-/* 30.00 => 26 */ 0x1a, /* => 29.09 */
-/* 31.00 => 27 */ 0x1b, /* => 30.31 */
-/* 32.00 => 28 */ 0x1c, /* => 31.56 */
-/* 34.00 => 29 */ 0x1d, /* => 32.94 */
-/* 36.00 => 31 */ 0x1f, /* => 35.69 */
-/* 38.00 => 32 */ 0x20, /* => 37.19 */
-/* 40.00 => 33 */ 0x21, /* => 38.75 */
-/* 42.00 => 34 */ 0x22, /* => 40.38 */
-/* 44.00 => 36 */ 0x24, /* => 43.88 */
-/* 46.00 => 37 */ 0x25, /* => 45.69 */
-/* 48.00 => 38 */ 0x26, /* => 47.62 */
-/* 50.00 => 39 */ 0x27, /* => 49.62 */
-/* 52.00 => 40 */ 0x28, /* => 51.69 */
-/* 54.00 => 41 */ 0x29, /* => 53.88 */
-/* 56.00 => 41 */ 0x29, /* => 53.88 */
-/* 58.00 => 42 */ 0x2a, /* => 56.12 */
-/* 60.00 => 43 */ 0x2b, /* => 58.44 */
-/* 62.00 => 44 */ 0x2c, /* => 60.94 */
-/* 64.00 => 45 */ 0x2d, /* => 63.50 */
-/* 68.00 => 46 */ 0x2e, /* => 66.12 */
-/* 72.00 => 48 */ 0x30, /* => 71.88 */
-/* 76.00 => 49 */ 0x31, /* => 74.75 */
-/* 80.00 => 50 */ 0x32, /* => 78.00 */
-/* 84.00 => 51 */ 0x33, /* => 81.25 */
-/* 88.00 => 52 */ 0x34, /* => 84.62 */
-/* 92.00 => 54 */ 0x36, /* => 91.88 */
-/* 96.00 => 55 */ 0x37, /* => 95.75 */
-/* 100.00 => 56 */ 0x38, /* => 99.75 */
-/* 104.00 => 56 */ 0x38, /* => 99.75 */
-/* 108.00 => 57 */ 0x39, /* => 104.00 */
-/* 112.00 => 58 */ 0x3a, /* => 108.25 */
-/* 116.00 => 59 */ 0x3b, /* => 112.88 */
-/* 120.00 => 60 */ 0x3c, /* => 117.50 */
-/* 124.00 => 61 */ 0x3d, /* => 122.38 */
-/* 128.00 => 62 */ 0x3e, /* => 127.50 */
-/* 136.00 => 63 */ 0x3f, /* => 132.75 */
-/* 144.00 => 64 */ 0x40, /* => 138.50 */
-/* 152.00 => 66 */ 0x42, /* => 150.25 */
-/* 160.00 => 67 */ 0x43, /* => 156.75 */
-/* 168.00 => 68 */ 0x44, /* => 163.50 */
-/* 176.00 => 69 */ 0x45, /* => 170.00 */
-/* 184.00 => 70 */ 0x46, /* => 177.25 */
-/* 192.00 => 71 */ 0x47, /* => 184.50 */
-/* 200.00 => 72 */ 0x48, /* => 192.25 */
-/* 208.00 => 73 */ 0x49, /* => 200.25 */
-/* 216.00 => 74 */ 0x4a, /* => 208.75 */
-/* 224.00 => 75 */ 0x4b, /* => 217.75 */
-/* 232.00 => 76 */ 0x4c, /* => 226.75 */
-/* 240.00 => 77 */ 0x4d, /* => 236.25 */
-/* 248.00 => 78 */ 0x4e, /* => 246.25 */
-/* 256.00 => 78 */ 0x4e, /* => 246.25 */
-/* 272.00 => 80 */ 0x50, /* => 267.50 */
-/* 288.00 => 81 */ 0x51, /* => 278.50 */
-/* 304.00 => 83 */ 0x53, /* => 302.00 */
-/* 320.00 => 84 */ 0x54, /* => 315.00 */
-/* 336.00 => 85 */ 0x55, /* => 328.00 */
-/* 352.00 => 86 */ 0x56, /* => 342.00 */
-/* 368.00 => 87 */ 0x57, /* => 356.00 */
-/* 384.00 => 88 */ 0x58, /* => 371.00 */
-/* 400.00 => 89 */ 0x59, /* => 386.50 */
-/* 416.00 => 90 */ 0x5a, /* => 403.00 */
-/* 432.00 => 91 */ 0x5b, /* => 419.50 */
-/* 448.00 => 92 */ 0x5c, /* => 437.50 */
-/* 464.00 => 93 */ 0x5d, /* => 455.50 */
-/* 480.00 => 94 */ 0x5e, /* => 475.00 */
-/* 496.00 => 95 */ 0x5f, /* => 495.00 */
-/* 512.00 => 95 */ 0x5f, /* => 495.00 */
-/* 544.00 => 97 */ 0x61, /* => 537.00 */
-/* 576.00 => 98 */ 0x62, /* => 559.00 */
-/* 608.00 => 100 */ 0x64, /* => 607.00 */
-/* 640.00 => 101 */ 0x65, /* => 632.00 */
-/* 672.00 => 102 */ 0x66, /* => 660.00 */
-/* 704.00 => 103 */ 0x67, /* => 687.00 */
-/* 736.00 => 104 */ 0x68, /* => 716.00 */
-/* 768.00 => 105 */ 0x69, /* => 746.00 */
-/* 800.00 => 106 */ 0x6a, /* => 777.00 */
-/* 832.00 => 107 */ 0x6b, /* => 810.00 */
-/* 864.00 => 108 */ 0x6c, /* => 843.00 */
-/* 896.00 => 109 */ 0x6d, /* => 879.00 */
-/* 928.00 => 110 */ 0x6e, /* => 916.00 */
-/* 960.00 => 111 */ 0x6f, /* => 954.00 */
-/* 992.00 => 111 */ 0x6f, /* => 954.00 */
-/* 1024.00 => 112 */ 0x70, /* => 994.00 */
-/* 1088.00 => 114 */ 0x72, /* => 1080.00 */
-/* 1152.00 => 115 */ 0x73, /* => 1124.00 */
-/* 1216.00 => 116 */ 0x74, /* => 1172.00 */
-/* 1280.00 => 118 */ 0x76, /* => 1272.00 */
-/* 1344.00 => 119 */ 0x77, /* => 1326.00 */
-/* 1408.00 => 120 */ 0x78, /* => 1382.00 */
-/* 1472.00 => 121 */ 0x79, /* => 1440.00 */
-/* 1536.00 => 122 */ 0x7a, /* => 1498.00 */
-/* 1600.00 => 123 */ 0x7b, /* => 1562.00 */
-/* 1664.00 => 124 */ 0x7c, /* => 1628.00 */
-/* 1728.00 => 125 */ 0x7d, /* => 1696.00 */
-/* 1792.00 => 126 */ 0x7e, /* => 1768.00 */
-/* 1856.00 => 127 */ 0x7f, /* => 1842.00 */
-/* 1920.00 => 128 */ 0x80, /* => 1918.00 */
-/* 1984.00 => 128 */ 0x80, /* => 1918.00 */
-/* 2048.00 => 129 */ 0x81, /* => 2000.00 */
-/* 2176.00 => 131 */ 0x83, /* => 2168.00 */
-/* 2304.00 => 132 */ 0x84, /* => 2264.00 */
-/* 2432.00 => 133 */ 0x85, /* => 2356.00 */
-/* 2560.00 => 135 */ 0x87, /* => 2556.00 */
-/* 2688.00 => 136 */ 0x88, /* => 2664.00 */
-/* 2816.00 => 137 */ 0x89, /* => 2776.00 */
-/* 2944.00 => 138 */ 0x8a, /* => 2892.00 */
-/* 3072.00 => 139 */ 0x8b, /* => 3012.00 */
-/* 3200.00 => 140 */ 0x8c, /* => 3140.00 */
-/* 3328.00 => 141 */ 0x8d, /* => 3272.00 */
-/* 3456.00 => 142 */ 0x8e, /* => 3412.00 */
-/* 3584.00 => 143 */ 0x8f, /* => 3552.00 */
-/* 3712.00 => 144 */ 0x90, /* => 3700.00 */
-/* 3840.00 => 144 */ 0x90, /* => 3700.00 */
-/* 3968.00 => 145 */ 0x91, /* => 3860.00 */
-/* 4096.00 => 146 */ 0x92, /* => 4016.00 */
-/* 4352.00 => 147 */ 0x93, /* => 4184.00 */
-/* 4608.00 => 149 */ 0x95, /* => 4544.00 */
-/* 4864.00 => 150 */ 0x96, /* => 4736.00 */
-/* 5120.00 => 151 */ 0x97, /* => 4936.00 */
-/* 5376.00 => 153 */ 0x99, /* => 5360.00 */
-/* 5632.00 => 154 */ 0x9a, /* => 5584.00 */
-/* 5888.00 => 155 */ 0x9b, /* => 5816.00 */
-/* 6144.00 => 156 */ 0x9c, /* => 6056.00 */
-/* 6400.00 => 157 */ 0x9d, /* => 6312.00 */
-/* 6656.00 => 158 */ 0x9e, /* => 6576.00 */
-/* 6912.00 => 159 */ 0x9f, /* => 6856.00 */
-/* 7168.00 => 160 */ 0xa0, /* => 7144.00 */
-/* 7424.00 => 160 */ 0xa0, /* => 7144.00 */
-/* 7680.00 => 161 */ 0xa1, /* => 7440.00 */
-/* 7936.00 => 162 */ 0xa2, /* => 7752.00 */
-/* 8192.00 => 163 */ 0xa3, /* => 8080.00 */
-/* 8704.00 => 164 */ 0xa4, /* => 8416.00 */
-/* 9216.00 => 166 */ 0xa6, /* => 9136.00 */
-/* 9728.00 => 167 */ 0xa7, /* => 9520.00 */
-/* 10240.00 => 168 */ 0xa8, /* => 9920.00 */
-/* 10752.00 => 169 */ 0xa9, /* => 10336.00 */
-/* 11264.00 => 171 */ 0xab, /* => 11216.00 */
-/* 11776.00 => 172 */ 0xac, /* => 11680.00 */
-/* 12288.00 => 173 */ 0xad, /* => 12176.00 */
-/* 12800.00 => 174 */ 0xae, /* => 12688.00 */
-/* 13312.00 => 175 */ 0xaf, /* => 13216.00 */
-/* 13824.00 => 176 */ 0xb0, /* => 13776.00 */
-/* 14336.00 => 176 */ 0xb0, /* => 13776.00 */
-/* 14848.00 => 177 */ 0xb1, /* => 14352.00 */
-/* 15360.00 => 178 */ 0xb2, /* => 14960.00 */
-/* 15872.00 => 179 */ 0xb3, /* => 15584.00 */
-/* 16384.00 => 180 */ 0xb4, /* => 16224.00 */
-/* 17408.00 => 181 */ 0xb5, /* => 16896.00 */
-/* 18432.00 => 183 */ 0xb7, /* => 18368.00 */
-/* 19456.00 => 184 */ 0xb8, /* => 19136.00 */
-/* 20480.00 => 185 */ 0xb9, /* => 19904.00 */
-/* 21504.00 => 186 */ 0xba, /* => 20768.00 */
-/* 22528.00 => 187 */ 0xbb, /* => 21632.00 */
-/* 23552.00 => 189 */ 0xbd, /* => 23488.00 */
-/* 24576.00 => 190 */ 0xbe, /* => 24512.00 */
-/* 25600.00 => 191 */ 0xbf, /* => 25504.00 */
-/* 26624.00 => 192 */ 0xc0, /* => 26592.00 */
-/* 27648.00 => 192 */ 0xc0, /* => 26592.00 */
-/* 28672.00 => 193 */ 0xc1, /* => 27680.00 */
-/* 29696.00 => 194 */ 0xc2, /* => 28896.00 */
-/* 30720.00 => 195 */ 0xc3, /* => 30048.00 */
-/* 31744.00 => 196 */ 0xc4, /* => 31392.00 */
-/* 32768.00 => 197 */ 0xc5, /* => 32640.00 */
-/* 34816.00 => 198 */ 0xc6, /* => 33984.00 */
-/* 36864.00 => 199 */ 0xc7, /* => 35392.00 */
-/* 38912.00 => 201 */ 0xc9, /* => 38528.00 */
-/* 40960.00 => 202 */ 0xca, /* => 40064.00 */
-/* 43008.00 => 203 */ 0xcb, /* => 41856.00 */
-/* 45056.00 => 204 */ 0xcc, /* => 43584.00 */
-/* 47104.00 => 205 */ 0xcd, /* => 45376.00 */
-/* 49152.00 => 206 */ 0xce, /* => 47232.00 */
-/* 51200.00 => 207 */ 0xcf, /* => 49344.00 */
-/* 53248.00 => 208 */ 0xd0, /* => 51328.00 */
-/* 55296.00 => 209 */ 0xd1, /* => 53504.00 */
-/* 57344.00 => 210 */ 0xd2, /* => 55616.00 */
-/* 59392.00 => 211 */ 0xd3, /* => 58240.00 */
-/* 61440.00 => 212 */ 0xd4, /* => 60416.00 */
-/* 63488.00 => 213 */ 0xd5, /* => 63104.00 */
-/* 65536.00 => 213 */ 0xd5, /* => 63104.00 */
-/* 69632.00 => 215 */ 0xd7, /* => 68480.00 */
-/* 73728.00 => 216 */ 0xd8, /* => 71424.00 */
-/* 77824.00 => 218 */ 0xda, /* => 77312.00 */
-/* 81920.00 => 219 */ 0xdb, /* => 80640.00 */
-/* 86016.00 => 220 */ 0xdc, /* => 84224.00 */
-/* 90112.00 => 221 */ 0xdd, /* => 87552.00 */
-/* 94208.00 => 222 */ 0xde, /* => 91136.00 */
-/* 98304.00 => 223 */ 0xdf, /* => 94976.00 */
-/* 102400.00 => 224 */ 0xe0, /* => 99072.00 */
-/* 106496.00 => 225 */ 0xe1, /* => 103680.00 */
-/* 110592.00 => 226 */ 0xe2, /* => 107520.00 */
-/* 114688.00 => 227 */ 0xe3, /* => 111872.00 */
-/* 118784.00 => 228 */ 0xe4, /* => 117632.00 */
-/* 122880.00 => 229 */ 0xe5, /* => 121472.00 */
-/* 126976.00 => 229 */ 0xe5, /* => 121472.00 */
-/* 131072.00 => 230 */ 0xe6, /* => 126976.00 */
-/* 139264.00 => 232 */ 0xe8, /* => 137728.00 */
-/* 147456.00 => 233 */ 0xe9, /* => 144896.00 */
-/* 155648.00 => 234 */ 0xea, /* => 150528.00 */
-/* 163840.00 => 236 */ 0xec, /* => 163584.00 */
-/* 172032.00 => 237 */ 0xed, /* => 168448.00 */
-/* 180224.00 => 238 */ 0xee, /* => 176384.00 */
-/* 188416.00 => 239 */ 0xef, /* => 185088.00 */
-/* 196608.00 => 240 */ 0xf0, /* => 191488.00 */
-/* 204800.00 => 241 */ 0xf1, /* => 201728.00 */
-/* 212992.00 => 242 */ 0xf2, /* => 209152.00 */
-/* 221184.00 => 243 */ 0xf3, /* => 217344.00 */
-/* 229376.00 => 244 */ 0xf4, /* => 226048.00 */
-/* 237568.00 => 245 */ 0xf5, /* => 235264.00 */
-/* 245760.00 => 246 */ 0xf6, /* => 245504.00 */
-/* 253952.00 => 246 */ 0xf6, /* => 245504.00 */
-/* 262144.00 => 247 */ 0xf7, /* => 256768.00 */
-/* 278528.00 => 248 */ 0xf8, /* => 268800.00 */
-/* 294912.00 => 250 */ 0xfa, /* => 289792.00 */
-/* 311296.00 => 251 */ 0xfb, /* => 305152.00 */
-/* 327680.00 => 252 */ 0xfc, /* => 313856.00 */
-/* 344064.00 => 254 */ 0xfe, /* => 342016.00 */
-/* 360448.00 => 255 */ 0xff, /* => 352768.00 */
-/* 376832.00 => 255 */ 0xff, /* => 352768.00 */
-/* 393216.00 => 255 */ 0xff, /* => 352768.00 */
-/* 409600.00 => 255 */ 0xff, /* => 352768.00 */
-/* 425984.00 => 255 */ 0xff, /* => 352768.00 */
-/* 442368.00 => 255 */ 0xff, /* => 352768.00 */
-/* 458752.00 => 255 */ 0xff, /* => 352768.00 */
-/* 475136.00 => 255 */ 0xff, /* => 352768.00 */
-/* 491520.00 => 255 */ 0xff, /* => 352768.00 */
-/* 507904.00 => 255 */ 0xff, /* => 352768.00 */
-/* 524288.00 => 255 */ 0xff, /* => 352768.00 */
-/* 557056.00 => 255 */ 0xff, /* => 352768.00 */
-/* 589824.00 => 255 */ 0xff, /* => 352768.00 */
-/* 622592.00 => 255 */ 0xff, /* => 352768.00 */
-/* 655360.00 => 255 */ 0xff, /* => 352768.00 */
-/* 688128.00 => 255 */ 0xff, /* => 352768.00 */
-/* 720896.00 => 255 */ 0xff, /* => 352768.00 */
-/* 753664.00 => 255 */ 0xff, /* => 352768.00 */
-/* 786432.00 => 255 */ 0xff, /* => 352768.00 */
-/* 819200.00 => 255 */ 0xff, /* => 352768.00 */
-/* 851968.00 => 255 */ 0xff, /* => 352768.00 */
-/* 884736.00 => 255 */ 0xff, /* => 352768.00 */
-/* 917504.00 => 255 */ 0xff, /* => 352768.00 */
-/* 950272.00 => 255 */ 0xff, /* => 352768.00 */
-/* 983040.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1015808.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1048576.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1114112.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1179648.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1245184.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1310720.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1376256.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1441792.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1507328.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1572864.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1638400.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1703936.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1769472.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1835008.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1900544.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1966080.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2031616.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2097152.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2228224.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2359296.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2490368.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2621440.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2752512.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2883584.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3014656.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3145728.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3276800.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3407872.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3538944.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3670016.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3801088.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3932160.00 => 255 */ 0xff, /* => 352768.00 */
-/* 4063232.00 => 255 */ 0xff, /* => 352768.00 */
-/* 4194304.00 => 255 */ 0xff, /* => 352768.00 */
-/* 4456448.00 => 255 */ 0xff, /* => 352768.00 */
-/* 4718592.00 => 255 */ 0xff, /* => 352768.00 */
-/* 4980736.00 => 255 */ 0xff, /* => 352768.00 */
-/* 5242880.00 => 255 */ 0xff, /* => 352768.00 */
-/* 5505024.00 => 255 */ 0xff, /* => 352768.00 */
-/* 5767168.00 => 255 */ 0xff, /* => 352768.00 */
-/* 6029312.00 => 255 */ 0xff, /* => 352768.00 */
-/* 6291456.00 => 255 */ 0xff, /* => 352768.00 */
-/* 6553600.00 => 255 */ 0xff, /* => 352768.00 */
-/* 6815744.00 => 255 */ 0xff, /* => 352768.00 */
-/* 7077888.00 => 255 */ 0xff, /* => 352768.00 */
-/* 7340032.00 => 255 */ 0xff, /* => 352768.00 */
-/* 7602176.00 => 255 */ 0xff, /* => 352768.00 */
-/* 7864320.00 => 255 */ 0xff, /* => 352768.00 */
-/* 8126464.00 => 255 */ 0xff, /* => 352768.00 */
-/* 8388608.00 => 255 */ 0xff, /* => 352768.00 */
-/* 8912896.00 => 255 */ 0xff, /* => 352768.00 */
-/* 9437184.00 => 255 */ 0xff, /* => 352768.00 */
-/* 9961472.00 => 255 */ 0xff, /* => 352768.00 */
-/* 10485760.00 => 255 */ 0xff, /* => 352768.00 */
-/* 11010048.00 => 255 */ 0xff, /* => 352768.00 */
-/* 11534336.00 => 255 */ 0xff, /* => 352768.00 */
-/* 12058624.00 => 255 */ 0xff, /* => 352768.00 */
-/* 12582912.00 => 255 */ 0xff, /* => 352768.00 */
-/* 13107200.00 => 255 */ 0xff, /* => 352768.00 */
-/* 13631488.00 => 255 */ 0xff, /* => 352768.00 */
-/* 14155776.00 => 255 */ 0xff, /* => 352768.00 */
-/* 14680064.00 => 255 */ 0xff, /* => 352768.00 */
-/* 15204352.00 => 255 */ 0xff, /* => 352768.00 */
-/* 15728640.00 => 255 */ 0xff, /* => 352768.00 */
-/* 16252928.00 => 255 */ 0xff, /* => 352768.00 */
-/* 16777216.00 => 255 */ 0xff, /* => 352768.00 */
-/* 17825792.00 => 255 */ 0xff, /* => 352768.00 */
-/* 18874368.00 => 255 */ 0xff, /* => 352768.00 */
-/* 19922944.00 => 255 */ 0xff, /* => 352768.00 */
-/* 20971520.00 => 255 */ 0xff, /* => 352768.00 */
-/* 22020096.00 => 255 */ 0xff, /* => 352768.00 */
-/* 23068672.00 => 255 */ 0xff, /* => 352768.00 */
-/* 24117248.00 => 255 */ 0xff, /* => 352768.00 */
-/* 25165824.00 => 255 */ 0xff, /* => 352768.00 */
-/* 26214400.00 => 255 */ 0xff, /* => 352768.00 */
-/* 27262976.00 => 255 */ 0xff, /* => 352768.00 */
-/* 28311552.00 => 255 */ 0xff, /* => 352768.00 */
-/* 29360128.00 => 255 */ 0xff, /* => 352768.00 */
-/* 30408704.00 => 255 */ 0xff, /* => 352768.00 */
-/* 31457280.00 => 255 */ 0xff, /* => 352768.00 */
-/* 32505856.00 => 255 */ 0xff, /* => 352768.00 */
-/* 33554432.00 => 255 */ 0xff, /* => 352768.00 */
-/* 35651584.00 => 255 */ 0xff, /* => 352768.00 */
-/* 37748736.00 => 255 */ 0xff, /* => 352768.00 */
-/* 39845888.00 => 255 */ 0xff, /* => 352768.00 */
-/* 41943040.00 => 255 */ 0xff, /* => 352768.00 */
-/* 44040192.00 => 255 */ 0xff, /* => 352768.00 */
-/* 46137344.00 => 255 */ 0xff, /* => 352768.00 */
-/* 48234496.00 => 255 */ 0xff, /* => 352768.00 */
-/* 50331648.00 => 255 */ 0xff, /* => 352768.00 */
-/* 52428800.00 => 255 */ 0xff, /* => 352768.00 */
-/* 54525952.00 => 255 */ 0xff, /* => 352768.00 */
-/* 56623104.00 => 255 */ 0xff, /* => 352768.00 */
-/* 58720256.00 => 255 */ 0xff, /* => 352768.00 */
-/* 60817408.00 => 255 */ 0xff, /* => 352768.00 */
-/* 62914560.00 => 255 */ 0xff, /* => 352768.00 */
-/* 65011712.00 => 255 */ 0xff, /* => 352768.00 */
-/* 67108864.00 => 255 */ 0xff, /* => 352768.00 */
-/* 71303168.00 => 255 */ 0xff, /* => 352768.00 */
-/* 75497472.00 => 255 */ 0xff, /* => 352768.00 */
-/* 79691776.00 => 255 */ 0xff, /* => 352768.00 */
-/* 83886080.00 => 255 */ 0xff, /* => 352768.00 */
-/* 88080384.00 => 255 */ 0xff, /* => 352768.00 */
-/* 92274688.00 => 255 */ 0xff, /* => 352768.00 */
-/* 96468992.00 => 255 */ 0xff, /* => 352768.00 */
-/* 100663296.00 => 255 */ 0xff, /* => 352768.00 */
-/* 104857600.00 => 255 */ 0xff, /* => 352768.00 */
-/* 109051904.00 => 255 */ 0xff, /* => 352768.00 */
-/* 113246208.00 => 255 */ 0xff, /* => 352768.00 */
-/* 117440512.00 => 255 */ 0xff, /* => 352768.00 */
-/* 121634816.00 => 255 */ 0xff, /* => 352768.00 */
-/* 125829120.00 => 255 */ 0xff, /* => 352768.00 */
-/* 130023424.00 => 255 */ 0xff, /* => 352768.00 */
-/* 134217728.00 => 255 */ 0xff, /* => 352768.00 */
-/* 142606336.00 => 255 */ 0xff, /* => 352768.00 */
-/* 150994944.00 => 255 */ 0xff, /* => 352768.00 */
-/* 159383552.00 => 255 */ 0xff, /* => 352768.00 */
-/* 167772160.00 => 255 */ 0xff, /* => 352768.00 */
-/* 176160768.00 => 255 */ 0xff, /* => 352768.00 */
-/* 184549376.00 => 255 */ 0xff, /* => 352768.00 */
-/* 192937984.00 => 255 */ 0xff, /* => 352768.00 */
-/* 201326592.00 => 255 */ 0xff, /* => 352768.00 */
-/* 209715200.00 => 255 */ 0xff, /* => 352768.00 */
-/* 218103808.00 => 255 */ 0xff, /* => 352768.00 */
-/* 226492416.00 => 255 */ 0xff, /* => 352768.00 */
-/* 234881024.00 => 255 */ 0xff, /* => 352768.00 */
-/* 243269632.00 => 255 */ 0xff, /* => 352768.00 */
-/* 251658240.00 => 255 */ 0xff, /* => 352768.00 */
-/* 260046848.00 => 255 */ 0xff, /* => 352768.00 */
-/* 268435456.00 => 255 */ 0xff, /* => 352768.00 */
-/* 285212672.00 => 255 */ 0xff, /* => 352768.00 */
-/* 301989888.00 => 255 */ 0xff, /* => 352768.00 */
-/* 318767104.00 => 255 */ 0xff, /* => 352768.00 */
-/* 335544320.00 => 255 */ 0xff, /* => 352768.00 */
-/* 352321536.00 => 255 */ 0xff, /* => 352768.00 */
-/* 369098752.00 => 255 */ 0xff, /* => 352768.00 */
-/* 385875968.00 => 255 */ 0xff, /* => 352768.00 */
-/* 402653184.00 => 255 */ 0xff, /* => 352768.00 */
-/* 419430400.00 => 255 */ 0xff, /* => 352768.00 */
-/* 436207616.00 => 255 */ 0xff, /* => 352768.00 */
-/* 452984832.00 => 255 */ 0xff, /* => 352768.00 */
-/* 469762048.00 => 255 */ 0xff, /* => 352768.00 */
-/* 486539264.00 => 255 */ 0xff, /* => 352768.00 */
-/* 503316480.00 => 255 */ 0xff, /* => 352768.00 */
-/* 520093696.00 => 255 */ 0xff, /* => 352768.00 */
-/* 536870912.00 => 255 */ 0xff, /* => 352768.00 */
-/* 570425344.00 => 255 */ 0xff, /* => 352768.00 */
-/* 603979776.00 => 255 */ 0xff, /* => 352768.00 */
-/* 637534208.00 => 255 */ 0xff, /* => 352768.00 */
-/* 671088640.00 => 255 */ 0xff, /* => 352768.00 */
-/* 704643072.00 => 255 */ 0xff, /* => 352768.00 */
-/* 738197504.00 => 255 */ 0xff, /* => 352768.00 */
-/* 771751936.00 => 255 */ 0xff, /* => 352768.00 */
-/* 805306368.00 => 255 */ 0xff, /* => 352768.00 */
-/* 838860800.00 => 255 */ 0xff, /* => 352768.00 */
-/* 872415232.00 => 255 */ 0xff, /* => 352768.00 */
-/* 905969664.00 => 255 */ 0xff, /* => 352768.00 */
-/* 939524096.00 => 255 */ 0xff, /* => 352768.00 */
-/* 973078528.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1006632960.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1040187392.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1073741824.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1140850688.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1207959552.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1275068416.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1342177280.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1409286144.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1476395008.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1543503872.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1610612736.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1677721600.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1744830464.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1811939328.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1879048192.00 => 255 */ 0xff, /* => 352768.00 */
-/* 1946157056.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2013265920.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2080374784.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2147483648.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2281701376.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2415919104.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2550136832.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2684354560.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2818572288.00 => 255 */ 0xff, /* => 352768.00 */
-/* 2952790016.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3087007744.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3221225472.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3355443200.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3489660928.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3623878656.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3758096384.00 => 255 */ 0xff, /* => 352768.00 */
-/* 3892314112.00 => 255 */ 0xff, /* => 352768.00 */
-/* 4026531840.00 => 255 */ 0xff, /* => 352768.00 */
-/* 4160749568.00 => 255 */ 0xff, /* => 352768.00 */
-};
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h
deleted file mode 100644
index 2f5f8875cbd1..000000000000
--- a/drivers/atm/iphase.h
+++ /dev/null
@@ -1,1452 +0,0 @@
-/******************************************************************************
- Device driver for Interphase ATM PCI adapter cards
- Author: Peter Wang <pwang@iphase.com>
- Interphase Corporation <www.iphase.com>
- Version: 1.0
- iphase.h: This is the header file for iphase.c.
-*******************************************************************************
-
- This software may be used and distributed according to the terms
- of the GNU General Public License (GPL), incorporated herein by reference.
- Drivers based on this skeleton fall under the GPL and must retain
- the authorship (implicit copyright) notice.
-
- 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.
-
- Modified from an incomplete driver for Interphase 5575 1KVC 1M card which
- was originally written by Monalisa Agrawal at UNH. Now this driver
- supports a variety of varients of Interphase ATM PCI (i)Chip adapter
- card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM)
- in terms of PHY type, the size of control memory and the size of
- packet memory. The following are the change log and history:
-
- Bugfix the Mona's UBR driver.
- Modify the basic memory allocation and dma logic.
- Port the driver to the latest kernel from 2.0.46.
- Complete the ABR logic of the driver, and added the ABR work-
- around for the hardware anormalies.
- Add the CBR support.
- Add the flow control logic to the driver to allow rate-limit VC.
- Add 4K VC support to the board with 512K control memory.
- Add the support of all the variants of the Interphase ATM PCI
- (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525
- (25M UTP25) and x531 (DS3 and E3).
- Add SMP support.
-
- Support and updates available at: ftp://ftp.iphase.com/pub/atm
-
-*******************************************************************************/
-
-#ifndef IPHASE_H
-#define IPHASE_H
-
-
-/************************ IADBG DEFINE *********************************/
-/* IADebugFlag Bit Map */
-#define IF_IADBG_INIT_ADAPTER 0x00000001 // init adapter info
-#define IF_IADBG_TX 0x00000002 // debug TX
-#define IF_IADBG_RX 0x00000004 // debug RX
-#define IF_IADBG_QUERY_INFO 0x00000008 // debug Request call
-#define IF_IADBG_SHUTDOWN 0x00000010 // debug shutdown event
-#define IF_IADBG_INTR 0x00000020 // debug interrupt DPC
-#define IF_IADBG_TXPKT 0x00000040 // debug TX PKT
-#define IF_IADBG_RXPKT 0x00000080 // debug RX PKT
-#define IF_IADBG_ERR 0x00000100 // debug system error
-#define IF_IADBG_EVENT 0x00000200 // debug event
-#define IF_IADBG_DIS_INTR 0x00001000 // debug disable interrupt
-#define IF_IADBG_EN_INTR 0x00002000 // debug enable interrupt
-#define IF_IADBG_LOUD 0x00004000 // debugging info
-#define IF_IADBG_VERY_LOUD 0x00008000 // excessive debugging info
-#define IF_IADBG_CBR 0x00100000 //
-#define IF_IADBG_UBR 0x00200000 //
-#define IF_IADBG_ABR 0x00400000 //
-#define IF_IADBG_DESC 0x01000000 //
-#define IF_IADBG_SUNI_STAT 0x02000000 // suni statistics
-#define IF_IADBG_RESET 0x04000000
-
-#define IF_IADBG(f) if (IADebugFlag & (f))
-
-#ifdef CONFIG_ATM_IA_DEBUG /* Debug build */
-
-#define IF_LOUD(A) IF_IADBG(IF_IADBG_LOUD) { A }
-#define IF_ERR(A) IF_IADBG(IF_IADBG_ERR) { A }
-#define IF_VERY_LOUD(A) IF_IADBG( IF_IADBG_VERY_LOUD ) { A }
-
-#define IF_INIT_ADAPTER(A) IF_IADBG( IF_IADBG_INIT_ADAPTER ) { A }
-#define IF_INIT(A) IF_IADBG( IF_IADBG_INIT_ADAPTER ) { A }
-#define IF_SUNI_STAT(A) IF_IADBG( IF_IADBG_SUNI_STAT ) { A }
-#define IF_QUERY_INFO(A) IF_IADBG( IF_IADBG_QUERY_INFO ) { A }
-#define IF_COPY_OVER(A) IF_IADBG( IF_IADBG_COPY_OVER ) { A }
-
-#define IF_INTR(A) IF_IADBG( IF_IADBG_INTR ) { A }
-#define IF_DIS_INTR(A) IF_IADBG( IF_IADBG_DIS_INTR ) { A }
-#define IF_EN_INTR(A) IF_IADBG( IF_IADBG_EN_INTR ) { A }
-
-#define IF_TX(A) IF_IADBG( IF_IADBG_TX ) { A }
-#define IF_RX(A) IF_IADBG( IF_IADBG_RX ) { A }
-#define IF_TXPKT(A) IF_IADBG( IF_IADBG_TXPKT ) { A }
-#define IF_RXPKT(A) IF_IADBG( IF_IADBG_RXPKT ) { A }
-
-#define IF_SHUTDOWN(A) IF_IADBG(IF_IADBG_SHUTDOWN) { A }
-#define IF_CBR(A) IF_IADBG( IF_IADBG_CBR ) { A }
-#define IF_UBR(A) IF_IADBG( IF_IADBG_UBR ) { A }
-#define IF_ABR(A) IF_IADBG( IF_IADBG_ABR ) { A }
-#define IF_EVENT(A) IF_IADBG( IF_IADBG_EVENT) { A }
-
-#else /* free build */
-#define IF_LOUD(A)
-#define IF_VERY_LOUD(A)
-#define IF_INIT_ADAPTER(A)
-#define IF_INIT(A)
-#define IF_SUNI_STAT(A)
-#define IF_PVC_CHKPKT(A)
-#define IF_QUERY_INFO(A)
-#define IF_COPY_OVER(A)
-#define IF_HANG(A)
-#define IF_INTR(A)
-#define IF_DIS_INTR(A)
-#define IF_EN_INTR(A)
-#define IF_TX(A)
-#define IF_RX(A)
-#define IF_TXDEBUG(A)
-#define IF_VC(A)
-#define IF_ERR(A)
-#define IF_CBR(A)
-#define IF_UBR(A)
-#define IF_ABR(A)
-#define IF_SHUTDOWN(A)
-#define DbgPrint(A)
-#define IF_EVENT(A)
-#define IF_TXPKT(A)
-#define IF_RXPKT(A)
-#endif /* CONFIG_ATM_IA_DEBUG */
-
-#define ATM_DESC(skb) (skb->protocol)
-#define IA_SKB_STATE(skb) (skb->protocol)
-#define IA_DLED 1
-#define IA_TX_DONE 2
-
-/* iadbg defines */
-#define IA_CMD 0x7749
-typedef struct {
- int cmd;
- int sub_cmd;
- int len;
- u32 maddr;
- int status;
- void __user *buf;
-} IA_CMDBUF, *PIA_CMDBUF;
-
-/* cmds */
-#define MEMDUMP 0x01
-
-/* sub_cmds */
-#define MEMDUMP_SEGREG 0x2
-#define MEMDUMP_DEV 0x1
-#define MEMDUMP_REASSREG 0x3
-#define MEMDUMP_FFL 0x4
-#define READ_REG 0x5
-#define WAKE_DBG_WAIT 0x6
-
-/************************ IADBG DEFINE END ***************************/
-
-#define Boolean(x) ((x) ? 1 : 0)
-#define NR_VCI 1024 /* number of VCIs */
-#define NR_VCI_LD 10 /* log2(NR_VCI) */
-#define NR_VCI_4K 4096 /* number of VCIs */
-#define NR_VCI_4K_LD 12 /* log2(NR_VCI) */
-#define MEM_VALID 0xfffffff0 /* mask base address with this */
-
-#ifndef PCI_VENDOR_ID_IPHASE
-#define PCI_VENDOR_ID_IPHASE 0x107e
-#endif
-#ifndef PCI_DEVICE_ID_IPHASE_5575
-#define PCI_DEVICE_ID_IPHASE_5575 0x0008
-#endif
-#define DEV_LABEL "ia"
-#define PCR 207692
-#define ICR 100000
-#define MCR 0
-#define TBE 1000
-#define FRTT 1
-#define RIF 2
-#define RDF 4
-#define NRMCODE 5 /* 0 - 7 */
-#define TRMCODE 3 /* 0 - 7 */
-#define CDFCODE 6
-#define ATDFCODE 2 /* 0 - 15 */
-
-/*---------------------- Packet/Cell Memory ------------------------*/
-#define TX_PACKET_RAM 0x00000 /* start of Trasnmit Packet memory - 0 */
-#define DFL_TX_BUF_SZ 10240 /* 10 K buffers */
-#define DFL_TX_BUFFERS 50 /* number of packet buffers for Tx
- - descriptor 0 unused */
-#define REASS_RAM_SIZE 0x10000 /* for 64K 1K VC board */
-#define RX_PACKET_RAM 0x80000 /* start of Receive Packet memory - 512K */
-#define DFL_RX_BUF_SZ 10240 /* 10k buffers */
-#define DFL_RX_BUFFERS 50 /* number of packet buffers for Rx
- - descriptor 0 unused */
-
-struct cpcs_trailer
-{
- u_short control;
- u_short length;
- u_int crc32;
-};
-
-struct cpcs_trailer_desc
-{
- struct cpcs_trailer *cpcs;
- dma_addr_t dma_addr;
-};
-
-struct ia_vcc
-{
- int rxing;
- int txing;
- int NumCbrEntry;
- u32 pcr;
- u32 saved_tx_quota;
- int flow_inc;
- struct sk_buff_head txing_skb;
- int ltimeout;
- u8 vc_desc_cnt;
-
-};
-
-struct abr_vc_table
-{
- u_char status;
- u_char rdf;
- u_short air;
- u_int res[3];
- u_int req_rm_cell_data1;
- u_int req_rm_cell_data2;
- u_int add_rm_cell_data1;
- u_int add_rm_cell_data2;
-};
-
-/* 32 byte entries */
-struct main_vc
-{
- u_short type;
-#define ABR 0x8000
-#define UBR 0xc000
-#define CBR 0x0000
- /* ABR fields */
- u_short nrm;
- u_short trm;
- u_short rm_timestamp_hi;
- u_short rm_timestamp_lo:8,
- crm:8;
- u_short remainder; /* ABR and UBR fields - last 10 bits*/
- u_short next_vc_sched;
- u_short present_desc; /* all classes */
- u_short last_cell_slot; /* ABR and UBR */
- u_short pcr;
- u_short fraction;
- u_short icr;
- u_short atdf;
- u_short mcr;
- u_short acr;
- u_short unack:8,
- status:8; /* all classes */
-#define UIOLI 0x80
-#define CRC_APPEND 0x40 /* for status field - CRC-32 append */
-#define ABR_STATE 0x02
-
-};
-
-
-/* 8 byte entries */
-struct ext_vc
-{
- u_short atm_hdr1;
- u_short atm_hdr2;
- u_short last_desc;
- u_short out_of_rate_link; /* reserved for UBR and CBR */
-};
-
-
-#define DLE_ENTRIES 256
-#define DMA_INT_ENABLE 0x0002 /* use for both Tx and Rx */
-#define TX_DLE_PSI 0x0001
-#define DLE_TOTAL_SIZE (sizeof(struct dle)*DLE_ENTRIES)
-
-/* Descriptor List Entries (DLE) */
-struct dle
-{
- u32 sys_pkt_addr;
- u32 local_pkt_addr;
- u32 bytes;
- u16 prq_wr_ptr_data;
- u16 mode;
-};
-
-struct dle_q
-{
- struct dle *start;
- struct dle *end;
- struct dle *read;
- struct dle *write;
-};
-
-struct free_desc_q
-{
- int desc; /* Descriptor number */
- struct free_desc_q *next;
-};
-
-struct tx_buf_desc {
- unsigned short desc_mode;
- unsigned short vc_index;
- unsigned short res1; /* reserved field */
- unsigned short bytes;
- unsigned short buf_start_hi;
- unsigned short buf_start_lo;
- unsigned short res2[10]; /* reserved field */
-};
-
-
-struct rx_buf_desc {
- unsigned short desc_mode;
- unsigned short vc_index;
- unsigned short vpi;
- unsigned short bytes;
- unsigned short buf_start_hi;
- unsigned short buf_start_lo;
- unsigned short dma_start_hi;
- unsigned short dma_start_lo;
- unsigned short crc_upper;
- unsigned short crc_lower;
- unsigned short res:8, timeout:8;
- unsigned short res2[5]; /* reserved field */
-};
-
-/*--------SAR stuff ---------------------*/
-
-#define EPROM_SIZE 0x40000 /* says 64K in the docs ??? */
-#define MAC1_LEN 4
-#define MAC2_LEN 2
-
-/*------------ PCI Memory Space Map, 128K SAR memory ----------------*/
-#define IPHASE5575_PCI_CONFIG_REG_BASE 0x0000
-#define IPHASE5575_BUS_CONTROL_REG_BASE 0x1000 /* offsets 0x00 - 0x3c */
-#define IPHASE5575_FRAG_CONTROL_REG_BASE 0x2000
-#define IPHASE5575_REASS_CONTROL_REG_BASE 0x3000
-#define IPHASE5575_DMA_CONTROL_REG_BASE 0x4000
-#define IPHASE5575_FRONT_END_REG_BASE IPHASE5575_DMA_CONTROL_REG_BASE
-#define IPHASE5575_FRAG_CONTROL_RAM_BASE 0x10000
-#define IPHASE5575_REASS_CONTROL_RAM_BASE 0x20000
-
-/*------------ Bus interface control registers -----------------*/
-#define IPHASE5575_BUS_CONTROL_REG 0x00
-#define IPHASE5575_BUS_STATUS_REG 0x01 /* actual offset 0x04 */
-#define IPHASE5575_MAC1 0x02
-#define IPHASE5575_REV 0x03
-#define IPHASE5575_MAC2 0x03 /*actual offset 0x0e-reg 0x0c*/
-#define IPHASE5575_EXT_RESET 0x04
-#define IPHASE5575_INT_RESET 0x05 /* addr 1c ?? reg 0x06 */
-#define IPHASE5575_PCI_ADDR_PAGE 0x07 /* reg 0x08, 0x09 ?? */
-#define IPHASE5575_EEPROM_ACCESS 0x0a /* actual offset 0x28 */
-#define IPHASE5575_CELL_FIFO_QUEUE_SZ 0x0b
-#define IPHASE5575_CELL_FIFO_MARK_STATE 0x0c
-#define IPHASE5575_CELL_FIFO_READ_PTR 0x0d
-#define IPHASE5575_CELL_FIFO_WRITE_PTR 0x0e
-#define IPHASE5575_CELL_FIFO_CELLS_AVL 0x0f /* actual offset 0x3c */
-
-/* Bus Interface Control Register bits */
-#define CTRL_FE_RST 0x80000000
-#define CTRL_LED 0x40000000
-#define CTRL_25MBPHY 0x10000000
-#define CTRL_ENCMBMEM 0x08000000
-#define CTRL_ENOFFSEG 0x01000000
-#define CTRL_ERRMASK 0x00400000
-#define CTRL_DLETMASK 0x00100000
-#define CTRL_DLERMASK 0x00080000
-#define CTRL_FEMASK 0x00040000
-#define CTRL_SEGMASK 0x00020000
-#define CTRL_REASSMASK 0x00010000
-#define CTRL_CSPREEMPT 0x00002000
-#define CTRL_B128 0x00000200
-#define CTRL_B64 0x00000100
-#define CTRL_B48 0x00000080
-#define CTRL_B32 0x00000040
-#define CTRL_B16 0x00000020
-#define CTRL_B8 0x00000010
-
-/* Bus Interface Status Register bits */
-#define STAT_CMEMSIZ 0xc0000000
-#define STAT_ADPARCK 0x20000000
-#define STAT_RESVD 0x1fffff80
-#define STAT_ERRINT 0x00000040
-#define STAT_MARKINT 0x00000020
-#define STAT_DLETINT 0x00000010
-#define STAT_DLERINT 0x00000008
-#define STAT_FEINT 0x00000004
-#define STAT_SEGINT 0x00000002
-#define STAT_REASSINT 0x00000001
-
-
-/*--------------- Segmentation control registers -----------------*/
-/* The segmentation registers are 16 bits access and the addresses
- are defined as such so the addresses are the actual "offsets" */
-#define IDLEHEADHI 0x00
-#define IDLEHEADLO 0x01
-#define MAXRATE 0x02
-/* Values for MAXRATE register for 155Mbps and 25.6 Mbps operation */
-#define RATE155 0x64b1 // 16 bits float format
-#define MAX_ATM_155 352768 // Cells/second p.118
-#define RATE25 0x5f9d
-
-#define STPARMS 0x03
-#define STPARMS_1K 0x008c
-#define STPARMS_2K 0x0049
-#define STPARMS_4K 0x0026
-#define COMP_EN 0x4000
-#define CBR_EN 0x2000
-#define ABR_EN 0x0800
-#define UBR_EN 0x0400
-
-#define ABRUBR_ARB 0x04
-#define RM_TYPE 0x05
-/*Value for RM_TYPE register for ATM Forum Traffic Mangement4.0 support*/
-#define RM_TYPE_4_0 0x0100
-
-#define SEG_COMMAND_REG 0x17
-/* Values for the command register */
-#define RESET_SEG 0x0055
-#define RESET_SEG_STATE 0x00aa
-#define RESET_TX_CELL_CTR 0x00cc
-
-#define CBR_PTR_BASE 0x20
-#define ABR_SBPTR_BASE 0x22
-#define UBR_SBPTR_BASE 0x23
-#define ABRWQ_BASE 0x26
-#define UBRWQ_BASE 0x27
-#define VCT_BASE 0x28
-#define VCTE_BASE 0x29
-#define CBR_TAB_BEG 0x2c
-#define CBR_TAB_END 0x2d
-#define PRQ_ST_ADR 0x30
-#define PRQ_ED_ADR 0x31
-#define PRQ_RD_PTR 0x32
-#define PRQ_WR_PTR 0x33
-#define TCQ_ST_ADR 0x34
-#define TCQ_ED_ADR 0x35
-#define TCQ_RD_PTR 0x36
-#define TCQ_WR_PTR 0x37
-#define SEG_QUEUE_BASE 0x40
-#define SEG_DESC_BASE 0x41
-#define MODE_REG_0 0x45
-#define T_ONLINE 0x0002 /* (i)chipSAR is online */
-
-#define MODE_REG_1 0x46
-#define MODE_REG_1_VAL 0x0400 /*for propoer device operation*/
-
-#define SEG_INTR_STATUS_REG 0x47
-#define SEG_MASK_REG 0x48
-#define TRANSMIT_DONE 0x0200
-#define TCQ_NOT_EMPTY 0x1000 /* this can be used for both the interrupt
- status registers as well as the mask register */
-
-#define CELL_CTR_HIGH_AUTO 0x49
-#define CELL_CTR_HIGH_NOAUTO 0xc9
-#define CELL_CTR_LO_AUTO 0x4a
-#define CELL_CTR_LO_NOAUTO 0xca
-
-/* Diagnostic registers */
-#define NEXTDESC 0x59
-#define NEXTVC 0x5a
-#define PSLOTCNT 0x5d
-#define NEWDN 0x6a
-#define NEWVC 0x6b
-#define SBPTR 0x6c
-#define ABRWQ_WRPTR 0x6f
-#define ABRWQ_RDPTR 0x70
-#define UBRWQ_WRPTR 0x71
-#define UBRWQ_RDPTR 0x72
-#define CBR_VC 0x73
-#define ABR_SBVC 0x75
-#define UBR_SBVC 0x76
-#define ABRNEXTLINK 0x78
-#define UBRNEXTLINK 0x79
-
-
-/*----------------- Reassembly control registers ---------------------*/
-/* The reassembly registers are 16 bits access and the addresses
- are defined as such so the addresses are the actual "offsets" */
-#define MODE_REG 0x00
-#define R_ONLINE 0x0002 /* (i)chip is online */
-#define IGN_RAW_FL 0x0004
-
-#define PROTOCOL_ID 0x01
-#define REASS_MASK_REG 0x02
-#define REASS_INTR_STATUS_REG 0x03
-/* Interrupt Status register bits */
-#define RX_PKT_CTR_OF 0x8000
-#define RX_ERR_CTR_OF 0x4000
-#define RX_CELL_CTR_OF 0x1000
-#define RX_FREEQ_EMPT 0x0200
-#define RX_EXCPQ_FL 0x0080
-#define RX_RAWQ_FL 0x0010
-#define RX_EXCP_RCVD 0x0008
-#define RX_PKT_RCVD 0x0004
-#define RX_RAW_RCVD 0x0001
-
-#define DRP_PKT_CNTR 0x04
-#define ERR_CNTR 0x05
-#define RAW_BASE_ADR 0x08
-#define CELL_CTR0 0x0c
-#define CELL_CTR1 0x0d
-#define REASS_COMMAND_REG 0x0f
-/* Values for command register */
-#define RESET_REASS 0x0055
-#define RESET_REASS_STATE 0x00aa
-#define RESET_DRP_PKT_CNTR 0x00f1
-#define RESET_ERR_CNTR 0x00f2
-#define RESET_CELL_CNTR 0x00f8
-#define RESET_REASS_ALL_REGS 0x00ff
-
-#define REASS_DESC_BASE 0x10
-#define VC_LKUP_BASE 0x11
-#define REASS_TABLE_BASE 0x12
-#define REASS_QUEUE_BASE 0x13
-#define PKT_TM_CNT 0x16
-#define TMOUT_RANGE 0x17
-#define INTRVL_CNTR 0x18
-#define TMOUT_INDX 0x19
-#define VP_LKUP_BASE 0x1c
-#define VP_FILTER 0x1d
-#define ABR_LKUP_BASE 0x1e
-#define FREEQ_ST_ADR 0x24
-#define FREEQ_ED_ADR 0x25
-#define FREEQ_RD_PTR 0x26
-#define FREEQ_WR_PTR 0x27
-#define PCQ_ST_ADR 0x28
-#define PCQ_ED_ADR 0x29
-#define PCQ_RD_PTR 0x2a
-#define PCQ_WR_PTR 0x2b
-#define EXCP_Q_ST_ADR 0x2c
-#define EXCP_Q_ED_ADR 0x2d
-#define EXCP_Q_RD_PTR 0x2e
-#define EXCP_Q_WR_PTR 0x2f
-#define CC_FIFO_ST_ADR 0x34
-#define CC_FIFO_ED_ADR 0x35
-#define CC_FIFO_RD_PTR 0x36
-#define CC_FIFO_WR_PTR 0x37
-#define STATE_REG 0x38
-#define BUF_SIZE 0x42
-#define XTRA_RM_OFFSET 0x44
-#define DRP_PKT_CNTR_NC 0x84
-#define ERR_CNTR_NC 0x85
-#define CELL_CNTR0_NC 0x8c
-#define CELL_CNTR1_NC 0x8d
-
-/* State Register bits */
-#define EXCPQ_EMPTY 0x0040
-#define PCQ_EMPTY 0x0010
-#define FREEQ_EMPTY 0x0004
-
-
-/*----------------- Front End registers/ DMA control --------------*/
-/* There is a lot of documentation error regarding these offsets ???
- eg:- 2 offsets given 800, a00 for rx counter
- similarly many others
- Remember again that the offsets are to be 4*register number, so
- correct the #defines here
-*/
-#define IPHASE5575_TX_COUNTER 0x200 /* offset - 0x800 */
-#define IPHASE5575_RX_COUNTER 0x280 /* offset - 0xa00 */
-#define IPHASE5575_TX_LIST_ADDR 0x300 /* offset - 0xc00 */
-#define IPHASE5575_RX_LIST_ADDR 0x380 /* offset - 0xe00 */
-
-/*--------------------------- RAM ---------------------------*/
-/* These memory maps are actually offsets from the segmentation and reassembly RAM base addresses */
-
-/* Segmentation Control Memory map */
-#define TX_DESC_BASE 0x0000 /* Buffer Decriptor Table */
-#define TX_COMP_Q 0x1000 /* Transmit Complete Queue */
-#define PKT_RDY_Q 0x1400 /* Packet Ready Queue */
-#define CBR_SCHED_TABLE 0x1800 /* CBR Table */
-#define UBR_SCHED_TABLE 0x3000 /* UBR Table */
-#define UBR_WAIT_Q 0x4000 /* UBR Wait Queue */
-#define ABR_SCHED_TABLE 0x5000 /* ABR Table */
-#define ABR_WAIT_Q 0x5800 /* ABR Wait Queue */
-#define EXT_VC_TABLE 0x6000 /* Extended VC Table */
-#define MAIN_VC_TABLE 0x8000 /* Main VC Table */
-#define SCHEDSZ 1024 /* ABR and UBR Scheduling Table size */
-#define TX_DESC_TABLE_SZ 128 /* Number of entries in the Transmit
- Buffer Descriptor Table */
-
-/* These are used as table offsets in Descriptor Table address generation */
-#define DESC_MODE 0x0
-#define VC_INDEX 0x1
-#define BYTE_CNT 0x3
-#define PKT_START_HI 0x4
-#define PKT_START_LO 0x5
-
-/* Descriptor Mode Word Bits */
-#define EOM_EN 0x0800
-#define AAL5 0x0100
-#define APP_CRC32 0x0400
-#define CMPL_INT 0x1000
-
-#define TABLE_ADDRESS(db, dn, to) \
- (((unsigned long)(db & 0x04)) << 16) | (dn << 5) | (to << 1)
-
-/* Reassembly Control Memory Map */
-#define RX_DESC_BASE 0x0000 /* Buffer Descriptor Table */
-#define VP_TABLE 0x5c00 /* VP Table */
-#define EXCEPTION_Q 0x5e00 /* Exception Queue */
-#define FREE_BUF_DESC_Q 0x6000 /* Free Buffer Descriptor Queue */
-#define PKT_COMP_Q 0x6800 /* Packet Complete Queue */
-#define REASS_TABLE 0x7000 /* Reassembly Table */
-#define RX_VC_TABLE 0x7800 /* VC Table */
-#define ABR_VC_TABLE 0x8000 /* ABR VC Table */
-#define RX_DESC_TABLE_SZ 736 /* Number of entries in the Receive
- Buffer Descriptor Table */
-#define VP_TABLE_SZ 256 /* Number of entries in VPTable */
-#define RX_VC_TABLE_SZ 1024 /* Number of entries in VC Table */
-#define REASS_TABLE_SZ 1024 /* Number of entries in Reassembly Table */
- /* Buffer Descriptor Table */
-#define RX_ACT 0x8000
-#define RX_VPVC 0x4000
-#define RX_CNG 0x0040
-#define RX_CER 0x0008
-#define RX_PTE 0x0004
-#define RX_OFL 0x0002
-#define NUM_RX_EXCP 32
-
-/* Reassembly Table */
-#define NO_AAL5_PKT 0x0000
-#define AAL5_PKT_REASSEMBLED 0x4000
-#define AAL5_PKT_TERMINATED 0x8000
-#define RAW_PKT 0xc000
-#define REASS_ABR 0x2000
-
-/*-------------------- Base Registers --------------------*/
-#define REG_BASE IPHASE5575_BUS_CONTROL_REG_BASE
-#define RAM_BASE IPHASE5575_FRAG_CONTROL_RAM_BASE
-#define PHY_BASE IPHASE5575_FRONT_END_REG_BASE
-#define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE
-#define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE
-
-typedef volatile u_int ffreg_t;
-typedef u_int rreg_t;
-
-typedef struct _ffredn_t {
- ffreg_t idlehead_high; /* Idle cell header (high) */
- ffreg_t idlehead_low; /* Idle cell header (low) */
- ffreg_t maxrate; /* Maximum rate */
- ffreg_t stparms; /* Traffic Management Parameters */
- ffreg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */
- ffreg_t rm_type; /* */
- u_int filler5[0x17 - 0x06];
- ffreg_t cmd_reg; /* Command register */
- u_int filler18[0x20 - 0x18];
- ffreg_t cbr_base; /* CBR Pointer Base */
- ffreg_t vbr_base; /* VBR Pointer Base */
- ffreg_t abr_base; /* ABR Pointer Base */
- ffreg_t ubr_base; /* UBR Pointer Base */
- u_int filler24;
- ffreg_t vbrwq_base; /* VBR Wait Queue Base */
- ffreg_t abrwq_base; /* ABR Wait Queue Base */
- ffreg_t ubrwq_base; /* UBR Wait Queue Base */
- ffreg_t vct_base; /* Main VC Table Base */
- ffreg_t vcte_base; /* Extended Main VC Table Base */
- u_int filler2a[0x2C - 0x2A];
- ffreg_t cbr_tab_beg; /* CBR Table Begin */
- ffreg_t cbr_tab_end; /* CBR Table End */
- ffreg_t cbr_pointer; /* CBR Pointer */
- u_int filler2f[0x30 - 0x2F];
- ffreg_t prq_st_adr; /* Packet Ready Queue Start Address */
- ffreg_t prq_ed_adr; /* Packet Ready Queue End Address */
- ffreg_t prq_rd_ptr; /* Packet Ready Queue read pointer */
- ffreg_t prq_wr_ptr; /* Packet Ready Queue write pointer */
- ffreg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/
- ffreg_t tcq_ed_adr; /* Transmit Complete Queue End Address */
- ffreg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */
- ffreg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/
- u_int filler38[0x40 - 0x38];
- ffreg_t queue_base; /* Base address for PRQ and TCQ */
- ffreg_t desc_base; /* Base address of descriptor table */
- u_int filler42[0x45 - 0x42];
- ffreg_t mode_reg_0; /* Mode register 0 */
- ffreg_t mode_reg_1; /* Mode register 1 */
- ffreg_t intr_status_reg;/* Interrupt Status register */
- ffreg_t mask_reg; /* Mask Register */
- ffreg_t cell_ctr_high1; /* Total cell transfer count (high) */
- ffreg_t cell_ctr_lo1; /* Total cell transfer count (low) */
- ffreg_t state_reg; /* Status register */
- u_int filler4c[0x58 - 0x4c];
- ffreg_t curr_desc_num; /* Contains the current descriptor num */
- ffreg_t next_desc; /* Next descriptor */
- ffreg_t next_vc; /* Next VC */
- u_int filler5b[0x5d - 0x5b];
- ffreg_t present_slot_cnt;/* Present slot count */
- u_int filler5e[0x6a - 0x5e];
- ffreg_t new_desc_num; /* New descriptor number */
- ffreg_t new_vc; /* New VC */
- ffreg_t sched_tbl_ptr; /* Schedule table pointer */
- ffreg_t vbrwq_wptr; /* VBR wait queue write pointer */
- ffreg_t vbrwq_rptr; /* VBR wait queue read pointer */
- ffreg_t abrwq_wptr; /* ABR wait queue write pointer */
- ffreg_t abrwq_rptr; /* ABR wait queue read pointer */
- ffreg_t ubrwq_wptr; /* UBR wait queue write pointer */
- ffreg_t ubrwq_rptr; /* UBR wait queue read pointer */
- ffreg_t cbr_vc; /* CBR VC */
- ffreg_t vbr_sb_vc; /* VBR SB VC */
- ffreg_t abr_sb_vc; /* ABR SB VC */
- ffreg_t ubr_sb_vc; /* UBR SB VC */
- ffreg_t vbr_next_link; /* VBR next link */
- ffreg_t abr_next_link; /* ABR next link */
- ffreg_t ubr_next_link; /* UBR next link */
- u_int filler7a[0x7c-0x7a];
- ffreg_t out_rate_head; /* Out of rate head */
- u_int filler7d[0xca-0x7d]; /* pad out to full address space */
- ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */
- ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */
- u_int fillercc[0x100-0xcc]; /* pad out to full address space */
-} ffredn_t;
-
-typedef struct _rfredn_t {
- rreg_t mode_reg_0; /* Mode register 0 */
- rreg_t protocol_id; /* Protocol ID */
- rreg_t mask_reg; /* Mask Register */
- rreg_t intr_status_reg;/* Interrupt status register */
- rreg_t drp_pkt_cntr; /* Dropped packet cntr (clear on read) */
- rreg_t err_cntr; /* Error Counter (cleared on read) */
- u_int filler6[0x08 - 0x06];
- rreg_t raw_base_adr; /* Base addr for raw cell Q */
- u_int filler2[0x0c - 0x09];
- rreg_t cell_ctr0; /* Cell Counter 0 (cleared when read) */
- rreg_t cell_ctr1; /* Cell Counter 1 (cleared when read) */
- u_int filler3[0x0f - 0x0e];
- rreg_t cmd_reg; /* Command register */
- rreg_t desc_base; /* Base address for description table */
- rreg_t vc_lkup_base; /* Base address for VC lookup table */
- rreg_t reass_base; /* Base address for reassembler table */
- rreg_t queue_base; /* Base address for Communication queue */
- u_int filler14[0x16 - 0x14];
- rreg_t pkt_tm_cnt; /* Packet Timeout and count register */
- rreg_t tmout_range; /* Range of reassembley IDs for timeout */
- rreg_t intrvl_cntr; /* Packet aging interval counter */
- rreg_t tmout_indx; /* index of pkt being tested for aging */
- u_int filler1a[0x1c - 0x1a];
- rreg_t vp_lkup_base; /* Base address for VP lookup table */
- rreg_t vp_filter; /* VP filter register */
- rreg_t abr_lkup_base; /* Base address of ABR VC Table */
- u_int filler1f[0x24 - 0x1f];
- rreg_t fdq_st_adr; /* Free desc queue start address */
- rreg_t fdq_ed_adr; /* Free desc queue end address */
- rreg_t fdq_rd_ptr; /* Free desc queue read pointer */
- rreg_t fdq_wr_ptr; /* Free desc queue write pointer */
- rreg_t pcq_st_adr; /* Packet Complete queue start address */
- rreg_t pcq_ed_adr; /* Packet Complete queue end address */
- rreg_t pcq_rd_ptr; /* Packet Complete queue read pointer */
- rreg_t pcq_wr_ptr; /* Packet Complete queue write pointer */
- rreg_t excp_st_adr; /* Exception queue start address */
- rreg_t excp_ed_adr; /* Exception queue end address */
- rreg_t excp_rd_ptr; /* Exception queue read pointer */
- rreg_t excp_wr_ptr; /* Exception queue write pointer */
- u_int filler30[0x34 - 0x30];
- rreg_t raw_st_adr; /* Raw Cell start address */
- rreg_t raw_ed_adr; /* Raw Cell end address */
- rreg_t raw_rd_ptr; /* Raw Cell read pointer */
- rreg_t raw_wr_ptr; /* Raw Cell write pointer */
- rreg_t state_reg; /* State Register */
- u_int filler39[0x42 - 0x39];
- rreg_t buf_size; /* Buffer size */
- u_int filler43;
- rreg_t xtra_rm_offset; /* Offset of the additional turnaround RM */
- u_int filler45[0x84 - 0x45];
- rreg_t drp_pkt_cntr_nc;/* Dropped Packet cntr, Not clear on rd */
- rreg_t err_cntr_nc; /* Error Counter, Not clear on read */
- u_int filler86[0x8c - 0x86];
- rreg_t cell_ctr0_nc; /* Cell Counter 0, Not clear on read */
- rreg_t cell_ctr1_nc; /* Cell Counter 1, Not clear on read */
- u_int filler8e[0x100-0x8e]; /* pad out to full address space */
-} rfredn_t;
-
-typedef struct {
- /* Atlantic */
- ffredn_t ffredn; /* F FRED */
- rfredn_t rfredn; /* R FRED */
-} ia_regs_t;
-
-typedef struct {
- u_short f_vc_type; /* VC type */
- u_short f_nrm; /* Nrm */
- u_short f_nrmexp; /* Nrm Exp */
- u_short reserved6; /* */
- u_short f_crm; /* Crm */
- u_short reserved10; /* Reserved */
- u_short reserved12; /* Reserved */
- u_short reserved14; /* Reserved */
- u_short last_cell_slot; /* last_cell_slot_count */
- u_short f_pcr; /* Peak Cell Rate */
- u_short fraction; /* fraction */
- u_short f_icr; /* Initial Cell Rate */
- u_short f_cdf; /* */
- u_short f_mcr; /* Minimum Cell Rate */
- u_short f_acr; /* Allowed Cell Rate */
- u_short f_status; /* */
-} f_vc_abr_entry;
-
-typedef struct {
- u_short r_status_rdf; /* status + RDF */
- u_short r_air; /* AIR */
- u_short reserved4[14]; /* Reserved */
-} r_vc_abr_entry;
-
-#define MRM 3
-
-typedef struct srv_cls_param {
- u32 class_type; /* CBR/VBR/ABR/UBR; use the enum above */
- u32 pcr; /* Peak Cell Rate (24-bit) */
- /* VBR parameters */
- u32 scr; /* sustainable cell rate */
- u32 max_burst_size; /* ?? cell rate or data rate */
-
- /* ABR only UNI 4.0 Parameters */
- u32 mcr; /* Min Cell Rate (24-bit) */
- u32 icr; /* Initial Cell Rate (24-bit) */
- u32 tbe; /* Transient Buffer Exposure (24-bit) */
- u32 frtt; /* Fixed Round Trip Time (24-bit) */
-
-#if 0 /* Additional Parameters of TM 4.0 */
-bits 31 30 29 28 27-25 24-22 21-19 18-9
------------------------------------------------------------------------------
-| NRM present | TRM prsnt | CDF prsnt | ADTF prsnt | NRM | TRM | CDF | ADTF |
------------------------------------------------------------------------------
-#endif /* 0 */
-
- u8 nrm; /* Max # of Cells for each forward RM
- cell (3-bit) */
- u8 trm; /* Time between forward RM cells (3-bit) */
- u16 adtf; /* ACR Decrease Time Factor (10-bit) */
- u8 cdf; /* Cutoff Decrease Factor (3-bit) */
- u8 rif; /* Rate Increment Factor (4-bit) */
- u8 rdf; /* Rate Decrease Factor (4-bit) */
- u8 reserved; /* 8 bits to keep structure word aligned */
-} srv_cls_param_t;
-
-struct testTable_t {
- u16 lastTime;
- u16 fract;
- u8 vc_status;
-};
-
-typedef struct {
- u16 vci;
- u16 error;
-} RX_ERROR_Q;
-
-typedef struct {
- u8 active: 1;
- u8 abr: 1;
- u8 ubr: 1;
- u8 cnt: 5;
-#define VC_ACTIVE 0x01
-#define VC_ABR 0x02
-#define VC_UBR 0x04
-} vcstatus_t;
-
-struct ia_rfL_t {
- u32 fdq_st; /* Free desc queue start address */
- u32 fdq_ed; /* Free desc queue end address */
- u32 fdq_rd; /* Free desc queue read pointer */
- u32 fdq_wr; /* Free desc queue write pointer */
- u32 pcq_st; /* Packet Complete queue start address */
- u32 pcq_ed; /* Packet Complete queue end address */
- u32 pcq_rd; /* Packet Complete queue read pointer */
- u32 pcq_wr; /* Packet Complete queue write pointer */
-};
-
-struct ia_ffL_t {
- u32 prq_st; /* Packet Ready Queue Start Address */
- u32 prq_ed; /* Packet Ready Queue End Address */
- u32 prq_wr; /* Packet Ready Queue write pointer */
- u32 tcq_st; /* Transmit Complete Queue Start Address*/
- u32 tcq_ed; /* Transmit Complete Queue End Address */
- u32 tcq_rd; /* Transmit Complete Queue read pointer */
-};
-
-struct desc_tbl_t {
- u32 timestamp;
- struct ia_vcc *iavcc;
- struct sk_buff *txskb;
-};
-
-typedef struct ia_rtn_q {
- struct desc_tbl_t data;
- struct ia_rtn_q *next, *tail;
-} IARTN_Q;
-
-#define SUNI_LOSV 0x04
-enum ia_suni {
- SUNI_MASTER_RESET = 0x000, /* SUNI Master Reset and Identity */
- SUNI_MASTER_CONFIG = 0x004, /* SUNI Master Configuration */
- SUNI_MASTER_INTR_STAT = 0x008, /* SUNI Master Interrupt Status */
- SUNI_RESERVED1 = 0x00c, /* Reserved */
- SUNI_MASTER_CLK_MONITOR = 0x010, /* SUNI Master Clock Monitor */
- SUNI_MASTER_CONTROL = 0x014, /* SUNI Master Clock Monitor */
- /* Reserved (10) */
- SUNI_RSOP_CONTROL = 0x040, /* RSOP Control/Interrupt Enable */
- SUNI_RSOP_STATUS = 0x044, /* RSOP Status/Interrupt States */
- SUNI_RSOP_SECTION_BIP8L = 0x048, /* RSOP Section BIP-8 LSB */
- SUNI_RSOP_SECTION_BIP8M = 0x04c, /* RSOP Section BIP-8 MSB */
-
- SUNI_TSOP_CONTROL = 0x050, /* TSOP Control */
- SUNI_TSOP_DIAG = 0x054, /* TSOP Disgnostics */
- /* Reserved (2) */
- SUNI_RLOP_CS = 0x060, /* RLOP Control/Status */
- SUNI_RLOP_INTR = 0x064, /* RLOP Interrupt Enable/Status */
- SUNI_RLOP_LINE_BIP24L = 0x068, /* RLOP Line BIP-24 LSB */
- SUNI_RLOP_LINE_BIP24 = 0x06c, /* RLOP Line BIP-24 */
- SUNI_RLOP_LINE_BIP24M = 0x070, /* RLOP Line BIP-24 MSB */
- SUNI_RLOP_LINE_FEBEL = 0x074, /* RLOP Line FEBE LSB */
- SUNI_RLOP_LINE_FEBE = 0x078, /* RLOP Line FEBE */
- SUNI_RLOP_LINE_FEBEM = 0x07c, /* RLOP Line FEBE MSB */
-
- SUNI_TLOP_CONTROL = 0x080, /* TLOP Control */
- SUNI_TLOP_DISG = 0x084, /* TLOP Disgnostics */
- /* Reserved (14) */
- SUNI_RPOP_CS = 0x0c0, /* RPOP Status/Control */
- SUNI_RPOP_INTR = 0x0c4, /* RPOP Interrupt/Status */
- SUNI_RPOP_RESERVED = 0x0c8, /* RPOP Reserved */
- SUNI_RPOP_INTR_ENA = 0x0cc, /* RPOP Interrupt Enable */
- /* Reserved (3) */
- SUNI_RPOP_PATH_SIG = 0x0dc, /* RPOP Path Signal Label */
- SUNI_RPOP_BIP8L = 0x0e0, /* RPOP Path BIP-8 LSB */
- SUNI_RPOP_BIP8M = 0x0e4, /* RPOP Path BIP-8 MSB */
- SUNI_RPOP_FEBEL = 0x0e8, /* RPOP Path FEBE LSB */
- SUNI_RPOP_FEBEM = 0x0ec, /* RPOP Path FEBE MSB */
- /* Reserved (4) */
- SUNI_TPOP_CNTRL_DAIG = 0x100, /* TPOP Control/Disgnostics */
- SUNI_TPOP_POINTER_CTRL = 0x104, /* TPOP Pointer Control */
- SUNI_TPOP_SOURCER_CTRL = 0x108, /* TPOP Source Control */
- /* Reserved (2) */
- SUNI_TPOP_ARB_PRTL = 0x114, /* TPOP Arbitrary Pointer LSB */
- SUNI_TPOP_ARB_PRTM = 0x118, /* TPOP Arbitrary Pointer MSB */
- SUNI_TPOP_RESERVED2 = 0x11c, /* TPOP Reserved */
- SUNI_TPOP_PATH_SIG = 0x120, /* TPOP Path Signal Lable */
- SUNI_TPOP_PATH_STATUS = 0x124, /* TPOP Path Status */
- /* Reserved (6) */
- SUNI_RACP_CS = 0x140, /* RACP Control/Status */
- SUNI_RACP_INTR = 0x144, /* RACP Interrupt Enable/Status */
- SUNI_RACP_HDR_PATTERN = 0x148, /* RACP Match Header Pattern */
- SUNI_RACP_HDR_MASK = 0x14c, /* RACP Match Header Mask */
- SUNI_RACP_CORR_HCS = 0x150, /* RACP Correctable HCS Error Count */
- SUNI_RACP_UNCORR_HCS = 0x154, /* RACP Uncorrectable HCS Err Count */
- /* Reserved (10) */
- SUNI_TACP_CONTROL = 0x180, /* TACP Control */
- SUNI_TACP_IDLE_HDR_PAT = 0x184, /* TACP Idle Cell Header Pattern */
- SUNI_TACP_IDLE_PAY_PAY = 0x188, /* TACP Idle Cell Payld Octet Patrn */
- /* Reserved (5) */
- /* Reserved (24) */
- /* FIXME: unused but name conflicts.
- * SUNI_MASTER_TEST = 0x200, SUNI Master Test */
- SUNI_RESERVED_TEST = 0x204 /* SUNI Reserved for Test */
-};
-
-typedef struct _SUNI_STATS_
-{
- u32 valid; // 1 = oc3 PHY card
- u32 carrier_detect; // GPIN input
- // RSOP: receive section overhead processor
- u16 rsop_oof_state; // 1 = out of frame
- u16 rsop_lof_state; // 1 = loss of frame
- u16 rsop_los_state; // 1 = loss of signal
- u32 rsop_los_count; // loss of signal count
- u32 rsop_bse_count; // section BIP-8 error count
- // RLOP: receive line overhead processor
- u16 rlop_ferf_state; // 1 = far end receive failure
- u16 rlop_lais_state; // 1 = line AIS
- u32 rlop_lbe_count; // BIP-24 count
- u32 rlop_febe_count; // FEBE count;
- // RPOP: receive path overhead processor
- u16 rpop_lop_state; // 1 = LOP
- u16 rpop_pais_state; // 1 = path AIS
- u16 rpop_pyel_state; // 1 = path yellow alert
- u32 rpop_bip_count; // path BIP-8 error count
- u32 rpop_febe_count; // path FEBE error count
- u16 rpop_psig; // path signal label value
- // RACP: receive ATM cell processor
- u16 racp_hp_state; // hunt/presync state
- u32 racp_fu_count; // FIFO underrun count
- u32 racp_fo_count; // FIFO overrun count
- u32 racp_chcs_count; // correctable HCS error count
- u32 racp_uchcs_count; // uncorrectable HCS error count
-} IA_SUNI_STATS;
-
-typedef struct iadev_priv {
- /*-----base pointers into (i)chipSAR+ address space */
- u32 __iomem *phy; /* Base pointer into phy (SUNI). */
- u32 __iomem *dma; /* Base pointer into DMA control registers. */
- u32 __iomem *reg; /* Base pointer to SAR registers. */
- u32 __iomem *seg_reg; /* base pointer to segmentation engine
- internal registers */
- u32 __iomem *reass_reg; /* base pointer to reassemble engine
- internal registers */
- u32 __iomem *ram; /* base pointer to SAR RAM */
- void __iomem *seg_ram;
- void __iomem *reass_ram;
- struct dle_q tx_dle_q;
- struct free_desc_q *tx_free_desc_qhead;
- struct sk_buff_head tx_dma_q, tx_backlog;
- spinlock_t tx_lock;
- IARTN_Q tx_return_q;
- u32 close_pending;
- wait_queue_head_t close_wait;
- wait_queue_head_t timeout_wait;
- struct cpcs_trailer_desc *tx_buf;
- u16 num_tx_desc, tx_buf_sz, rate_limit;
- u32 tx_cell_cnt, tx_pkt_cnt;
- void __iomem *MAIN_VC_TABLE_ADDR, *EXT_VC_TABLE_ADDR, *ABR_SCHED_TABLE_ADDR;
- struct dle_q rx_dle_q;
- struct free_desc_q *rx_free_desc_qhead;
- struct sk_buff_head rx_dma_q;
- spinlock_t rx_lock;
- struct atm_vcc **rx_open; /* list of all open VCs */
- u16 num_rx_desc, rx_buf_sz, rxing;
- u32 rx_pkt_ram, rx_tmp_cnt;
- unsigned long rx_tmp_jif;
- void __iomem *RX_DESC_BASE_ADDR;
- u32 drop_rxpkt, drop_rxcell, rx_cell_cnt, rx_pkt_cnt;
- struct atm_dev *next_board; /* other iphase devices */
- struct pci_dev *pci;
- int mem;
- unsigned int real_base; /* real and virtual base address */
- void __iomem *base;
- unsigned int pci_map_size; /*pci map size of board */
- unsigned char irq;
- unsigned char bus;
- unsigned char dev_fn;
- u_short phy_type;
- u_short num_vc, memSize, memType;
- struct ia_ffL_t ffL;
- struct ia_rfL_t rfL;
- /* Suni stat */
- // IA_SUNI_STATS suni_stats;
- unsigned char carrier_detect;
- /* CBR related */
- // transmit DMA & Receive
- unsigned int tx_dma_cnt; // number of elements on dma queue
- unsigned int rx_dma_cnt; // number of elements on rx dma queue
- unsigned int NumEnabledCBR; // number of CBR VCI's enabled. CBR
- // receive MARK for Cell FIFO
- unsigned int rx_mark_cnt; // number of elements on mark queue
- unsigned int CbrTotEntries; // Total CBR Entries in Scheduling Table.
- unsigned int CbrRemEntries; // Remaining CBR Entries in Scheduling Table.
- unsigned int CbrEntryPt; // CBR Sched Table Entry Point.
- unsigned int Granularity; // CBR Granularity given Table Size.
- /* ABR related */
- unsigned int sum_mcr, sum_cbr, LineRate;
- unsigned int n_abr;
- struct desc_tbl_t *desc_tbl;
- u_short host_tcq_wr;
- struct testTable_t **testTable;
- dma_addr_t tx_dle_dma;
- dma_addr_t rx_dle_dma;
-} IADEV;
-
-
-#define INPH_IA_DEV(d) ((IADEV *) (d)->dev_data)
-#define INPH_IA_VCC(v) ((struct ia_vcc *) (v)->dev_data)
-
-/******************* IDT77105 25MB/s PHY DEFINE *****************************/
-enum ia_mb25 {
- MB25_MASTER_CTRL = 0x00, /* Master control */
- MB25_INTR_STATUS = 0x04, /* Interrupt status */
- MB25_DIAG_CONTROL = 0x08, /* Diagnostic control */
- MB25_LED_HEC = 0x0c, /* LED driver and HEC status/control */
- MB25_LOW_BYTE_COUNTER = 0x10,
- MB25_HIGH_BYTE_COUNTER = 0x14
-};
-
-/*
- * Master Control
- */
-#define MB25_MC_UPLO 0x80 /* UPLO */
-#define MB25_MC_DREC 0x40 /* Discard receive cell errors */
-#define MB25_MC_ECEIO 0x20 /* Enable Cell Error Interrupts Only */
-#define MB25_MC_TDPC 0x10 /* Transmit data parity check */
-#define MB25_MC_DRIC 0x08 /* Discard receive idle cells */
-#define MB25_MC_HALTTX 0x04 /* Halt Tx */
-#define MB25_MC_UMS 0x02 /* UTOPIA mode select */
-#define MB25_MC_ENABLED 0x01 /* Enable interrupt */
-
-/*
- * Interrupt Status
- */
-#define MB25_IS_GSB 0x40 /* GOOD Symbol Bit */
-#define MB25_IS_HECECR 0x20 /* HEC error cell received */
-#define MB25_IS_SCR 0x10 /* "Short Cell" Received */
-#define MB25_IS_TPE 0x08 /* Trnamsit Parity Error */
-#define MB25_IS_RSCC 0x04 /* Receive Signal Condition change */
-#define MB25_IS_RCSE 0x02 /* Received Cell Symbol Error */
-#define MB25_IS_RFIFOO 0x01 /* Received FIFO Overrun */
-
-/*
- * Diagnostic Control
- */
-#define MB25_DC_FTXCD 0x80 /* Force TxClav deassert */
-#define MB25_DC_RXCOS 0x40 /* RxClav operation select */
-#define MB25_DC_ECEIO 0x20 /* Single/Multi-PHY config select */
-#define MB25_DC_RLFLUSH 0x10 /* Clear receive FIFO */
-#define MB25_DC_IXPE 0x08 /* Insert xmit payload error */
-#define MB25_DC_IXHECE 0x04 /* Insert Xmit HEC Error */
-#define MB25_DC_LB_MASK 0x03 /* Loopback control mask */
-
-#define MB25_DC_LL 0x03 /* Line Loopback */
-#define MB25_DC_PL 0x02 /* PHY Loopback */
-#define MB25_DC_NM 0x00
-
-#define FE_MASK 0x00F0
-#define FE_MULTI_MODE 0x0000
-#define FE_SINGLE_MODE 0x0010
-#define FE_UTP_OPTION 0x0020
-#define FE_25MBIT_PHY 0x0040
-#define FE_DS3_PHY 0x0080 /* DS3 */
-#define FE_E3_PHY 0x0090 /* E3 */
-
-/*********************** SUNI_PM7345 PHY DEFINE HERE *********************/
-enum suni_pm7345 {
- SUNI_CONFIG = 0x000, /* SUNI Configuration */
- SUNI_INTR_ENBL = 0x004, /* SUNI Interrupt Enable */
- SUNI_INTR_STAT = 0x008, /* SUNI Interrupt Status */
- SUNI_CONTROL = 0x00c, /* SUNI Control */
- SUNI_ID_RESET = 0x010, /* SUNI Reset and Identity */
- SUNI_DATA_LINK_CTRL = 0x014,
- SUNI_RBOC_CONF_INTR_ENBL = 0x018,
- SUNI_RBOC_STAT = 0x01c,
- SUNI_DS3_FRM_CFG = 0x020,
- SUNI_DS3_FRM_INTR_ENBL = 0x024,
- SUNI_DS3_FRM_INTR_STAT = 0x028,
- SUNI_DS3_FRM_STAT = 0x02c,
- SUNI_RFDL_CFG = 0x030,
- SUNI_RFDL_ENBL_STAT = 0x034,
- SUNI_RFDL_STAT = 0x038,
- SUNI_RFDL_DATA = 0x03c,
- SUNI_PMON_CHNG = 0x040,
- SUNI_PMON_INTR_ENBL_STAT = 0x044,
- /* SUNI_RESERVED1 (0x13 - 0x11) */
- SUNI_PMON_LCV_EVT_CNT_LSB = 0x050,
- SUNI_PMON_LCV_EVT_CNT_MSB = 0x054,
- SUNI_PMON_FBE_EVT_CNT_LSB = 0x058,
- SUNI_PMON_FBE_EVT_CNT_MSB = 0x05c,
- SUNI_PMON_SEZ_DET_CNT_LSB = 0x060,
- SUNI_PMON_SEZ_DET_CNT_MSB = 0x064,
- SUNI_PMON_PE_EVT_CNT_LSB = 0x068,
- SUNI_PMON_PE_EVT_CNT_MSB = 0x06c,
- SUNI_PMON_PPE_EVT_CNT_LSB = 0x070,
- SUNI_PMON_PPE_EVT_CNT_MSB = 0x074,
- SUNI_PMON_FEBE_EVT_CNT_LSB = 0x078,
- SUNI_PMON_FEBE_EVT_CNT_MSB = 0x07c,
- SUNI_DS3_TRAN_CFG = 0x080,
- SUNI_DS3_TRAN_DIAG = 0x084,
- /* SUNI_RESERVED2 (0x23 - 0x21) */
- SUNI_XFDL_CFG = 0x090,
- SUNI_XFDL_INTR_ST = 0x094,
- SUNI_XFDL_XMIT_DATA = 0x098,
- SUNI_XBOC_CODE = 0x09c,
- SUNI_SPLR_CFG = 0x0a0,
- SUNI_SPLR_INTR_EN = 0x0a4,
- SUNI_SPLR_INTR_ST = 0x0a8,
- SUNI_SPLR_STATUS = 0x0ac,
- SUNI_SPLT_CFG = 0x0b0,
- SUNI_SPLT_CNTL = 0x0b4,
- SUNI_SPLT_DIAG_G1 = 0x0b8,
- SUNI_SPLT_F1 = 0x0bc,
- SUNI_CPPM_LOC_METERS = 0x0c0,
- SUNI_CPPM_CHG_OF_CPPM_PERF_METR = 0x0c4,
- SUNI_CPPM_B1_ERR_CNT_LSB = 0x0c8,
- SUNI_CPPM_B1_ERR_CNT_MSB = 0x0cc,
- SUNI_CPPM_FRAMING_ERR_CNT_LSB = 0x0d0,
- SUNI_CPPM_FRAMING_ERR_CNT_MSB = 0x0d4,
- SUNI_CPPM_FEBE_CNT_LSB = 0x0d8,
- SUNI_CPPM_FEBE_CNT_MSB = 0x0dc,
- SUNI_CPPM_HCS_ERR_CNT_LSB = 0x0e0,
- SUNI_CPPM_HCS_ERR_CNT_MSB = 0x0e4,
- SUNI_CPPM_IDLE_UN_CELL_CNT_LSB = 0x0e8,
- SUNI_CPPM_IDLE_UN_CELL_CNT_MSB = 0x0ec,
- SUNI_CPPM_RCV_CELL_CNT_LSB = 0x0f0,
- SUNI_CPPM_RCV_CELL_CNT_MSB = 0x0f4,
- SUNI_CPPM_XMIT_CELL_CNT_LSB = 0x0f8,
- SUNI_CPPM_XMIT_CELL_CNT_MSB = 0x0fc,
- SUNI_RXCP_CTRL = 0x100,
- SUNI_RXCP_FCTRL = 0x104,
- SUNI_RXCP_INTR_EN_STS = 0x108,
- SUNI_RXCP_IDLE_PAT_H1 = 0x10c,
- SUNI_RXCP_IDLE_PAT_H2 = 0x110,
- SUNI_RXCP_IDLE_PAT_H3 = 0x114,
- SUNI_RXCP_IDLE_PAT_H4 = 0x118,
- SUNI_RXCP_IDLE_MASK_H1 = 0x11c,
- SUNI_RXCP_IDLE_MASK_H2 = 0x120,
- SUNI_RXCP_IDLE_MASK_H3 = 0x124,
- SUNI_RXCP_IDLE_MASK_H4 = 0x128,
- SUNI_RXCP_CELL_PAT_H1 = 0x12c,
- SUNI_RXCP_CELL_PAT_H2 = 0x130,
- SUNI_RXCP_CELL_PAT_H3 = 0x134,
- SUNI_RXCP_CELL_PAT_H4 = 0x138,
- SUNI_RXCP_CELL_MASK_H1 = 0x13c,
- SUNI_RXCP_CELL_MASK_H2 = 0x140,
- SUNI_RXCP_CELL_MASK_H3 = 0x144,
- SUNI_RXCP_CELL_MASK_H4 = 0x148,
- SUNI_RXCP_HCS_CS = 0x14c,
- SUNI_RXCP_LCD_CNT_THRESHOLD = 0x150,
- /* SUNI_RESERVED3 (0x57 - 0x54) */
- SUNI_TXCP_CTRL = 0x160,
- SUNI_TXCP_INTR_EN_STS = 0x164,
- SUNI_TXCP_IDLE_PAT_H1 = 0x168,
- SUNI_TXCP_IDLE_PAT_H2 = 0x16c,
- SUNI_TXCP_IDLE_PAT_H3 = 0x170,
- SUNI_TXCP_IDLE_PAT_H4 = 0x174,
- SUNI_TXCP_IDLE_PAT_H5 = 0x178,
- SUNI_TXCP_IDLE_PAYLOAD = 0x17c,
- SUNI_E3_FRM_FRAM_OPTIONS = 0x180,
- SUNI_E3_FRM_MAINT_OPTIONS = 0x184,
- SUNI_E3_FRM_FRAM_INTR_ENBL = 0x188,
- SUNI_E3_FRM_FRAM_INTR_IND_STAT = 0x18c,
- SUNI_E3_FRM_MAINT_INTR_ENBL = 0x190,
- SUNI_E3_FRM_MAINT_INTR_IND = 0x194,
- SUNI_E3_FRM_MAINT_STAT = 0x198,
- SUNI_RESERVED4 = 0x19c,
- SUNI_E3_TRAN_FRAM_OPTIONS = 0x1a0,
- SUNI_E3_TRAN_STAT_DIAG_OPTIONS = 0x1a4,
- SUNI_E3_TRAN_BIP_8_ERR_MASK = 0x1a8,
- SUNI_E3_TRAN_MAINT_ADAPT_OPTS = 0x1ac,
- SUNI_TTB_CTRL = 0x1b0,
- SUNI_TTB_TRAIL_TRACE_ID_STAT = 0x1b4,
- SUNI_TTB_IND_ADDR = 0x1b8,
- SUNI_TTB_IND_DATA = 0x1bc,
- SUNI_TTB_EXP_PAYLOAD_TYPE = 0x1c0,
- SUNI_TTB_PAYLOAD_TYPE_CTRL_STAT = 0x1c4,
- /* SUNI_PAD5 (0x7f - 0x71) */
- SUNI_MASTER_TEST = 0x200,
- /* SUNI_PAD6 (0xff - 0x80) */
-};
-
-#define SUNI_PM7345_T suni_pm7345_t
-#define SUNI_PM7345 0x20 /* Suni chip type */
-#define SUNI_PM5346 0x30 /* Suni chip type */
-/*
- * SUNI_PM7345 Configuration
- */
-#define SUNI_PM7345_CLB 0x01 /* Cell loopback */
-#define SUNI_PM7345_PLB 0x02 /* Payload loopback */
-#define SUNI_PM7345_DLB 0x04 /* Diagnostic loopback */
-#define SUNI_PM7345_LLB 0x80 /* Line loopback */
-#define SUNI_PM7345_E3ENBL 0x40 /* E3 enable bit */
-#define SUNI_PM7345_LOOPT 0x10 /* LOOPT enable bit */
-#define SUNI_PM7345_FIFOBP 0x20 /* FIFO bypass */
-#define SUNI_PM7345_FRMRBP 0x08 /* Framer bypass */
-/*
- * DS3 FRMR Interrupt Enable
- */
-#define SUNI_DS3_COFAE 0x80 /* Enable change of frame align */
-#define SUNI_DS3_REDE 0x40 /* Enable DS3 RED state intr */
-#define SUNI_DS3_CBITE 0x20 /* Enable Appl ID channel intr */
-#define SUNI_DS3_FERFE 0x10 /* Enable Far End Receive Failure intr*/
-#define SUNI_DS3_IDLE 0x08 /* Enable Idle signal intr */
-#define SUNI_DS3_AISE 0x04 /* Enable Alarm Indication signal intr*/
-#define SUNI_DS3_OOFE 0x02 /* Enable Out of frame intr */
-#define SUNI_DS3_LOSE 0x01 /* Enable Loss of signal intr */
-
-/*
- * DS3 FRMR Status
- */
-#define SUNI_DS3_ACE 0x80 /* Additional Configuration Reg */
-#define SUNI_DS3_REDV 0x40 /* DS3 RED state */
-#define SUNI_DS3_CBITV 0x20 /* Application ID channel state */
-#define SUNI_DS3_FERFV 0x10 /* Far End Receive Failure state*/
-#define SUNI_DS3_IDLV 0x08 /* Idle signal state */
-#define SUNI_DS3_AISV 0x04 /* Alarm Indication signal state*/
-#define SUNI_DS3_OOFV 0x02 /* Out of frame state */
-#define SUNI_DS3_LOSV 0x01 /* Loss of signal state */
-
-/*
- * E3 FRMR Interrupt/Status
- */
-#define SUNI_E3_CZDI 0x40 /* Consecutive Zeros indicator */
-#define SUNI_E3_LOSI 0x20 /* Loss of signal intr status */
-#define SUNI_E3_LCVI 0x10 /* Line code violation intr */
-#define SUNI_E3_COFAI 0x08 /* Change of frame align intr */
-#define SUNI_E3_OOFI 0x04 /* Out of frame intr status */
-#define SUNI_E3_LOS 0x02 /* Loss of signal state */
-#define SUNI_E3_OOF 0x01 /* Out of frame state */
-
-/*
- * E3 FRMR Maintenance Status
- */
-#define SUNI_E3_AISD 0x80 /* Alarm Indication signal state*/
-#define SUNI_E3_FERF_RAI 0x40 /* FERF/RAI indicator */
-#define SUNI_E3_FEBE 0x20 /* Far End Block Error indicator*/
-
-/*
- * RXCP Control/Status
- */
-#define SUNI_DS3_HCSPASS 0x80 /* Pass cell with HEC errors */
-#define SUNI_DS3_HCSDQDB 0x40 /* Control octets in HCS calc */
-#define SUNI_DS3_HCSADD 0x20 /* Add coset poly */
-#define SUNI_DS3_HCK 0x10 /* Control FIFO data path integ chk*/
-#define SUNI_DS3_BLOCK 0x08 /* Enable cell filtering */
-#define SUNI_DS3_DSCR 0x04 /* Disable payload descrambling */
-#define SUNI_DS3_OOCDV 0x02 /* Cell delineation state */
-#define SUNI_DS3_FIFORST 0x01 /* Cell FIFO reset */
-
-/*
- * RXCP Interrupt Enable/Status
- */
-#define SUNI_DS3_OOCDE 0x80 /* Intr enable, change in CDS */
-#define SUNI_DS3_HCSE 0x40 /* Intr enable, corr HCS errors */
-#define SUNI_DS3_FIFOE 0x20 /* Intr enable, unco HCS errors */
-#define SUNI_DS3_OOCDI 0x10 /* SYNC state */
-#define SUNI_DS3_UHCSI 0x08 /* Uncorr. HCS errors detected */
-#define SUNI_DS3_COCAI 0x04 /* Corr. HCS errors detected */
-#define SUNI_DS3_FOVRI 0x02 /* FIFO overrun */
-#define SUNI_DS3_FUDRI 0x01 /* FIFO underrun */
-
-///////////////////SUNI_PM7345 PHY DEFINE END /////////////////////////////
-
-/* ia_eeprom define*/
-#define MEM_SIZE_MASK 0x000F /* mask of 4 bits defining memory size*/
-#define MEM_SIZE_128K 0x0000 /* board has 128k buffer */
-#define MEM_SIZE_512K 0x0001 /* board has 512K of buffer */
-#define MEM_SIZE_1M 0x0002 /* board has 1M of buffer */
- /* 0x3 to 0xF are reserved for future */
-
-#define FE_MASK 0x00F0 /* mask of 4 bits defining FE type */
-#define FE_MULTI_MODE 0x0000 /* 155 MBit multimode fiber */
-#define FE_SINGLE_MODE 0x0010 /* 155 MBit single mode laser */
-#define FE_UTP_OPTION 0x0020 /* 155 MBit UTP front end */
-
-#define NOVRAM_SIZE 64
-#define CMD_LEN 10
-
-/***********
- *
- * Switches and defines for header files.
- *
- * The following defines are used to turn on and off
- * various options in the header files. Primarily useful
- * for debugging.
- *
- ***********/
-
-/*
- * a list of the commands that can be sent to the NOVRAM
- */
-
-#define EXTEND 0x100
-#define IAWRITE 0x140
-#define IAREAD 0x180
-#define ERASE 0x1c0
-
-#define EWDS 0x00
-#define WRAL 0x10
-#define ERAL 0x20
-#define EWEN 0x30
-
-/*
- * these bits duplicate the hw_flip.h register settings
- * note: how the data in / out bits are defined in the flipper specification
- */
-
-#define NVCE 0x02
-#define NVSK 0x01
-#define NVDO 0x08
-#define NVDI 0x04
-/***********************
- *
- * This define ands the value and the current config register and puts
- * the result in the config register
- *
- ***********************/
-
-#define CFG_AND(val) { \
- u32 t; \
- t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \
- t &= (val); \
- writel(t, iadev->reg+IPHASE5575_EEPROM_ACCESS); \
- }
-
-/***********************
- *
- * This define ors the value and the current config register and puts
- * the result in the config register
- *
- ***********************/
-
-#define CFG_OR(val) { \
- u32 t; \
- t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \
- t |= (val); \
- writel(t, iadev->reg+IPHASE5575_EEPROM_ACCESS); \
- }
-
-/***********************
- *
- * Send a command to the NOVRAM, the command is in cmd.
- *
- * clear CE and SK. Then assert CE.
- * Clock each of the command bits out in the correct order with SK
- * exit with CE still asserted
- *
- ***********************/
-
-#define NVRAM_CMD(cmd) { \
- int i; \
- u_short c = cmd; \
- CFG_AND(~(NVCE|NVSK)); \
- CFG_OR(NVCE); \
- for (i=0; i<CMD_LEN; i++) { \
- NVRAM_CLKOUT((c & (1 << (CMD_LEN - 1))) ? 1 : 0); \
- c <<= 1; \
- } \
- }
-
-/***********************
- *
- * clear the CE, this must be used after each command is complete
- *
- ***********************/
-
-#define NVRAM_CLR_CE {CFG_AND(~NVCE)}
-
-/***********************
- *
- * clock the data bit in bitval out to the NOVRAM. The bitval must be
- * a 1 or 0, or the clockout operation is undefined
- *
- ***********************/
-
-#define NVRAM_CLKOUT(bitval) { \
- CFG_AND(~NVDI); \
- CFG_OR((bitval) ? NVDI : 0); \
- CFG_OR(NVSK); \
- CFG_AND( ~NVSK); \
- }
-
-/***********************
- *
- * clock the data bit in and return a 1 or 0, depending on the value
- * that was received from the NOVRAM
- *
- ***********************/
-
-#define NVRAM_CLKIN(value) { \
- u32 _t; \
- CFG_OR(NVSK); \
- CFG_AND(~NVSK); \
- _t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \
- value = (_t & NVDO) ? 1 : 0; \
- }
-
-
-#endif /* IPHASE_H */
diff --git a/drivers/atm/midway.h b/drivers/atm/midway.h
deleted file mode 100644
index d47307adc0c9..000000000000
--- a/drivers/atm/midway.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */
-
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef DRIVERS_ATM_MIDWAY_H
-#define DRIVERS_ATM_MIDWAY_H
-
-
-#define NR_VCI 1024 /* number of VCIs */
-#define NR_VCI_LD 10 /* log2(NR_VCI) */
-#define NR_DMA_RX 512 /* RX DMA queue entries */
-#define NR_DMA_TX 512 /* TX DMA queue entries */
-#define NR_SERVICE NR_VCI /* service list size */
-#define NR_CHAN 8 /* number of TX channels */
-#define TS_CLOCK 25000000 /* traffic shaper clock (cell/sec) */
-
-#define MAP_MAX_SIZE 0x00400000 /* memory window for max config */
-#define EPROM_SIZE 0x00010000
-#define MEM_VALID 0xffc00000 /* mask base address with this */
-#define PHY_BASE 0x00020000 /* offset of PHY register are */
-#define REG_BASE 0x00040000 /* offset of Midway register area */
-#define RAM_BASE 0x00200000 /* offset of RAM area */
-#define RAM_INCREMENT 0x00020000 /* probe for RAM every 128kB */
-
-#define MID_VCI_BASE RAM_BASE
-#define MID_DMA_RX_BASE (MID_VCI_BASE+NR_VCI*16)
-#define MID_DMA_TX_BASE (MID_DMA_RX_BASE+NR_DMA_RX*8)
-#define MID_SERVICE_BASE (MID_DMA_TX_BASE+NR_DMA_TX*8)
-#define MID_FREE_BASE (MID_SERVICE_BASE+NR_SERVICE*4)
-
-#define MAC_LEN 6 /* atm.h */
-
-#define MID_MIN_BUF_SIZE (1024) /* 1 kB is minimum */
-#define MID_MAX_BUF_SIZE (128*1024) /* 128 kB is maximum */
-
-#define RX_DESCR_SIZE 1 /* RX PDU descr is 1 longword */
-#define TX_DESCR_SIZE 2 /* TX PDU descr is 2 longwords */
-#define AAL5_TRAILER (ATM_AAL5_TRAILER/4) /* AAL5 trailer is 2 longwords */
-
-#define TX_GAP 8 /* TX buffer gap (words) */
-
-/*
- * Midway Reset/ID
- *
- * All values read-only. Writing to this register resets Midway chip.
- */
-
-#define MID_RES_ID_MCON 0x00 /* Midway Reset/ID */
-
-#define MID_ID 0xf0000000 /* Midway version */
-#define MID_SHIFT 24
-#define MID_MOTHER_ID 0x00000700 /* mother board id */
-#define MID_MOTHER_SHIFT 8
-#define MID_CON_TI 0x00000080 /* 0: normal ctrl; 1: SABRE */
-#define MID_CON_SUNI 0x00000040 /* 0: UTOPIA; 1: SUNI */
-#define MID_CON_V6 0x00000020 /* 0: non-pipel UTOPIA (required iff
- !CON_SUNI; 1: UTOPIA */
-#define DAUGHTER_ID 0x0000001f /* daughter board id */
-
-/*
- * Interrupt Status Acknowledge, Interrupt Status & Interrupt Enable
- */
-
-#define MID_ISA 0x01 /* Interrupt Status Acknowledge */
-#define MID_IS 0x02 /* Interrupt Status */
-#define MID_IE 0x03 /* Interrupt Enable */
-
-#define MID_TX_COMPLETE_7 0x00010000 /* channel N completed a PDU */
-#define MID_TX_COMPLETE_6 0x00008000 /* transmission */
-#define MID_TX_COMPLETE_5 0x00004000
-#define MID_TX_COMPLETE_4 0x00002000
-#define MID_TX_COMPLETE_3 0x00001000
-#define MID_TX_COMPLETE_2 0x00000800
-#define MID_TX_COMPLETE_1 0x00000400
-#define MID_TX_COMPLETE_0 0x00000200
-#define MID_TX_COMPLETE 0x0001fe00 /* any TX */
-#define MID_TX_DMA_OVFL 0x00000100 /* DMA to adapter overflow */
-#define MID_TX_IDENT_MISM 0x00000080 /* TX: ident mismatch => halted */
-#define MID_DMA_LERR_ACK 0x00000040 /* LERR - SBus ? */
-#define MID_DMA_ERR_ACK 0x00000020 /* DMA error */
-#define MID_RX_DMA_COMPLETE 0x00000010 /* DMA to host done */
-#define MID_TX_DMA_COMPLETE 0x00000008 /* DMA from host done */
-#define MID_SERVICE 0x00000004 /* something in service list */
-#define MID_SUNI_INT 0x00000002 /* interrupt from SUNI */
-#define MID_STAT_OVFL 0x00000001 /* statistics overflow */
-
-/*
- * Master Control/Status
- */
-
-#define MID_MC_S 0x04
-
-#define MID_INT_SELECT 0x000001C0 /* Interrupt level (000: off) */
-#define MID_INT_SEL_SHIFT 6
-#define MID_TX_LOCK_MODE 0x00000020 /* 0: streaming; 1: TX ovfl->lock */
-#define MID_DMA_ENABLE 0x00000010 /* R: 0: disable; 1: enable
- W: 0: no change; 1: enable */
-#define MID_TX_ENABLE 0x00000008 /* R: 0: TX disabled; 1: enabled
- W: 0: no change; 1: enable */
-#define MID_RX_ENABLE 0x00000004 /* like TX */
-#define MID_WAIT_1MS 0x00000002 /* R: 0: timer not running; 1: running
- W: 0: no change; 1: no interrupts
- for 1 ms */
-#define MID_WAIT_500US 0x00000001 /* like WAIT_1MS, but 0.5 ms */
-
-/*
- * Statistics
- *
- * Cleared when reading.
- */
-
-#define MID_STAT 0x05
-
-#define MID_VCI_TRASH 0xFFFF0000 /* trashed cells because of VCI mode */
-#define MID_VCI_TRASH_SHIFT 16
-#define MID_OVFL_TRASH 0x0000FFFF /* trashed cells because of overflow */
-
-/*
- * Address registers
- */
-
-#define MID_SERV_WRITE 0x06 /* free pos in service area (R, 10 bits) */
-#define MID_DMA_ADDR 0x07 /* virtual DMA address (R, 32 bits) */
-#define MID_DMA_WR_RX 0x08 /* (RW, 9 bits) */
-#define MID_DMA_RD_RX 0x09
-#define MID_DMA_WR_TX 0x0A
-#define MID_DMA_RD_TX 0x0B
-
-/*
- * Transmit Place Registers (0x10+4*channel)
- */
-
-#define MID_TX_PLACE(c) (0x10+4*(c))
-
-#define MID_SIZE 0x00003800 /* size, N*256 x 32 bit */
-#define MID_SIZE_SHIFT 11
-#define MID_LOCATION 0x000007FF /* location in adapter memory (word) */
-
-#define MID_LOC_SKIP 8 /* 8 bits of location are always zero
- (applies to all uses of location) */
-
-/*
- * Transmit ReadPtr Registers (0x11+4*channel)
- */
-
-#define MID_TX_RDPTR(c) (0x11+4*(c))
-
-#define MID_READ_PTR 0x00007FFF /* next word for PHY */
-
-/*
- * Transmit DescrStart Registers (0x12+4*channel)
- */
-
-#define MID_TX_DESCRSTART(c) (0x12+4*(c))
-
-#define MID_DESCR_START 0x00007FFF /* seg buffer being DMAed */
-
-#define ENI155_MAGIC 0xa54b872d
-
-struct midway_eprom {
- unsigned char mac[MAC_LEN],inv_mac[MAC_LEN];
- unsigned char pad[36];
- u32 serial,inv_serial;
- u32 magic,inv_magic;
-};
-
-
-/*
- * VCI table entry
- */
-
-#define MID_VCI_IN_SERVICE 0x00000001 /* set if VCI is currently in
- service list */
-#define MID_VCI_SIZE 0x00038000 /* reassembly buffer size,
- 2*<size> kB */
-#define MID_VCI_SIZE_SHIFT 15
-#define MID_VCI_LOCATION 0x1ffc0000 /* buffer location */
-#define MID_VCI_LOCATION_SHIFT 18
-#define MID_VCI_PTI_MODE 0x20000000 /* 0: trash, 1: preserve */
-#define MID_VCI_MODE 0xc0000000
-#define MID_VCI_MODE_SHIFT 30
-#define MID_VCI_READ 0x00007fff
-#define MID_VCI_READ_SHIFT 0
-#define MID_VCI_DESCR 0x7fff0000
-#define MID_VCI_DESCR_SHIFT 16
-#define MID_VCI_COUNT 0x000007ff
-#define MID_VCI_COUNT_SHIFT 0
-#define MID_VCI_STATE 0x0000c000
-#define MID_VCI_STATE_SHIFT 14
-#define MID_VCI_WRITE 0x7fff0000
-#define MID_VCI_WRITE_SHIFT 16
-
-#define MID_MODE_TRASH 0
-#define MID_MODE_RAW 1
-#define MID_MODE_AAL5 2
-
-/*
- * Reassembly buffer descriptor
- */
-
-#define MID_RED_COUNT 0x000007ff
-#define MID_RED_CRC_ERR 0x00000800
-#define MID_RED_T 0x00001000
-#define MID_RED_CE 0x00010000
-#define MID_RED_CLP 0x01000000
-#define MID_RED_IDEN 0xfe000000
-#define MID_RED_SHIFT 25
-
-#define MID_RED_RX_ID 0x1b /* constant identifier */
-
-/*
- * Segmentation buffer descriptor
- */
-
-#define MID_SEG_COUNT MID_RED_COUNT
-#define MID_SEG_RATE 0x01f80000
-#define MID_SEG_RATE_SHIFT 19
-#define MID_SEG_PR 0x06000000
-#define MID_SEG_PR_SHIFT 25
-#define MID_SEG_AAL5 0x08000000
-#define MID_SEG_ID 0xf0000000
-#define MID_SEG_ID_SHIFT 28
-#define MID_SEG_MAX_RATE 63
-
-#define MID_SEG_CLP 0x00000001
-#define MID_SEG_PTI 0x0000000e
-#define MID_SEG_PTI_SHIFT 1
-#define MID_SEG_VCI 0x00003ff0
-#define MID_SEG_VCI_SHIFT 4
-
-#define MID_SEG_TX_ID 0xb /* constant identifier */
-
-/*
- * DMA entry
- */
-
-#define MID_DMA_COUNT 0xffff0000
-#define MID_DMA_COUNT_SHIFT 16
-#define MID_DMA_END 0x00000020
-#define MID_DMA_TYPE 0x0000000f
-
-#define MID_DT_JK 0x3
-#define MID_DT_WORD 0x0
-#define MID_DT_2W 0x7
-#define MID_DT_4W 0x4
-#define MID_DT_8W 0x5
-#define MID_DT_16W 0x6
-#define MID_DT_2WM 0xf
-#define MID_DT_4WM 0xc
-#define MID_DT_8WM 0xd
-#define MID_DT_16WM 0xe
-
-/* only for RX*/
-#define MID_DMA_VCI 0x0000ffc0
-#define MID_DMA_VCI_SHIFT 6
-
-/* only for TX */
-#define MID_DMA_CHAN 0x000001c0
-#define MID_DMA_CHAN_SHIFT 6
-
-#define MID_DT_BYTE 0x1
-#define MID_DT_HWORD 0x2
-
-#endif
diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
deleted file mode 100644
index 1b7f1dfc1735..000000000000
--- a/drivers/atm/nicstar.h
+++ /dev/null
@@ -1,759 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * nicstar.h
- *
- * Header file for the nicstar device driver.
- *
- * Author: Rui Prior (rprior@inescn.pt)
- * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999
- *
- * (C) INESC 1998
- */
-
-#ifndef _LINUX_NICSTAR_H_
-#define _LINUX_NICSTAR_H_
-
-/* Includes */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/idr.h>
-#include <linux/uio.h>
-#include <linux/skbuff.h>
-#include <linux/atmdev.h>
-#include <linux/atm_nicstar.h>
-
-/* Options */
-
-#define NS_MAX_CARDS 4 /* Maximum number of NICStAR based cards
- controlled by the device driver. Must
- be <= 5 */
-
-#undef RCQ_SUPPORT /* Do not define this for now */
-
-#define NS_TST_NUM_ENTRIES 2340 /* + 1 for return */
-#define NS_TST_RESERVED 340 /* N. entries reserved for UBR/ABR/VBR */
-
-#define NS_SMBUFSIZE 48 /* 48, 96, 240 or 2048 */
-#define NS_LGBUFSIZE 16384 /* 2048, 4096, 8192 or 16384 */
-#define NS_RSQSIZE 8192 /* 2048, 4096 or 8192 */
-#define NS_VPIBITS 2 /* 0, 1, 2, or 8 */
-
-#define NS_MAX_RCTSIZE 4096 /* Number of entries. 4096 or 16384.
- Define 4096 only if (all) your card(s)
- have 32K x 32bit SRAM, in which case
- setting this to 16384 will just waste a
- lot of memory.
- Setting this to 4096 for a card with
- 128K x 32bit SRAM will limit the maximum
- VCI. */
-
- /*#define NS_PCI_LATENCY 64*//* Must be a multiple of 32 */
-
- /* Number of buffers initially allocated */
-#define NUM_SB 32 /* Must be even */
-#define NUM_LB 24 /* Must be even */
-#define NUM_HB 8 /* Pre-allocated huge buffers */
-#define NUM_IOVB 48 /* Iovec buffers */
-
- /* Lower level for count of buffers */
-#define MIN_SB 8 /* Must be even */
-#define MIN_LB 8 /* Must be even */
-#define MIN_HB 6
-#define MIN_IOVB 8
-
- /* Upper level for count of buffers */
-#define MAX_SB 64 /* Must be even, <= 508 */
-#define MAX_LB 48 /* Must be even, <= 508 */
-#define MAX_HB 10
-#define MAX_IOVB 80
-
- /* These are the absolute maximum allowed for the ioctl() */
-#define TOP_SB 256 /* Must be even, <= 508 */
-#define TOP_LB 128 /* Must be even, <= 508 */
-#define TOP_HB 64
-#define TOP_IOVB 256
-
-#define MAX_TBD_PER_VC 1 /* Number of TBDs before a TSR */
-#define MAX_TBD_PER_SCQ 10 /* Only meaningful for variable rate SCQs */
-
-#undef ENABLE_TSQFIE
-
-#define SCQFULL_TIMEOUT (5 * HZ)
-
-#define NS_POLL_PERIOD (HZ)
-
-#define PCR_TOLERANCE (1.0001)
-
-/* ESI stuff */
-
-#define NICSTAR_EPROM_MAC_ADDR_OFFSET 0x6C
-#define NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT 0xF6
-
-/* #defines */
-
-#define NS_IOREMAP_SIZE 4096
-
-/*
- * BUF_XX distinguish the Rx buffers depending on their (small/large) size.
- * BUG_SM and BUG_LG are both used by the driver and the device.
- * BUF_NONE is only used by the driver.
- */
-#define BUF_SM 0x00000000 /* These two are used for push_rxbufs() */
-#define BUF_LG 0x00000001 /* CMD, Write_FreeBufQ, LBUF bit */
-#define BUF_NONE 0xffffffff /* Software only: */
-
-#define NS_HBUFSIZE 65568 /* Size of max. AAL5 PDU */
-#define NS_MAX_IOVECS (2 + (65568 - NS_SMBUFSIZE) / \
- (NS_LGBUFSIZE - (NS_LGBUFSIZE % 48)))
-#define NS_IOVBUFSIZE (NS_MAX_IOVECS * (sizeof(struct iovec)))
-
-#define NS_SMBUFSIZE_USABLE (NS_SMBUFSIZE - NS_SMBUFSIZE % 48)
-#define NS_LGBUFSIZE_USABLE (NS_LGBUFSIZE - NS_LGBUFSIZE % 48)
-
-#define NS_AAL0_HEADER (ATM_AAL0_SDU - ATM_CELL_PAYLOAD) /* 4 bytes */
-
-#define NS_SMSKBSIZE (NS_SMBUFSIZE + NS_AAL0_HEADER)
-#define NS_LGSKBSIZE (NS_SMBUFSIZE + NS_LGBUFSIZE)
-
-/* NICStAR structures located in host memory */
-
-/*
- * RSQ - Receive Status Queue
- *
- * Written by the NICStAR, read by the device driver.
- */
-
-typedef struct ns_rsqe {
- u32 word_1;
- u32 buffer_handle;
- u32 final_aal5_crc32;
- u32 word_4;
-} ns_rsqe;
-
-#define ns_rsqe_vpi(ns_rsqep) \
- ((le32_to_cpu((ns_rsqep)->word_1) & 0x00FF0000) >> 16)
-#define ns_rsqe_vci(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_1) & 0x0000FFFF)
-
-#define NS_RSQE_VALID 0x80000000
-#define NS_RSQE_NZGFC 0x00004000
-#define NS_RSQE_EOPDU 0x00002000
-#define NS_RSQE_BUFSIZE 0x00001000
-#define NS_RSQE_CONGESTION 0x00000800
-#define NS_RSQE_CLP 0x00000400
-#define NS_RSQE_CRCERR 0x00000200
-
-#define NS_RSQE_BUFSIZE_SM 0x00000000
-#define NS_RSQE_BUFSIZE_LG 0x00001000
-
-#define ns_rsqe_valid(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_VALID)
-#define ns_rsqe_nzgfc(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_NZGFC)
-#define ns_rsqe_eopdu(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_EOPDU)
-#define ns_rsqe_bufsize(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_BUFSIZE)
-#define ns_rsqe_congestion(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CONGESTION)
-#define ns_rsqe_clp(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CLP)
-#define ns_rsqe_crcerr(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CRCERR)
-
-#define ns_rsqe_cellcount(ns_rsqep) \
- (le32_to_cpu((ns_rsqep)->word_4) & 0x000001FF)
-#define ns_rsqe_init(ns_rsqep) \
- ((ns_rsqep)->word_4 = cpu_to_le32(0x00000000))
-
-#define NS_RSQ_NUM_ENTRIES (NS_RSQSIZE / 16)
-#define NS_RSQ_ALIGNMENT NS_RSQSIZE
-
-/*
- * RCQ - Raw Cell Queue
- *
- * Written by the NICStAR, read by the device driver.
- */
-
-typedef struct cell_payload {
- u32 word[12];
-} cell_payload;
-
-typedef struct ns_rcqe {
- u32 word_1;
- u32 word_2;
- u32 word_3;
- u32 word_4;
- cell_payload payload;
-} ns_rcqe;
-
-#define NS_RCQE_SIZE 64 /* bytes */
-
-#define ns_rcqe_islast(ns_rcqep) \
- (le32_to_cpu((ns_rcqep)->word_2) != 0x00000000)
-#define ns_rcqe_cellheader(ns_rcqep) \
- (le32_to_cpu((ns_rcqep)->word_1))
-#define ns_rcqe_nextbufhandle(ns_rcqep) \
- (le32_to_cpu((ns_rcqep)->word_2))
-
-/*
- * SCQ - Segmentation Channel Queue
- *
- * Written by the device driver, read by the NICStAR.
- */
-
-typedef struct ns_scqe {
- u32 word_1;
- u32 word_2;
- u32 word_3;
- u32 word_4;
-} ns_scqe;
-
- /* NOTE: SCQ entries can be either a TBD (Transmit Buffer Descriptors)
- or TSR (Transmit Status Requests) */
-
-#define NS_SCQE_TYPE_TBD 0x00000000
-#define NS_SCQE_TYPE_TSR 0x80000000
-
-#define NS_TBD_EOPDU 0x40000000
-#define NS_TBD_AAL0 0x00000000
-#define NS_TBD_AAL34 0x04000000
-#define NS_TBD_AAL5 0x08000000
-
-#define NS_TBD_VPI_MASK 0x0FF00000
-#define NS_TBD_VCI_MASK 0x000FFFF0
-#define NS_TBD_VC_MASK (NS_TBD_VPI_MASK | NS_TBD_VCI_MASK)
-
-#define NS_TBD_VPI_SHIFT 20
-#define NS_TBD_VCI_SHIFT 4
-
-#define ns_tbd_mkword_1(flags, m, n, buflen) \
- (cpu_to_le32((flags) | (m) << 23 | (n) << 16 | (buflen)))
-#define ns_tbd_mkword_1_novbr(flags, buflen) \
- (cpu_to_le32((flags) | (buflen) | 0x00810000))
-#define ns_tbd_mkword_3(control, pdulen) \
- (cpu_to_le32((control) << 16 | (pdulen)))
-#define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) \
- (cpu_to_le32((gfc) << 28 | (vpi) << 20 | (vci) << 4 | (pt) << 1 | (clp)))
-
-#define NS_TSR_INTENABLE 0x20000000
-
-#define NS_TSR_SCDISVBR 0xFFFF /* Use as scdi for VBR SCD */
-
-#define ns_tsr_mkword_1(flags) \
- (cpu_to_le32(NS_SCQE_TYPE_TSR | (flags)))
-#define ns_tsr_mkword_2(scdi, scqi) \
- (cpu_to_le32((scdi) << 16 | 0x00008000 | (scqi)))
-
-#define ns_scqe_is_tsr(ns_scqep) \
- (le32_to_cpu((ns_scqep)->word_1) & NS_SCQE_TYPE_TSR)
-
-#define VBR_SCQ_NUM_ENTRIES 512
-#define VBR_SCQSIZE 8192
-#define CBR_SCQ_NUM_ENTRIES 64
-#define CBR_SCQSIZE 1024
-
-#define NS_SCQE_SIZE 16
-
-/*
- * TSQ - Transmit Status Queue
- *
- * Written by the NICStAR, read by the device driver.
- */
-
-typedef struct ns_tsi {
- u32 word_1;
- u32 word_2;
-} ns_tsi;
-
- /* NOTE: The first word can be a status word copied from the TSR which
- originated the TSI, or a timer overflow indicator. In this last
- case, the value of the first word is all zeroes. */
-
-#define NS_TSI_EMPTY 0x80000000
-#define NS_TSI_TIMESTAMP_MASK 0x00FFFFFF
-
-#define ns_tsi_isempty(ns_tsip) \
- (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_EMPTY)
-#define ns_tsi_gettimestamp(ns_tsip) \
- (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_TIMESTAMP_MASK)
-
-#define ns_tsi_init(ns_tsip) \
- ((ns_tsip)->word_2 = cpu_to_le32(NS_TSI_EMPTY))
-
-#define NS_TSQSIZE 8192
-#define NS_TSQ_NUM_ENTRIES 1024
-#define NS_TSQ_ALIGNMENT 8192
-
-#define NS_TSI_SCDISVBR NS_TSR_SCDISVBR
-
-#define ns_tsi_tmrof(ns_tsip) \
- (le32_to_cpu((ns_tsip)->word_1) == 0x00000000)
-#define ns_tsi_getscdindex(ns_tsip) \
- ((le32_to_cpu((ns_tsip)->word_1) & 0xFFFF0000) >> 16)
-#define ns_tsi_getscqpos(ns_tsip) \
- (le32_to_cpu((ns_tsip)->word_1) & 0x00007FFF)
-
-/* NICStAR structures located in local SRAM */
-
-/*
- * RCT - Receive Connection Table
- *
- * Written by both the NICStAR and the device driver.
- */
-
-typedef struct ns_rcte {
- u32 word_1;
- u32 buffer_handle;
- u32 dma_address;
- u32 aal5_crc32;
-} ns_rcte;
-
-#define NS_RCTE_BSFB 0x00200000 /* Rev. D only */
-#define NS_RCTE_NZGFC 0x00100000
-#define NS_RCTE_CONNECTOPEN 0x00080000
-#define NS_RCTE_AALMASK 0x00070000
-#define NS_RCTE_AAL0 0x00000000
-#define NS_RCTE_AAL34 0x00010000
-#define NS_RCTE_AAL5 0x00020000
-#define NS_RCTE_RCQ 0x00030000
-#define NS_RCTE_RAWCELLINTEN 0x00008000
-#define NS_RCTE_RXCONSTCELLADDR 0x00004000
-#define NS_RCTE_BUFFVALID 0x00002000
-#define NS_RCTE_FBDSIZE 0x00001000
-#define NS_RCTE_EFCI 0x00000800
-#define NS_RCTE_CLP 0x00000400
-#define NS_RCTE_CRCERROR 0x00000200
-#define NS_RCTE_CELLCOUNT_MASK 0x000001FF
-
-#define NS_RCTE_FBDSIZE_SM 0x00000000
-#define NS_RCTE_FBDSIZE_LG 0x00001000
-
-#define NS_RCT_ENTRY_SIZE 4 /* Number of dwords */
-
- /* NOTE: We could make macros to contruct the first word of the RCTE,
- but that doesn't seem to make much sense... */
-
-/*
- * FBD - Free Buffer Descriptor
- *
- * Written by the device driver using via the command register.
- */
-
-typedef struct ns_fbd {
- u32 buffer_handle;
- u32 dma_address;
-} ns_fbd;
-
-/*
- * TST - Transmit Schedule Table
- *
- * Written by the device driver.
- */
-
-typedef u32 ns_tste;
-
-#define NS_TST_OPCODE_MASK 0x60000000
-
-#define NS_TST_OPCODE_NULL 0x00000000 /* Insert null cell */
-#define NS_TST_OPCODE_FIXED 0x20000000 /* Cell from a fixed rate channel */
-#define NS_TST_OPCODE_VARIABLE 0x40000000
-#define NS_TST_OPCODE_END 0x60000000 /* Jump */
-
-#define ns_tste_make(opcode, sramad) (opcode | sramad)
-
- /* NOTE:
-
- - When the opcode is FIXED, sramad specifies the SRAM address of the
- SCD for that fixed rate channel.
- - When the opcode is END, sramad specifies the SRAM address of the
- location of the next TST entry to read.
- */
-
-/*
- * SCD - Segmentation Channel Descriptor
- *
- * Written by both the device driver and the NICStAR
- */
-
-typedef struct ns_scd {
- u32 word_1;
- u32 word_2;
- u32 partial_aal5_crc;
- u32 reserved;
- ns_scqe cache_a;
- ns_scqe cache_b;
-} ns_scd;
-
-#define NS_SCD_BASE_MASK_VAR 0xFFFFE000 /* Variable rate */
-#define NS_SCD_BASE_MASK_FIX 0xFFFFFC00 /* Fixed rate */
-#define NS_SCD_TAIL_MASK_VAR 0x00001FF0
-#define NS_SCD_TAIL_MASK_FIX 0x000003F0
-#define NS_SCD_HEAD_MASK_VAR 0x00001FF0
-#define NS_SCD_HEAD_MASK_FIX 0x000003F0
-#define NS_SCD_XMITFOREVER 0x02000000
-
- /* NOTE: There are other fields in word 2 of the SCD, but as they should
- not be needed in the device driver they are not defined here. */
-
-/* NICStAR local SRAM memory map */
-
-#define NS_RCT 0x00000
-#define NS_RCT_32_END 0x03FFF
-#define NS_RCT_128_END 0x0FFFF
-#define NS_UNUSED_32 0x04000
-#define NS_UNUSED_128 0x10000
-#define NS_UNUSED_END 0x1BFFF
-#define NS_TST_FRSCD 0x1C000
-#define NS_TST_FRSCD_END 0x1E7DB
-#define NS_VRSCD2 0x1E7DC
-#define NS_VRSCD2_END 0x1E7E7
-#define NS_VRSCD1 0x1E7E8
-#define NS_VRSCD1_END 0x1E7F3
-#define NS_VRSCD0 0x1E7F4
-#define NS_VRSCD0_END 0x1E7FF
-#define NS_RXFIFO 0x1E800
-#define NS_RXFIFO_END 0x1F7FF
-#define NS_SMFBQ 0x1F800
-#define NS_SMFBQ_END 0x1FBFF
-#define NS_LGFBQ 0x1FC00
-#define NS_LGFBQ_END 0x1FFFF
-
-/* NISCtAR operation registers */
-
-/* See Section 3.4 of `IDT77211 NICStAR User Manual' from www.idt.com */
-
-enum ns_regs {
- DR0 = 0x00, /* Data Register 0 R/W */
- DR1 = 0x04, /* Data Register 1 W */
- DR2 = 0x08, /* Data Register 2 W */
- DR3 = 0x0C, /* Data Register 3 W */
- CMD = 0x10, /* Command W */
- CFG = 0x14, /* Configuration R/W */
- STAT = 0x18, /* Status R/W */
- RSQB = 0x1C, /* Receive Status Queue Base W */
- RSQT = 0x20, /* Receive Status Queue Tail R */
- RSQH = 0x24, /* Receive Status Queue Head W */
- CDC = 0x28, /* Cell Drop Counter R/clear */
- VPEC = 0x2C, /* VPI/VCI Lookup Error Count R/clear */
- ICC = 0x30, /* Invalid Cell Count R/clear */
- RAWCT = 0x34, /* Raw Cell Tail R */
- TMR = 0x38, /* Timer R */
- TSTB = 0x3C, /* Transmit Schedule Table Base R/W */
- TSQB = 0x40, /* Transmit Status Queue Base W */
- TSQT = 0x44, /* Transmit Status Queue Tail R */
- TSQH = 0x48, /* Transmit Status Queue Head W */
- GP = 0x4C, /* General Purpose R/W */
- VPM = 0x50 /* VPI/VCI Mask W */
-};
-
-/* NICStAR commands issued to the CMD register */
-
-/* Top 4 bits are command opcode, lower 28 are parameters. */
-
-#define NS_CMD_NO_OPERATION 0x00000000
- /* params always 0 */
-
-#define NS_CMD_OPENCLOSE_CONNECTION 0x20000000
- /* b19{1=open,0=close} b18-2{SRAM addr} */
-
-#define NS_CMD_WRITE_SRAM 0x40000000
- /* b18-2{SRAM addr} b1-0{burst size} */
-
-#define NS_CMD_READ_SRAM 0x50000000
- /* b18-2{SRAM addr} */
-
-#define NS_CMD_WRITE_FREEBUFQ 0x60000000
- /* b0{large buf indicator} */
-
-#define NS_CMD_READ_UTILITY 0x80000000
- /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */
-
-#define NS_CMD_WRITE_UTILITY 0x90000000
- /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */
-
-#define NS_CMD_OPEN_CONNECTION (NS_CMD_OPENCLOSE_CONNECTION | 0x00080000)
-#define NS_CMD_CLOSE_CONNECTION NS_CMD_OPENCLOSE_CONNECTION
-
-/* NICStAR configuration bits */
-
-#define NS_CFG_SWRST 0x80000000 /* Software Reset */
-#define NS_CFG_RXPATH 0x20000000 /* Receive Path Enable */
-#define NS_CFG_SMBUFSIZE_MASK 0x18000000 /* Small Receive Buffer Size */
-#define NS_CFG_LGBUFSIZE_MASK 0x06000000 /* Large Receive Buffer Size */
-#define NS_CFG_EFBIE 0x01000000 /* Empty Free Buffer Queue
- Interrupt Enable */
-#define NS_CFG_RSQSIZE_MASK 0x00C00000 /* Receive Status Queue Size */
-#define NS_CFG_ICACCEPT 0x00200000 /* Invalid Cell Accept */
-#define NS_CFG_IGNOREGFC 0x00100000 /* Ignore General Flow Control */
-#define NS_CFG_VPIBITS_MASK 0x000C0000 /* VPI/VCI Bits Size Select */
-#define NS_CFG_RCTSIZE_MASK 0x00030000 /* Receive Connection Table Size */
-#define NS_CFG_VCERRACCEPT 0x00008000 /* VPI/VCI Error Cell Accept */
-#define NS_CFG_RXINT_MASK 0x00007000 /* End of Receive PDU Interrupt
- Handling */
-#define NS_CFG_RAWIE 0x00000800 /* Raw Cell Qu' Interrupt Enable */
-#define NS_CFG_RSQAFIE 0x00000400 /* Receive Queue Almost Full
- Interrupt Enable */
-#define NS_CFG_RXRM 0x00000200 /* Receive RM Cells */
-#define NS_CFG_TMRROIE 0x00000080 /* Timer Roll Over Interrupt
- Enable */
-#define NS_CFG_TXEN 0x00000020 /* Transmit Operation Enable */
-#define NS_CFG_TXIE 0x00000010 /* Transmit Status Interrupt
- Enable */
-#define NS_CFG_TXURIE 0x00000008 /* Transmit Under-run Interrupt
- Enable */
-#define NS_CFG_UMODE 0x00000004 /* Utopia Mode (cell/byte) Select */
-#define NS_CFG_TSQFIE 0x00000002 /* Transmit Status Queue Full
- Interrupt Enable */
-#define NS_CFG_PHYIE 0x00000001 /* PHY Interrupt Enable */
-
-#define NS_CFG_SMBUFSIZE_48 0x00000000
-#define NS_CFG_SMBUFSIZE_96 0x08000000
-#define NS_CFG_SMBUFSIZE_240 0x10000000
-#define NS_CFG_SMBUFSIZE_2048 0x18000000
-
-#define NS_CFG_LGBUFSIZE_2048 0x00000000
-#define NS_CFG_LGBUFSIZE_4096 0x02000000
-#define NS_CFG_LGBUFSIZE_8192 0x04000000
-#define NS_CFG_LGBUFSIZE_16384 0x06000000
-
-#define NS_CFG_RSQSIZE_2048 0x00000000
-#define NS_CFG_RSQSIZE_4096 0x00400000
-#define NS_CFG_RSQSIZE_8192 0x00800000
-
-#define NS_CFG_VPIBITS_0 0x00000000
-#define NS_CFG_VPIBITS_1 0x00040000
-#define NS_CFG_VPIBITS_2 0x00080000
-#define NS_CFG_VPIBITS_8 0x000C0000
-
-#define NS_CFG_RCTSIZE_4096_ENTRIES 0x00000000
-#define NS_CFG_RCTSIZE_8192_ENTRIES 0x00010000
-#define NS_CFG_RCTSIZE_16384_ENTRIES 0x00020000
-
-#define NS_CFG_RXINT_NOINT 0x00000000
-#define NS_CFG_RXINT_NODELAY 0x00001000
-#define NS_CFG_RXINT_314US 0x00002000
-#define NS_CFG_RXINT_624US 0x00003000
-#define NS_CFG_RXINT_899US 0x00004000
-
-/* NICStAR STATus bits */
-
-#define NS_STAT_SFBQC_MASK 0xFF000000 /* hi 8 bits Small Buffer Queue Count */
-#define NS_STAT_LFBQC_MASK 0x00FF0000 /* hi 8 bits Large Buffer Queue Count */
-#define NS_STAT_TSIF 0x00008000 /* Transmit Status Queue Indicator */
-#define NS_STAT_TXICP 0x00004000 /* Transmit Incomplete PDU */
-#define NS_STAT_TSQF 0x00001000 /* Transmit Status Queue Full */
-#define NS_STAT_TMROF 0x00000800 /* Timer Overflow */
-#define NS_STAT_PHYI 0x00000400 /* PHY Device Interrupt */
-#define NS_STAT_CMDBZ 0x00000200 /* Command Busy */
-#define NS_STAT_SFBQF 0x00000100 /* Small Buffer Queue Full */
-#define NS_STAT_LFBQF 0x00000080 /* Large Buffer Queue Full */
-#define NS_STAT_RSQF 0x00000040 /* Receive Status Queue Full */
-#define NS_STAT_EOPDU 0x00000020 /* End of PDU */
-#define NS_STAT_RAWCF 0x00000010 /* Raw Cell Flag */
-#define NS_STAT_SFBQE 0x00000008 /* Small Buffer Queue Empty */
-#define NS_STAT_LFBQE 0x00000004 /* Large Buffer Queue Empty */
-#define NS_STAT_RSQAF 0x00000002 /* Receive Status Queue Almost Full */
-
-#define ns_stat_sfbqc_get(stat) (((stat) & NS_STAT_SFBQC_MASK) >> 23)
-#define ns_stat_lfbqc_get(stat) (((stat) & NS_STAT_LFBQC_MASK) >> 15)
-
-/* #defines which depend on other #defines */
-
-#define NS_TST0 NS_TST_FRSCD
-#define NS_TST1 (NS_TST_FRSCD + NS_TST_NUM_ENTRIES + 1)
-
-#define NS_FRSCD (NS_TST1 + NS_TST_NUM_ENTRIES + 1)
-#define NS_FRSCD_SIZE 12 /* 12 dwords */
-#define NS_FRSCD_NUM ((NS_TST_FRSCD_END + 1 - NS_FRSCD) / NS_FRSCD_SIZE)
-
-#if (NS_SMBUFSIZE == 48)
-#define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_48
-#elif (NS_SMBUFSIZE == 96)
-#define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_96
-#elif (NS_SMBUFSIZE == 240)
-#define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_240
-#elif (NS_SMBUFSIZE == 2048)
-#define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_2048
-#else
-#error NS_SMBUFSIZE is incorrect in nicstar.h
-#endif /* NS_SMBUFSIZE */
-
-#if (NS_LGBUFSIZE == 2048)
-#define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_2048
-#elif (NS_LGBUFSIZE == 4096)
-#define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_4096
-#elif (NS_LGBUFSIZE == 8192)
-#define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_8192
-#elif (NS_LGBUFSIZE == 16384)
-#define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_16384
-#else
-#error NS_LGBUFSIZE is incorrect in nicstar.h
-#endif /* NS_LGBUFSIZE */
-
-#if (NS_RSQSIZE == 2048)
-#define NS_CFG_RSQSIZE NS_CFG_RSQSIZE_2048
-#elif (NS_RSQSIZE == 4096)
-#define NS_CFG_RSQSIZE NS_CFG_RSQSIZE_4096
-#elif (NS_RSQSIZE == 8192)
-#define NS_CFG_RSQSIZE NS_CFG_RSQSIZE_8192
-#else
-#error NS_RSQSIZE is incorrect in nicstar.h
-#endif /* NS_RSQSIZE */
-
-#if (NS_VPIBITS == 0)
-#define NS_CFG_VPIBITS NS_CFG_VPIBITS_0
-#elif (NS_VPIBITS == 1)
-#define NS_CFG_VPIBITS NS_CFG_VPIBITS_1
-#elif (NS_VPIBITS == 2)
-#define NS_CFG_VPIBITS NS_CFG_VPIBITS_2
-#elif (NS_VPIBITS == 8)
-#define NS_CFG_VPIBITS NS_CFG_VPIBITS_8
-#else
-#error NS_VPIBITS is incorrect in nicstar.h
-#endif /* NS_VPIBITS */
-
-#ifdef RCQ_SUPPORT
-#define NS_CFG_RAWIE_OPT NS_CFG_RAWIE
-#else
-#define NS_CFG_RAWIE_OPT 0x00000000
-#endif /* RCQ_SUPPORT */
-
-#ifdef ENABLE_TSQFIE
-#define NS_CFG_TSQFIE_OPT NS_CFG_TSQFIE
-#else
-#define NS_CFG_TSQFIE_OPT 0x00000000
-#endif /* ENABLE_TSQFIE */
-
-/* PCI stuff */
-
-#ifndef PCI_VENDOR_ID_IDT
-#define PCI_VENDOR_ID_IDT 0x111D
-#endif /* PCI_VENDOR_ID_IDT */
-
-#ifndef PCI_DEVICE_ID_IDT_IDT77201
-#define PCI_DEVICE_ID_IDT_IDT77201 0x0001
-#endif /* PCI_DEVICE_ID_IDT_IDT77201 */
-
-/* Device driver structures */
-
-struct ns_skb_prv {
- u32 buf_type; /* BUF_SM/BUF_LG/BUF_NONE */
- u32 dma;
- int iovcnt;
-};
-
-#define NS_PRV_BUFTYPE(skb) \
- (((struct ns_skb_prv *)(ATM_SKB(skb)+1))->buf_type)
-#define NS_PRV_DMA(skb) \
- (((struct ns_skb_prv *)(ATM_SKB(skb)+1))->dma)
-#define NS_PRV_IOVCNT(skb) \
- (((struct ns_skb_prv *)(ATM_SKB(skb)+1))->iovcnt)
-
-typedef struct tsq_info {
- void *org;
- dma_addr_t dma;
- ns_tsi *base;
- ns_tsi *next;
- ns_tsi *last;
-} tsq_info;
-
-typedef struct scq_info {
- void *org;
- dma_addr_t dma;
- ns_scqe *base;
- ns_scqe *last;
- ns_scqe *next;
- volatile ns_scqe *tail; /* Not related to the nicstar register */
- unsigned num_entries;
- struct sk_buff **skb; /* Pointer to an array of pointers
- to the sk_buffs used for tx */
- u32 scd; /* SRAM address of the corresponding
- SCD */
- int tbd_count; /* Only meaningful on variable rate */
- wait_queue_head_t scqfull_waitq;
- volatile char full; /* SCQ full indicator */
- spinlock_t lock; /* SCQ spinlock */
-} scq_info;
-
-typedef struct rsq_info {
- void *org;
- dma_addr_t dma;
- ns_rsqe *base;
- ns_rsqe *next;
- ns_rsqe *last;
-} rsq_info;
-
-typedef struct skb_pool {
- volatile int count; /* number of buffers in the queue */
- struct sk_buff_head queue;
-} skb_pool;
-
-/* NOTE: for small and large buffer pools, the count is not used, as the
- actual value used for buffer management is the one read from the
- card. */
-
-typedef struct vc_map {
- volatile unsigned int tx:1; /* TX vc? */
- volatile unsigned int rx:1; /* RX vc? */
- struct atm_vcc *tx_vcc, *rx_vcc;
- struct sk_buff *rx_iov; /* RX iovector skb */
- scq_info *scq; /* To keep track of the SCQ */
- u32 cbr_scd; /* SRAM address of the corresponding
- SCD. 0x00000000 for UBR/VBR/ABR */
- int tbd_count;
-} vc_map;
-
-typedef struct ns_dev {
- int index; /* Card ID to the device driver */
- int sram_size; /* In k x 32bit words. 32 or 128 */
- void __iomem *membase; /* Card's memory base address */
- unsigned long max_pcr;
- int rct_size; /* Number of entries */
- int vpibits;
- int vcibits;
- struct pci_dev *pcidev;
- struct idr idr;
- struct atm_dev *atmdev;
- tsq_info tsq;
- rsq_info rsq;
- scq_info *scq0, *scq1, *scq2; /* VBR SCQs */
- skb_pool sbpool; /* Small buffers */
- skb_pool lbpool; /* Large buffers */
- skb_pool hbpool; /* Pre-allocated huge buffers */
- skb_pool iovpool; /* iovector buffers */
- volatile int efbie; /* Empty free buf. queue int. enabled */
- volatile u32 tst_addr; /* SRAM address of the TST in use */
- volatile int tst_free_entries;
- vc_map vcmap[NS_MAX_RCTSIZE];
- vc_map *tste2vc[NS_TST_NUM_ENTRIES];
- vc_map *scd2vc[NS_FRSCD_NUM];
- buf_nr sbnr;
- buf_nr lbnr;
- buf_nr hbnr;
- buf_nr iovnr;
- int sbfqc;
- int lbfqc;
- struct sk_buff *sm_handle;
- u32 sm_addr;
- struct sk_buff *lg_handle;
- u32 lg_addr;
- struct sk_buff *rcbuf; /* Current raw cell buffer */
- struct ns_rcqe *rawcell;
- u32 rawch; /* Raw cell queue head */
- unsigned intcnt; /* Interrupt counter */
- spinlock_t int_lock; /* Interrupt lock */
- spinlock_t res_lock; /* Card resource lock */
-} ns_dev;
-
- /* NOTE: Each tste2vc entry relates a given TST entry to the corresponding
- CBR vc. If the entry is not allocated, it must be NULL.
-
- There are two TSTs so the driver can modify them on the fly
- without stopping the transmission.
-
- scd2vc allows us to find out unused fixed rate SCDs, because
- they must have a NULL pointer here. */
-
-#endif /* _LINUX_NICSTAR_H_ */
diff --git a/drivers/atm/suni.h b/drivers/atm/suni.h
deleted file mode 100644
index d28a50d47d8b..000000000000
--- a/drivers/atm/suni.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * drivers/atm/suni.h - S/UNI PHY driver
- */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-#ifndef DRIVER_ATM_SUNI_H
-#define DRIVER_ATM_SUNI_H
-
-#include <linux/atmdev.h>
-#include <linux/atmioc.h>
-#include <linux/sonet.h>
-
-/* SUNI registers */
-
-#define SUNI_MRI 0x00 /* Master Reset and Identity / Load
- Meter */
-#define SUNI_MC 0x01 /* Master Configuration */
-#define SUNI_MIS 0x02 /* Master Interrupt Status */
- /* no 0x03 */
-#define SUNI_MCM 0x04 /* Master Clock Monitor */
-#define SUNI_MCT 0x05 /* Master Control */
-#define SUNI_CSCS 0x06 /* Clock Synthesis Control and Status */
-#define SUNI_CRCS 0x07 /* Clock Recovery Control and Status */
- /* 0x08-0x0F reserved */
-#define SUNI_RSOP_CIE 0x10 /* RSOP Control/Interrupt Enable */
-#define SUNI_RSOP_SIS 0x11 /* RSOP Status/Interrupt Status */
-#define SUNI_RSOP_SBL 0x12 /* RSOP Section BIP-8 LSB */
-#define SUNI_RSOP_SBM 0x13 /* RSOP Section BIP-8 MSB */
-#define SUNI_TSOP_CTRL 0x14 /* TSOP Control */
-#define SUNI_TSOP_DIAG 0x15 /* TSOP Diagnostic */
- /* 0x16-0x17 reserved */
-#define SUNI_RLOP_CS 0x18 /* RLOP Control/Status */
-#define SUNI_RLOP_IES 0x19 /* RLOP Interrupt Enable/Status */
-#define SUNI_RLOP_LBL 0x1A /* RLOP Line BIP-8/24 LSB */
-#define SUNI_RLOP_LB 0x1B /* RLOP Line BIP-8/24 */
-#define SUNI_RLOP_LBM 0x1C /* RLOP Line BIP-8/24 MSB */
-#define SUNI_RLOP_LFL 0x1D /* RLOP Line FEBE LSB */
-#define SUNI_RLOP_LF 0x1E /* RLOP Line FEBE */
-#define SUNI_RLOP_LFM 0x1F /* RLOP Line FEBE MSB */
-#define SUNI_TLOP_CTRL 0x20 /* TLOP Control */
-#define SUNI_TLOP_DIAG 0x21 /* TLOP Diagnostic */
- /* 0x22-0x27 reserved */
-#define SUNI_SSTB_CTRL 0x28
-#define SUNI_RPOP_SC 0x30 /* RPOP Status/Control */
-#define SUNI_RPOP_IS 0x31 /* RPOP Interrupt Status */
- /* 0x32 reserved */
-#define SUNI_RPOP_IE 0x33 /* RPOP Interrupt Enable */
- /* 0x34-0x36 reserved */
-#define SUNI_RPOP_PSL 0x37 /* RPOP Path Signal Label */
-#define SUNI_RPOP_PBL 0x38 /* RPOP Path BIP-8 LSB */
-#define SUNI_RPOP_PBM 0x39 /* RPOP Path BIP-8 MSB */
-#define SUNI_RPOP_PFL 0x3A /* RPOP Path FEBE LSB */
-#define SUNI_RPOP_PFM 0x3B /* RPOP Path FEBE MSB */
- /* 0x3C reserved */
-#define SUNI_RPOP_PBC 0x3D /* RPOP Path BIP-8 Configuration */
-#define SUNI_RPOP_RC 0x3D /* RPOP Ring Control (PM5355) */
- /* 0x3E-0x3F reserved */
-#define SUNI_TPOP_CD 0x40 /* TPOP Control/Diagnostic */
-#define SUNI_TPOP_PC 0x41 /* TPOP Pointer Control */
- /* 0x42-0x44 reserved */
-#define SUNI_TPOP_APL 0x45 /* TPOP Arbitrary Pointer LSB */
-#define SUNI_TPOP_APM 0x46 /* TPOP Arbitrary Pointer MSB */
- /* 0x47 reserved */
-#define SUNI_TPOP_PSL 0x48 /* TPOP Path Signal Label */
-#define SUNI_TPOP_PS 0x49 /* TPOP Path Status */
- /* 0x4A-0x4F reserved */
-#define SUNI_RACP_CS 0x50 /* RACP Control/Status */
-#define SUNI_RACP_IES 0x51 /* RACP Interrupt Enable/Status */
-#define SUNI_RACP_MHP 0x52 /* RACP Match Header Pattern */
-#define SUNI_RACP_MHM 0x53 /* RACP Match Header Mask */
-#define SUNI_RACP_CHEC 0x54 /* RACP Correctable HCS Error Count */
-#define SUNI_RACP_UHEC 0x55 /* RACP Uncorrectable HCS Err Count */
-#define SUNI_RACP_RCCL 0x56 /* RACP Receive Cell Counter LSB */
-#define SUNI_RACP_RCC 0x57 /* RACP Receive Cell Counter */
-#define SUNI_RACP_RCCM 0x58 /* RACP Receive Cell Counter MSB */
-#define SUNI_RACP_CFG 0x59 /* RACP Configuration */
- /* 0x5A-0x5F reserved */
-#define SUNI_TACP_CS 0x60 /* TACP Control/Status */
-#define SUNI_TACP_IUCHP 0x61 /* TACP Idle/Unassigned Cell Hdr Pat */
-#define SUNI_TACP_IUCPOP 0x62 /* TACP Idle/Unassigned Cell Payload
- Octet Pattern */
-#define SUNI_TACP_FIFO 0x63 /* TACP FIFO Configuration */
-#define SUNI_TACP_TCCL 0x64 /* TACP Transmit Cell Counter LSB */
-#define SUNI_TACP_TCC 0x65 /* TACP Transmit Cell Counter */
-#define SUNI_TACP_TCCM 0x66 /* TACP Transmit Cell Counter MSB */
-#define SUNI_TACP_CFG 0x67 /* TACP Configuration */
-#define SUNI_SPTB_CTRL 0x68 /* SPTB Control */
- /* 0x69-0x7F reserved */
-#define SUNI_MT 0x80 /* Master Test */
- /* 0x81-0xFF reserved */
-
-/* SUNI register values */
-
-
-/* MRI is reg 0 */
-#define SUNI_MRI_ID 0x0f /* R, SUNI revision number */
-#define SUNI_MRI_ID_SHIFT 0
-#define SUNI_MRI_TYPE 0x70 /* R, SUNI type (lite is 011) */
-#define SUNI_MRI_TYPE_SHIFT 4
-#define SUNI_MRI_TYPE_PM5346 0x3 /* S/UNI 155 LITE */
-#define SUNI_MRI_TYPE_PM5347 0x4 /* S/UNI 155 PLUS */
-#define SUNI_MRI_TYPE_PM5350 0x7 /* S/UNI 155 ULTRA */
-#define SUNI_MRI_TYPE_PM5355 0x1 /* S/UNI 622 */
-#define SUNI_MRI_RESET 0x80 /* RW, reset & power down chip
- 0: normal operation
- 1: reset & low power */
-
-/* MCM is reg 0x4 */
-#define SUNI_MCM_LLE 0x20 /* line loopback (PM5355) */
-#define SUNI_MCM_DLE 0x10 /* diagnostic loopback (PM5355) */
-
-/* MCT is reg 5 */
-#define SUNI_MCT_LOOPT 0x01 /* RW, timing source, 0: from
- TRCLK+/- */
-#define SUNI_MCT_DLE 0x02 /* RW, diagnostic loopback */
-#define SUNI_MCT_LLE 0x04 /* RW, line loopback */
-#define SUNI_MCT_FIXPTR 0x20 /* RW, disable transmit payload pointer
- adjustments
- 0: payload ptr controlled by TPOP
- ptr control reg
- 1: payload pointer fixed at 522 */
-#define SUNI_MCT_LCDV 0x40 /* R, loss of cell delineation */
-#define SUNI_MCT_LCDE 0x80 /* RW, loss of cell delineation
- interrupt (1: on) */
-/* RSOP_CIE is reg 0x10 */
-#define SUNI_RSOP_CIE_OOFE 0x01 /* RW, enable interrupt on frame alarm
- state change */
-#define SUNI_RSOP_CIE_LOFE 0x02 /* RW, enable interrupt on loss of
- frame state change */
-#define SUNI_RSOP_CIE_LOSE 0x04 /* RW, enable interrupt on loss of
- signal state change */
-#define SUNI_RSOP_CIE_BIPEE 0x08 /* RW, enable interrupt on section
- BIP-8 error (B1) */
-#define SUNI_RSOP_CIE_FOOF 0x20 /* W, force RSOP out of frame at next
- boundary */
-#define SUNI_RSOP_CIE_DDS 0x40 /* RW, disable scrambling */
-
-/* RSOP_SIS is reg 0x11 */
-#define SUNI_RSOP_SIS_OOFV 0x01 /* R, out of frame */
-#define SUNI_RSOP_SIS_LOFV 0x02 /* R, loss of frame */
-#define SUNI_RSOP_SIS_LOSV 0x04 /* R, loss of signal */
-#define SUNI_RSOP_SIS_OOFI 0x08 /* R, out of frame interrupt */
-#define SUNI_RSOP_SIS_LOFI 0x10 /* R, loss of frame interrupt */
-#define SUNI_RSOP_SIS_LOSI 0x20 /* R, loss of signal interrupt */
-#define SUNI_RSOP_SIS_BIPEI 0x40 /* R, section BIP-8 interrupt */
-
-/* TSOP_CTRL is reg 0x14 */
-#define SUNI_TSOP_CTRL_LAIS 0x01 /* insert alarm indication signal */
-#define SUNI_TSOP_CTRL_DS 0x40 /* disable scrambling */
-
-/* TSOP_DIAG is reg 0x15 */
-#define SUNI_TSOP_DIAG_DFP 0x01 /* insert single bit error cont. */
-#define SUNI_TSOP_DIAG_DBIP8 0x02 /* insert section BIP err (cont) */
-#define SUNI_TSOP_DIAG_DLOS 0x04 /* set line to zero (loss of signal) */
-
-/* TLOP_DIAG is reg 0x21 */
-#define SUNI_TLOP_DIAG_DBIP 0x01 /* insert line BIP err (continuously) */
-
-/* SSTB_CTRL is reg 0x28 */
-#define SUNI_SSTB_CTRL_LEN16 0x01 /* path trace message length bit */
-
-/* RPOP_RC is reg 0x3D (PM5355) */
-#define SUNI_RPOP_RC_ENSS 0x40 /* enable size bit */
-
-/* TPOP_DIAG is reg 0x40 */
-#define SUNI_TPOP_DIAG_PAIS 0x01 /* insert STS path alarm ind (cont) */
-#define SUNI_TPOP_DIAG_DB3 0x02 /* insert path BIP err (continuously) */
-
-/* TPOP_APM is reg 0x46 */
-#define SUNI_TPOP_APM_APTR 0x03 /* RW, arbitrary pointer, upper 2
- bits */
-#define SUNI_TPOP_APM_APTR_SHIFT 0
-#define SUNI_TPOP_APM_S 0x0c /* RW, "unused" bits of payload
- pointer */
-#define SUNI_TPOP_APM_S_SHIFT 2
-#define SUNI_TPOP_APM_NDF 0xf0 /* RW, NDF bits */
-#define SUNI_TPOP_APM_NDF_SHIFT 4
-
-#define SUNI_TPOP_S_SONET 0 /* set S bits to 00 */
-#define SUNI_TPOP_S_SDH 2 /* set S bits to 10 */
-
-/* RACP_IES is reg 0x51 */
-#define SUNI_RACP_IES_FOVRI 0x02 /* R, FIFO overrun */
-#define SUNI_RACP_IES_UHCSI 0x04 /* R, uncorrectable HCS error */
-#define SUNI_RACP_IES_CHCSI 0x08 /* R, correctable HCS error */
-#define SUNI_RACP_IES_OOCDI 0x10 /* R, change of cell delineation
- state */
-#define SUNI_RACP_IES_FIFOE 0x20 /* RW, enable FIFO overrun interrupt */
-#define SUNI_RACP_IES_HCSE 0x40 /* RW, enable HCS error interrupt */
-#define SUNI_RACP_IES_OOCDE 0x80 /* RW, enable cell delineation state
- change interrupt */
-
-/* TACP_CS is reg 0x60 */
-#define SUNI_TACP_CS_FIFORST 0x01 /* RW, reset transmit FIFO (sticky) */
-#define SUNI_TACP_CS_DSCR 0x02 /* RW, disable payload scrambling */
-#define SUNI_TACP_CS_HCAADD 0x04 /* RW, add coset polynomial to HCS */
-#define SUNI_TACP_CS_DHCS 0x10 /* RW, insert HCS errors */
-#define SUNI_TACP_CS_FOVRI 0x20 /* R, FIFO overrun */
-#define SUNI_TACP_CS_TSOCI 0x40 /* R, TSOC input high */
-#define SUNI_TACP_CS_FIFOE 0x80 /* RW, enable FIFO overrun interrupt */
-
-/* TACP_IUCHP is reg 0x61 */
-#define SUNI_TACP_IUCHP_CLP 0x01 /* RW, 8th bit of 4th octet of i/u
- pattern */
-#define SUNI_TACP_IUCHP_PTI 0x0e /* RW, 5th-7th bits of 4th octet of i/u
- pattern */
-#define SUNI_TACP_IUCHP_PTI_SHIFT 1
-#define SUNI_TACP_IUCHP_GFC 0xf0 /* RW, 1st-4th bits of 1st octet of i/u
- pattern */
-#define SUNI_TACP_IUCHP_GFC_SHIFT 4
-
-/* SPTB_CTRL is reg 0x68 */
-#define SUNI_SPTB_CTRL_LEN16 0x01 /* path trace message length */
-
-/* MT is reg 0x80 */
-#define SUNI_MT_HIZIO 0x01 /* RW, all but data bus & MP interface
- tri-state */
-#define SUNI_MT_HIZDATA 0x02 /* W, also tri-state data bus */
-#define SUNI_MT_IOTST 0x04 /* RW, enable test mode */
-#define SUNI_MT_DBCTRL 0x08 /* W, control data bus by CSB pin */
-#define SUNI_MT_PMCTST 0x10 /* W, PMC test mode */
-#define SUNI_MT_DS27_53 0x80 /* RW, select between 8- or 16- bit */
-
-
-#define SUNI_IDLE_PATTERN 0x6a /* idle pattern */
-
-
-#ifdef __KERNEL__
-struct suni_priv {
- struct k_sonet_stats sonet_stats; /* link diagnostics */
- int loop_mode; /* loopback mode */
- int type; /* phy type */
- struct atm_dev *dev; /* device back-pointer */
- struct suni_priv *next; /* next SUNI */
-};
-
-int suni_init(struct atm_dev *dev);
-#endif
-
-#endif
diff --git a/drivers/atm/tonga.h b/drivers/atm/tonga.h
deleted file mode 100644
index 771b3f95246c..000000000000
--- a/drivers/atm/tonga.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* drivers/atm/tonga.h - Efficient Networks Tonga (PCI bridge) declarations */
-
-/* Written 1995 by Werner Almesberger, EPFL LRC */
-
-
-#ifndef DRIVER_ATM_TONGA_H
-#define DRIVER_ATM_TONGA_H
-
-#define PCI_TONGA_CTRL 0x60 /* control register */
-
-#define END_SWAP_DMA 0x80 /* endian swap on DMA */
-#define END_SWAP_BYTE 0x40 /* endian swap on slave byte accesses */
-#define END_SWAP_WORD 0x20 /* endian swap on slave word accesses */
-#define SEPROM_MAGIC 0x0c /* obscure required pattern (ASIC only) */
-#define SEPROM_DATA 0x02 /* serial EEPROM data (ASIC only) */
-#define SEPROM_CLK 0x01 /* serial EEPROM clock (ASIC only) */
-
-#define SEPROM_ESI_BASE 64 /* start of ESI in serial EEPROM */
-
-#endif
diff --git a/drivers/atm/zeprom.h b/drivers/atm/zeprom.h
deleted file mode 100644
index 8e8819a3840d..000000000000
--- a/drivers/atm/zeprom.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* drivers/atm/zeprom.h - ZeitNet ZN122x EEPROM (NM93C46) declarations */
-
-/* Written 1995,1996 by Werner Almesberger, EPFL LRC */
-
-
-#ifndef DRIVER_ATM_ZEPROM_H
-#define DRIVER_ATM_ZEPROM_H
-
-/* Different versions use different control registers */
-
-#define ZEPROM_V1_REG PCI_VENDOR_ID /* PCI register */
-#define ZEPROM_V2_REG 0x40
-
-/* Bits in control register */
-
-#define ZEPROM_SK 0x80000000 /* strobe (probably on raising edge) */
-#define ZEPROM_CS 0x40000000 /* Chip Select */
-#define ZEPROM_DI 0x20000000 /* Data Input */
-#define ZEPROM_DO 0x10000000 /* Data Output */
-
-#define ZEPROM_SIZE 32 /* 32 bytes */
-#define ZEPROM_V1_ESI_OFF 24 /* ESI offset in EEPROM (V1) */
-#define ZEPROM_V2_ESI_OFF 4 /* ESI offset in EEPROM (V2) */
-
-#define ZEPROM_CMD_LEN 3 /* commands are three bits */
-#define ZEPROM_ADDR_LEN 6 /* addresses are six bits */
-
-/* Commands (3 bits) */
-
-#define ZEPROM_CMD_READ 6
-
-/* No other commands are needed. */
-
-#endif
diff --git a/net/atm/lec.h b/net/atm/lec.h
deleted file mode 100644
index ec85709bf818..000000000000
--- a/net/atm/lec.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Lan Emulation client header file
- *
- * Marko Kiiskila <mkiiskila@yahoo.com>
- */
-
-#ifndef _LEC_H_
-#define _LEC_H_
-
-#include <linux/atmdev.h>
-#include <linux/netdevice.h>
-#include <linux/atmlec.h>
-
-#define LEC_HEADER_LEN 16
-
-struct lecdatahdr_8023 {
- __be16 le_header;
- unsigned char h_dest[ETH_ALEN];
- unsigned char h_source[ETH_ALEN];
- __be16 h_type;
-};
-
-struct lecdatahdr_8025 {
- __be16 le_header;
- unsigned char ac_pad;
- unsigned char fc;
- unsigned char h_dest[ETH_ALEN];
- unsigned char h_source[ETH_ALEN];
-};
-
-#define LEC_MINIMUM_8023_SIZE 62
-#define LEC_MINIMUM_8025_SIZE 16
-
-/*
- * Operations that LANE2 capable device can do. Two first functions
- * are used to make the device do things. See spec 3.1.3 and 3.1.4.
- *
- * The third function is intended for the MPOA component sitting on
- * top of the LANE device. The MPOA component assigns it's own function
- * to (*associate_indicator)() and the LANE device will use that
- * function to tell about TLVs it sees floating through.
- *
- */
-struct lane2_ops {
- int (*resolve) (struct net_device *dev, const u8 *dst_mac, int force,
- u8 **tlvs, u32 *sizeoftlvs);
- int (*associate_req) (struct net_device *dev, const u8 *lan_dst,
- const u8 *tlvs, u32 sizeoftlvs);
- void (*associate_indicator) (struct net_device *dev, const u8 *mac_addr,
- const u8 *tlvs, u32 sizeoftlvs);
-};
-
-/*
- * ATM LAN Emulation supports both LLC & Dix Ethernet EtherType
- * frames.
- *
- * 1. Dix Ethernet EtherType frames encoded by placing EtherType
- * field in h_type field. Data follows immediately after header.
- * 2. LLC Data frames whose total length, including LLC field and data,
- * but not padding required to meet the minimum data frame length,
- * is less than ETH_P_802_3_MIN MUST be encoded by placing that length
- * in the h_type field. The LLC field follows header immediately.
- * 3. LLC data frames longer than this maximum MUST be encoded by placing
- * the value 0 in the h_type field.
- *
- */
-
-/* Hash table size */
-#define LEC_ARP_TABLE_SIZE 16
-
-struct lec_priv {
- unsigned short lecid; /* Lecid of this client */
- struct hlist_head lec_arp_empty_ones;
- /* Used for storing VCC's that don't have a MAC address attached yet */
- struct hlist_head lec_arp_tables[LEC_ARP_TABLE_SIZE];
- /* Actual LE ARP table */
- struct hlist_head lec_no_forward;
- /*
- * Used for storing VCC's (and forward packets from) which are to
- * age out by not using them to forward packets.
- * This is because to some LE clients there will be 2 VCCs. Only
- * one of them gets used.
- */
- struct hlist_head mcast_fwds;
- /*
- * With LANEv2 it is possible that BUS (or a special multicast server)
- * establishes multiple Multicast Forward VCCs to us. This list
- * collects all those VCCs. LANEv1 client has only one item in this
- * list. These entries are not aged out.
- */
- spinlock_t lec_arp_lock;
- struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
- struct atm_vcc __rcu *lecd;
- struct delayed_work lec_arp_work; /* C10 */
- unsigned int maximum_unknown_frame_count;
- /*
- * Within the period of time defined by this variable, the client will send
- * no more than C10 frames to BUS for a given unicast destination. (C11)
- */
- unsigned long max_unknown_frame_time;
- /*
- * If no traffic has been sent in this vcc for this period of time,
- * vcc will be torn down (C12)
- */
- unsigned long vcc_timeout_period;
- /*
- * An LE Client MUST not retry an LE_ARP_REQUEST for a
- * given frame's LAN Destination more than maximum retry count times,
- * after the first LEC_ARP_REQUEST (C13)
- */
- unsigned short max_retry_count;
- /*
- * Max time the client will maintain an entry in its arp cache in
- * absence of a verification of that relationship (C17)
- */
- unsigned long aging_time;
- /*
- * Max time the client will maintain an entry in cache when
- * topology change flag is true (C18)
- */
- unsigned long forward_delay_time; /* Topology change flag (C19) */
- int topology_change;
- /*
- * Max time the client expects an LE_ARP_REQUEST/LE_ARP_RESPONSE
- * cycle to take (C20)
- */
- unsigned long arp_response_time;
- /*
- * Time limit ot wait to receive an LE_FLUSH_RESPONSE after the
- * LE_FLUSH_REQUEST has been sent before taking recover action. (C21)
- */
- unsigned long flush_timeout;
- /* The time since sending a frame to the bus after which the
- * LE Client may assume that the frame has been either discarded or
- * delivered to the recipient (C22)
- */
- unsigned long path_switching_delay;
-
- u8 *tlvs; /* LANE2: TLVs are new */
- u32 sizeoftlvs; /* The size of the tlv array in bytes */
- int lane_version; /* LANE2 */
- int itfnum; /* e.g. 2 for lec2, 5 for lec5 */
- struct lane2_ops *lane2_ops; /* can be NULL for LANE v1 */
- int is_proxy; /* bridge between ATM and Ethernet */
-};
-
-struct lec_vcc_priv {
- void (*old_pop) (struct atm_vcc *vcc, struct sk_buff *skb);
- int xoff;
-};
-
-#define LEC_VCC_PRIV(vcc) ((struct lec_vcc_priv *)((vcc)->user_back))
-
-#endif /* _LEC_H_ */
diff --git a/net/atm/lec_arpc.h b/net/atm/lec_arpc.h
deleted file mode 100644
index 39115fe074c4..000000000000
--- a/net/atm/lec_arpc.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Lec arp cache
- *
- * Marko Kiiskila <mkiiskila@yahoo.com>
- */
-#ifndef _LEC_ARP_H_
-#define _LEC_ARP_H_
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/if_ether.h>
-#include <linux/atmlec.h>
-
-struct lec_arp_table {
- struct hlist_node next; /* Linked entry list */
- unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */
- unsigned char mac_addr[ETH_ALEN]; /* Mac address */
- int is_rdesc; /* Mac address is a route descriptor */
- struct atm_vcc *vcc; /* Vcc this entry is attached */
- struct atm_vcc *recv_vcc; /* Vcc we receive data from */
-
- void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb);
- /* Push that leads to daemon */
-
- void (*old_recv_push) (struct atm_vcc *vcc, struct sk_buff *skb);
- /* Push that leads to daemon */
-
- unsigned long last_used; /* For expiry */
- unsigned long timestamp; /* Used for various timestamping things:
- * 1. FLUSH started
- * (status=ESI_FLUSH_PENDING)
- * 2. Counting to
- * max_unknown_frame_time
- * (status=ESI_ARP_PENDING||
- * status=ESI_VC_PENDING)
- */
- unsigned char no_tries; /* No of times arp retry has been tried */
- unsigned char status; /* Status of this entry */
- unsigned short flags; /* Flags for this entry */
- unsigned short packets_flooded; /* Data packets flooded */
- unsigned long flush_tran_id; /* Transaction id in flush protocol */
- struct timer_list timer; /* Arping timer */
- struct lec_priv *priv; /* Pointer back */
- u8 *tlvs;
- u32 sizeoftlvs; /*
- * LANE2: Each MAC address can have TLVs
- * associated with it. sizeoftlvs tells
- * the length of the tlvs array
- */
- struct sk_buff_head tx_wait; /* wait queue for outgoing packets */
- refcount_t usage; /* usage count */
-};
-
-/*
- * LANE2: Template tlv struct for accessing
- * the tlvs in the lec_arp_table->tlvs array
- */
-struct tlv {
- u32 type;
- u8 length;
- u8 value[255];
-};
-
-/* Status fields */
-#define ESI_UNKNOWN 0 /*
- * Next packet sent to this mac address
- * causes ARP-request to be sent
- */
-#define ESI_ARP_PENDING 1 /*
- * There is no ATM address associated with this
- * 48-bit address. The LE-ARP protocol is in
- * progress.
- */
-#define ESI_VC_PENDING 2 /*
- * There is a valid ATM address associated with
- * this 48-bit address but there is no VC set
- * up to that ATM address. The signaling
- * protocol is in process.
- */
-#define ESI_FLUSH_PENDING 4 /*
- * The LEC has been notified of the FLUSH_START
- * status and it is assumed that the flush
- * protocol is in process.
- */
-#define ESI_FORWARD_DIRECT 5 /*
- * Either the Path Switching Delay (C22) has
- * elapsed or the LEC has notified the Mapping
- * that the flush protocol has completed. In
- * either case, it is safe to forward packets
- * to this address via the data direct VC.
- */
-
-/* Flag values */
-#define LEC_REMOTE_FLAG 0x0001
-#define LEC_PERMANENT_FLAG 0x0002
-
-#endif /* _LEC_ARP_H_ */
diff --git a/net/atm/mpc.h b/net/atm/mpc.h
deleted file mode 100644
index 454abd07651a..000000000000
--- a/net/atm/mpc.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _MPC_H_
-#define _MPC_H_
-
-#include <linux/types.h>
-#include <linux/atm.h>
-#include <linux/atmmpc.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include "mpoa_caches.h"
-
-/* kernel -> mpc-daemon */
-int msg_to_mpoad(struct k_message *msg, struct mpoa_client *mpc);
-
-struct mpoa_client {
- struct mpoa_client *next;
- struct net_device *dev; /* lec in question */
- int dev_num; /* e.g. 2 for lec2 */
-
- struct atm_vcc *mpoad_vcc; /* control channel to mpoad */
- uint8_t mps_ctrl_addr[ATM_ESA_LEN]; /* MPS control ATM address */
- uint8_t our_ctrl_addr[ATM_ESA_LEN]; /* MPC's control ATM address */
-
- rwlock_t ingress_lock;
- const struct in_cache_ops *in_ops; /* ingress cache operations */
- in_cache_entry *in_cache; /* the ingress cache of this MPC */
-
- rwlock_t egress_lock;
- const struct eg_cache_ops *eg_ops; /* egress cache operations */
- eg_cache_entry *eg_cache; /* the egress cache of this MPC */
-
- uint8_t *mps_macs; /* array of MPS MAC addresses, >=1 */
- int number_of_mps_macs; /* number of the above MAC addresses */
- struct mpc_parameters parameters; /* parameters for this client */
-
- const struct net_device_ops *old_ops;
- struct net_device_ops new_ops;
-};
-
-
-struct atm_mpoa_qos {
- struct atm_mpoa_qos *next;
- __be32 ipaddr;
- struct atm_qos qos;
-};
-
-
-/* MPOA QoS operations */
-struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos);
-struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip);
-int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos);
-
-/* Display QoS entries. This is for the procfs */
-struct seq_file;
-void atm_mpoa_disp_qos(struct seq_file *m);
-
-#ifdef CONFIG_PROC_FS
-int mpc_proc_init(void);
-void mpc_proc_clean(void);
-#else
-#define mpc_proc_init() (0)
-#define mpc_proc_clean() do { } while(0)
-#endif
-
-#endif /* _MPC_H_ */
diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h
deleted file mode 100644
index 464c4c7f8d1f..000000000000
--- a/net/atm/mpoa_caches.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef MPOA_CACHES_H
-#define MPOA_CACHES_H
-
-#include <linux/time64.h>
-#include <linux/netdevice.h>
-#include <linux/types.h>
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/atmmpc.h>
-#include <linux/refcount.h>
-
-struct mpoa_client;
-
-void atm_mpoa_init_cache(struct mpoa_client *mpc);
-
-typedef struct in_cache_entry {
- struct in_cache_entry *next;
- struct in_cache_entry *prev;
- time64_t time;
- time64_t reply_wait;
- time64_t hold_down;
- uint32_t packets_fwded;
- uint16_t entry_state;
- uint32_t retry_time;
- uint32_t refresh_time;
- uint32_t count;
- struct atm_vcc *shortcut;
- uint8_t MPS_ctrl_ATM_addr[ATM_ESA_LEN];
- struct in_ctrl_info ctrl_info;
- refcount_t use;
-} in_cache_entry;
-
-struct in_cache_ops{
- in_cache_entry *(*add_entry)(__be32 dst_ip,
- struct mpoa_client *client);
- in_cache_entry *(*get)(__be32 dst_ip, struct mpoa_client *client);
- in_cache_entry *(*get_with_mask)(__be32 dst_ip,
- struct mpoa_client *client,
- __be32 mask);
- in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc,
- struct mpoa_client *client);
- void (*put)(in_cache_entry *entry);
- void (*remove_entry)(in_cache_entry *delEntry,
- struct mpoa_client *client );
- int (*cache_hit)(in_cache_entry *entry,
- struct mpoa_client *client);
- void (*clear_count)(struct mpoa_client *client);
- void (*check_resolving)(struct mpoa_client *client);
- void (*refresh)(struct mpoa_client *client);
- void (*destroy_cache)(struct mpoa_client *mpc);
-};
-
-typedef struct eg_cache_entry{
- struct eg_cache_entry *next;
- struct eg_cache_entry *prev;
- time64_t time;
- uint8_t MPS_ctrl_ATM_addr[ATM_ESA_LEN];
- struct atm_vcc *shortcut;
- uint32_t packets_rcvd;
- uint16_t entry_state;
- __be32 latest_ip_addr; /* The src IP address of the last packet */
- struct eg_ctrl_info ctrl_info;
- refcount_t use;
-} eg_cache_entry;
-
-struct eg_cache_ops{
- eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
- eg_cache_entry *(*get_by_cache_id)(__be32 cache_id, struct mpoa_client *client);
- eg_cache_entry *(*get_by_tag)(__be32 cache_id, struct mpoa_client *client);
- eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
- eg_cache_entry *(*get_by_src_ip)(__be32 ipaddr, struct mpoa_client *client);
- void (*put)(eg_cache_entry *entry);
- void (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
- void (*update)(eg_cache_entry *entry, uint16_t holding_time);
- void (*clear_expired)(struct mpoa_client *client);
- void (*destroy_cache)(struct mpoa_client *mpc);
-};
-
-
-/* Ingress cache entry states */
-
-#define INGRESS_REFRESHING 3
-#define INGRESS_RESOLVED 2
-#define INGRESS_RESOLVING 1
-#define INGRESS_INVALID 0
-
-/* VCC states */
-
-#define OPEN 1
-#define CLOSED 0
-
-/* Egress cache entry states */
-
-#define EGRESS_RESOLVED 2
-#define EGRESS_PURGE 1
-#define EGRESS_INVALID 0
-
-#endif
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 361a9b84451e..bed1b1d9b282 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -855,7 +855,6 @@ void br_fdb_delete_by_port(struct net_bridge *br,
struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br,
const unsigned char *addr,
__u16 vid);
-int br_fdb_test_addr(struct net_device *dev, unsigned char *addr);
int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count,
unsigned long off);
int br_fdb_add_local(struct net_bridge *br, struct net_bridge_port *source,
@@ -2065,9 +2064,6 @@ void br_stp_port_timer_init(struct net_bridge_port *p);
unsigned long br_timer_value(const struct timer_list *timer);
/* br.c */
-#if IS_ENABLED(CONFIG_ATM_LANE)
-extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr);
-#endif
/* br_mrp.c */
#if IS_ENABLED(CONFIG_BRIDGE_MRP)
diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c
deleted file mode 100644
index c8d00537d236..000000000000
--- a/drivers/atm/adummy.c
+++ /dev/null
@@ -1,202 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * adummy.c: a dummy ATM driver
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <linux/uaccess.h>
-
-#include <linux/atmdev.h>
-#include <linux/atm.h>
-#include <linux/sonet.h>
-
-/* version definition */
-
-#define DRV_VERSION "1.0"
-
-#define DEV_LABEL "adummy"
-
-#define ADUMMY_DEV(dev) ((struct adummy_dev *) (dev)->dev_data)
-
-struct adummy_dev {
- struct atm_dev *atm_dev;
-
- struct list_head entry;
-};
-
-/* globals */
-
-static LIST_HEAD(adummy_devs);
-
-static ssize_t __set_signal(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev);
- int signal;
-
- if (sscanf(buf, "%d", &signal) == 1) {
-
- if (signal < ATM_PHY_SIG_LOST || signal > ATM_PHY_SIG_FOUND)
- signal = ATM_PHY_SIG_UNKNOWN;
-
- atm_dev_signal_change(atm_dev, signal);
- return 1;
- }
- return -EINVAL;
-}
-
-static ssize_t __show_signal(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev);
- return sprintf(buf, "%d\n", atm_dev->signal);
-}
-static DEVICE_ATTR(signal, 0644, __show_signal, __set_signal);
-
-static struct attribute *adummy_attrs[] = {
- &dev_attr_signal.attr,
- NULL
-};
-
-static const struct attribute_group adummy_group_attrs = {
- .name = NULL, /* We want them in dev's root folder */
- .attrs = adummy_attrs
-};
-
-static int __init
-adummy_start(struct atm_dev *dev)
-{
- dev->ci_range.vpi_bits = 4;
- dev->ci_range.vci_bits = 12;
-
- return 0;
-}
-
-static int
-adummy_open(struct atm_vcc *vcc)
-{
- short vpi = vcc->vpi;
- int vci = vcc->vci;
-
- if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
- return 0;
-
- set_bit(ATM_VF_ADDR, &vcc->flags);
- set_bit(ATM_VF_READY, &vcc->flags);
-
- return 0;
-}
-
-static void
-adummy_close(struct atm_vcc *vcc)
-{
- clear_bit(ATM_VF_READY, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
-}
-
-static int
-adummy_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- atomic_inc(&vcc->stats->tx);
-
- return 0;
-}
-
-static int
-adummy_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
-{
- int left = *pos;
-
- if (!left--)
- return sprintf(page, "version %s\n", DRV_VERSION);
-
- return 0;
-}
-
-static const struct atmdev_ops adummy_ops =
-{
- .open = adummy_open,
- .close = adummy_close,
- .send = adummy_send,
- .proc_read = adummy_proc_read,
- .owner = THIS_MODULE
-};
-
-static int __init adummy_init(void)
-{
- struct atm_dev *atm_dev;
- struct adummy_dev *adummy_dev;
- int err = 0;
-
- printk(KERN_ERR "adummy: version %s\n", DRV_VERSION);
-
- adummy_dev = kzalloc_obj(struct adummy_dev);
- if (!adummy_dev) {
- printk(KERN_ERR DEV_LABEL ": kzalloc() failed\n");
- err = -ENOMEM;
- goto out;
- }
- atm_dev = atm_dev_register(DEV_LABEL, NULL, &adummy_ops, -1, NULL);
- if (!atm_dev) {
- printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n");
- err = -ENODEV;
- goto out_kfree;
- }
-
- adummy_dev->atm_dev = atm_dev;
- atm_dev->dev_data = adummy_dev;
-
- if (sysfs_create_group(&atm_dev->class_dev.kobj, &adummy_group_attrs))
- dev_err(&atm_dev->class_dev, "Could not register attrs for adummy\n");
-
- if (adummy_start(atm_dev)) {
- printk(KERN_ERR DEV_LABEL ": adummy_start() failed\n");
- err = -ENODEV;
- goto out_unregister;
- }
-
- list_add(&adummy_dev->entry, &adummy_devs);
-out:
- return err;
-
-out_unregister:
- atm_dev_deregister(atm_dev);
-out_kfree:
- kfree(adummy_dev);
- goto out;
-}
-
-static void __exit adummy_cleanup(void)
-{
- struct adummy_dev *adummy_dev, *next;
-
- list_for_each_entry_safe(adummy_dev, next, &adummy_devs, entry) {
- atm_dev_deregister(adummy_dev->atm_dev);
- kfree(adummy_dev);
- }
-}
-
-module_init(adummy_init);
-module_exit(adummy_cleanup);
-
-MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>");
-MODULE_DESCRIPTION("dummy ATM driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
deleted file mode 100644
index 96719851ae2a..000000000000
--- a/drivers/atm/atmtcp.c
+++ /dev/null
@@ -1,513 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
-
-/* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#include <linux/module.h>
-#include <linux/wait.h>
-#include <linux/atmdev.h>
-#include <linux/atm_tcp.h>
-#include <linux/bitops.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-
-
-extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
-
-
-#define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data))
-
-
-struct atmtcp_dev_data {
- struct atm_vcc *vcc; /* control VCC; NULL if detached */
- int persist; /* non-zero if persistent */
-};
-
-
-#define DEV_LABEL "atmtcp"
-
-#define MAX_VPI_BITS 8 /* simplifies life */
-#define MAX_VCI_BITS 16
-
-
-/*
- * Hairy code ahead: the control VCC may be closed while we're still
- * waiting for an answer, so we need to re-validate out_vcc every once
- * in a while.
- */
-
-
-static int atmtcp_send_control(struct atm_vcc *vcc,int type,
- const struct atmtcp_control *msg,int flag)
-{
- DECLARE_WAITQUEUE(wait,current);
- struct atm_vcc *out_vcc;
- struct sk_buff *skb;
- struct atmtcp_control *new_msg;
- int old_test;
- int error = 0;
-
- out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
- if (!out_vcc) return -EUNATCH;
- skb = alloc_skb(sizeof(*msg),GFP_KERNEL);
- if (!skb) return -ENOMEM;
- mb();
- out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
- if (!out_vcc) {
- dev_kfree_skb(skb);
- return -EUNATCH;
- }
- atm_force_charge(out_vcc,skb->truesize);
- new_msg = skb_put(skb, sizeof(*new_msg));
- *new_msg = *msg;
- new_msg->hdr.length = ATMTCP_HDR_MAGIC;
- new_msg->type = type;
- memset(&new_msg->vcc,0,sizeof(atm_kptr_t));
- *(struct atm_vcc **) &new_msg->vcc = vcc;
- old_test = test_bit(flag,&vcc->flags);
- out_vcc->push(out_vcc,skb);
- add_wait_queue(sk_sleep(sk_atm(vcc)), &wait);
- while (test_bit(flag,&vcc->flags) == old_test) {
- mb();
- out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
- if (!out_vcc) {
- error = -EUNATCH;
- break;
- }
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(sk_sleep(sk_atm(vcc)), &wait);
- return error;
-}
-
-
-static int atmtcp_recv_control(const struct atmtcp_control *msg)
-{
- struct atm_vcc *vcc = *(struct atm_vcc **) &msg->vcc;
-
- vcc->vpi = msg->addr.sap_addr.vpi;
- vcc->vci = msg->addr.sap_addr.vci;
- vcc->qos = msg->qos;
- sk_atm(vcc)->sk_err = -msg->result;
- switch (msg->type) {
- case ATMTCP_CTRL_OPEN:
- change_bit(ATM_VF_READY,&vcc->flags);
- break;
- case ATMTCP_CTRL_CLOSE:
- change_bit(ATM_VF_ADDR,&vcc->flags);
- break;
- default:
- printk(KERN_ERR "atmtcp_recv_control: unknown type %d\n",
- msg->type);
- return -EINVAL;
- }
- wake_up(sk_sleep(sk_atm(vcc)));
- return 0;
-}
-
-
-static void atmtcp_v_dev_close(struct atm_dev *dev)
-{
- /* Nothing.... Isn't this simple :-) -- REW */
-}
-
-
-static int atmtcp_v_open(struct atm_vcc *vcc)
-{
- struct atmtcp_control msg;
- int error;
- short vpi = vcc->vpi;
- int vci = vcc->vci;
-
- memset(&msg,0,sizeof(msg));
- msg.addr.sap_family = AF_ATMPVC;
- msg.hdr.vpi = htons(vpi);
- msg.addr.sap_addr.vpi = vpi;
- msg.hdr.vci = htons(vci);
- msg.addr.sap_addr.vci = vci;
- if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0;
- msg.type = ATMTCP_CTRL_OPEN;
- msg.qos = vcc->qos;
- set_bit(ATM_VF_ADDR,&vcc->flags);
- clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */
- error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
- if (error) return error;
- return -sk_atm(vcc)->sk_err;
-}
-
-
-static void atmtcp_v_close(struct atm_vcc *vcc)
-{
- struct atmtcp_control msg;
-
- memset(&msg,0,sizeof(msg));
- msg.addr.sap_family = AF_ATMPVC;
- msg.addr.sap_addr.vpi = vcc->vpi;
- msg.addr.sap_addr.vci = vcc->vci;
- clear_bit(ATM_VF_READY,&vcc->flags);
- (void) atmtcp_send_control(vcc,ATMTCP_CTRL_CLOSE,&msg,ATM_VF_ADDR);
-}
-
-
-static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
-{
- struct atm_cirange ci;
- struct atm_vcc *vcc;
- struct sock *s;
- int i;
-
- if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
- if (copy_from_user(&ci, arg,sizeof(ci))) return -EFAULT;
- if (ci.vpi_bits == ATM_CI_MAX) ci.vpi_bits = MAX_VPI_BITS;
- if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS;
- if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 ||
- ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL;
- read_lock(&vcc_sklist_lock);
- for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
- struct hlist_head *head = &vcc_hash[i];
-
- sk_for_each(s, head) {
- vcc = atm_sk(s);
- if (vcc->dev != dev)
- continue;
- if ((vcc->vpi >> ci.vpi_bits) ||
- (vcc->vci >> ci.vci_bits)) {
- read_unlock(&vcc_sklist_lock);
- return -EBUSY;
- }
- }
- }
- read_unlock(&vcc_sklist_lock);
- dev->ci_range = ci;
- return 0;
-}
-
-
-static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb)
-{
- struct atmtcp_dev_data *dev_data;
- struct atm_vcc *out_vcc=NULL; /* Initializer quietens GCC warning */
- struct sk_buff *new_skb;
- struct atmtcp_hdr *hdr;
- int size;
-
- if (vcc->qos.txtp.traffic_class == ATM_NONE) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb(skb);
- return -EINVAL;
- }
- dev_data = PRIV(vcc->dev);
- if (dev_data) out_vcc = dev_data->vcc;
- if (!dev_data || !out_vcc) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb(skb);
- if (dev_data) return 0;
- atomic_inc(&vcc->stats->tx_err);
- return -ENOLINK;
- }
- size = skb->len+sizeof(struct atmtcp_hdr);
- new_skb = atm_alloc_charge(out_vcc,size,GFP_ATOMIC);
- if (!new_skb) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb(skb);
- atomic_inc(&vcc->stats->tx_err);
- return -ENOBUFS;
- }
- hdr = skb_put(new_skb, sizeof(struct atmtcp_hdr));
- hdr->vpi = htons(vcc->vpi);
- hdr->vci = htons(vcc->vci);
- hdr->length = htonl(skb->len);
- skb_copy_from_linear_data(skb, skb_put(new_skb, skb->len), skb->len);
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb(skb);
- out_vcc->push(out_vcc,new_skb);
- atomic_inc(&vcc->stats->tx);
- atomic_inc(&out_vcc->stats->rx);
- return 0;
-}
-
-
-static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page)
-{
- struct atmtcp_dev_data *dev_data = PRIV(dev);
-
- if (*pos) return 0;
- if (!dev_data->persist) return sprintf(page,"ephemeral\n");
- return sprintf(page,"persistent, %sconnected\n",
- dev_data->vcc ? "" : "dis");
-}
-
-
-static void atmtcp_c_close(struct atm_vcc *vcc)
-{
- struct atm_dev *atmtcp_dev;
- struct atmtcp_dev_data *dev_data;
-
- atmtcp_dev = (struct atm_dev *) vcc->dev_data;
- dev_data = PRIV(atmtcp_dev);
- dev_data->vcc = NULL;
- if (dev_data->persist) return;
- atmtcp_dev->dev_data = NULL;
- kfree(dev_data);
- atm_dev_deregister(atmtcp_dev);
- vcc->dev_data = NULL;
- module_put(THIS_MODULE);
-}
-
-
-static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci)
-{
- struct hlist_head *head;
- struct atm_vcc *vcc;
- struct sock *s;
-
- head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
-
- sk_for_each(s, head) {
- vcc = atm_sk(s);
- if (vcc->dev == dev &&
- vcc->vci == vci && vcc->vpi == vpi &&
- vcc->qos.rxtp.traffic_class != ATM_NONE) {
- return vcc;
- }
- }
- return NULL;
-}
-
-static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct atmtcp_hdr *hdr;
-
- if (skb->len < sizeof(struct atmtcp_hdr))
- return -EINVAL;
-
- hdr = (struct atmtcp_hdr *)skb->data;
- if (hdr->length == ATMTCP_HDR_MAGIC)
- return -EINVAL;
-
- return 0;
-}
-
-static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
-{
- struct atm_dev *dev;
- struct atmtcp_hdr *hdr;
- struct atm_vcc *out_vcc;
- struct sk_buff *new_skb;
- int result = 0;
-
- dev = vcc->dev_data;
- hdr = (struct atmtcp_hdr *) skb->data;
- if (hdr->length == ATMTCP_HDR_MAGIC) {
- result = atmtcp_recv_control(
- (struct atmtcp_control *) skb->data);
- goto done;
- }
- read_lock(&vcc_sklist_lock);
- out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci));
- read_unlock(&vcc_sklist_lock);
- if (!out_vcc) {
- result = -EUNATCH;
- atomic_inc(&vcc->stats->tx_err);
- goto done;
- }
- skb_pull(skb,sizeof(struct atmtcp_hdr));
- new_skb = atm_alloc_charge(out_vcc,skb->len,GFP_KERNEL);
- if (!new_skb) {
- result = -ENOBUFS;
- goto done;
- }
- __net_timestamp(new_skb);
- skb_copy_from_linear_data(skb, skb_put(new_skb, skb->len), skb->len);
- out_vcc->push(out_vcc,new_skb);
- atomic_inc(&vcc->stats->tx);
- atomic_inc(&out_vcc->stats->rx);
-done:
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb(skb);
- return result;
-}
-
-
-/*
- * Device operations for the virtual ATM devices created by ATMTCP.
- */
-
-
-static const struct atmdev_ops atmtcp_v_dev_ops = {
- .dev_close = atmtcp_v_dev_close,
- .open = atmtcp_v_open,
- .close = atmtcp_v_close,
- .ioctl = atmtcp_v_ioctl,
- .send = atmtcp_v_send,
- .proc_read = atmtcp_v_proc,
- .owner = THIS_MODULE
-};
-
-
-/*
- * Device operations for the ATMTCP control device.
- */
-
-
-static const struct atmdev_ops atmtcp_c_dev_ops = {
- .close = atmtcp_c_close,
- .pre_send = atmtcp_c_pre_send,
- .send = atmtcp_c_send
-};
-
-
-static struct atm_dev atmtcp_control_dev = {
- .ops = &atmtcp_c_dev_ops,
- .type = "atmtcp",
- .number = 999,
- .lock = __SPIN_LOCK_UNLOCKED(atmtcp_control_dev.lock)
-};
-
-
-static int atmtcp_create(int itf,int persist,struct atm_dev **result)
-{
- struct atmtcp_dev_data *dev_data;
- struct atm_dev *dev;
-
- dev_data = kmalloc_obj(*dev_data);
- if (!dev_data)
- return -ENOMEM;
-
- dev = atm_dev_register(DEV_LABEL,NULL,&atmtcp_v_dev_ops,itf,NULL);
- if (!dev) {
- kfree(dev_data);
- return itf == -1 ? -ENOMEM : -EBUSY;
- }
- dev->ci_range.vpi_bits = MAX_VPI_BITS;
- dev->ci_range.vci_bits = MAX_VCI_BITS;
- dev->dev_data = dev_data;
- PRIV(dev)->vcc = NULL;
- PRIV(dev)->persist = persist;
- if (result) *result = dev;
- return 0;
-}
-
-
-static int atmtcp_attach(struct atm_vcc *vcc,int itf)
-{
- struct atm_dev *dev;
-
- dev = NULL;
- if (itf != -1) dev = atm_dev_lookup(itf);
- if (dev) {
- if (dev->ops != &atmtcp_v_dev_ops) {
- atm_dev_put(dev);
- return -EMEDIUMTYPE;
- }
- if (PRIV(dev)->vcc) {
- atm_dev_put(dev);
- return -EBUSY;
- }
- }
- else {
- int error;
-
- error = atmtcp_create(itf,0,&dev);
- if (error) return error;
- }
- PRIV(dev)->vcc = vcc;
- vcc->dev = &atmtcp_control_dev;
- vcc_insert_socket(sk_atm(vcc));
- set_bit(ATM_VF_META,&vcc->flags);
- set_bit(ATM_VF_READY,&vcc->flags);
- vcc->dev_data = dev;
- (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */
- vcc->stats = &atmtcp_control_dev.stats.aal5;
- return dev->number;
-}
-
-
-static int atmtcp_create_persistent(int itf)
-{
- return atmtcp_create(itf,1,NULL);
-}
-
-
-static int atmtcp_remove_persistent(int itf)
-{
- struct atm_dev *dev;
- struct atmtcp_dev_data *dev_data;
-
- dev = atm_dev_lookup(itf);
- if (!dev) return -ENODEV;
- if (dev->ops != &atmtcp_v_dev_ops) {
- atm_dev_put(dev);
- return -EMEDIUMTYPE;
- }
- dev_data = PRIV(dev);
- if (!dev_data->persist) {
- atm_dev_put(dev);
- return 0;
- }
- dev_data->persist = 0;
- if (PRIV(dev)->vcc) {
- atm_dev_put(dev);
- return 0;
- }
- kfree(dev_data);
- atm_dev_put(dev);
- atm_dev_deregister(dev);
- return 0;
-}
-
-static int atmtcp_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- int err = 0;
- struct atm_vcc *vcc = ATM_SD(sock);
-
- if (cmd != SIOCSIFATMTCP && cmd != ATMTCP_CREATE && cmd != ATMTCP_REMOVE)
- return -ENOIOCTLCMD;
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- switch (cmd) {
- case SIOCSIFATMTCP:
- err = atmtcp_attach(vcc, (int) arg);
- if (err >= 0) {
- sock->state = SS_CONNECTED;
- __module_get(THIS_MODULE);
- }
- break;
- case ATMTCP_CREATE:
- err = atmtcp_create_persistent((int) arg);
- break;
- case ATMTCP_REMOVE:
- err = atmtcp_remove_persistent((int) arg);
- break;
- }
- return err;
-}
-
-static struct atm_ioctl atmtcp_ioctl_ops = {
- .owner = THIS_MODULE,
- .ioctl = atmtcp_ioctl,
-};
-
-static __init int atmtcp_init(void)
-{
- register_atm_ioctl(&atmtcp_ioctl_ops);
- return 0;
-}
-
-
-static void __exit atmtcp_exit(void)
-{
- deregister_atm_ioctl(&atmtcp_ioctl_ops);
-}
-
-MODULE_DESCRIPTION("ATM over TCP");
-MODULE_LICENSE("GPL");
-module_init(atmtcp_init);
-module_exit(atmtcp_exit);
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
deleted file mode 100644
index 12cb3aa588bc..000000000000
--- a/drivers/atm/eni.c
+++ /dev/null
@@ -1,2321 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/sonet.h>
-#include <linux/skbuff.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/uio.h>
-#include <linux/init.h>
-#include <linux/atm_eni.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <linux/atomic.h>
-#include <linux/uaccess.h>
-#include <asm/string.h>
-#include <asm/byteorder.h>
-
-#include "tonga.h"
-#include "midway.h"
-#include "suni.h"
-#include "eni.h"
-
-/*
- * TODO:
- *
- * Show stoppers
- * none
- *
- * Minor
- * - OAM support
- * - fix bugs listed below
- */
-
-/*
- * KNOWN BUGS:
- *
- * - may run into JK-JK bug and deadlock
- * - should allocate UBR channel first
- * - buffer space allocation algorithm is stupid
- * (RX: should be maxSDU+maxdelay*rate
- * TX: should be maxSDU+min(maxSDU,maxdelay*rate) )
- * - doesn't support OAM cells
- * - eni_put_free may hang if not putting memory fragments that _complete_
- * 2^n block (never happens in real life, though)
- */
-
-
-#if 0
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-
-#ifndef CONFIG_ATM_ENI_TUNE_BURST
-#define CONFIG_ATM_ENI_BURST_TX_8W
-#define CONFIG_ATM_ENI_BURST_RX_4W
-#endif
-
-
-#ifndef CONFIG_ATM_ENI_DEBUG
-
-
-#define NULLCHECK(x)
-
-#define EVENT(s,a,b)
-
-
-static void event_dump(void)
-{
-}
-
-
-#else
-
-
-/*
- * NULL pointer checking
- */
-
-#define NULLCHECK(x) \
- if ((unsigned long) (x) < 0x30) \
- printk(KERN_CRIT #x "==0x%lx\n",(unsigned long) (x))
-
-/*
- * Very extensive activity logging. Greatly improves bug detection speed but
- * costs a few Mbps if enabled.
- */
-
-#define EV 64
-
-static const char *ev[EV];
-static unsigned long ev_a[EV],ev_b[EV];
-static int ec = 0;
-
-
-static void EVENT(const char *s,unsigned long a,unsigned long b)
-{
- ev[ec] = s;
- ev_a[ec] = a;
- ev_b[ec] = b;
- ec = (ec+1) % EV;
-}
-
-
-static void event_dump(void)
-{
- int n,i;
-
- for (n = 0; n < EV; n++) {
- i = (ec+n) % EV;
- printk(KERN_NOTICE);
- printk(ev[i] ? ev[i] : "(null)",ev_a[i],ev_b[i]);
- }
-}
-
-
-#endif /* CONFIG_ATM_ENI_DEBUG */
-
-
-/*
- * NExx must not be equal at end
- * EExx may be equal at end
- * xxPJOK verify validity of pointer jumps
- * xxPMOK operating on a circular buffer of "c" words
- */
-
-#define NEPJOK(a0,a1,b) \
- ((a0) < (a1) ? (b) <= (a0) || (b) > (a1) : (b) <= (a0) && (b) > (a1))
-#define EEPJOK(a0,a1,b) \
- ((a0) < (a1) ? (b) < (a0) || (b) >= (a1) : (b) < (a0) && (b) >= (a1))
-#define NEPMOK(a0,d,b,c) NEPJOK(a0,(a0+d) & (c-1),b)
-#define EEPMOK(a0,d,b,c) EEPJOK(a0,(a0+d) & (c-1),b)
-
-
-static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0,
- backlogged = 0,rx_enqueued = 0,rx_dequeued = 0,pushed = 0,submitted = 0,
- putting = 0;
-
-static struct atm_dev *eni_boards = NULL;
-
-/* Read/write registers on card */
-#define eni_in(r) readl(eni_dev->reg+(r)*4)
-#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4)
-
-
-/*-------------------------------- utilities --------------------------------*/
-
-
-static void dump_mem(struct eni_dev *eni_dev)
-{
- int i;
-
- for (i = 0; i < eni_dev->free_len; i++)
- printk(KERN_DEBUG " %d: %p %d\n",i,
- eni_dev->free_list[i].start,
- 1 << eni_dev->free_list[i].order);
-}
-
-
-static void dump(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
-
- int i;
-
- eni_dev = ENI_DEV(dev);
- printk(KERN_NOTICE "Free memory\n");
- dump_mem(eni_dev);
- printk(KERN_NOTICE "TX buffers\n");
- for (i = 0; i < NR_CHAN; i++)
- if (eni_dev->tx[i].send)
- printk(KERN_NOTICE " TX %d @ %p: %ld\n",i,
- eni_dev->tx[i].send,eni_dev->tx[i].words*4);
- printk(KERN_NOTICE "RX buffers\n");
- for (i = 0; i < 1024; i++)
- if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx)
- printk(KERN_NOTICE " RX %d @ %p: %ld\n",i,
- ENI_VCC(eni_dev->rx_map[i])->recv,
- ENI_VCC(eni_dev->rx_map[i])->words*4);
- printk(KERN_NOTICE "----\n");
-}
-
-
-static void eni_put_free(struct eni_dev *eni_dev, void __iomem *start,
- unsigned long size)
-{
- struct eni_free *list;
- int len,order;
-
- DPRINTK("init 0x%lx+%ld(0x%lx)\n",start,size,size);
- start += eni_dev->base_diff;
- list = eni_dev->free_list;
- len = eni_dev->free_len;
- while (size) {
- if (len >= eni_dev->free_list_size) {
- printk(KERN_CRIT "eni_put_free overflow (%p,%ld)\n",
- start,size);
- break;
- }
- for (order = 0; !(((unsigned long)start | size) & (1 << order)); order++);
- if (MID_MIN_BUF_SIZE > (1 << order)) {
- printk(KERN_CRIT "eni_put_free: order %d too small\n",
- order);
- break;
- }
- list[len].start = (void __iomem *) start;
- list[len].order = order;
- len++;
- start += 1 << order;
- size -= 1 << order;
- }
- eni_dev->free_len = len;
- /*dump_mem(eni_dev);*/
-}
-
-
-static void __iomem *eni_alloc_mem(struct eni_dev *eni_dev, unsigned long *size)
-{
- struct eni_free *list;
- void __iomem *start;
- int len,i,order,best_order,index;
-
- list = eni_dev->free_list;
- len = eni_dev->free_len;
- if (*size < MID_MIN_BUF_SIZE) *size = MID_MIN_BUF_SIZE;
- if (*size > MID_MAX_BUF_SIZE) return NULL;
- for (order = 0; (1 << order) < *size; order++)
- ;
- DPRINTK("trying: %ld->%d\n",*size,order);
- best_order = 65; /* we don't have more than 2^64 of anything ... */
- index = 0; /* silence GCC */
- for (i = 0; i < len; i++)
- if (list[i].order == order) {
- best_order = order;
- index = i;
- break;
- }
- else if (best_order > list[i].order && list[i].order > order) {
- best_order = list[i].order;
- index = i;
- }
- if (best_order == 65) return NULL;
- start = list[index].start-eni_dev->base_diff;
- list[index] = list[--len];
- eni_dev->free_len = len;
- *size = 1 << order;
- eni_put_free(eni_dev,start+*size,(1 << best_order)-*size);
- DPRINTK("%ld bytes (order %d) at 0x%lx\n",*size,order,start);
- memset_io(start,0,*size); /* never leak data */
- /*dump_mem(eni_dev);*/
- return start;
-}
-
-
-static void eni_free_mem(struct eni_dev *eni_dev, void __iomem *start,
- unsigned long size)
-{
- struct eni_free *list;
- int len,i,order;
-
- start += eni_dev->base_diff;
- list = eni_dev->free_list;
- len = eni_dev->free_len;
- for (order = -1; size; order++) size >>= 1;
- DPRINTK("eni_free_mem: %p+0x%lx (order %d)\n",start,size,order);
- for (i = 0; i < len; i++)
- if (((unsigned long) list[i].start) == ((unsigned long)start^(1 << order)) &&
- list[i].order == order) {
- DPRINTK("match[%d]: 0x%lx/0x%lx(0x%x), %d/%d\n",i,
- list[i].start,start,1 << order,list[i].order,order);
- list[i] = list[--len];
- start = (void __iomem *) ((unsigned long) start & ~(unsigned long) (1 << order));
- order++;
- i = -1;
- continue;
- }
- if (len >= eni_dev->free_list_size) {
- printk(KERN_ALERT "eni_free_mem overflow (%p,%d)\n",start,
- order);
- return;
- }
- list[len].start = start;
- list[len].order = order;
- eni_dev->free_len = len+1;
- /*dump_mem(eni_dev);*/
-}
-
-
-/*----------------------------------- RX ------------------------------------*/
-
-
-#define ENI_VCC_NOS ((struct atm_vcc *) 1)
-
-
-static void rx_ident_err(struct atm_vcc *vcc)
-{
- struct atm_dev *dev;
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
-
- dev = vcc->dev;
- eni_dev = ENI_DEV(dev);
- /* immediately halt adapter */
- eni_out(eni_in(MID_MC_S) &
- ~(MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE),MID_MC_S);
- /* dump useful information */
- eni_vcc = ENI_VCC(vcc);
- printk(KERN_ALERT DEV_LABEL "(itf %d): driver error - RX ident "
- "mismatch\n",dev->number);
- printk(KERN_ALERT " VCI %d, rxing %d, words %ld\n",vcc->vci,
- eni_vcc->rxing,eni_vcc->words);
- printk(KERN_ALERT " host descr 0x%lx, rx pos 0x%lx, descr value "
- "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos,
- (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4));
- printk(KERN_ALERT " last %p, servicing %d\n",eni_vcc->last,
- eni_vcc->servicing);
- EVENT("---dump ends here---\n",0,0);
- printk(KERN_NOTICE "---recent events---\n");
- event_dump();
- ENI_DEV(dev)->fast = NULL; /* really stop it */
- ENI_DEV(dev)->slow = NULL;
- skb_queue_head_init(&ENI_DEV(dev)->rx_queue);
-}
-
-
-static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb,
- unsigned long skip,unsigned long size,unsigned long eff)
-{
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
- u32 dma_rd,dma_wr;
- u32 dma[RX_DMA_BUF*2];
- dma_addr_t paddr;
- unsigned long here;
- int i,j;
-
- eni_dev = ENI_DEV(vcc->dev);
- eni_vcc = ENI_VCC(vcc);
- paddr = 0; /* GCC, shut up */
- if (skb) {
- paddr = dma_map_single(&eni_dev->pci_dev->dev,skb->data,skb->len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(&eni_dev->pci_dev->dev, paddr))
- goto dma_map_error;
- ENI_PRV_PADDR(skb) = paddr;
- if (paddr & 3)
- printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d has "
- "mis-aligned RX data (0x%lx)\n",vcc->dev->number,
- vcc->vci,(unsigned long) paddr);
- ENI_PRV_SIZE(skb) = size+skip;
- /* PDU plus descriptor */
- ATM_SKB(skb)->vcc = vcc;
- }
- j = 0;
- if ((eff && skip) || 1) { /* @@@ actually, skip is always == 1 ... */
- here = (eni_vcc->descr+skip) & (eni_vcc->words-1);
- dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci
- << MID_DMA_VCI_SHIFT) | MID_DT_JK;
- dma[j++] = 0;
- }
- here = (eni_vcc->descr+size+skip) & (eni_vcc->words-1);
- if (!eff) size += skip;
- else {
- unsigned long words;
-
- if (!size) {
- DPRINTK("strange things happen ...\n");
- EVENT("strange things happen ... (skip=%ld,eff=%ld)\n",
- size,eff);
- }
- words = eff;
- if (paddr & 15) {
- unsigned long init;
-
- init = 4-((paddr & 15) >> 2);
- if (init > words) init = words;
- dma[j++] = MID_DT_WORD | (init << MID_DMA_COUNT_SHIFT) |
- (vcc->vci << MID_DMA_VCI_SHIFT);
- dma[j++] = paddr;
- paddr += init << 2;
- words -= init;
- }
-#ifdef CONFIG_ATM_ENI_BURST_RX_16W /* may work with some PCI chipsets ... */
- if (words & ~15) {
- dma[j++] = MID_DT_16W | ((words >> 4) <<
- MID_DMA_COUNT_SHIFT) | (vcc->vci <<
- MID_DMA_VCI_SHIFT);
- dma[j++] = paddr;
- paddr += (words & ~15) << 2;
- words &= 15;
- }
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_RX_8W /* works only with *some* PCI chipsets ... */
- if (words & ~7) {
- dma[j++] = MID_DT_8W | ((words >> 3) <<
- MID_DMA_COUNT_SHIFT) | (vcc->vci <<
- MID_DMA_VCI_SHIFT);
- dma[j++] = paddr;
- paddr += (words & ~7) << 2;
- words &= 7;
- }
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_RX_4W /* recommended */
- if (words & ~3) {
- dma[j++] = MID_DT_4W | ((words >> 2) <<
- MID_DMA_COUNT_SHIFT) | (vcc->vci <<
- MID_DMA_VCI_SHIFT);
- dma[j++] = paddr;
- paddr += (words & ~3) << 2;
- words &= 3;
- }
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_RX_2W /* probably useless if RX_4W, RX_8W, ... */
- if (words & ~1) {
- dma[j++] = MID_DT_2W | ((words >> 1) <<
- MID_DMA_COUNT_SHIFT) | (vcc->vci <<
- MID_DMA_VCI_SHIFT);
- dma[j++] = paddr;
- paddr += (words & ~1) << 2;
- words &= 1;
- }
-#endif
- if (words) {
- dma[j++] = MID_DT_WORD | (words << MID_DMA_COUNT_SHIFT)
- | (vcc->vci << MID_DMA_VCI_SHIFT);
- dma[j++] = paddr;
- }
- }
- if (size != eff) {
- dma[j++] = (here << MID_DMA_COUNT_SHIFT) |
- (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK;
- dma[j++] = 0;
- }
- if (!j || j > 2*RX_DMA_BUF) {
- printk(KERN_CRIT DEV_LABEL "!j or j too big!!!\n");
- goto trouble;
- }
- dma[j-2] |= MID_DMA_END;
- j = j >> 1;
- dma_wr = eni_in(MID_DMA_WR_RX);
- dma_rd = eni_in(MID_DMA_RD_RX);
- /*
- * Can I move the dma_wr pointer by 2j+1 positions without overwriting
- * data that hasn't been read (position of dma_rd) yet ?
- */
- if (!NEPMOK(dma_wr,j+j+1,dma_rd,NR_DMA_RX)) { /* @@@ +1 is ugly */
- printk(KERN_WARNING DEV_LABEL "(itf %d): RX DMA full\n",
- vcc->dev->number);
- goto trouble;
- }
- for (i = 0; i < j; i++) {
- writel(dma[i*2],eni_dev->rx_dma+dma_wr*8);
- writel(dma[i*2+1],eni_dev->rx_dma+dma_wr*8+4);
- dma_wr = (dma_wr+1) & (NR_DMA_RX-1);
- }
- if (skb) {
- ENI_PRV_POS(skb) = eni_vcc->descr+size+1;
- skb_queue_tail(&eni_dev->rx_queue,skb);
- eni_vcc->last = skb;
- rx_enqueued++;
- }
- eni_vcc->descr = here;
- eni_out(dma_wr,MID_DMA_WR_RX);
- return 0;
-
-trouble:
- if (paddr)
- dma_unmap_single(&eni_dev->pci_dev->dev,paddr,skb->len,
- DMA_FROM_DEVICE);
-dma_map_error:
- if (skb) dev_kfree_skb_irq(skb);
- return -1;
-}
-
-
-static void discard(struct atm_vcc *vcc,unsigned long size)
-{
- struct eni_vcc *eni_vcc;
-
- eni_vcc = ENI_VCC(vcc);
- EVENT("discard (size=%ld)\n",size,0);
- while (do_rx_dma(vcc,NULL,1,size,0)) EVENT("BUSY LOOP",0,0);
- /* could do a full fallback, but that might be more expensive */
- if (eni_vcc->rxing) ENI_PRV_POS(eni_vcc->last) += size+1;
- else eni_vcc->rx_pos = (eni_vcc->rx_pos+size+1) & (eni_vcc->words-1);
-}
-
-
-/*
- * TODO: should check whether direct copies (without DMA setup, dequeuing on
- * interrupt, etc.) aren't much faster for AAL0
- */
-
-static int rx_aal0(struct atm_vcc *vcc)
-{
- struct eni_vcc *eni_vcc;
- unsigned long descr;
- unsigned long length;
- struct sk_buff *skb;
-
- DPRINTK(">rx_aal0\n");
- eni_vcc = ENI_VCC(vcc);
- descr = readl(eni_vcc->recv+eni_vcc->descr*4);
- if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) {
- rx_ident_err(vcc);
- return 1;
- }
- if (descr & MID_RED_T) {
- DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n",
- vcc->dev->number);
- length = 0;
- atomic_inc(&vcc->stats->rx_err);
- }
- else {
- length = ATM_CELL_SIZE-1; /* no HEC */
- }
- skb = length ? atm_alloc_charge(vcc,length,GFP_ATOMIC) : NULL;
- if (!skb) {
- discard(vcc,length >> 2);
- return 0;
- }
- skb_put(skb,length);
- skb->tstamp = eni_vcc->timestamp;
- DPRINTK("got len %ld\n",length);
- if (do_rx_dma(vcc,skb,1,length >> 2,length >> 2)) return 1;
- eni_vcc->rxing++;
- return 0;
-}
-
-
-static int rx_aal5(struct atm_vcc *vcc)
-{
- struct eni_vcc *eni_vcc;
- unsigned long descr;
- unsigned long size,eff,length;
- struct sk_buff *skb;
-
- EVENT("rx_aal5\n",0,0);
- DPRINTK(">rx_aal5\n");
- eni_vcc = ENI_VCC(vcc);
- descr = readl(eni_vcc->recv+eni_vcc->descr*4);
- if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) {
- rx_ident_err(vcc);
- return 1;
- }
- if (descr & (MID_RED_T | MID_RED_CRC_ERR)) {
- if (descr & MID_RED_T) {
- EVENT("empty cell (descr=0x%lx)\n",descr,0);
- DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n",
- vcc->dev->number);
- size = 0;
- }
- else {
- static unsigned long silence = 0;
-
- if (time_after(jiffies, silence) || silence == 0) {
- printk(KERN_WARNING DEV_LABEL "(itf %d): "
- "discarding PDU(s) with CRC error\n",
- vcc->dev->number);
- silence = (jiffies+2*HZ)|1;
- }
- size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2);
- EVENT("CRC error (descr=0x%lx,size=%ld)\n",descr,
- size);
- }
- eff = length = 0;
- atomic_inc(&vcc->stats->rx_err);
- }
- else {
- size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2);
- DPRINTK("size=%ld\n",size);
- length = readl(eni_vcc->recv+(((eni_vcc->descr+size-1) &
- (eni_vcc->words-1)))*4) & 0xffff;
- /* -trailer(2)+header(1) */
- if (length && length <= (size << 2)-8 && length <=
- ATM_MAX_AAL5_PDU) eff = (length+3) >> 2;
- else { /* ^ trailer length (8) */
- EVENT("bad PDU (descr=0x08%lx,length=%ld)\n",descr,
- length);
- printk(KERN_ERR DEV_LABEL "(itf %d): bad AAL5 PDU "
- "(VCI=%d,length=%ld,size=%ld (descr 0x%lx))\n",
- vcc->dev->number,vcc->vci,length,size << 2,descr);
- length = eff = 0;
- atomic_inc(&vcc->stats->rx_err);
- }
- }
- skb = eff ? atm_alloc_charge(vcc,eff << 2,GFP_ATOMIC) : NULL;
- if (!skb) {
- discard(vcc,size);
- return 0;
- }
- skb_put(skb,length);
- DPRINTK("got len %ld\n",length);
- if (do_rx_dma(vcc,skb,1,size,eff)) return 1;
- eni_vcc->rxing++;
- return 0;
-}
-
-
-static inline int rx_vcc(struct atm_vcc *vcc)
-{
- void __iomem *vci_dsc;
- unsigned long tmp;
- struct eni_vcc *eni_vcc;
-
- eni_vcc = ENI_VCC(vcc);
- vci_dsc = ENI_DEV(vcc->dev)->vci+vcc->vci*16;
- EVENT("rx_vcc(1)\n",0,0);
- while (eni_vcc->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR) >>
- MID_VCI_DESCR_SHIFT)) {
- EVENT("rx_vcc(2: host dsc=0x%lx, nic dsc=0x%lx)\n",
- eni_vcc->descr,tmp);
- DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr,
- (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >>
- MID_VCI_DESCR_SHIFT));
- if (ENI_VCC(vcc)->rx(vcc)) return 1;
- }
- /* clear IN_SERVICE flag */
- writel(readl(vci_dsc) & ~MID_VCI_IN_SERVICE,vci_dsc);
- /*
- * If new data has arrived between evaluating the while condition and
- * clearing IN_SERVICE, we wouldn't be notified until additional data
- * follows. So we have to loop again to be sure.
- */
- EVENT("rx_vcc(3)\n",0,0);
- while (ENI_VCC(vcc)->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR)
- >> MID_VCI_DESCR_SHIFT)) {
- EVENT("rx_vcc(4: host dsc=0x%lx, nic dsc=0x%lx)\n",
- eni_vcc->descr,tmp);
- DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr,
- (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >>
- MID_VCI_DESCR_SHIFT));
- if (ENI_VCC(vcc)->rx(vcc)) return 1;
- }
- return 0;
-}
-
-
-static void poll_rx(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
- struct atm_vcc *curr;
-
- eni_dev = ENI_DEV(dev);
- while ((curr = eni_dev->fast)) {
- EVENT("poll_rx.fast\n",0,0);
- if (rx_vcc(curr)) return;
- eni_dev->fast = ENI_VCC(curr)->next;
- ENI_VCC(curr)->next = ENI_VCC_NOS;
- barrier();
- ENI_VCC(curr)->servicing--;
- }
- while ((curr = eni_dev->slow)) {
- EVENT("poll_rx.slow\n",0,0);
- if (rx_vcc(curr)) return;
- eni_dev->slow = ENI_VCC(curr)->next;
- ENI_VCC(curr)->next = ENI_VCC_NOS;
- barrier();
- ENI_VCC(curr)->servicing--;
- }
-}
-
-
-static void get_service(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
- struct atm_vcc *vcc;
- unsigned long vci;
-
- DPRINTK(">get_service\n");
- eni_dev = ENI_DEV(dev);
- while (eni_in(MID_SERV_WRITE) != eni_dev->serv_read) {
- vci = readl(eni_dev->service+eni_dev->serv_read*4);
- eni_dev->serv_read = (eni_dev->serv_read+1) & (NR_SERVICE-1);
- vcc = eni_dev->rx_map[vci & 1023];
- if (!vcc) {
- printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %ld not "
- "found\n",dev->number,vci);
- continue; /* nasty but we try to go on anyway */
- /* @@@ nope, doesn't work */
- }
- EVENT("getting from service\n",0,0);
- if (ENI_VCC(vcc)->next != ENI_VCC_NOS) {
- EVENT("double service\n",0,0);
- DPRINTK("Grr, servicing VCC %ld twice\n",vci);
- continue;
- }
- ENI_VCC(vcc)->timestamp = ktime_get_real();
- ENI_VCC(vcc)->next = NULL;
- if (vcc->qos.rxtp.traffic_class == ATM_CBR) {
- if (eni_dev->fast)
- ENI_VCC(eni_dev->last_fast)->next = vcc;
- else eni_dev->fast = vcc;
- eni_dev->last_fast = vcc;
- }
- else {
- if (eni_dev->slow)
- ENI_VCC(eni_dev->last_slow)->next = vcc;
- else eni_dev->slow = vcc;
- eni_dev->last_slow = vcc;
- }
- putting++;
- ENI_VCC(vcc)->servicing++;
- }
-}
-
-
-static void dequeue_rx(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
- struct atm_vcc *vcc;
- struct sk_buff *skb;
- void __iomem *vci_dsc;
- int first;
-
- eni_dev = ENI_DEV(dev);
- first = 1;
- while (1) {
- skb = skb_dequeue(&eni_dev->rx_queue);
- if (!skb) {
- if (first) {
- DPRINTK(DEV_LABEL "(itf %d): RX but not "
- "rxing\n",dev->number);
- EVENT("nothing to dequeue\n",0,0);
- }
- break;
- }
- EVENT("dequeued (size=%ld,pos=0x%lx)\n",ENI_PRV_SIZE(skb),
- ENI_PRV_POS(skb));
- rx_dequeued++;
- vcc = ATM_SKB(skb)->vcc;
- eni_vcc = ENI_VCC(vcc);
- first = 0;
- vci_dsc = eni_dev->vci+vcc->vci*16;
- if (!EEPMOK(eni_vcc->rx_pos,ENI_PRV_SIZE(skb),
- (readl(vci_dsc+4) & MID_VCI_READ) >> MID_VCI_READ_SHIFT,
- eni_vcc->words)) {
- EVENT("requeuing\n",0,0);
- skb_queue_head(&eni_dev->rx_queue,skb);
- break;
- }
- eni_vcc->rxing--;
- eni_vcc->rx_pos = ENI_PRV_POS(skb) & (eni_vcc->words-1);
- dma_unmap_single(&eni_dev->pci_dev->dev,ENI_PRV_PADDR(skb),skb->len,
- DMA_TO_DEVICE);
- if (!skb->len) dev_kfree_skb_irq(skb);
- else {
- EVENT("pushing (len=%ld)\n",skb->len,0);
- if (vcc->qos.aal == ATM_AAL0)
- *(unsigned long *) skb->data =
- ntohl(*(unsigned long *) skb->data);
- memset(skb->cb,0,sizeof(struct eni_skb_prv));
- vcc->push(vcc,skb);
- pushed++;
- }
- atomic_inc(&vcc->stats->rx);
- }
- wake_up(&eni_dev->rx_wait);
-}
-
-
-static int open_rx_first(struct atm_vcc *vcc)
-{
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
- unsigned long size;
-
- DPRINTK("open_rx_first\n");
- eni_dev = ENI_DEV(vcc->dev);
- eni_vcc = ENI_VCC(vcc);
- eni_vcc->rx = NULL;
- if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0;
- size = vcc->qos.rxtp.max_sdu*eni_dev->rx_mult/100;
- if (size > MID_MAX_BUF_SIZE && vcc->qos.rxtp.max_sdu <=
- MID_MAX_BUF_SIZE)
- size = MID_MAX_BUF_SIZE;
- eni_vcc->recv = eni_alloc_mem(eni_dev,&size);
- DPRINTK("rx at 0x%lx\n",eni_vcc->recv);
- eni_vcc->words = size >> 2;
- if (!eni_vcc->recv) return -ENOBUFS;
- eni_vcc->rx = vcc->qos.aal == ATM_AAL5 ? rx_aal5 : rx_aal0;
- eni_vcc->descr = 0;
- eni_vcc->rx_pos = 0;
- eni_vcc->rxing = 0;
- eni_vcc->servicing = 0;
- eni_vcc->next = ENI_VCC_NOS;
- return 0;
-}
-
-
-static int open_rx_second(struct atm_vcc *vcc)
-{
- void __iomem *here;
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
- unsigned long size;
- int order;
-
- DPRINTK("open_rx_second\n");
- eni_dev = ENI_DEV(vcc->dev);
- eni_vcc = ENI_VCC(vcc);
- if (!eni_vcc->rx) return 0;
- /* set up VCI descriptor */
- here = eni_dev->vci+vcc->vci*16;
- DPRINTK("loc 0x%x\n",(unsigned) (eni_vcc->recv-eni_dev->ram)/4);
- size = eni_vcc->words >> 8;
- for (order = -1; size; order++) size >>= 1;
- writel(0,here+4); /* descr, read = 0 */
- writel(0,here+8); /* write, state, count = 0 */
- if (eni_dev->rx_map[vcc->vci])
- printk(KERN_CRIT DEV_LABEL "(itf %d): BUG - VCI %d already "
- "in use\n",vcc->dev->number,vcc->vci);
- eni_dev->rx_map[vcc->vci] = vcc; /* now it counts */
- writel(((vcc->qos.aal != ATM_AAL5 ? MID_MODE_RAW : MID_MODE_AAL5) <<
- MID_VCI_MODE_SHIFT) | MID_VCI_PTI_MODE |
- (((eni_vcc->recv-eni_dev->ram) >> (MID_LOC_SKIP+2)) <<
- MID_VCI_LOCATION_SHIFT) | (order << MID_VCI_SIZE_SHIFT),here);
- return 0;
-}
-
-
-static void close_rx(struct atm_vcc *vcc)
-{
- DECLARE_WAITQUEUE(wait,current);
- void __iomem *here;
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
-
- eni_vcc = ENI_VCC(vcc);
- if (!eni_vcc->rx) return;
- eni_dev = ENI_DEV(vcc->dev);
- if (vcc->vpi != ATM_VPI_UNSPEC && vcc->vci != ATM_VCI_UNSPEC) {
- here = eni_dev->vci+vcc->vci*16;
- /* block receiver */
- writel((readl(here) & ~MID_VCI_MODE) | (MID_MODE_TRASH <<
- MID_VCI_MODE_SHIFT),here);
- /* wait for receiver to become idle */
- udelay(27);
- /* discard pending cell */
- writel(readl(here) & ~MID_VCI_IN_SERVICE,here);
- /* don't accept any new ones */
- eni_dev->rx_map[vcc->vci] = NULL;
- /* wait for RX queue to drain */
- DPRINTK("eni_close: waiting for RX ...\n");
- EVENT("RX closing\n",0,0);
- add_wait_queue(&eni_dev->rx_wait,&wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
- barrier();
- for (;;) {
- /* transition service->rx: rxing++, servicing-- */
- if (!eni_vcc->servicing) {
- barrier();
- if (!eni_vcc->rxing) break;
- }
- EVENT("drain PDUs (rx %ld, serv %ld)\n",eni_vcc->rxing,
- eni_vcc->servicing);
- printk(KERN_INFO "%d+%d RX left\n",eni_vcc->servicing,
- eni_vcc->rxing);
- schedule();
- set_current_state(TASK_UNINTERRUPTIBLE);
- }
- for (;;) {
- int at_end;
- u32 tmp;
-
- tasklet_disable(&eni_dev->task);
- tmp = readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ;
- at_end = eni_vcc->rx_pos == tmp >> MID_VCI_READ_SHIFT;
- tasklet_enable(&eni_dev->task);
- if (at_end) break;
- EVENT("drain discard (host 0x%lx, nic 0x%lx)\n",
- eni_vcc->rx_pos,tmp);
- printk(KERN_INFO "draining RX: host 0x%lx, nic 0x%x\n",
- eni_vcc->rx_pos,tmp);
- schedule();
- set_current_state(TASK_UNINTERRUPTIBLE);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&eni_dev->rx_wait,&wait);
- }
- eni_free_mem(eni_dev,eni_vcc->recv,eni_vcc->words << 2);
- eni_vcc->rx = NULL;
-}
-
-
-static int start_rx(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
-
- eni_dev = ENI_DEV(dev);
- eni_dev->rx_map = (struct atm_vcc **) get_zeroed_page(GFP_KERNEL);
- if (!eni_dev->rx_map) {
- printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
- dev->number);
- free_page((unsigned long) eni_dev->free_list);
- return -ENOMEM;
- }
- eni_dev->rx_mult = DEFAULT_RX_MULT;
- eni_dev->fast = eni_dev->last_fast = NULL;
- eni_dev->slow = eni_dev->last_slow = NULL;
- init_waitqueue_head(&eni_dev->rx_wait);
- skb_queue_head_init(&eni_dev->rx_queue);
- eni_dev->serv_read = eni_in(MID_SERV_WRITE);
- eni_out(0,MID_DMA_WR_RX);
- return 0;
-}
-
-
-/*----------------------------------- TX ------------------------------------*/
-
-
-enum enq_res { enq_ok,enq_next,enq_jam };
-
-
-static inline void put_dma(int chan,u32 *dma,int *j,dma_addr_t paddr,
- u32 size)
-{
- u32 init,words;
-
- DPRINTK("put_dma: 0x%lx+0x%x\n",(unsigned long) paddr,size);
- EVENT("put_dma: 0x%lx+0x%lx\n",(unsigned long) paddr,size);
-#if 0 /* don't complain anymore */
- if (paddr & 3)
- printk(KERN_ERR "put_dma: unaligned addr (0x%lx)\n",paddr);
- if (size & 3)
- printk(KERN_ERR "put_dma: unaligned size (0x%lx)\n",size);
-#endif
- if (paddr & 3) {
- init = 4-(paddr & 3);
- if (init > size || size < 7) init = size;
- DPRINTK("put_dma: %lx DMA: %d/%d bytes\n",
- (unsigned long) paddr,init,size);
- dma[(*j)++] = MID_DT_BYTE | (init << MID_DMA_COUNT_SHIFT) |
- (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- paddr += init;
- size -= init;
- }
- words = size >> 2;
- size &= 3;
- if (words && (paddr & 31)) {
- init = 8-((paddr & 31) >> 2);
- if (init > words) init = words;
- DPRINTK("put_dma: %lx DMA: %d/%d words\n",
- (unsigned long) paddr,init,words);
- dma[(*j)++] = MID_DT_WORD | (init << MID_DMA_COUNT_SHIFT) |
- (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- paddr += init << 2;
- words -= init;
- }
-#ifdef CONFIG_ATM_ENI_BURST_TX_16W /* may work with some PCI chipsets ... */
- if (words & ~15) {
- DPRINTK("put_dma: %lx DMA: %d*16/%d words\n",
- (unsigned long) paddr,words >> 4,words);
- dma[(*j)++] = MID_DT_16W | ((words >> 4) << MID_DMA_COUNT_SHIFT)
- | (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- paddr += (words & ~15) << 2;
- words &= 15;
- }
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_TX_8W /* recommended */
- if (words & ~7) {
- DPRINTK("put_dma: %lx DMA: %d*8/%d words\n",
- (unsigned long) paddr,words >> 3,words);
- dma[(*j)++] = MID_DT_8W | ((words >> 3) << MID_DMA_COUNT_SHIFT)
- | (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- paddr += (words & ~7) << 2;
- words &= 7;
- }
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_TX_4W /* probably useless if TX_8W or TX_16W */
- if (words & ~3) {
- DPRINTK("put_dma: %lx DMA: %d*4/%d words\n",
- (unsigned long) paddr,words >> 2,words);
- dma[(*j)++] = MID_DT_4W | ((words >> 2) << MID_DMA_COUNT_SHIFT)
- | (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- paddr += (words & ~3) << 2;
- words &= 3;
- }
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_TX_2W /* probably useless if TX_4W, TX_8W, ... */
- if (words & ~1) {
- DPRINTK("put_dma: %lx DMA: %d*2/%d words\n",
- (unsigned long) paddr,words >> 1,words);
- dma[(*j)++] = MID_DT_2W | ((words >> 1) << MID_DMA_COUNT_SHIFT)
- | (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- paddr += (words & ~1) << 2;
- words &= 1;
- }
-#endif
- if (words) {
- DPRINTK("put_dma: %lx DMA: %d words\n",(unsigned long) paddr,
- words);
- dma[(*j)++] = MID_DT_WORD | (words << MID_DMA_COUNT_SHIFT) |
- (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- paddr += words << 2;
- }
- if (size) {
- DPRINTK("put_dma: %lx DMA: %d bytes\n",(unsigned long) paddr,
- size);
- dma[(*j)++] = MID_DT_BYTE | (size << MID_DMA_COUNT_SHIFT) |
- (chan << MID_DMA_CHAN_SHIFT);
- dma[(*j)++] = paddr;
- }
-}
-
-
-static enum enq_res do_tx(struct sk_buff *skb)
-{
- struct atm_vcc *vcc;
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
- struct eni_tx *tx;
- dma_addr_t paddr;
- u32 dma_rd,dma_wr;
- u32 size; /* in words */
- int aal5,dma_size,i,j;
- unsigned char skb_data3;
-
- DPRINTK(">do_tx\n");
- NULLCHECK(skb);
- EVENT("do_tx: skb=0x%lx, %ld bytes\n",(unsigned long) skb,skb->len);
- vcc = ATM_SKB(skb)->vcc;
- NULLCHECK(vcc);
- eni_dev = ENI_DEV(vcc->dev);
- NULLCHECK(eni_dev);
- eni_vcc = ENI_VCC(vcc);
- tx = eni_vcc->tx;
- NULLCHECK(tx);
-#if 0 /* Enable this for testing with the "align" program */
- {
- unsigned int hack = *((char *) skb->data)-'0';
-
- if (hack < 8) {
- skb->data += hack;
- skb->len -= hack;
- }
- }
-#endif
-#if 0 /* should work now */
- if ((unsigned long) skb->data & 3)
- printk(KERN_ERR DEV_LABEL "(itf %d): VCI %d has mis-aligned "
- "TX data\n",vcc->dev->number,vcc->vci);
-#endif
- /*
- * Potential future IP speedup: make hard_header big enough to put
- * segmentation descriptor directly into PDU. Saves: 4 slave writes,
- * 1 DMA xfer & 2 DMA'ed bytes (protocol layering is for wimps :-)
- */
-
- aal5 = vcc->qos.aal == ATM_AAL5;
- /* check space in buffer */
- if (!aal5)
- size = (ATM_CELL_PAYLOAD >> 2)+TX_DESCR_SIZE;
- /* cell without HEC plus segmentation header (includes
- four-byte cell header) */
- else {
- size = skb->len+4*AAL5_TRAILER+ATM_CELL_PAYLOAD-1;
- /* add AAL5 trailer */
- size = ((size-(size % ATM_CELL_PAYLOAD)) >> 2)+TX_DESCR_SIZE;
- /* add segmentation header */
- }
- /*
- * Can I move tx_pos by size bytes without getting closer than TX_GAP
- * to the read pointer ? TX_GAP means to leave some space for what
- * the manual calls "too close".
- */
- if (!NEPMOK(tx->tx_pos,size+TX_GAP,
- eni_in(MID_TX_RDPTR(tx->index)),tx->words)) {
- DPRINTK(DEV_LABEL "(itf %d): TX full (size %d)\n",
- vcc->dev->number,size);
- return enq_next;
- }
- /* check DMA */
- dma_wr = eni_in(MID_DMA_WR_TX);
- dma_rd = eni_in(MID_DMA_RD_TX);
- dma_size = 3; /* JK for descriptor and final fill, plus final size
- mis-alignment fix */
-DPRINTK("iovcnt = %d\n",skb_shinfo(skb)->nr_frags);
- if (!skb_shinfo(skb)->nr_frags) dma_size += 5;
- else dma_size += 5*(skb_shinfo(skb)->nr_frags+1);
- if (dma_size > TX_DMA_BUF) {
- printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries "
- "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF);
- }
- DPRINTK("dma_wr is %d, tx_pos is %ld\n",dma_wr,tx->tx_pos);
- if (dma_wr != dma_rd && ((dma_rd+NR_DMA_TX-dma_wr) & (NR_DMA_TX-1)) <
- dma_size) {
- printk(KERN_WARNING DEV_LABEL "(itf %d): TX DMA full\n",
- vcc->dev->number);
- return enq_jam;
- }
- skb_data3 = skb->data[3];
- paddr = dma_map_single(&eni_dev->pci_dev->dev,skb->data,skb->len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(&eni_dev->pci_dev->dev, paddr))
- return enq_next;
- ENI_PRV_PADDR(skb) = paddr;
- /* prepare DMA queue entries */
- j = 0;
- eni_dev->dma[j++] = (((tx->tx_pos+TX_DESCR_SIZE) & (tx->words-1)) <<
- MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
- MID_DT_JK;
- j++;
- if (!skb_shinfo(skb)->nr_frags)
- if (aal5) put_dma(tx->index,eni_dev->dma,&j,paddr,skb->len);
- else put_dma(tx->index,eni_dev->dma,&j,paddr+4,skb->len-4);
- else {
-DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
- for (i = -1; i < skb_shinfo(skb)->nr_frags; i++)
- if (i == -1)
- put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
- skb->data,
- skb_headlen(skb));
- else
- put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
- skb_frag_page(&skb_shinfo(skb)->frags[i]) +
- skb_frag_off(&skb_shinfo(skb)->frags[i]),
- skb_frag_size(&skb_shinfo(skb)->frags[i]));
- }
- if (skb->len & 3) {
- put_dma(tx->index, eni_dev->dma, &j, eni_dev->zero.dma,
- 4 - (skb->len & 3));
- }
- /* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */
- eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) <<
- MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
- MID_DMA_END | MID_DT_JK;
- j++;
- DPRINTK("DMA at end: %d\n",j);
- /* store frame */
- writel((MID_SEG_TX_ID << MID_SEG_ID_SHIFT) |
- (aal5 ? MID_SEG_AAL5 : 0) | (tx->prescaler << MID_SEG_PR_SHIFT) |
- (tx->resolution << MID_SEG_RATE_SHIFT) |
- (size/(ATM_CELL_PAYLOAD/4)),tx->send+tx->tx_pos*4);
-/*printk("dsc = 0x%08lx\n",(unsigned long) readl(tx->send+tx->tx_pos*4));*/
- writel((vcc->vci << MID_SEG_VCI_SHIFT) |
- (aal5 ? 0 : (skb_data3 & 0xf)) |
- (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? MID_SEG_CLP : 0),
- tx->send+((tx->tx_pos+1) & (tx->words-1))*4);
- DPRINTK("size: %d, len:%d\n",size,skb->len);
- if (aal5)
- writel(skb->len,tx->send+
- ((tx->tx_pos+size-AAL5_TRAILER) & (tx->words-1))*4);
- j = j >> 1;
- for (i = 0; i < j; i++) {
- writel(eni_dev->dma[i*2],eni_dev->tx_dma+dma_wr*8);
- writel(eni_dev->dma[i*2+1],eni_dev->tx_dma+dma_wr*8+4);
- dma_wr = (dma_wr+1) & (NR_DMA_TX-1);
- }
- ENI_PRV_POS(skb) = tx->tx_pos;
- ENI_PRV_SIZE(skb) = size;
- ENI_VCC(vcc)->txing += size;
- tx->tx_pos = (tx->tx_pos+size) & (tx->words-1);
- DPRINTK("dma_wr set to %d, tx_pos is now %ld\n",dma_wr,tx->tx_pos);
- eni_out(dma_wr,MID_DMA_WR_TX);
- skb_queue_tail(&eni_dev->tx_queue,skb);
- queued++;
- return enq_ok;
-}
-
-
-static void poll_tx(struct atm_dev *dev)
-{
- struct eni_tx *tx;
- struct sk_buff *skb;
- enum enq_res res;
- int i;
-
- DPRINTK(">poll_tx\n");
- for (i = NR_CHAN-1; i >= 0; i--) {
- tx = &ENI_DEV(dev)->tx[i];
- if (tx->send)
- while ((skb = skb_dequeue(&tx->backlog))) {
- res = do_tx(skb);
- if (res == enq_ok) continue;
- DPRINTK("re-queuing TX PDU\n");
- skb_queue_head(&tx->backlog,skb);
- requeued++;
- if (res == enq_jam) return;
- break;
- }
- }
-}
-
-
-static void dequeue_tx(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
- struct atm_vcc *vcc;
- struct sk_buff *skb;
- struct eni_tx *tx;
-
- NULLCHECK(dev);
- eni_dev = ENI_DEV(dev);
- NULLCHECK(eni_dev);
- while ((skb = skb_dequeue(&eni_dev->tx_queue))) {
- vcc = ATM_SKB(skb)->vcc;
- NULLCHECK(vcc);
- tx = ENI_VCC(vcc)->tx;
- NULLCHECK(ENI_VCC(vcc)->tx);
- DPRINTK("dequeue_tx: next 0x%lx curr 0x%x\n",ENI_PRV_POS(skb),
- (unsigned) eni_in(MID_TX_DESCRSTART(tx->index)));
- if (ENI_VCC(vcc)->txing < tx->words && ENI_PRV_POS(skb) ==
- eni_in(MID_TX_DESCRSTART(tx->index))) {
- skb_queue_head(&eni_dev->tx_queue,skb);
- break;
- }
- ENI_VCC(vcc)->txing -= ENI_PRV_SIZE(skb);
- dma_unmap_single(&eni_dev->pci_dev->dev,ENI_PRV_PADDR(skb),skb->len,
- DMA_TO_DEVICE);
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb_irq(skb);
- atomic_inc(&vcc->stats->tx);
- wake_up(&eni_dev->tx_wait);
- dma_complete++;
- }
-}
-
-
-static struct eni_tx *alloc_tx(struct eni_dev *eni_dev,int ubr)
-{
- int i;
-
- for (i = !ubr; i < NR_CHAN; i++)
- if (!eni_dev->tx[i].send) return eni_dev->tx+i;
- return NULL;
-}
-
-
-static int comp_tx(struct eni_dev *eni_dev,int *pcr,int reserved,int *pre,
- int *res,int unlimited)
-{
- static const int pre_div[] = { 4,16,128,2048 };
- /* 2^(((x+2)^2-(x+2))/2+1) */
-
- if (unlimited) *pre = *res = 0;
- else {
- if (*pcr > 0) {
- int div;
-
- for (*pre = 0; *pre < 3; (*pre)++)
- if (TS_CLOCK/pre_div[*pre]/64 <= *pcr) break;
- div = pre_div[*pre]**pcr;
- DPRINTK("min div %d\n",div);
- *res = TS_CLOCK/div-1;
- }
- else {
- int div;
-
- if (!*pcr) *pcr = eni_dev->tx_bw+reserved;
- for (*pre = 3; *pre >= 0; (*pre)--)
- if (TS_CLOCK/pre_div[*pre]/64 > -*pcr) break;
- if (*pre < 3) (*pre)++; /* else fail later */
- div = pre_div[*pre]*-*pcr;
- DPRINTK("max div %d\n",div);
- *res = DIV_ROUND_UP(TS_CLOCK, div)-1;
- }
- if (*res < 0) *res = 0;
- if (*res > MID_SEG_MAX_RATE) *res = MID_SEG_MAX_RATE;
- }
- *pcr = TS_CLOCK/pre_div[*pre]/(*res+1);
- DPRINTK("out pcr: %d (%d:%d)\n",*pcr,*pre,*res);
- return 0;
-}
-
-
-static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp,
- int set_rsv,int set_shp)
-{
- struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
- struct eni_vcc *eni_vcc = ENI_VCC(vcc);
- struct eni_tx *tx;
- unsigned long size;
- void __iomem *mem;
- int rate,ubr,unlimited,new_tx;
- int pre,res,order;
- int error;
-
- rate = atm_pcr_goal(txtp);
- ubr = txtp->traffic_class == ATM_UBR;
- unlimited = ubr && (!rate || rate <= -ATM_OC3_PCR ||
- rate >= ATM_OC3_PCR);
- if (!unlimited) {
- size = txtp->max_sdu*eni_dev->tx_mult/100;
- if (size > MID_MAX_BUF_SIZE && txtp->max_sdu <=
- MID_MAX_BUF_SIZE)
- size = MID_MAX_BUF_SIZE;
- }
- else {
- if (eni_dev->ubr) {
- eni_vcc->tx = eni_dev->ubr;
- txtp->pcr = ATM_OC3_PCR;
- return 0;
- }
- size = UBR_BUFFER;
- }
- new_tx = !eni_vcc->tx;
- mem = NULL; /* for gcc */
- if (!new_tx) tx = eni_vcc->tx;
- else {
- mem = eni_alloc_mem(eni_dev,&size);
- if (!mem) return -ENOBUFS;
- tx = alloc_tx(eni_dev,unlimited);
- if (!tx) {
- eni_free_mem(eni_dev,mem,size);
- return -EBUSY;
- }
- DPRINTK("got chan %d\n",tx->index);
- tx->reserved = tx->shaping = 0;
- tx->send = mem;
- tx->words = size >> 2;
- skb_queue_head_init(&tx->backlog);
- for (order = 0; size > (1 << (order+10)); order++);
- eni_out((order << MID_SIZE_SHIFT) |
- ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)),
- MID_TX_PLACE(tx->index));
- tx->tx_pos = eni_in(MID_TX_DESCRSTART(tx->index)) &
- MID_DESCR_START;
- }
- error = comp_tx(eni_dev,&rate,tx->reserved,&pre,&res,unlimited);
- if (!error && txtp->min_pcr > rate) error = -EINVAL;
- if (!error && txtp->max_pcr && txtp->max_pcr != ATM_MAX_PCR &&
- txtp->max_pcr < rate) error = -EINVAL;
- if (!error && !ubr && rate > eni_dev->tx_bw+tx->reserved)
- error = -EINVAL;
- if (!error && set_rsv && !set_shp && rate < tx->shaping)
- error = -EINVAL;
- if (!error && !set_rsv && rate > tx->reserved && !ubr)
- error = -EINVAL;
- if (error) {
- if (new_tx) {
- tx->send = NULL;
- eni_free_mem(eni_dev,mem,size);
- }
- return error;
- }
- txtp->pcr = rate;
- if (set_rsv && !ubr) {
- eni_dev->tx_bw += tx->reserved;
- tx->reserved = rate;
- eni_dev->tx_bw -= rate;
- }
- if (set_shp || (unlimited && new_tx)) {
- if (unlimited && new_tx) eni_dev->ubr = tx;
- tx->prescaler = pre;
- tx->resolution = res;
- tx->shaping = rate;
- }
- if (set_shp) eni_vcc->tx = tx;
- DPRINTK("rsv %d shp %d\n",tx->reserved,tx->shaping);
- return 0;
-}
-
-
-static int open_tx_first(struct atm_vcc *vcc)
-{
- ENI_VCC(vcc)->tx = NULL;
- if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;
- ENI_VCC(vcc)->txing = 0;
- return reserve_or_set_tx(vcc,&vcc->qos.txtp,1,1);
-}
-
-
-static int open_tx_second(struct atm_vcc *vcc)
-{
- return 0; /* nothing to do */
-}
-
-
-static void close_tx(struct atm_vcc *vcc)
-{
- DECLARE_WAITQUEUE(wait,current);
- struct eni_dev *eni_dev;
- struct eni_vcc *eni_vcc;
-
- eni_vcc = ENI_VCC(vcc);
- if (!eni_vcc->tx) return;
- eni_dev = ENI_DEV(vcc->dev);
- /* wait for TX queue to drain */
- DPRINTK("eni_close: waiting for TX ...\n");
- add_wait_queue(&eni_dev->tx_wait,&wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
- for (;;) {
- int txing;
-
- tasklet_disable(&eni_dev->task);
- txing = skb_peek(&eni_vcc->tx->backlog) || eni_vcc->txing;
- tasklet_enable(&eni_dev->task);
- if (!txing) break;
- DPRINTK("%d TX left\n",eni_vcc->txing);
- schedule();
- set_current_state(TASK_UNINTERRUPTIBLE);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&eni_dev->tx_wait,&wait);
- if (eni_vcc->tx != eni_dev->ubr) {
- /*
- * Looping a few times in here is probably far cheaper than
- * keeping track of TX completions all the time, so let's poll
- * a bit ...
- */
- while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) !=
- eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index)))
- schedule();
- eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2);
- eni_vcc->tx->send = NULL;
- eni_dev->tx_bw += eni_vcc->tx->reserved;
- }
- eni_vcc->tx = NULL;
-}
-
-
-static int start_tx(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
- int i;
-
- eni_dev = ENI_DEV(dev);
- eni_dev->lost = 0;
- eni_dev->tx_bw = ATM_OC3_PCR;
- eni_dev->tx_mult = DEFAULT_TX_MULT;
- init_waitqueue_head(&eni_dev->tx_wait);
- eni_dev->ubr = NULL;
- skb_queue_head_init(&eni_dev->tx_queue);
- eni_out(0,MID_DMA_WR_TX);
- for (i = 0; i < NR_CHAN; i++) {
- eni_dev->tx[i].send = NULL;
- eni_dev->tx[i].index = i;
- }
- return 0;
-}
-
-
-/*--------------------------------- common ----------------------------------*/
-
-
-#if 0 /* may become useful again when tuning things */
-
-static void foo(void)
-{
-printk(KERN_INFO
- "tx_complete=%d,dma_complete=%d,queued=%d,requeued=%d,sub=%d,\n"
- "backlogged=%d,rx_enqueued=%d,rx_dequeued=%d,putting=%d,pushed=%d\n",
- tx_complete,dma_complete,queued,requeued,submitted,backlogged,
- rx_enqueued,rx_dequeued,putting,pushed);
-if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);
-}
-
-#endif
-
-
-static void bug_int(struct atm_dev *dev,unsigned long reason)
-{
- DPRINTK(">bug_int\n");
- if (reason & MID_DMA_ERR_ACK)
- printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
- "error\n",dev->number);
- if (reason & MID_TX_IDENT_MISM)
- printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - ident "
- "mismatch\n",dev->number);
- if (reason & MID_TX_DMA_OVFL)
- printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
- "overflow\n",dev->number);
- EVENT("---dump ends here---\n",0,0);
- printk(KERN_NOTICE "---recent events---\n");
- event_dump();
-}
-
-
-static irqreturn_t eni_int(int irq,void *dev_id)
-{
- struct atm_dev *dev;
- struct eni_dev *eni_dev;
- u32 reason;
-
- DPRINTK(">eni_int\n");
- dev = dev_id;
- eni_dev = ENI_DEV(dev);
- reason = eni_in(MID_ISA);
- DPRINTK(DEV_LABEL ": int 0x%lx\n",(unsigned long) reason);
- /*
- * Must handle these two right now, because reading ISA doesn't clear
- * them, so they re-occur and we never make it to the tasklet. Since
- * they're rare, we don't mind the occasional invocation of eni_tasklet
- * with eni_dev->events == 0.
- */
- if (reason & MID_STAT_OVFL) {
- EVENT("stat overflow\n",0,0);
- eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;
- }
- if (reason & MID_SUNI_INT) {
- EVENT("SUNI int\n",0,0);
- dev->phy->interrupt(dev);
-#if 0
- foo();
-#endif
- }
- spin_lock(&eni_dev->lock);
- eni_dev->events |= reason;
- spin_unlock(&eni_dev->lock);
- tasklet_schedule(&eni_dev->task);
- return IRQ_HANDLED;
-}
-
-
-static void eni_tasklet(unsigned long data)
-{
- struct atm_dev *dev = (struct atm_dev *) data;
- struct eni_dev *eni_dev = ENI_DEV(dev);
- unsigned long flags;
- u32 events;
-
- DPRINTK("eni_tasklet (dev %p)\n",dev);
- spin_lock_irqsave(&eni_dev->lock,flags);
- events = xchg(&eni_dev->events,0);
- spin_unlock_irqrestore(&eni_dev->lock,flags);
- if (events & MID_RX_DMA_COMPLETE) {
- EVENT("INT: RX DMA complete, starting dequeue_rx\n",0,0);
- dequeue_rx(dev);
- EVENT("dequeue_rx done, starting poll_rx\n",0,0);
- poll_rx(dev);
- EVENT("poll_rx done\n",0,0);
- /* poll_tx ? */
- }
- if (events & MID_SERVICE) {
- EVENT("INT: service, starting get_service\n",0,0);
- get_service(dev);
- EVENT("get_service done, starting poll_rx\n",0,0);
- poll_rx(dev);
- EVENT("poll_rx done\n",0,0);
- }
- if (events & MID_TX_DMA_COMPLETE) {
- EVENT("INT: TX DMA COMPLETE\n",0,0);
- dequeue_tx(dev);
- }
- if (events & MID_TX_COMPLETE) {
- EVENT("INT: TX COMPLETE\n",0,0);
- tx_complete++;
- wake_up(&eni_dev->tx_wait);
- /* poll_rx ? */
- }
- if (events & (MID_DMA_ERR_ACK | MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) {
- EVENT("bug interrupt\n",0,0);
- bug_int(dev,events);
- }
- poll_tx(dev);
-}
-
-
-/*--------------------------------- entries ---------------------------------*/
-
-
-static char * const media_name[] = {
- "MMF", "SMF", "MMF", "03?", /* 0- 3 */
- "UTP", "05?", "06?", "07?", /* 4- 7 */
- "TAXI","09?", "10?", "11?", /* 8-11 */
- "12?", "13?", "14?", "15?", /* 12-15 */
- "MMF", "SMF", "18?", "19?", /* 16-19 */
- "UTP", "21?", "22?", "23?", /* 20-23 */
- "24?", "25?", "26?", "27?", /* 24-27 */
- "28?", "29?", "30?", "31?" /* 28-31 */
-};
-
-
-#define SET_SEPROM \
- ({ if (!error && !pci_error) { \
- pci_error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,tonga); \
- udelay(10); /* 10 usecs */ \
- } })
-#define GET_SEPROM \
- ({ if (!error && !pci_error) { \
- pci_error = pci_read_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,&tonga); \
- udelay(10); /* 10 usecs */ \
- } })
-
-
-static int get_esi_asic(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
- unsigned char tonga;
- int error,failed,pci_error;
- int address,i,j;
-
- eni_dev = ENI_DEV(dev);
- error = pci_error = 0;
- tonga = SEPROM_MAGIC | SEPROM_DATA | SEPROM_CLK;
- SET_SEPROM;
- for (i = 0; i < ESI_LEN && !error && !pci_error; i++) {
- /* start operation */
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- tonga |= SEPROM_CLK;
- SET_SEPROM;
- tonga &= ~SEPROM_DATA;
- SET_SEPROM;
- tonga &= ~SEPROM_CLK;
- SET_SEPROM;
- /* send address */
- address = ((i+SEPROM_ESI_BASE) << 1)+1;
- for (j = 7; j >= 0; j--) {
- tonga = (address >> j) & 1 ? tonga | SEPROM_DATA :
- tonga & ~SEPROM_DATA;
- SET_SEPROM;
- tonga |= SEPROM_CLK;
- SET_SEPROM;
- tonga &= ~SEPROM_CLK;
- SET_SEPROM;
- }
- /* get ack */
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- tonga |= SEPROM_CLK;
- SET_SEPROM;
- GET_SEPROM;
- failed = tonga & SEPROM_DATA;
- tonga &= ~SEPROM_CLK;
- SET_SEPROM;
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- if (failed) error = -EIO;
- else {
- dev->esi[i] = 0;
- for (j = 7; j >= 0; j--) {
- dev->esi[i] <<= 1;
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- tonga |= SEPROM_CLK;
- SET_SEPROM;
- GET_SEPROM;
- if (tonga & SEPROM_DATA) dev->esi[i] |= 1;
- tonga &= ~SEPROM_CLK;
- SET_SEPROM;
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- }
- /* get ack */
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- tonga |= SEPROM_CLK;
- SET_SEPROM;
- GET_SEPROM;
- if (!(tonga & SEPROM_DATA)) error = -EIO;
- tonga &= ~SEPROM_CLK;
- SET_SEPROM;
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- }
- /* stop operation */
- tonga &= ~SEPROM_DATA;
- SET_SEPROM;
- tonga |= SEPROM_CLK;
- SET_SEPROM;
- tonga |= SEPROM_DATA;
- SET_SEPROM;
- }
- if (pci_error) {
- printk(KERN_ERR DEV_LABEL "(itf %d): error reading ESI "
- "(0x%02x)\n",dev->number,pci_error);
- error = -EIO;
- }
- return error;
-}
-
-
-#undef SET_SEPROM
-#undef GET_SEPROM
-
-
-static int get_esi_fpga(struct atm_dev *dev, void __iomem *base)
-{
- void __iomem *mac_base;
- int i;
-
- mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom);
- for (i = 0; i < ESI_LEN; i++) dev->esi[i] = readb(mac_base+(i^3));
- return 0;
-}
-
-
-static int eni_do_init(struct atm_dev *dev)
-{
- struct midway_eprom __iomem *eprom;
- struct eni_dev *eni_dev;
- struct pci_dev *pci_dev;
- unsigned long real_base;
- void __iomem *base;
- int error,i,last;
-
- DPRINTK(">eni_init\n");
- dev->ci_range.vpi_bits = 0;
- dev->ci_range.vci_bits = NR_VCI_LD;
- dev->link_rate = ATM_OC3_PCR;
- eni_dev = ENI_DEV(dev);
- pci_dev = eni_dev->pci_dev;
- real_base = pci_resource_start(pci_dev, 0);
- eni_dev->irq = pci_dev->irq;
- if ((error = pci_write_config_word(pci_dev,PCI_COMMAND,
- PCI_COMMAND_MEMORY |
- (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory "
- "(0x%02x)\n",dev->number,error);
- return -EIO;
- }
- printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
- dev->number,pci_dev->revision,real_base,eni_dev->irq);
- if (!(base = ioremap(real_base,MAP_MAX_SIZE))) {
- printk("\n");
- printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
- "mapping\n",dev->number);
- return -ENOMEM;
- }
- eni_dev->ioaddr = base;
- eni_dev->base_diff = real_base - (unsigned long) base;
- /* id may not be present in ASIC Tonga boards - check this @@@ */
- if (!eni_dev->asic) {
- eprom = (base+EPROM_SIZE-sizeof(struct midway_eprom));
- if (readl(&eprom->magic) != ENI155_MAGIC) {
- printk("\n");
- printk(KERN_ERR DEV_LABEL
- "(itf %d): bad magic - expected 0x%x, got 0x%x\n",
- dev->number, ENI155_MAGIC,
- (unsigned)readl(&eprom->magic));
- error = -EINVAL;
- goto unmap;
- }
- }
- eni_dev->phy = base+PHY_BASE;
- eni_dev->reg = base+REG_BASE;
- eni_dev->ram = base+RAM_BASE;
- last = MAP_MAX_SIZE-RAM_BASE;
- for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) {
- writel(0x55555555,eni_dev->ram+i);
- if (readl(eni_dev->ram+i) != 0x55555555) last = i;
- else {
- writel(0xAAAAAAAA,eni_dev->ram+i);
- if (readl(eni_dev->ram+i) != 0xAAAAAAAA) last = i;
- else writel(i,eni_dev->ram+i);
- }
- }
- for (i = 0; i < last; i += RAM_INCREMENT)
- if (readl(eni_dev->ram+i) != i) break;
- eni_dev->mem = i;
- memset_io(eni_dev->ram,0,eni_dev->mem);
- /* TODO: should shrink allocation now */
- printk("mem=%dkB (",eni_dev->mem >> 10);
- /* TODO: check for non-SUNI, check for TAXI ? */
- if (!(eni_in(MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) {
- printk(")\n");
- printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%x\n",
- dev->number,(unsigned) eni_in(MID_RES_ID_MCON));
- error = -EINVAL;
- goto unmap;
- }
- error = eni_dev->asic ? get_esi_asic(dev) : get_esi_fpga(dev,base);
- if (error)
- goto unmap;
- for (i = 0; i < ESI_LEN; i++)
- printk("%s%02X",i ? "-" : "",dev->esi[i]);
- printk(")\n");
- printk(KERN_NOTICE DEV_LABEL "(itf %d): %s,%s\n",dev->number,
- eni_in(MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA",
- media_name[eni_in(MID_RES_ID_MCON) & DAUGHTER_ID]);
-
- error = suni_init(dev);
- if (error)
- goto unmap;
-out:
- return error;
-unmap:
- iounmap(base);
- goto out;
-}
-
-static void eni_do_release(struct atm_dev *dev)
-{
- struct eni_dev *ed = ENI_DEV(dev);
-
- dev->phy->stop(dev);
- dev->phy = NULL;
- iounmap(ed->ioaddr);
-}
-
-static int eni_start(struct atm_dev *dev)
-{
- struct eni_dev *eni_dev;
-
- void __iomem *buf;
- unsigned long buffer_mem;
- int error;
-
- DPRINTK(">eni_start\n");
- eni_dev = ENI_DEV(dev);
- if (request_irq(eni_dev->irq,&eni_int,IRQF_SHARED,DEV_LABEL,dev)) {
- printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
- dev->number,eni_dev->irq);
- error = -EAGAIN;
- goto out;
- }
- pci_set_master(eni_dev->pci_dev);
- if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
- (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
- "master (0x%02x)\n",dev->number,error);
- goto free_irq;
- }
- if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,
- END_SWAP_DMA))) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "
- "(0x%02x)\n",dev->number,error);
- goto free_irq;
- }
- /* determine addresses of internal tables */
- eni_dev->vci = eni_dev->ram;
- eni_dev->rx_dma = eni_dev->ram+NR_VCI*16;
- eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*8;
- eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*8;
- buf = eni_dev->service+NR_SERVICE*4;
- DPRINTK("vci 0x%lx,rx 0x%lx, tx 0x%lx,srv 0x%lx,buf 0x%lx\n",
- eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,
- eni_dev->service,buf);
- spin_lock_init(&eni_dev->lock);
- tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);
- eni_dev->events = 0;
- /* initialize memory management */
- buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
- eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
- eni_dev->free_list = kmalloc_objs(*eni_dev->free_list,
- eni_dev->free_list_size + 1);
- if (!eni_dev->free_list) {
- printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
- dev->number);
- error = -ENOMEM;
- goto free_irq;
- }
- eni_dev->free_len = 0;
- eni_put_free(eni_dev,buf,buffer_mem);
- memset_io(eni_dev->vci,0,16*NR_VCI); /* clear VCI table */
- /*
- * byte_addr free (k)
- * 0x00000000 512 VCI table
- * 0x00004000 496 RX DMA
- * 0x00005000 492 TX DMA
- * 0x00006000 488 service list
- * 0x00007000 484 buffers
- * 0x00080000 0 end (512kB)
- */
- eni_out(0xffffffff,MID_IE);
- error = start_tx(dev);
- if (error) goto free_list;
- error = start_rx(dev);
- if (error) goto free_list;
- error = dev->phy->start(dev);
- if (error) goto free_list;
- eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |
- MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,
- MID_MC_S);
- /* Tonga uses SBus INTReq1 */
- (void) eni_in(MID_ISA); /* clear Midway interrupts */
- return 0;
-
-free_list:
- kfree(eni_dev->free_list);
-
-free_irq:
- free_irq(eni_dev->irq, dev);
-
-out:
- return error;
-}
-
-
-static void eni_close(struct atm_vcc *vcc)
-{
- DPRINTK(">eni_close\n");
- if (!ENI_VCC(vcc)) return;
- clear_bit(ATM_VF_READY,&vcc->flags);
- close_rx(vcc);
- close_tx(vcc);
- DPRINTK("eni_close: done waiting\n");
- /* deallocate memory */
- kfree(ENI_VCC(vcc));
- vcc->dev_data = NULL;
- clear_bit(ATM_VF_ADDR,&vcc->flags);
- /*foo();*/
-}
-
-
-static int eni_open(struct atm_vcc *vcc)
-{
- struct eni_vcc *eni_vcc;
- int error;
- short vpi = vcc->vpi;
- int vci = vcc->vci;
-
- DPRINTK(">eni_open\n");
- EVENT("eni_open\n",0,0);
- if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
- vcc->dev_data = NULL;
- if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
- set_bit(ATM_VF_ADDR,&vcc->flags);
- if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5)
- return -EINVAL;
- DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi,
- vcc->vci);
- if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) {
- eni_vcc = kmalloc_obj(struct eni_vcc);
- if (!eni_vcc) return -ENOMEM;
- vcc->dev_data = eni_vcc;
- eni_vcc->tx = NULL; /* for eni_close after open_rx */
- if ((error = open_rx_first(vcc))) {
- eni_close(vcc);
- return error;
- }
- if ((error = open_tx_first(vcc))) {
- eni_close(vcc);
- return error;
- }
- }
- if (vci == ATM_VPI_UNSPEC || vpi == ATM_VCI_UNSPEC) return 0;
- if ((error = open_rx_second(vcc))) {
- eni_close(vcc);
- return error;
- }
- if ((error = open_tx_second(vcc))) {
- eni_close(vcc);
- return error;
- }
- set_bit(ATM_VF_READY,&vcc->flags);
- /* should power down SUNI while !ref_count @@@ */
- return 0;
-}
-
-
-static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
-{
- struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
- struct eni_tx *tx = ENI_VCC(vcc)->tx;
- struct sk_buff *skb;
- int error,rate,rsv,shp;
-
- if (qos->txtp.traffic_class == ATM_NONE) return 0;
- if (tx == eni_dev->ubr) return -EBADFD;
- rate = atm_pcr_goal(&qos->txtp);
- if (rate < 0) rate = -rate;
- rsv = shp = 0;
- if ((flgs & ATM_MF_DEC_RSV) && rate && rate < tx->reserved) rsv = 1;
- if ((flgs & ATM_MF_INC_RSV) && (!rate || rate > tx->reserved)) rsv = 1;
- if ((flgs & ATM_MF_DEC_SHP) && rate && rate < tx->shaping) shp = 1;
- if ((flgs & ATM_MF_INC_SHP) && (!rate || rate > tx->shaping)) shp = 1;
- if (!rsv && !shp) return 0;
- error = reserve_or_set_tx(vcc,&qos->txtp,rsv,shp);
- if (error) return error;
- if (shp && !(flgs & ATM_MF_IMMED)) return 0;
- /*
- * Walk through the send buffer and patch the rate information in all
- * segmentation buffer descriptors of this VCC.
- */
- tasklet_disable(&eni_dev->task);
- skb_queue_walk(&eni_dev->tx_queue, skb) {
- void __iomem *dsc;
-
- if (ATM_SKB(skb)->vcc != vcc) continue;
- dsc = tx->send+ENI_PRV_POS(skb)*4;
- writel((readl(dsc) & ~(MID_SEG_RATE | MID_SEG_PR)) |
- (tx->prescaler << MID_SEG_PR_SHIFT) |
- (tx->resolution << MID_SEG_RATE_SHIFT), dsc);
- }
- tasklet_enable(&eni_dev->task);
- return 0;
-}
-
-
-static int eni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
-{
- struct eni_dev *eni_dev = ENI_DEV(dev);
-
- if (cmd == ENI_MEMDUMP) {
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- printk(KERN_WARNING "Please use /proc/atm/" DEV_LABEL ":%d "
- "instead of obsolete ioctl ENI_MEMDUMP\n",dev->number);
- dump(dev);
- return 0;
- }
- if (cmd == ENI_SETMULT) {
- struct eni_multipliers mult;
-
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (copy_from_user(&mult, arg,
- sizeof(struct eni_multipliers)))
- return -EFAULT;
- if ((mult.tx && mult.tx <= 100) || (mult.rx &&mult.rx <= 100) ||
- mult.tx > 65536 || mult.rx > 65536)
- return -EINVAL;
- if (mult.tx) eni_dev->tx_mult = mult.tx;
- if (mult.rx) eni_dev->rx_mult = mult.rx;
- return 0;
- }
- if (cmd == ATM_SETCIRANGE) {
- struct atm_cirange ci;
-
- if (copy_from_user(&ci, arg,sizeof(struct atm_cirange)))
- return -EFAULT;
- if ((ci.vpi_bits == 0 || ci.vpi_bits == ATM_CI_MAX) &&
- (ci.vci_bits == NR_VCI_LD || ci.vpi_bits == ATM_CI_MAX))
- return 0;
- return -EINVAL;
- }
- if (!dev->phy->ioctl) return -ENOIOCTLCMD;
- return dev->phy->ioctl(dev,cmd,arg);
-}
-
-static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb)
-{
- enum enq_res res;
-
- DPRINTK(">eni_send\n");
- if (!ENI_VCC(vcc)->tx) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb(skb);
- return -EINVAL;
- }
- if (!skb) {
- printk(KERN_CRIT "!skb in eni_send ?\n");
- if (vcc->pop) vcc->pop(vcc,skb);
- return -EINVAL;
- }
- if (vcc->qos.aal == ATM_AAL0) {
- if (skb->len != ATM_CELL_SIZE-1) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb(skb);
- return -EINVAL;
- }
- *(u32 *) skb->data = htonl(*(u32 *) skb->data);
- }
- submitted++;
- ATM_SKB(skb)->vcc = vcc;
- tasklet_disable_in_atomic(&ENI_DEV(vcc->dev)->task);
- res = do_tx(skb);
- tasklet_enable(&ENI_DEV(vcc->dev)->task);
- if (res == enq_ok) return 0;
- skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
- backlogged++;
- tasklet_schedule(&ENI_DEV(vcc->dev)->task);
- return 0;
-}
-
-static void eni_phy_put(struct atm_dev *dev,unsigned char value,
- unsigned long addr)
-{
- writel(value,ENI_DEV(dev)->phy+addr*4);
-}
-
-
-
-static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr)
-{
- return readl(ENI_DEV(dev)->phy+addr*4);
-}
-
-
-static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
-{
- struct sock *s;
- static const char *signal[] = { "LOST","unknown","okay" };
- struct eni_dev *eni_dev = ENI_DEV(dev);
- struct atm_vcc *vcc;
- int left,i;
-
- left = *pos;
- if (!left)
- return sprintf(page,DEV_LABEL "(itf %d) signal %s, %dkB, "
- "%d cps remaining\n",dev->number,signal[(int) dev->signal],
- eni_dev->mem >> 10,eni_dev->tx_bw);
- if (!--left)
- return sprintf(page,"%4sBursts: TX"
-#if !defined(CONFIG_ATM_ENI_BURST_TX_16W) && \
- !defined(CONFIG_ATM_ENI_BURST_TX_8W) && \
- !defined(CONFIG_ATM_ENI_BURST_TX_4W) && \
- !defined(CONFIG_ATM_ENI_BURST_TX_2W)
- " none"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_TX_16W
- " 16W"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_TX_8W
- " 8W"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_TX_4W
- " 4W"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_TX_2W
- " 2W"
-#endif
- ", RX"
-#if !defined(CONFIG_ATM_ENI_BURST_RX_16W) && \
- !defined(CONFIG_ATM_ENI_BURST_RX_8W) && \
- !defined(CONFIG_ATM_ENI_BURST_RX_4W) && \
- !defined(CONFIG_ATM_ENI_BURST_RX_2W)
- " none"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_RX_16W
- " 16W"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_RX_8W
- " 8W"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_RX_4W
- " 4W"
-#endif
-#ifdef CONFIG_ATM_ENI_BURST_RX_2W
- " 2W"
-#endif
-#ifndef CONFIG_ATM_ENI_TUNE_BURST
- " (default)"
-#endif
- "\n","");
- if (!--left)
- return sprintf(page,"%4sBuffer multipliers: tx %d%%, rx %d%%\n",
- "",eni_dev->tx_mult,eni_dev->rx_mult);
- for (i = 0; i < NR_CHAN; i++) {
- struct eni_tx *tx = eni_dev->tx+i;
-
- if (!tx->send) continue;
- if (!--left) {
- return sprintf(page, "tx[%d]: 0x%lx-0x%lx "
- "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
- (unsigned long) (tx->send - eni_dev->ram),
- tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
- tx->reserved,tx->shaping,
- tx == eni_dev->ubr ? " (UBR)" : "");
- }
- if (--left) continue;
- return sprintf(page,"%10sbacklog %u packets\n","",
- skb_queue_len(&tx->backlog));
- }
- read_lock(&vcc_sklist_lock);
- for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
- struct hlist_head *head = &vcc_hash[i];
-
- sk_for_each(s, head) {
- struct eni_vcc *eni_vcc;
- int length;
-
- vcc = atm_sk(s);
- if (vcc->dev != dev)
- continue;
- eni_vcc = ENI_VCC(vcc);
- if (--left) continue;
- length = sprintf(page,"vcc %4d: ",vcc->vci);
- if (eni_vcc->rx) {
- length += sprintf(page+length, "0x%lx-0x%lx "
- "(%6ld bytes)",
- (unsigned long) (eni_vcc->recv - eni_dev->ram),
- eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
- eni_vcc->words*4);
- if (eni_vcc->tx) length += sprintf(page+length,", ");
- }
- if (eni_vcc->tx)
- length += sprintf(page+length,"tx[%d], txing %d bytes",
- eni_vcc->tx->index,eni_vcc->txing);
- page[length] = '\n';
- read_unlock(&vcc_sklist_lock);
- return length+1;
- }
- }
- read_unlock(&vcc_sklist_lock);
- for (i = 0; i < eni_dev->free_len; i++) {
- struct eni_free *fe = eni_dev->free_list+i;
- unsigned long offset;
-
- if (--left) continue;
- offset = (unsigned long) eni_dev->ram+eni_dev->base_diff;
- return sprintf(page,"free %p-%p (%6d bytes)\n",
- fe->start-offset,fe->start-offset+(1 << fe->order)-1,
- 1 << fe->order);
- }
- return 0;
-}
-
-
-static const struct atmdev_ops ops = {
- .open = eni_open,
- .close = eni_close,
- .ioctl = eni_ioctl,
- .send = eni_send,
- .phy_put = eni_phy_put,
- .phy_get = eni_phy_get,
- .change_qos = eni_change_qos,
- .proc_read = eni_proc_read
-};
-
-
-static int eni_init_one(struct pci_dev *pci_dev,
- const struct pci_device_id *ent)
-{
- struct atm_dev *dev;
- struct eni_dev *eni_dev;
- struct eni_zero *zero;
- int rc;
-
- rc = pci_enable_device(pci_dev);
- if (rc < 0)
- goto out;
-
- rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
- if (rc < 0)
- goto err_disable;
-
- rc = -ENOMEM;
- eni_dev = kmalloc_obj(struct eni_dev);
- if (!eni_dev)
- goto err_disable;
-
- zero = &eni_dev->zero;
- zero->addr = dma_alloc_coherent(&pci_dev->dev,
- ENI_ZEROES_SIZE, &zero->dma, GFP_KERNEL);
- if (!zero->addr)
- goto err_kfree;
-
- dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
- if (!dev)
- goto err_free_consistent;
-
- dev->dev_data = eni_dev;
- pci_set_drvdata(pci_dev, dev);
- eni_dev->pci_dev = pci_dev;
- eni_dev->asic = ent->driver_data;
-
- rc = eni_do_init(dev);
- if (rc < 0)
- goto err_unregister;
-
- rc = eni_start(dev);
- if (rc < 0)
- goto err_eni_release;
-
- eni_dev->more = eni_boards;
- eni_boards = dev;
-out:
- return rc;
-
-err_eni_release:
- dev->phy = NULL;
- iounmap(ENI_DEV(dev)->ioaddr);
-err_unregister:
- atm_dev_deregister(dev);
-err_free_consistent:
- dma_free_coherent(&pci_dev->dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
-err_kfree:
- kfree(eni_dev);
-err_disable:
- pci_disable_device(pci_dev);
- goto out;
-}
-
-
-static const struct pci_device_id eni_pci_tbl[] = {
- { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_FPGA), 0 /* FPGA */ },
- { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_ASIC), 1 /* ASIC */ },
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
-
-
-static void eni_remove_one(struct pci_dev *pdev)
-{
- struct atm_dev *dev = pci_get_drvdata(pdev);
- struct eni_dev *ed = ENI_DEV(dev);
- struct eni_zero *zero = &ed->zero;
-
- eni_do_release(dev);
- atm_dev_deregister(dev);
- dma_free_coherent(&pdev->dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
- kfree(ed);
- pci_disable_device(pdev);
-}
-
-
-static struct pci_driver eni_driver = {
- .name = DEV_LABEL,
- .id_table = eni_pci_tbl,
- .probe = eni_init_one,
- .remove = eni_remove_one,
-};
-
-
-static int __init eni_init(void)
-{
- struct sk_buff *skb; /* dummy for sizeof */
-
- BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct eni_skb_prv));
- return pci_register_driver(&eni_driver);
-}
-
-
-module_init(eni_init);
-/* @@@ since exit routine not defined, this module can not be unloaded */
-
-MODULE_DESCRIPTION("Efficient Networks ENI155P ATM NIC driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
deleted file mode 100644
index 2423eed506c1..000000000000
--- a/drivers/atm/fore200e.c
+++ /dev/null
@@ -1,3012 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- A FORE Systems 200E-series driver for ATM on Linux.
- Christophe Lizzi (lizzi@cnam.fr), October 1999-March 2003.
-
- Based on the PCA-200E driver from Uwe Dannowski (Uwe.Dannowski@inf.tu-dresden.de).
-
- This driver simultaneously supports PCA-200E and SBA-200E adapters
- on i386, alpha (untested), powerpc, sparc and sparc64 architectures.
-
-*/
-
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/capability.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/pci.h>
-#include <linux/module.h>
-#include <linux/atmdev.h>
-#include <linux/sonet.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/pgtable.h>
-#include <asm/io.h>
-#include <asm/string.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-
-#ifdef CONFIG_SBUS
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <asm/idprom.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#endif
-
-#if defined(CONFIG_ATM_FORE200E_USE_TASKLET) /* defer interrupt work to a tasklet */
-#define FORE200E_USE_TASKLET
-#endif
-
-#if 0 /* enable the debugging code of the buffer supply queues */
-#define FORE200E_BSQ_DEBUG
-#endif
-
-#if 1 /* ensure correct handling of 52-byte AAL0 SDUs expected by atmdump-like apps */
-#define FORE200E_52BYTE_AAL0_SDU
-#endif
-
-#include "fore200e.h"
-#include "suni.h"
-
-#define FORE200E_VERSION "0.3e"
-
-#define FORE200E "fore200e: "
-
-#if 0 /* override .config */
-#define CONFIG_ATM_FORE200E_DEBUG 1
-#endif
-#if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0)
-#define DPRINTK(level, format, args...) do { if (CONFIG_ATM_FORE200E_DEBUG >= (level)) \
- printk(FORE200E format, ##args); } while (0)
-#else
-#define DPRINTK(level, format, args...) do {} while (0)
-#endif
-
-
-#define FORE200E_ALIGN(addr, alignment) \
- ((((unsigned long)(addr) + (alignment - 1)) & ~(alignment - 1)) - (unsigned long)(addr))
-
-#define FORE200E_DMA_INDEX(dma_addr, type, index) ((dma_addr) + (index) * sizeof(type))
-
-#define FORE200E_INDEX(virt_addr, type, index) (&((type *)(virt_addr))[ index ])
-
-#define FORE200E_NEXT_ENTRY(index, modulo) (index = ((index) + 1) % (modulo))
-
-#if 1
-#define ASSERT(expr) if (!(expr)) { \
- printk(FORE200E "assertion failed! %s[%d]: %s\n", \
- __func__, __LINE__, #expr); \
- panic(FORE200E "%s", __func__); \
- }
-#else
-#define ASSERT(expr) do {} while (0)
-#endif
-
-
-static const struct atmdev_ops fore200e_ops;
-
-MODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen");
-MODULE_DESCRIPTION("FORE Systems 200E-series ATM driver - version " FORE200E_VERSION);
-
-static const int fore200e_rx_buf_nbr[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = {
- { BUFFER_S1_NBR, BUFFER_L1_NBR },
- { BUFFER_S2_NBR, BUFFER_L2_NBR }
-};
-
-static const int fore200e_rx_buf_size[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = {
- { BUFFER_S1_SIZE, BUFFER_L1_SIZE },
- { BUFFER_S2_SIZE, BUFFER_L2_SIZE }
-};
-
-
-#if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0)
-static const char* fore200e_traffic_class[] = { "NONE", "UBR", "CBR", "VBR", "ABR", "ANY" };
-#endif
-
-
-#if 0 /* currently unused */
-static int
-fore200e_fore2atm_aal(enum fore200e_aal aal)
-{
- switch(aal) {
- case FORE200E_AAL0: return ATM_AAL0;
- case FORE200E_AAL34: return ATM_AAL34;
- case FORE200E_AAL5: return ATM_AAL5;
- }
-
- return -EINVAL;
-}
-#endif
-
-
-static enum fore200e_aal
-fore200e_atm2fore_aal(int aal)
-{
- switch(aal) {
- case ATM_AAL0: return FORE200E_AAL0;
- case ATM_AAL34: return FORE200E_AAL34;
- case ATM_AAL1:
- case ATM_AAL2:
- case ATM_AAL5: return FORE200E_AAL5;
- }
-
- return -EINVAL;
-}
-
-
-static char*
-fore200e_irq_itoa(int irq)
-{
- static char str[8];
- sprintf(str, "%d", irq);
- return str;
-}
-
-
-/* allocate and align a chunk of memory intended to hold the data behing exchanged
- between the driver and the adapter (using streaming DVMA) */
-
-static int
-fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment, int direction)
-{
- unsigned long offset = 0;
-
- if (alignment <= sizeof(int))
- alignment = 0;
-
- chunk->alloc_size = size + alignment;
- chunk->direction = direction;
-
- chunk->alloc_addr = kzalloc(chunk->alloc_size, GFP_KERNEL);
- if (chunk->alloc_addr == NULL)
- return -ENOMEM;
-
- if (alignment > 0)
- offset = FORE200E_ALIGN(chunk->alloc_addr, alignment);
-
- chunk->align_addr = chunk->alloc_addr + offset;
-
- chunk->dma_addr = dma_map_single(fore200e->dev, chunk->align_addr,
- size, direction);
- if (dma_mapping_error(fore200e->dev, chunk->dma_addr)) {
- kfree(chunk->alloc_addr);
- return -ENOMEM;
- }
- return 0;
-}
-
-
-/* free a chunk of memory */
-
-static void
-fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
-{
- dma_unmap_single(fore200e->dev, chunk->dma_addr, chunk->dma_size,
- chunk->direction);
- kfree(chunk->alloc_addr);
-}
-
-/*
- * Allocate a DMA consistent chunk of memory intended to act as a communication
- * mechanism (to hold descriptors, status, queues, etc.) shared by the driver
- * and the adapter.
- */
-static int
-fore200e_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk,
- int size, int nbr, int alignment)
-{
- /* returned chunks are page-aligned */
- chunk->alloc_size = size * nbr;
- chunk->alloc_addr = dma_alloc_coherent(fore200e->dev, chunk->alloc_size,
- &chunk->dma_addr, GFP_KERNEL);
- if (!chunk->alloc_addr)
- return -ENOMEM;
- chunk->align_addr = chunk->alloc_addr;
- return 0;
-}
-
-/*
- * Free a DMA consistent chunk of memory.
- */
-static void
-fore200e_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
-{
- dma_free_coherent(fore200e->dev, chunk->alloc_size, chunk->alloc_addr,
- chunk->dma_addr);
-}
-
-static void
-fore200e_spin(int msecs)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
- while (time_before(jiffies, timeout));
-}
-
-
-static int
-fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
- int ok;
-
- mb();
- do {
- if ((ok = (*addr == val)) || (*addr & STATUS_ERROR))
- break;
-
- } while (time_before(jiffies, timeout));
-
-#if 1
- if (!ok) {
- printk(FORE200E "cmd polling failed, got status 0x%08x, expected 0x%08x\n",
- *addr, val);
- }
-#endif
-
- return ok;
-}
-
-
-static int
-fore200e_io_poll(struct fore200e* fore200e, volatile u32 __iomem *addr, u32 val, int msecs)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
- int ok;
-
- do {
- if ((ok = (fore200e->bus->read(addr) == val)))
- break;
-
- } while (time_before(jiffies, timeout));
-
-#if 1
- if (!ok) {
- printk(FORE200E "I/O polling failed, got status 0x%08x, expected 0x%08x\n",
- fore200e->bus->read(addr), val);
- }
-#endif
-
- return ok;
-}
-
-
-static void
-fore200e_free_rx_buf(struct fore200e* fore200e)
-{
- int scheme, magn, nbr;
- struct buffer* buffer;
-
- for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
- for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
-
- if ((buffer = fore200e->host_bsq[ scheme ][ magn ].buffer) != NULL) {
-
- for (nbr = 0; nbr < fore200e_rx_buf_nbr[ scheme ][ magn ]; nbr++) {
-
- struct chunk* data = &buffer[ nbr ].data;
-
- if (data->alloc_addr != NULL)
- fore200e_chunk_free(fore200e, data);
- }
- }
- }
- }
-}
-
-
-static void
-fore200e_uninit_bs_queue(struct fore200e* fore200e)
-{
- int scheme, magn;
-
- for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
- for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
-
- struct chunk* status = &fore200e->host_bsq[ scheme ][ magn ].status;
- struct chunk* rbd_block = &fore200e->host_bsq[ scheme ][ magn ].rbd_block;
-
- if (status->alloc_addr)
- fore200e_dma_chunk_free(fore200e, status);
-
- if (rbd_block->alloc_addr)
- fore200e_dma_chunk_free(fore200e, rbd_block);
- }
- }
-}
-
-
-static int
-fore200e_reset(struct fore200e* fore200e, int diag)
-{
- int ok;
-
- fore200e->cp_monitor = fore200e->virt_base + FORE200E_CP_MONITOR_OFFSET;
-
- fore200e->bus->write(BSTAT_COLD_START, &fore200e->cp_monitor->bstat);
-
- fore200e->bus->reset(fore200e);
-
- if (diag) {
- ok = fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_SELFTEST_OK, 1000);
- if (ok == 0) {
-
- printk(FORE200E "device %s self-test failed\n", fore200e->name);
- return -ENODEV;
- }
-
- printk(FORE200E "device %s self-test passed\n", fore200e->name);
-
- fore200e->state = FORE200E_STATE_RESET;
- }
-
- return 0;
-}
-
-
-static void
-fore200e_shutdown(struct fore200e* fore200e)
-{
- printk(FORE200E "removing device %s at 0x%lx, IRQ %s\n",
- fore200e->name, fore200e->phys_base,
- fore200e_irq_itoa(fore200e->irq));
-
- if (fore200e->state > FORE200E_STATE_RESET) {
- /* first, reset the board to prevent further interrupts or data transfers */
- fore200e_reset(fore200e, 0);
- }
-
- /* then, release all allocated resources */
- switch(fore200e->state) {
-
- case FORE200E_STATE_COMPLETE:
- kfree(fore200e->stats);
-
- fallthrough;
- case FORE200E_STATE_IRQ:
- free_irq(fore200e->irq, fore200e->atm_dev);
-#ifdef FORE200E_USE_TASKLET
- tasklet_kill(&fore200e->tx_tasklet);
- tasklet_kill(&fore200e->rx_tasklet);
-#endif
-
- fallthrough;
- case FORE200E_STATE_ALLOC_BUF:
- fore200e_free_rx_buf(fore200e);
-
- fallthrough;
- case FORE200E_STATE_INIT_BSQ:
- fore200e_uninit_bs_queue(fore200e);
-
- fallthrough;
- case FORE200E_STATE_INIT_RXQ:
- fore200e_dma_chunk_free(fore200e, &fore200e->host_rxq.status);
- fore200e_dma_chunk_free(fore200e, &fore200e->host_rxq.rpd);
-
- fallthrough;
- case FORE200E_STATE_INIT_TXQ:
- fore200e_dma_chunk_free(fore200e, &fore200e->host_txq.status);
- fore200e_dma_chunk_free(fore200e, &fore200e->host_txq.tpd);
-
- fallthrough;
- case FORE200E_STATE_INIT_CMDQ:
- fore200e_dma_chunk_free(fore200e, &fore200e->host_cmdq.status);
-
- fallthrough;
- case FORE200E_STATE_INITIALIZE:
- /* nothing to do for that state */
-
- case FORE200E_STATE_START_FW:
- /* nothing to do for that state */
-
- case FORE200E_STATE_RESET:
- /* nothing to do for that state */
-
- case FORE200E_STATE_MAP:
- fore200e->bus->unmap(fore200e);
-
- fallthrough;
- case FORE200E_STATE_CONFIGURE:
- /* nothing to do for that state */
-
- case FORE200E_STATE_REGISTER:
- /* XXX shouldn't we *start* by deregistering the device? */
- atm_dev_deregister(fore200e->atm_dev);
-
- fallthrough;
- case FORE200E_STATE_BLANK:
- /* nothing to do for that state */
- break;
- }
-}
-
-
-#ifdef CONFIG_PCI
-
-static u32 fore200e_pca_read(volatile u32 __iomem *addr)
-{
- /* on big-endian hosts, the board is configured to convert
- the endianess of slave RAM accesses */
- return le32_to_cpu(readl(addr));
-}
-
-
-static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr)
-{
- /* on big-endian hosts, the board is configured to convert
- the endianess of slave RAM accesses */
- writel(cpu_to_le32(val), addr);
-}
-
-static int
-fore200e_pca_irq_check(struct fore200e* fore200e)
-{
- /* this is a 1 bit register */
- int irq_posted = readl(fore200e->regs.pca.psr);
-
-#if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG == 2)
- if (irq_posted && (readl(fore200e->regs.pca.hcr) & PCA200E_HCR_OUTFULL)) {
- DPRINTK(2,"FIFO OUT full, device %d\n", fore200e->atm_dev->number);
- }
-#endif
-
- return irq_posted;
-}
-
-
-static void
-fore200e_pca_irq_ack(struct fore200e* fore200e)
-{
- writel(PCA200E_HCR_CLRINTR, fore200e->regs.pca.hcr);
-}
-
-
-static void
-fore200e_pca_reset(struct fore200e* fore200e)
-{
- writel(PCA200E_HCR_RESET, fore200e->regs.pca.hcr);
- fore200e_spin(10);
- writel(0, fore200e->regs.pca.hcr);
-}
-
-
-static int fore200e_pca_map(struct fore200e* fore200e)
-{
- DPRINTK(2, "device %s being mapped in memory\n", fore200e->name);
-
- fore200e->virt_base = ioremap(fore200e->phys_base, PCA200E_IOSPACE_LENGTH);
-
- if (fore200e->virt_base == NULL) {
- printk(FORE200E "can't map device %s\n", fore200e->name);
- return -EFAULT;
- }
-
- DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);
-
- /* gain access to the PCA specific registers */
- fore200e->regs.pca.hcr = fore200e->virt_base + PCA200E_HCR_OFFSET;
- fore200e->regs.pca.imr = fore200e->virt_base + PCA200E_IMR_OFFSET;
- fore200e->regs.pca.psr = fore200e->virt_base + PCA200E_PSR_OFFSET;
-
- fore200e->state = FORE200E_STATE_MAP;
- return 0;
-}
-
-
-static void
-fore200e_pca_unmap(struct fore200e* fore200e)
-{
- DPRINTK(2, "device %s being unmapped from memory\n", fore200e->name);
-
- if (fore200e->virt_base != NULL)
- iounmap(fore200e->virt_base);
-}
-
-
-static int fore200e_pca_configure(struct fore200e *fore200e)
-{
- struct pci_dev *pci_dev = to_pci_dev(fore200e->dev);
- u8 master_ctrl, latency;
-
- DPRINTK(2, "device %s being configured\n", fore200e->name);
-
- if ((pci_dev->irq == 0) || (pci_dev->irq == 0xFF)) {
- printk(FORE200E "incorrect IRQ setting - misconfigured PCI-PCI bridge?\n");
- return -EIO;
- }
-
- pci_read_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, &master_ctrl);
-
- master_ctrl = master_ctrl
-#if defined(__BIG_ENDIAN)
- /* request the PCA board to convert the endianess of slave RAM accesses */
- | PCA200E_CTRL_CONVERT_ENDIAN
-#endif
-#if 0
- | PCA200E_CTRL_DIS_CACHE_RD
- | PCA200E_CTRL_DIS_WRT_INVAL
- | PCA200E_CTRL_ENA_CONT_REQ_MODE
- | PCA200E_CTRL_2_CACHE_WRT_INVAL
-#endif
- | PCA200E_CTRL_LARGE_PCI_BURSTS;
-
- pci_write_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, master_ctrl);
-
- /* raise latency from 32 (default) to 192, as this seems to prevent NIC
- lockups (under heavy rx loads) due to continuous 'FIFO OUT full' condition.
- this may impact the performances of other PCI devices on the same bus, though */
- latency = 192;
- pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
-
- fore200e->state = FORE200E_STATE_CONFIGURE;
- return 0;
-}
-
-
-static int __init
-fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom)
-{
- struct host_cmdq* cmdq = &fore200e->host_cmdq;
- struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
- struct prom_opcode opcode;
- int ok;
- u32 prom_dma;
-
- FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
-
- opcode.opcode = OPCODE_GET_PROM;
- opcode.pad = 0;
-
- prom_dma = dma_map_single(fore200e->dev, prom, sizeof(struct prom_data),
- DMA_FROM_DEVICE);
- if (dma_mapping_error(fore200e->dev, prom_dma))
- return -ENOMEM;
-
- fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr);
-
- *entry->status = STATUS_PENDING;
-
- fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.prom_block.opcode);
-
- ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
-
- *entry->status = STATUS_FREE;
-
- dma_unmap_single(fore200e->dev, prom_dma, sizeof(struct prom_data), DMA_FROM_DEVICE);
-
- if (ok == 0) {
- printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name);
- return -EIO;
- }
-
-#if defined(__BIG_ENDIAN)
-
-#define swap_here(addr) (*((u32*)(addr)) = swab32( *((u32*)(addr)) ))
-
- /* MAC address is stored as little-endian */
- swap_here(&prom->mac_addr[0]);
- swap_here(&prom->mac_addr[4]);
-#endif
-
- return 0;
-}
-
-
-static int
-fore200e_pca_proc_read(struct fore200e* fore200e, char *page)
-{
- struct pci_dev *pci_dev = to_pci_dev(fore200e->dev);
-
- return sprintf(page, " PCI bus/slot/function:\t%d/%d/%d\n",
- pci_dev->bus->number, PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn));
-}
-
-static const struct fore200e_bus fore200e_pci_ops = {
- .model_name = "PCA-200E",
- .proc_name = "pca200e",
- .descr_alignment = 32,
- .buffer_alignment = 4,
- .status_alignment = 32,
- .read = fore200e_pca_read,
- .write = fore200e_pca_write,
- .configure = fore200e_pca_configure,
- .map = fore200e_pca_map,
- .reset = fore200e_pca_reset,
- .prom_read = fore200e_pca_prom_read,
- .unmap = fore200e_pca_unmap,
- .irq_check = fore200e_pca_irq_check,
- .irq_ack = fore200e_pca_irq_ack,
- .proc_read = fore200e_pca_proc_read,
-};
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_SBUS
-
-static u32 fore200e_sba_read(volatile u32 __iomem *addr)
-{
- return sbus_readl(addr);
-}
-
-static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr)
-{
- sbus_writel(val, addr);
-}
-
-static void fore200e_sba_irq_enable(struct fore200e *fore200e)
-{
- u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
- fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr);
-}
-
-static int fore200e_sba_irq_check(struct fore200e *fore200e)
-{
- return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ;
-}
-
-static void fore200e_sba_irq_ack(struct fore200e *fore200e)
-{
- u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY;
- fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr);
-}
-
-static void fore200e_sba_reset(struct fore200e *fore200e)
-{
- fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr);
- fore200e_spin(10);
- fore200e->bus->write(0, fore200e->regs.sba.hcr);
-}
-
-static int __init fore200e_sba_map(struct fore200e *fore200e)
-{
- struct platform_device *op = to_platform_device(fore200e->dev);
- unsigned int bursts;
-
- /* gain access to the SBA specific registers */
- fore200e->regs.sba.hcr = of_ioremap(&op->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
- fore200e->regs.sba.bsr = of_ioremap(&op->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
- fore200e->regs.sba.isr = of_ioremap(&op->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
- fore200e->virt_base = of_ioremap(&op->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");
-
- if (!fore200e->virt_base) {
- printk(FORE200E "unable to map RAM of device %s\n", fore200e->name);
- return -EFAULT;
- }
-
- DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);
-
- fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */
-
- /* get the supported DVMA burst sizes */
- bursts = of_getintprop_default(op->dev.of_node->parent, "burst-sizes", 0x00);
-
- if (sbus_can_dma_64bit())
- sbus_set_sbus64(&op->dev, bursts);
-
- fore200e->state = FORE200E_STATE_MAP;
- return 0;
-}
-
-static void fore200e_sba_unmap(struct fore200e *fore200e)
-{
- struct platform_device *op = to_platform_device(fore200e->dev);
-
- of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);
- of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);
- of_iounmap(&op->resource[2], fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);
- of_iounmap(&op->resource[3], fore200e->virt_base, SBA200E_RAM_LENGTH);
-}
-
-static int __init fore200e_sba_configure(struct fore200e *fore200e)
-{
- fore200e->state = FORE200E_STATE_CONFIGURE;
- return 0;
-}
-
-static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom)
-{
- struct platform_device *op = to_platform_device(fore200e->dev);
- const u8 *prop;
- int len;
-
- prop = of_get_property(op->dev.of_node, "madaddrlo2", &len);
- if (!prop)
- return -ENODEV;
- memcpy(&prom->mac_addr[4], prop, 4);
-
- prop = of_get_property(op->dev.of_node, "madaddrhi4", &len);
- if (!prop)
- return -ENODEV;
- memcpy(&prom->mac_addr[2], prop, 4);
-
- prom->serial_number = of_getintprop_default(op->dev.of_node,
- "serialnumber", 0);
- prom->hw_revision = of_getintprop_default(op->dev.of_node,
- "promversion", 0);
-
- return 0;
-}
-
-static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page)
-{
- struct platform_device *op = to_platform_device(fore200e->dev);
- const struct linux_prom_registers *regs;
-
- regs = of_get_property(op->dev.of_node, "reg", NULL);
-
- return sprintf(page, " SBUS slot/device:\t\t%d/'%pOFn'\n",
- (regs ? regs->which_io : 0), op->dev.of_node);
-}
-
-static const struct fore200e_bus fore200e_sbus_ops = {
- .model_name = "SBA-200E",
- .proc_name = "sba200e",
- .descr_alignment = 32,
- .buffer_alignment = 64,
- .status_alignment = 32,
- .read = fore200e_sba_read,
- .write = fore200e_sba_write,
- .configure = fore200e_sba_configure,
- .map = fore200e_sba_map,
- .reset = fore200e_sba_reset,
- .prom_read = fore200e_sba_prom_read,
- .unmap = fore200e_sba_unmap,
- .irq_enable = fore200e_sba_irq_enable,
- .irq_check = fore200e_sba_irq_check,
- .irq_ack = fore200e_sba_irq_ack,
- .proc_read = fore200e_sba_proc_read,
-};
-#endif /* CONFIG_SBUS */
-
-static void
-fore200e_tx_irq(struct fore200e* fore200e)
-{
- struct host_txq* txq = &fore200e->host_txq;
- struct host_txq_entry* entry;
- struct atm_vcc* vcc;
- struct fore200e_vc_map* vc_map;
-
- if (fore200e->host_txq.txing == 0)
- return;
-
- for (;;) {
-
- entry = &txq->host_entry[ txq->tail ];
-
- if ((*entry->status & STATUS_COMPLETE) == 0) {
- break;
- }
-
- DPRINTK(3, "TX COMPLETED: entry = %p [tail = %d], vc_map = %p, skb = %p\n",
- entry, txq->tail, entry->vc_map, entry->skb);
-
- /* free copy of misaligned data */
- kfree(entry->data);
-
- /* remove DMA mapping */
- dma_unmap_single(fore200e->dev, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
- DMA_TO_DEVICE);
-
- vc_map = entry->vc_map;
-
- /* vcc closed since the time the entry was submitted for tx? */
- if ((vc_map->vcc == NULL) ||
- (test_bit(ATM_VF_READY, &vc_map->vcc->flags) == 0)) {
-
- DPRINTK(1, "no ready vcc found for PDU sent on device %d\n",
- fore200e->atm_dev->number);
-
- dev_kfree_skb_any(entry->skb);
- }
- else {
- ASSERT(vc_map->vcc);
-
- /* vcc closed then immediately re-opened? */
- if (vc_map->incarn != entry->incarn) {
-
- /* when a vcc is closed, some PDUs may be still pending in the tx queue.
- if the same vcc is immediately re-opened, those pending PDUs must
- not be popped after the completion of their emission, as they refer
- to the prior incarnation of that vcc. otherwise, sk_atm(vcc)->sk_wmem_alloc
- would be decremented by the size of the (unrelated) skb, possibly
- leading to a negative sk->sk_wmem_alloc count, ultimately freezing the vcc.
- we thus bind the tx entry to the current incarnation of the vcc
- when the entry is submitted for tx. When the tx later completes,
- if the incarnation number of the tx entry does not match the one
- of the vcc, then this implies that the vcc has been closed then re-opened.
- we thus just drop the skb here. */
-
- DPRINTK(1, "vcc closed-then-re-opened; dropping PDU sent on device %d\n",
- fore200e->atm_dev->number);
-
- dev_kfree_skb_any(entry->skb);
- }
- else {
- vcc = vc_map->vcc;
- ASSERT(vcc);
-
- /* notify tx completion */
- if (vcc->pop) {
- vcc->pop(vcc, entry->skb);
- }
- else {
- dev_kfree_skb_any(entry->skb);
- }
-
- /* check error condition */
- if (*entry->status & STATUS_ERROR)
- atomic_inc(&vcc->stats->tx_err);
- else
- atomic_inc(&vcc->stats->tx);
- }
- }
-
- *entry->status = STATUS_FREE;
-
- fore200e->host_txq.txing--;
-
- FORE200E_NEXT_ENTRY(txq->tail, QUEUE_SIZE_TX);
- }
-}
-
-
-#ifdef FORE200E_BSQ_DEBUG
-int bsq_audit(int where, struct host_bsq* bsq, int scheme, int magn)
-{
- struct buffer* buffer;
- int count = 0;
-
- buffer = bsq->freebuf;
- while (buffer) {
-
- if (buffer->supplied) {
- printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld supplied but in free list!\n",
- where, scheme, magn, buffer->index);
- }
-
- if (buffer->magn != magn) {
- printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected magn = %d\n",
- where, scheme, magn, buffer->index, buffer->magn);
- }
-
- if (buffer->scheme != scheme) {
- printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected scheme = %d\n",
- where, scheme, magn, buffer->index, buffer->scheme);
- }
-
- if ((buffer->index < 0) || (buffer->index >= fore200e_rx_buf_nbr[ scheme ][ magn ])) {
- printk(FORE200E "bsq_audit(%d): queue %d.%d, out of range buffer index = %ld !\n",
- where, scheme, magn, buffer->index);
- }
-
- count++;
- buffer = buffer->next;
- }
-
- if (count != bsq->freebuf_count) {
- printk(FORE200E "bsq_audit(%d): queue %d.%d, %d bufs in free list, but freebuf_count = %d\n",
- where, scheme, magn, count, bsq->freebuf_count);
- }
- return 0;
-}
-#endif
-
-
-static void
-fore200e_supply(struct fore200e* fore200e)
-{
- int scheme, magn, i;
-
- struct host_bsq* bsq;
- struct host_bsq_entry* entry;
- struct buffer* buffer;
-
- for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
- for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
-
- bsq = &fore200e->host_bsq[ scheme ][ magn ];
-
-#ifdef FORE200E_BSQ_DEBUG
- bsq_audit(1, bsq, scheme, magn);
-#endif
- while (bsq->freebuf_count >= RBD_BLK_SIZE) {
-
- DPRINTK(2, "supplying %d rx buffers to queue %d / %d, freebuf_count = %d\n",
- RBD_BLK_SIZE, scheme, magn, bsq->freebuf_count);
-
- entry = &bsq->host_entry[ bsq->head ];
-
- for (i = 0; i < RBD_BLK_SIZE; i++) {
-
- /* take the first buffer in the free buffer list */
- buffer = bsq->freebuf;
- if (!buffer) {
- printk(FORE200E "no more free bufs in queue %d.%d, but freebuf_count = %d\n",
- scheme, magn, bsq->freebuf_count);
- return;
- }
- bsq->freebuf = buffer->next;
-
-#ifdef FORE200E_BSQ_DEBUG
- if (buffer->supplied)
- printk(FORE200E "queue %d.%d, buffer %lu already supplied\n",
- scheme, magn, buffer->index);
- buffer->supplied = 1;
-#endif
- entry->rbd_block->rbd[ i ].buffer_haddr = buffer->data.dma_addr;
- entry->rbd_block->rbd[ i ].handle = FORE200E_BUF2HDL(buffer);
- }
-
- FORE200E_NEXT_ENTRY(bsq->head, QUEUE_SIZE_BS);
-
- /* decrease accordingly the number of free rx buffers */
- bsq->freebuf_count -= RBD_BLK_SIZE;
-
- *entry->status = STATUS_PENDING;
- fore200e->bus->write(entry->rbd_block_dma, &entry->cp_entry->rbd_block_haddr);
- }
- }
- }
-}
-
-
-static int
-fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rpd)
-{
- struct sk_buff* skb;
- struct buffer* buffer;
- struct fore200e_vcc* fore200e_vcc;
- int i, pdu_len = 0;
-#ifdef FORE200E_52BYTE_AAL0_SDU
- u32 cell_header = 0;
-#endif
-
- ASSERT(vcc);
-
- fore200e_vcc = FORE200E_VCC(vcc);
- ASSERT(fore200e_vcc);
-
-#ifdef FORE200E_52BYTE_AAL0_SDU
- if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.rxtp.max_sdu == ATM_AAL0_SDU)) {
-
- cell_header = (rpd->atm_header.gfc << ATM_HDR_GFC_SHIFT) |
- (rpd->atm_header.vpi << ATM_HDR_VPI_SHIFT) |
- (rpd->atm_header.vci << ATM_HDR_VCI_SHIFT) |
- (rpd->atm_header.plt << ATM_HDR_PTI_SHIFT) |
- rpd->atm_header.clp;
- pdu_len = 4;
- }
-#endif
-
- /* compute total PDU length */
- for (i = 0; i < rpd->nseg; i++)
- pdu_len += rpd->rsd[ i ].length;
-
- skb = alloc_skb(pdu_len, GFP_ATOMIC);
- if (skb == NULL) {
- DPRINTK(2, "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
-
- atomic_inc(&vcc->stats->rx_drop);
- return -ENOMEM;
- }
-
- __net_timestamp(skb);
-
-#ifdef FORE200E_52BYTE_AAL0_SDU
- if (cell_header) {
- *((u32*)skb_put(skb, 4)) = cell_header;
- }
-#endif
-
- /* reassemble segments */
- for (i = 0; i < rpd->nseg; i++) {
-
- /* rebuild rx buffer address from rsd handle */
- buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle);
-
- /* Make device DMA transfer visible to CPU. */
- dma_sync_single_for_cpu(fore200e->dev, buffer->data.dma_addr,
- rpd->rsd[i].length, DMA_FROM_DEVICE);
-
- skb_put_data(skb, buffer->data.align_addr, rpd->rsd[i].length);
-
- /* Now let the device get at it again. */
- dma_sync_single_for_device(fore200e->dev, buffer->data.dma_addr,
- rpd->rsd[i].length, DMA_FROM_DEVICE);
- }
-
- DPRINTK(3, "rx skb: len = %d, truesize = %d\n", skb->len, skb->truesize);
-
- if (pdu_len < fore200e_vcc->rx_min_pdu)
- fore200e_vcc->rx_min_pdu = pdu_len;
- if (pdu_len > fore200e_vcc->rx_max_pdu)
- fore200e_vcc->rx_max_pdu = pdu_len;
- fore200e_vcc->rx_pdu++;
-
- /* push PDU */
- if (atm_charge(vcc, skb->truesize) == 0) {
-
- DPRINTK(2, "receive buffers saturated for %d.%d.%d - PDU dropped\n",
- vcc->itf, vcc->vpi, vcc->vci);
-
- dev_kfree_skb_any(skb);
-
- atomic_inc(&vcc->stats->rx_drop);
- return -ENOMEM;
- }
-
- vcc->push(vcc, skb);
- atomic_inc(&vcc->stats->rx);
-
- return 0;
-}
-
-
-static void
-fore200e_collect_rpd(struct fore200e* fore200e, struct rpd* rpd)
-{
- struct host_bsq* bsq;
- struct buffer* buffer;
- int i;
-
- for (i = 0; i < rpd->nseg; i++) {
-
- /* rebuild rx buffer address from rsd handle */
- buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle);
-
- bsq = &fore200e->host_bsq[ buffer->scheme ][ buffer->magn ];
-
-#ifdef FORE200E_BSQ_DEBUG
- bsq_audit(2, bsq, buffer->scheme, buffer->magn);
-
- if (buffer->supplied == 0)
- printk(FORE200E "queue %d.%d, buffer %ld was not supplied\n",
- buffer->scheme, buffer->magn, buffer->index);
- buffer->supplied = 0;
-#endif
-
- /* re-insert the buffer into the free buffer list */
- buffer->next = bsq->freebuf;
- bsq->freebuf = buffer;
-
- /* then increment the number of free rx buffers */
- bsq->freebuf_count++;
- }
-}
-
-
-static void
-fore200e_rx_irq(struct fore200e* fore200e)
-{
- struct host_rxq* rxq = &fore200e->host_rxq;
- struct host_rxq_entry* entry;
- struct atm_vcc* vcc;
- struct fore200e_vc_map* vc_map;
-
- for (;;) {
-
- entry = &rxq->host_entry[ rxq->head ];
-
- /* no more received PDUs */
- if ((*entry->status & STATUS_COMPLETE) == 0)
- break;
-
- vc_map = FORE200E_VC_MAP(fore200e, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
-
- if ((vc_map->vcc == NULL) ||
- (test_bit(ATM_VF_READY, &vc_map->vcc->flags) == 0)) {
-
- DPRINTK(1, "no ready VC found for PDU received on %d.%d.%d\n",
- fore200e->atm_dev->number,
- entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
- }
- else {
- vcc = vc_map->vcc;
- ASSERT(vcc);
-
- if ((*entry->status & STATUS_ERROR) == 0) {
-
- fore200e_push_rpd(fore200e, vcc, entry->rpd);
- }
- else {
- DPRINTK(2, "damaged PDU on %d.%d.%d\n",
- fore200e->atm_dev->number,
- entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
- atomic_inc(&vcc->stats->rx_err);
- }
- }
-
- FORE200E_NEXT_ENTRY(rxq->head, QUEUE_SIZE_RX);
-
- fore200e_collect_rpd(fore200e, entry->rpd);
-
- /* rewrite the rpd address to ack the received PDU */
- fore200e->bus->write(entry->rpd_dma, &entry->cp_entry->rpd_haddr);
- *entry->status = STATUS_FREE;
-
- fore200e_supply(fore200e);
- }
-}
-
-
-#ifndef FORE200E_USE_TASKLET
-static void
-fore200e_irq(struct fore200e* fore200e)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
- fore200e_rx_irq(fore200e);
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
- fore200e_tx_irq(fore200e);
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-}
-#endif
-
-
-static irqreturn_t
-fore200e_interrupt(int irq, void* dev)
-{
- struct fore200e* fore200e = FORE200E_DEV((struct atm_dev*)dev);
-
- if (fore200e->bus->irq_check(fore200e) == 0) {
-
- DPRINTK(3, "interrupt NOT triggered by device %d\n", fore200e->atm_dev->number);
- return IRQ_NONE;
- }
- DPRINTK(3, "interrupt triggered by device %d\n", fore200e->atm_dev->number);
-
-#ifdef FORE200E_USE_TASKLET
- tasklet_schedule(&fore200e->tx_tasklet);
- tasklet_schedule(&fore200e->rx_tasklet);
-#else
- fore200e_irq(fore200e);
-#endif
-
- fore200e->bus->irq_ack(fore200e);
- return IRQ_HANDLED;
-}
-
-
-#ifdef FORE200E_USE_TASKLET
-static void
-fore200e_tx_tasklet(unsigned long data)
-{
- struct fore200e* fore200e = (struct fore200e*) data;
- unsigned long flags;
-
- DPRINTK(3, "tx tasklet scheduled for device %d\n", fore200e->atm_dev->number);
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
- fore200e_tx_irq(fore200e);
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-}
-
-
-static void
-fore200e_rx_tasklet(unsigned long data)
-{
- struct fore200e* fore200e = (struct fore200e*) data;
- unsigned long flags;
-
- DPRINTK(3, "rx tasklet scheduled for device %d\n", fore200e->atm_dev->number);
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
- fore200e_rx_irq((struct fore200e*) data);
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-}
-#endif
-
-
-static int
-fore200e_select_scheme(struct atm_vcc* vcc)
-{
- /* fairly balance the VCs over (identical) buffer schemes */
- int scheme = vcc->vci % 2 ? BUFFER_SCHEME_ONE : BUFFER_SCHEME_TWO;
-
- DPRINTK(1, "VC %d.%d.%d uses buffer scheme %d\n",
- vcc->itf, vcc->vpi, vcc->vci, scheme);
-
- return scheme;
-}
-
-
-static int
-fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc* vcc, int mtu)
-{
- struct host_cmdq* cmdq = &fore200e->host_cmdq;
- struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
- struct activate_opcode activ_opcode;
- struct deactivate_opcode deactiv_opcode;
- struct vpvc vpvc;
- int ok;
- enum fore200e_aal aal = fore200e_atm2fore_aal(vcc->qos.aal);
-
- FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
-
- if (activate) {
- FORE200E_VCC(vcc)->scheme = fore200e_select_scheme(vcc);
-
- activ_opcode.opcode = OPCODE_ACTIVATE_VCIN;
- activ_opcode.aal = aal;
- activ_opcode.scheme = FORE200E_VCC(vcc)->scheme;
- activ_opcode.pad = 0;
- }
- else {
- deactiv_opcode.opcode = OPCODE_DEACTIVATE_VCIN;
- deactiv_opcode.pad = 0;
- }
-
- vpvc.vci = vcc->vci;
- vpvc.vpi = vcc->vpi;
-
- *entry->status = STATUS_PENDING;
-
- if (activate) {
-
-#ifdef FORE200E_52BYTE_AAL0_SDU
- mtu = 48;
-#endif
- /* the MTU is not used by the cp, except in the case of AAL0 */
- fore200e->bus->write(mtu, &entry->cp_entry->cmd.activate_block.mtu);
- fore200e->bus->write(*(u32*)&vpvc, (u32 __iomem *)&entry->cp_entry->cmd.activate_block.vpvc);
- fore200e->bus->write(*(u32*)&activ_opcode, (u32 __iomem *)&entry->cp_entry->cmd.activate_block.opcode);
- }
- else {
- fore200e->bus->write(*(u32*)&vpvc, (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.vpvc);
- fore200e->bus->write(*(u32*)&deactiv_opcode, (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.opcode);
- }
-
- ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
-
- *entry->status = STATUS_FREE;
-
- if (ok == 0) {
- printk(FORE200E "unable to %s VC %d.%d.%d\n",
- activate ? "open" : "close", vcc->itf, vcc->vpi, vcc->vci);
- return -EIO;
- }
-
- DPRINTK(1, "VC %d.%d.%d %sed\n", vcc->itf, vcc->vpi, vcc->vci,
- activate ? "open" : "clos");
-
- return 0;
-}
-
-
-#define FORE200E_MAX_BACK2BACK_CELLS 255 /* XXX depends on CDVT */
-
-static void
-fore200e_rate_ctrl(struct atm_qos* qos, struct tpd_rate* rate)
-{
- if (qos->txtp.max_pcr < ATM_OC3_PCR) {
-
- /* compute the data cells to idle cells ratio from the tx PCR */
- rate->data_cells = qos->txtp.max_pcr * FORE200E_MAX_BACK2BACK_CELLS / ATM_OC3_PCR;
- rate->idle_cells = FORE200E_MAX_BACK2BACK_CELLS - rate->data_cells;
- }
- else {
- /* disable rate control */
- rate->data_cells = rate->idle_cells = 0;
- }
-}
-
-
-static int
-fore200e_open(struct atm_vcc *vcc)
-{
- struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
- struct fore200e_vcc* fore200e_vcc;
- struct fore200e_vc_map* vc_map;
- unsigned long flags;
- int vci = vcc->vci;
- short vpi = vcc->vpi;
-
- ASSERT((vpi >= 0) && (vpi < 1<<FORE200E_VPI_BITS));
- ASSERT((vci >= 0) && (vci < 1<<FORE200E_VCI_BITS));
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
-
- vc_map = FORE200E_VC_MAP(fore200e, vpi, vci);
- if (vc_map->vcc) {
-
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-
- printk(FORE200E "VC %d.%d.%d already in use\n",
- fore200e->atm_dev->number, vpi, vci);
-
- return -EINVAL;
- }
-
- vc_map->vcc = vcc;
-
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-
- fore200e_vcc = kzalloc_obj(struct fore200e_vcc, GFP_ATOMIC);
- if (fore200e_vcc == NULL) {
- vc_map->vcc = NULL;
- return -ENOMEM;
- }
-
- DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
- "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d)\n",
- vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
- fore200e_traffic_class[ vcc->qos.txtp.traffic_class ],
- vcc->qos.txtp.min_pcr, vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_cdv, vcc->qos.txtp.max_sdu,
- fore200e_traffic_class[ vcc->qos.rxtp.traffic_class ],
- vcc->qos.rxtp.min_pcr, vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_cdv, vcc->qos.rxtp.max_sdu);
-
- /* pseudo-CBR bandwidth requested? */
- if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
-
- mutex_lock(&fore200e->rate_mtx);
- if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) {
- mutex_unlock(&fore200e->rate_mtx);
-
- kfree(fore200e_vcc);
- vc_map->vcc = NULL;
- return -EAGAIN;
- }
-
- /* reserve bandwidth */
- fore200e->available_cell_rate -= vcc->qos.txtp.max_pcr;
- mutex_unlock(&fore200e->rate_mtx);
- }
-
- vcc->itf = vcc->dev->number;
-
- set_bit(ATM_VF_PARTIAL,&vcc->flags);
- set_bit(ATM_VF_ADDR, &vcc->flags);
-
- vcc->dev_data = fore200e_vcc;
-
- if (fore200e_activate_vcin(fore200e, 1, vcc, vcc->qos.rxtp.max_sdu) < 0) {
-
- vc_map->vcc = NULL;
-
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- clear_bit(ATM_VF_PARTIAL,&vcc->flags);
-
- vcc->dev_data = NULL;
-
- mutex_lock(&fore200e->rate_mtx);
- fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
- mutex_unlock(&fore200e->rate_mtx);
-
- kfree(fore200e_vcc);
- return -EINVAL;
- }
-
- /* compute rate control parameters */
- if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
-
- fore200e_rate_ctrl(&vcc->qos, &fore200e_vcc->rate);
- set_bit(ATM_VF_HASQOS, &vcc->flags);
-
- DPRINTK(3, "tx on %d.%d.%d:%d, tx PCR = %d, rx PCR = %d, data_cells = %u, idle_cells = %u\n",
- vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
- vcc->qos.txtp.max_pcr, vcc->qos.rxtp.max_pcr,
- fore200e_vcc->rate.data_cells, fore200e_vcc->rate.idle_cells);
- }
-
- fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = MAX_PDU_SIZE + 1;
- fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0;
- fore200e_vcc->tx_pdu = fore200e_vcc->rx_pdu = 0;
-
- /* new incarnation of the vcc */
- vc_map->incarn = ++fore200e->incarn_count;
-
- /* VC unusable before this flag is set */
- set_bit(ATM_VF_READY, &vcc->flags);
-
- return 0;
-}
-
-
-static void
-fore200e_close(struct atm_vcc* vcc)
-{
- struct fore200e_vcc* fore200e_vcc;
- struct fore200e* fore200e;
- struct fore200e_vc_map* vc_map;
- unsigned long flags;
-
- ASSERT(vcc);
- fore200e = FORE200E_DEV(vcc->dev);
-
- ASSERT((vcc->vpi >= 0) && (vcc->vpi < 1<<FORE200E_VPI_BITS));
- ASSERT((vcc->vci >= 0) && (vcc->vci < 1<<FORE200E_VCI_BITS));
-
- DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal));
-
- clear_bit(ATM_VF_READY, &vcc->flags);
-
- fore200e_activate_vcin(fore200e, 0, vcc, 0);
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
-
- vc_map = FORE200E_VC_MAP(fore200e, vcc->vpi, vcc->vci);
-
- /* the vc is no longer considered as "in use" by fore200e_open() */
- vc_map->vcc = NULL;
-
- vcc->itf = vcc->vci = vcc->vpi = 0;
-
- fore200e_vcc = FORE200E_VCC(vcc);
- vcc->dev_data = NULL;
-
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-
- /* release reserved bandwidth, if any */
- if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
-
- mutex_lock(&fore200e->rate_mtx);
- fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
- mutex_unlock(&fore200e->rate_mtx);
-
- clear_bit(ATM_VF_HASQOS, &vcc->flags);
- }
-
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- clear_bit(ATM_VF_PARTIAL,&vcc->flags);
-
- ASSERT(fore200e_vcc);
- kfree(fore200e_vcc);
-}
-
-
-static int
-fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct fore200e* fore200e;
- struct fore200e_vcc* fore200e_vcc;
- struct fore200e_vc_map* vc_map;
- struct host_txq* txq;
- struct host_txq_entry* entry;
- struct tpd* tpd;
- struct tpd_haddr tpd_haddr;
- int retry = CONFIG_ATM_FORE200E_TX_RETRY;
- int tx_copy = 0;
- int tx_len = skb->len;
- u32* cell_header = NULL;
- unsigned char* skb_data;
- int skb_len;
- unsigned char* data;
- unsigned long flags;
-
- if (!vcc)
- return -EINVAL;
-
- fore200e = FORE200E_DEV(vcc->dev);
- fore200e_vcc = FORE200E_VCC(vcc);
-
- if (!fore200e)
- return -EINVAL;
-
- txq = &fore200e->host_txq;
- if (!fore200e_vcc)
- return -EINVAL;
-
- if (!test_bit(ATM_VF_READY, &vcc->flags)) {
- DPRINTK(1, "VC %d.%d.%d not ready for tx\n", vcc->itf, vcc->vpi, vcc->vpi);
- dev_kfree_skb_any(skb);
- return -EINVAL;
- }
-
-#ifdef FORE200E_52BYTE_AAL0_SDU
- if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.txtp.max_sdu == ATM_AAL0_SDU)) {
- cell_header = (u32*) skb->data;
- skb_data = skb->data + 4; /* skip 4-byte cell header */
- skb_len = tx_len = skb->len - 4;
-
- DPRINTK(3, "user-supplied cell header = 0x%08x\n", *cell_header);
- }
- else
-#endif
- {
- skb_data = skb->data;
- skb_len = skb->len;
- }
-
- if (((unsigned long)skb_data) & 0x3) {
-
- DPRINTK(2, "misaligned tx PDU on device %s\n", fore200e->name);
- tx_copy = 1;
- tx_len = skb_len;
- }
-
- if ((vcc->qos.aal == ATM_AAL0) && (skb_len % ATM_CELL_PAYLOAD)) {
-
- /* this simply NUKES the PCA board */
- DPRINTK(2, "incomplete tx AAL0 PDU on device %s\n", fore200e->name);
- tx_copy = 1;
- tx_len = ((skb_len / ATM_CELL_PAYLOAD) + 1) * ATM_CELL_PAYLOAD;
- }
-
- if (tx_copy) {
- data = kmalloc(tx_len, GFP_ATOMIC);
- if (data == NULL) {
- if (vcc->pop) {
- vcc->pop(vcc, skb);
- }
- else {
- dev_kfree_skb_any(skb);
- }
- return -ENOMEM;
- }
-
- memcpy(data, skb_data, skb_len);
- if (skb_len < tx_len)
- memset(data + skb_len, 0x00, tx_len - skb_len);
- }
- else {
- data = skb_data;
- }
-
- vc_map = FORE200E_VC_MAP(fore200e, vcc->vpi, vcc->vci);
- ASSERT(vc_map->vcc == vcc);
-
- retry_here:
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
-
- entry = &txq->host_entry[ txq->head ];
-
- if ((*entry->status != STATUS_FREE) || (txq->txing >= QUEUE_SIZE_TX - 2)) {
-
- /* try to free completed tx queue entries */
- fore200e_tx_irq(fore200e);
-
- if (*entry->status != STATUS_FREE) {
-
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-
- /* retry once again? */
- if (--retry > 0) {
- udelay(50);
- goto retry_here;
- }
-
- atomic_inc(&vcc->stats->tx_err);
-
- fore200e->tx_sat++;
- DPRINTK(2, "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n",
- fore200e->name, fore200e->cp_queues->heartbeat);
- if (vcc->pop) {
- vcc->pop(vcc, skb);
- }
- else {
- dev_kfree_skb_any(skb);
- }
-
- if (tx_copy)
- kfree(data);
-
- return -ENOBUFS;
- }
- }
-
- entry->incarn = vc_map->incarn;
- entry->vc_map = vc_map;
- entry->skb = skb;
- entry->data = tx_copy ? data : NULL;
-
- tpd = entry->tpd;
- tpd->tsd[ 0 ].buffer = dma_map_single(fore200e->dev, data, tx_len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(fore200e->dev, tpd->tsd[0].buffer)) {
- if (tx_copy)
- kfree(data);
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
- return -ENOMEM;
- }
- tpd->tsd[ 0 ].length = tx_len;
-
- FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
- txq->txing++;
-
- /* The dma_map call above implies a dma_sync so the device can use it,
- * thus no explicit dma_sync call is necessary here.
- */
-
- DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n",
- vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
- tpd->tsd[0].length, skb_len);
-
- if (skb_len < fore200e_vcc->tx_min_pdu)
- fore200e_vcc->tx_min_pdu = skb_len;
- if (skb_len > fore200e_vcc->tx_max_pdu)
- fore200e_vcc->tx_max_pdu = skb_len;
- fore200e_vcc->tx_pdu++;
-
- /* set tx rate control information */
- tpd->rate.data_cells = fore200e_vcc->rate.data_cells;
- tpd->rate.idle_cells = fore200e_vcc->rate.idle_cells;
-
- if (cell_header) {
- tpd->atm_header.clp = (*cell_header & ATM_HDR_CLP);
- tpd->atm_header.plt = (*cell_header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;
- tpd->atm_header.vci = (*cell_header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;
- tpd->atm_header.vpi = (*cell_header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;
- tpd->atm_header.gfc = (*cell_header & ATM_HDR_GFC_MASK) >> ATM_HDR_GFC_SHIFT;
- }
- else {
- /* set the ATM header, common to all cells conveying the PDU */
- tpd->atm_header.clp = 0;
- tpd->atm_header.plt = 0;
- tpd->atm_header.vci = vcc->vci;
- tpd->atm_header.vpi = vcc->vpi;
- tpd->atm_header.gfc = 0;
- }
-
- tpd->spec.length = tx_len;
- tpd->spec.nseg = 1;
- tpd->spec.aal = fore200e_atm2fore_aal(vcc->qos.aal);
- tpd->spec.intr = 1;
-
- tpd_haddr.size = sizeof(struct tpd) / (1<<TPD_HADDR_SHIFT); /* size is expressed in 32 byte blocks */
- tpd_haddr.pad = 0;
- tpd_haddr.haddr = entry->tpd_dma >> TPD_HADDR_SHIFT; /* shift the address, as we are in a bitfield */
-
- *entry->status = STATUS_PENDING;
- fore200e->bus->write(*(u32*)&tpd_haddr, (u32 __iomem *)&entry->cp_entry->tpd_haddr);
-
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
-
- return 0;
-}
-
-
-static int
-fore200e_getstats(struct fore200e* fore200e)
-{
- struct host_cmdq* cmdq = &fore200e->host_cmdq;
- struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
- struct stats_opcode opcode;
- int ok;
- u32 stats_dma_addr;
-
- if (fore200e->stats == NULL) {
- fore200e->stats = kzalloc_obj(struct stats);
- if (fore200e->stats == NULL)
- return -ENOMEM;
- }
-
- stats_dma_addr = dma_map_single(fore200e->dev, fore200e->stats,
- sizeof(struct stats), DMA_FROM_DEVICE);
- if (dma_mapping_error(fore200e->dev, stats_dma_addr))
- return -ENOMEM;
-
- FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
-
- opcode.opcode = OPCODE_GET_STATS;
- opcode.pad = 0;
-
- fore200e->bus->write(stats_dma_addr, &entry->cp_entry->cmd.stats_block.stats_haddr);
-
- *entry->status = STATUS_PENDING;
-
- fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.stats_block.opcode);
-
- ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
-
- *entry->status = STATUS_FREE;
-
- dma_unmap_single(fore200e->dev, stats_dma_addr, sizeof(struct stats), DMA_FROM_DEVICE);
-
- if (ok == 0) {
- printk(FORE200E "unable to get statistics from device %s\n", fore200e->name);
- return -EIO;
- }
-
- return 0;
-}
-
-#if 0 /* currently unused */
-static int
-fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs)
-{
- struct host_cmdq* cmdq = &fore200e->host_cmdq;
- struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
- struct oc3_opcode opcode;
- int ok;
- u32 oc3_regs_dma_addr;
-
- oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), DMA_FROM_DEVICE);
-
- FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
-
- opcode.opcode = OPCODE_GET_OC3;
- opcode.reg = 0;
- opcode.value = 0;
- opcode.mask = 0;
-
- fore200e->bus->write(oc3_regs_dma_addr, &entry->cp_entry->cmd.oc3_block.regs_haddr);
-
- *entry->status = STATUS_PENDING;
-
- fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.oc3_block.opcode);
-
- ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
-
- *entry->status = STATUS_FREE;
-
- fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), DMA_FROM_DEVICE);
-
- if (ok == 0) {
- printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name);
- return -EIO;
- }
-
- return 0;
-}
-#endif
-
-
-static int
-fore200e_set_oc3(struct fore200e* fore200e, u32 reg, u32 value, u32 mask)
-{
- struct host_cmdq* cmdq = &fore200e->host_cmdq;
- struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
- struct oc3_opcode opcode;
- int ok;
-
- DPRINTK(2, "set OC-3 reg = 0x%02x, value = 0x%02x, mask = 0x%02x\n", reg, value, mask);
-
- FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
-
- opcode.opcode = OPCODE_SET_OC3;
- opcode.reg = reg;
- opcode.value = value;
- opcode.mask = mask;
-
- fore200e->bus->write(0, &entry->cp_entry->cmd.oc3_block.regs_haddr);
-
- *entry->status = STATUS_PENDING;
-
- fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.oc3_block.opcode);
-
- ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
-
- *entry->status = STATUS_FREE;
-
- if (ok == 0) {
- printk(FORE200E "unable to set OC-3 reg 0x%02x of device %s\n", reg, fore200e->name);
- return -EIO;
- }
-
- return 0;
-}
-
-
-static int
-fore200e_setloop(struct fore200e* fore200e, int loop_mode)
-{
- u32 mct_value, mct_mask;
- int error;
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- switch (loop_mode) {
-
- case ATM_LM_NONE:
- mct_value = 0;
- mct_mask = SUNI_MCT_DLE | SUNI_MCT_LLE;
- break;
-
- case ATM_LM_LOC_PHY:
- mct_value = mct_mask = SUNI_MCT_DLE;
- break;
-
- case ATM_LM_RMT_PHY:
- mct_value = mct_mask = SUNI_MCT_LLE;
- break;
-
- default:
- return -EINVAL;
- }
-
- error = fore200e_set_oc3(fore200e, SUNI_MCT, mct_value, mct_mask);
- if (error == 0)
- fore200e->loop_mode = loop_mode;
-
- return error;
-}
-
-
-static int
-fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats __user *arg)
-{
- struct sonet_stats tmp;
-
- if (fore200e_getstats(fore200e) < 0)
- return -EIO;
-
- tmp.section_bip = be32_to_cpu(fore200e->stats->oc3.section_bip8_errors);
- tmp.line_bip = be32_to_cpu(fore200e->stats->oc3.line_bip24_errors);
- tmp.path_bip = be32_to_cpu(fore200e->stats->oc3.path_bip8_errors);
- tmp.line_febe = be32_to_cpu(fore200e->stats->oc3.line_febe_errors);
- tmp.path_febe = be32_to_cpu(fore200e->stats->oc3.path_febe_errors);
- tmp.corr_hcs = be32_to_cpu(fore200e->stats->oc3.corr_hcs_errors);
- tmp.uncorr_hcs = be32_to_cpu(fore200e->stats->oc3.ucorr_hcs_errors);
- tmp.tx_cells = be32_to_cpu(fore200e->stats->aal0.cells_transmitted) +
- be32_to_cpu(fore200e->stats->aal34.cells_transmitted) +
- be32_to_cpu(fore200e->stats->aal5.cells_transmitted);
- tmp.rx_cells = be32_to_cpu(fore200e->stats->aal0.cells_received) +
- be32_to_cpu(fore200e->stats->aal34.cells_received) +
- be32_to_cpu(fore200e->stats->aal5.cells_received);
-
- if (arg)
- return copy_to_user(arg, &tmp, sizeof(struct sonet_stats)) ? -EFAULT : 0;
-
- return 0;
-}
-
-
-static int
-fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void __user * arg)
-{
- struct fore200e* fore200e = FORE200E_DEV(dev);
-
- DPRINTK(2, "ioctl cmd = 0x%x (%u), arg = 0x%p (%lu)\n", cmd, cmd, arg, (unsigned long)arg);
-
- switch (cmd) {
-
- case SONET_GETSTAT:
- return fore200e_fetch_stats(fore200e, (struct sonet_stats __user *)arg);
-
- case SONET_GETDIAG:
- return put_user(0, (int __user *)arg) ? -EFAULT : 0;
-
- case ATM_SETLOOP:
- return fore200e_setloop(fore200e, (int)(unsigned long)arg);
-
- case ATM_GETLOOP:
- return put_user(fore200e->loop_mode, (int __user *)arg) ? -EFAULT : 0;
-
- case ATM_QUERYLOOP:
- return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int __user *)arg) ? -EFAULT : 0;
- }
-
- return -ENOSYS; /* not implemented */
-}
-
-
-static int
-fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags)
-{
- struct fore200e_vcc* fore200e_vcc = FORE200E_VCC(vcc);
- struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
-
- if (!test_bit(ATM_VF_READY, &vcc->flags)) {
- DPRINTK(1, "VC %d.%d.%d not ready for QoS change\n", vcc->itf, vcc->vpi, vcc->vpi);
- return -EINVAL;
- }
-
- DPRINTK(2, "change_qos %d.%d.%d, "
- "(tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
- "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d), flags = 0x%x\n"
- "available_cell_rate = %u",
- vcc->itf, vcc->vpi, vcc->vci,
- fore200e_traffic_class[ qos->txtp.traffic_class ],
- qos->txtp.min_pcr, qos->txtp.max_pcr, qos->txtp.max_cdv, qos->txtp.max_sdu,
- fore200e_traffic_class[ qos->rxtp.traffic_class ],
- qos->rxtp.min_pcr, qos->rxtp.max_pcr, qos->rxtp.max_cdv, qos->rxtp.max_sdu,
- flags, fore200e->available_cell_rate);
-
- if ((qos->txtp.traffic_class == ATM_CBR) && (qos->txtp.max_pcr > 0)) {
-
- mutex_lock(&fore200e->rate_mtx);
- if (fore200e->available_cell_rate + vcc->qos.txtp.max_pcr < qos->txtp.max_pcr) {
- mutex_unlock(&fore200e->rate_mtx);
- return -EAGAIN;
- }
-
- fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
- fore200e->available_cell_rate -= qos->txtp.max_pcr;
-
- mutex_unlock(&fore200e->rate_mtx);
-
- memcpy(&vcc->qos, qos, sizeof(struct atm_qos));
-
- /* update rate control parameters */
- fore200e_rate_ctrl(qos, &fore200e_vcc->rate);
-
- set_bit(ATM_VF_HASQOS, &vcc->flags);
-
- return 0;
- }
-
- return -EINVAL;
-}
-
-
-static int fore200e_irq_request(struct fore200e *fore200e)
-{
- if (request_irq(fore200e->irq, fore200e_interrupt, IRQF_SHARED, fore200e->name, fore200e->atm_dev) < 0) {
-
- printk(FORE200E "unable to reserve IRQ %s for device %s\n",
- fore200e_irq_itoa(fore200e->irq), fore200e->name);
- return -EBUSY;
- }
-
- printk(FORE200E "IRQ %s reserved for device %s\n",
- fore200e_irq_itoa(fore200e->irq), fore200e->name);
-
-#ifdef FORE200E_USE_TASKLET
- tasklet_init(&fore200e->tx_tasklet, fore200e_tx_tasklet, (unsigned long)fore200e);
- tasklet_init(&fore200e->rx_tasklet, fore200e_rx_tasklet, (unsigned long)fore200e);
-#endif
-
- fore200e->state = FORE200E_STATE_IRQ;
- return 0;
-}
-
-
-static int fore200e_get_esi(struct fore200e *fore200e)
-{
- struct prom_data* prom = kzalloc_obj(struct prom_data);
- int ok, i;
-
- if (!prom)
- return -ENOMEM;
-
- ok = fore200e->bus->prom_read(fore200e, prom);
- if (ok < 0) {
- kfree(prom);
- return -EBUSY;
- }
-
- printk(FORE200E "device %s, rev. %c, S/N: %d, ESI: %pM\n",
- fore200e->name,
- (prom->hw_revision & 0xFF) + '@', /* probably meaningless with SBA boards */
- prom->serial_number & 0xFFFF, &prom->mac_addr[2]);
-
- for (i = 0; i < ESI_LEN; i++) {
- fore200e->esi[ i ] = fore200e->atm_dev->esi[ i ] = prom->mac_addr[ i + 2 ];
- }
-
- kfree(prom);
-
- return 0;
-}
-
-
-static int fore200e_alloc_rx_buf(struct fore200e *fore200e)
-{
- int scheme, magn, nbr, size, i;
-
- struct host_bsq* bsq;
- struct buffer* buffer;
-
- for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
- for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
-
- bsq = &fore200e->host_bsq[ scheme ][ magn ];
-
- nbr = fore200e_rx_buf_nbr[ scheme ][ magn ];
- size = fore200e_rx_buf_size[ scheme ][ magn ];
-
- DPRINTK(2, "rx buffers %d / %d are being allocated\n", scheme, magn);
-
- /* allocate the array of receive buffers */
- buffer = bsq->buffer = kzalloc_objs(struct buffer, nbr);
-
- if (buffer == NULL)
- return -ENOMEM;
-
- bsq->freebuf = NULL;
-
- for (i = 0; i < nbr; i++) {
-
- buffer[ i ].scheme = scheme;
- buffer[ i ].magn = magn;
-#ifdef FORE200E_BSQ_DEBUG
- buffer[ i ].index = i;
- buffer[ i ].supplied = 0;
-#endif
-
- /* allocate the receive buffer body */
- if (fore200e_chunk_alloc(fore200e,
- &buffer[ i ].data, size, fore200e->bus->buffer_alignment,
- DMA_FROM_DEVICE) < 0) {
-
- while (i > 0)
- fore200e_chunk_free(fore200e, &buffer[ --i ].data);
- kfree(buffer);
-
- return -ENOMEM;
- }
-
- /* insert the buffer into the free buffer list */
- buffer[ i ].next = bsq->freebuf;
- bsq->freebuf = &buffer[ i ];
- }
- /* all the buffers are free, initially */
- bsq->freebuf_count = nbr;
-
-#ifdef FORE200E_BSQ_DEBUG
- bsq_audit(3, bsq, scheme, magn);
-#endif
- }
- }
-
- fore200e->state = FORE200E_STATE_ALLOC_BUF;
- return 0;
-}
-
-
-static int fore200e_init_bs_queue(struct fore200e *fore200e)
-{
- int scheme, magn, i;
-
- struct host_bsq* bsq;
- struct cp_bsq_entry __iomem * cp_entry;
-
- for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
- for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
-
- DPRINTK(2, "buffer supply queue %d / %d is being initialized\n", scheme, magn);
-
- bsq = &fore200e->host_bsq[ scheme ][ magn ];
-
- /* allocate and align the array of status words */
- if (fore200e_dma_chunk_alloc(fore200e,
- &bsq->status,
- sizeof(enum status),
- QUEUE_SIZE_BS,
- fore200e->bus->status_alignment) < 0) {
- return -ENOMEM;
- }
-
- /* allocate and align the array of receive buffer descriptors */
- if (fore200e_dma_chunk_alloc(fore200e,
- &bsq->rbd_block,
- sizeof(struct rbd_block),
- QUEUE_SIZE_BS,
- fore200e->bus->descr_alignment) < 0) {
-
- fore200e_dma_chunk_free(fore200e, &bsq->status);
- return -ENOMEM;
- }
-
- /* get the base address of the cp resident buffer supply queue entries */
- cp_entry = fore200e->virt_base +
- fore200e->bus->read(&fore200e->cp_queues->cp_bsq[ scheme ][ magn ]);
-
- /* fill the host resident and cp resident buffer supply queue entries */
- for (i = 0; i < QUEUE_SIZE_BS; i++) {
-
- bsq->host_entry[ i ].status =
- FORE200E_INDEX(bsq->status.align_addr, enum status, i);
- bsq->host_entry[ i ].rbd_block =
- FORE200E_INDEX(bsq->rbd_block.align_addr, struct rbd_block, i);
- bsq->host_entry[ i ].rbd_block_dma =
- FORE200E_DMA_INDEX(bsq->rbd_block.dma_addr, struct rbd_block, i);
- bsq->host_entry[ i ].cp_entry = &cp_entry[ i ];
-
- *bsq->host_entry[ i ].status = STATUS_FREE;
-
- fore200e->bus->write(FORE200E_DMA_INDEX(bsq->status.dma_addr, enum status, i),
- &cp_entry[ i ].status_haddr);
- }
- }
- }
-
- fore200e->state = FORE200E_STATE_INIT_BSQ;
- return 0;
-}
-
-
-static int fore200e_init_rx_queue(struct fore200e *fore200e)
-{
- struct host_rxq* rxq = &fore200e->host_rxq;
- struct cp_rxq_entry __iomem * cp_entry;
- int i;
-
- DPRINTK(2, "receive queue is being initialized\n");
-
- /* allocate and align the array of status words */
- if (fore200e_dma_chunk_alloc(fore200e,
- &rxq->status,
- sizeof(enum status),
- QUEUE_SIZE_RX,
- fore200e->bus->status_alignment) < 0) {
- return -ENOMEM;
- }
-
- /* allocate and align the array of receive PDU descriptors */
- if (fore200e_dma_chunk_alloc(fore200e,
- &rxq->rpd,
- sizeof(struct rpd),
- QUEUE_SIZE_RX,
- fore200e->bus->descr_alignment) < 0) {
-
- fore200e_dma_chunk_free(fore200e, &rxq->status);
- return -ENOMEM;
- }
-
- /* get the base address of the cp resident rx queue entries */
- cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_rxq);
-
- /* fill the host resident and cp resident rx entries */
- for (i=0; i < QUEUE_SIZE_RX; i++) {
-
- rxq->host_entry[ i ].status =
- FORE200E_INDEX(rxq->status.align_addr, enum status, i);
- rxq->host_entry[ i ].rpd =
- FORE200E_INDEX(rxq->rpd.align_addr, struct rpd, i);
- rxq->host_entry[ i ].rpd_dma =
- FORE200E_DMA_INDEX(rxq->rpd.dma_addr, struct rpd, i);
- rxq->host_entry[ i ].cp_entry = &cp_entry[ i ];
-
- *rxq->host_entry[ i ].status = STATUS_FREE;
-
- fore200e->bus->write(FORE200E_DMA_INDEX(rxq->status.dma_addr, enum status, i),
- &cp_entry[ i ].status_haddr);
-
- fore200e->bus->write(FORE200E_DMA_INDEX(rxq->rpd.dma_addr, struct rpd, i),
- &cp_entry[ i ].rpd_haddr);
- }
-
- /* set the head entry of the queue */
- rxq->head = 0;
-
- fore200e->state = FORE200E_STATE_INIT_RXQ;
- return 0;
-}
-
-
-static int fore200e_init_tx_queue(struct fore200e *fore200e)
-{
- struct host_txq* txq = &fore200e->host_txq;
- struct cp_txq_entry __iomem * cp_entry;
- int i;
-
- DPRINTK(2, "transmit queue is being initialized\n");
-
- /* allocate and align the array of status words */
- if (fore200e_dma_chunk_alloc(fore200e,
- &txq->status,
- sizeof(enum status),
- QUEUE_SIZE_TX,
- fore200e->bus->status_alignment) < 0) {
- return -ENOMEM;
- }
-
- /* allocate and align the array of transmit PDU descriptors */
- if (fore200e_dma_chunk_alloc(fore200e,
- &txq->tpd,
- sizeof(struct tpd),
- QUEUE_SIZE_TX,
- fore200e->bus->descr_alignment) < 0) {
-
- fore200e_dma_chunk_free(fore200e, &txq->status);
- return -ENOMEM;
- }
-
- /* get the base address of the cp resident tx queue entries */
- cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_txq);
-
- /* fill the host resident and cp resident tx entries */
- for (i=0; i < QUEUE_SIZE_TX; i++) {
-
- txq->host_entry[ i ].status =
- FORE200E_INDEX(txq->status.align_addr, enum status, i);
- txq->host_entry[ i ].tpd =
- FORE200E_INDEX(txq->tpd.align_addr, struct tpd, i);
- txq->host_entry[ i ].tpd_dma =
- FORE200E_DMA_INDEX(txq->tpd.dma_addr, struct tpd, i);
- txq->host_entry[ i ].cp_entry = &cp_entry[ i ];
-
- *txq->host_entry[ i ].status = STATUS_FREE;
-
- fore200e->bus->write(FORE200E_DMA_INDEX(txq->status.dma_addr, enum status, i),
- &cp_entry[ i ].status_haddr);
-
- /* although there is a one-to-one mapping of tx queue entries and tpds,
- we do not write here the DMA (physical) base address of each tpd into
- the related cp resident entry, because the cp relies on this write
- operation to detect that a new pdu has been submitted for tx */
- }
-
- /* set the head and tail entries of the queue */
- txq->head = 0;
- txq->tail = 0;
-
- fore200e->state = FORE200E_STATE_INIT_TXQ;
- return 0;
-}
-
-
-static int fore200e_init_cmd_queue(struct fore200e *fore200e)
-{
- struct host_cmdq* cmdq = &fore200e->host_cmdq;
- struct cp_cmdq_entry __iomem * cp_entry;
- int i;
-
- DPRINTK(2, "command queue is being initialized\n");
-
- /* allocate and align the array of status words */
- if (fore200e_dma_chunk_alloc(fore200e,
- &cmdq->status,
- sizeof(enum status),
- QUEUE_SIZE_CMD,
- fore200e->bus->status_alignment) < 0) {
- return -ENOMEM;
- }
-
- /* get the base address of the cp resident cmd queue entries */
- cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_cmdq);
-
- /* fill the host resident and cp resident cmd entries */
- for (i=0; i < QUEUE_SIZE_CMD; i++) {
-
- cmdq->host_entry[ i ].status =
- FORE200E_INDEX(cmdq->status.align_addr, enum status, i);
- cmdq->host_entry[ i ].cp_entry = &cp_entry[ i ];
-
- *cmdq->host_entry[ i ].status = STATUS_FREE;
-
- fore200e->bus->write(FORE200E_DMA_INDEX(cmdq->status.dma_addr, enum status, i),
- &cp_entry[ i ].status_haddr);
- }
-
- /* set the head entry of the queue */
- cmdq->head = 0;
-
- fore200e->state = FORE200E_STATE_INIT_CMDQ;
- return 0;
-}
-
-
-static void fore200e_param_bs_queue(struct fore200e *fore200e,
- enum buffer_scheme scheme,
- enum buffer_magn magn, int queue_length,
- int pool_size, int supply_blksize)
-{
- struct bs_spec __iomem * bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ];
-
- fore200e->bus->write(queue_length, &bs_spec->queue_length);
- fore200e->bus->write(fore200e_rx_buf_size[ scheme ][ magn ], &bs_spec->buffer_size);
- fore200e->bus->write(pool_size, &bs_spec->pool_size);
- fore200e->bus->write(supply_blksize, &bs_spec->supply_blksize);
-}
-
-
-static int fore200e_initialize(struct fore200e *fore200e)
-{
- struct cp_queues __iomem * cpq;
- int ok, scheme, magn;
-
- DPRINTK(2, "device %s being initialized\n", fore200e->name);
-
- mutex_init(&fore200e->rate_mtx);
- spin_lock_init(&fore200e->q_lock);
-
- cpq = fore200e->cp_queues = fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET;
-
- /* enable cp to host interrupts */
- fore200e->bus->write(1, &cpq->imask);
-
- if (fore200e->bus->irq_enable)
- fore200e->bus->irq_enable(fore200e);
-
- fore200e->bus->write(NBR_CONNECT, &cpq->init.num_connect);
-
- fore200e->bus->write(QUEUE_SIZE_CMD, &cpq->init.cmd_queue_len);
- fore200e->bus->write(QUEUE_SIZE_RX, &cpq->init.rx_queue_len);
- fore200e->bus->write(QUEUE_SIZE_TX, &cpq->init.tx_queue_len);
-
- fore200e->bus->write(RSD_EXTENSION, &cpq->init.rsd_extension);
- fore200e->bus->write(TSD_EXTENSION, &cpq->init.tsd_extension);
-
- for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++)
- for (magn = 0; magn < BUFFER_MAGN_NBR; magn++)
- fore200e_param_bs_queue(fore200e, scheme, magn,
- QUEUE_SIZE_BS,
- fore200e_rx_buf_nbr[ scheme ][ magn ],
- RBD_BLK_SIZE);
-
- /* issue the initialize command */
- fore200e->bus->write(STATUS_PENDING, &cpq->init.status);
- fore200e->bus->write(OPCODE_INITIALIZE, &cpq->init.opcode);
-
- ok = fore200e_io_poll(fore200e, &cpq->init.status, STATUS_COMPLETE, 3000);
- if (ok == 0) {
- printk(FORE200E "device %s initialization failed\n", fore200e->name);
- return -ENODEV;
- }
-
- printk(FORE200E "device %s initialized\n", fore200e->name);
-
- fore200e->state = FORE200E_STATE_INITIALIZE;
- return 0;
-}
-
-
-static void fore200e_monitor_putc(struct fore200e *fore200e, char c)
-{
- struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
-
-#if 0
- printk("%c", c);
-#endif
- fore200e->bus->write(((u32) c) | FORE200E_CP_MONITOR_UART_AVAIL, &monitor->soft_uart.send);
-}
-
-
-static int fore200e_monitor_getc(struct fore200e *fore200e)
-{
- struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
- unsigned long timeout = jiffies + msecs_to_jiffies(50);
- int c;
-
- while (time_before(jiffies, timeout)) {
-
- c = (int) fore200e->bus->read(&monitor->soft_uart.recv);
-
- if (c & FORE200E_CP_MONITOR_UART_AVAIL) {
-
- fore200e->bus->write(FORE200E_CP_MONITOR_UART_FREE, &monitor->soft_uart.recv);
-#if 0
- printk("%c", c & 0xFF);
-#endif
- return c & 0xFF;
- }
- }
-
- return -1;
-}
-
-
-static void fore200e_monitor_puts(struct fore200e *fore200e, char *str)
-{
- while (*str) {
-
- /* the i960 monitor doesn't accept any new character if it has something to say */
- while (fore200e_monitor_getc(fore200e) >= 0);
-
- fore200e_monitor_putc(fore200e, *str++);
- }
-
- while (fore200e_monitor_getc(fore200e) >= 0);
-}
-
-#ifdef __LITTLE_ENDIAN
-#define FW_EXT ".bin"
-#else
-#define FW_EXT "_ecd.bin2"
-#endif
-
-static int fore200e_load_and_start_fw(struct fore200e *fore200e)
-{
- const struct firmware *firmware;
- const struct fw_header *fw_header;
- const __le32 *fw_data;
- u32 fw_size;
- u32 __iomem *load_addr;
- char buf[48];
- int err;
-
- sprintf(buf, "%s%s", fore200e->bus->proc_name, FW_EXT);
- if ((err = request_firmware(&firmware, buf, fore200e->dev)) < 0) {
- printk(FORE200E "problem loading firmware image %s\n", fore200e->bus->model_name);
- return err;
- }
-
- fw_data = (const __le32 *)firmware->data;
- fw_size = firmware->size / sizeof(u32);
- fw_header = (const struct fw_header *)firmware->data;
- load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset);
-
- DPRINTK(2, "device %s firmware being loaded at 0x%p (%d words)\n",
- fore200e->name, load_addr, fw_size);
-
- if (le32_to_cpu(fw_header->magic) != FW_HEADER_MAGIC) {
- printk(FORE200E "corrupted %s firmware image\n", fore200e->bus->model_name);
- goto release;
- }
-
- for (; fw_size--; fw_data++, load_addr++)
- fore200e->bus->write(le32_to_cpu(*fw_data), load_addr);
-
- DPRINTK(2, "device %s firmware being started\n", fore200e->name);
-
-#if defined(__sparc_v9__)
- /* reported to be required by SBA cards on some sparc64 hosts */
- fore200e_spin(100);
-#endif
-
- sprintf(buf, "\rgo %x\r", le32_to_cpu(fw_header->start_offset));
- fore200e_monitor_puts(fore200e, buf);
-
- if (fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_CP_RUNNING, 1000) == 0) {
- printk(FORE200E "device %s firmware didn't start\n", fore200e->name);
- goto release;
- }
-
- printk(FORE200E "device %s firmware started\n", fore200e->name);
-
- fore200e->state = FORE200E_STATE_START_FW;
- err = 0;
-
-release:
- release_firmware(firmware);
- return err;
-}
-
-
-static int fore200e_register(struct fore200e *fore200e, struct device *parent)
-{
- struct atm_dev* atm_dev;
-
- DPRINTK(2, "device %s being registered\n", fore200e->name);
-
- atm_dev = atm_dev_register(fore200e->bus->proc_name, parent, &fore200e_ops,
- -1, NULL);
- if (atm_dev == NULL) {
- printk(FORE200E "unable to register device %s\n", fore200e->name);
- return -ENODEV;
- }
-
- atm_dev->dev_data = fore200e;
- fore200e->atm_dev = atm_dev;
-
- atm_dev->ci_range.vpi_bits = FORE200E_VPI_BITS;
- atm_dev->ci_range.vci_bits = FORE200E_VCI_BITS;
-
- fore200e->available_cell_rate = ATM_OC3_PCR;
-
- fore200e->state = FORE200E_STATE_REGISTER;
- return 0;
-}
-
-
-static int fore200e_init(struct fore200e *fore200e, struct device *parent)
-{
- if (fore200e_register(fore200e, parent) < 0)
- return -ENODEV;
-
- if (fore200e->bus->configure(fore200e) < 0)
- return -ENODEV;
-
- if (fore200e->bus->map(fore200e) < 0)
- return -ENODEV;
-
- if (fore200e_reset(fore200e, 1) < 0)
- return -ENODEV;
-
- if (fore200e_load_and_start_fw(fore200e) < 0)
- return -ENODEV;
-
- if (fore200e_initialize(fore200e) < 0)
- return -ENODEV;
-
- if (fore200e_init_cmd_queue(fore200e) < 0)
- return -ENOMEM;
-
- if (fore200e_init_tx_queue(fore200e) < 0)
- return -ENOMEM;
-
- if (fore200e_init_rx_queue(fore200e) < 0)
- return -ENOMEM;
-
- if (fore200e_init_bs_queue(fore200e) < 0)
- return -ENOMEM;
-
- if (fore200e_alloc_rx_buf(fore200e) < 0)
- return -ENOMEM;
-
- if (fore200e_get_esi(fore200e) < 0)
- return -EIO;
-
- if (fore200e_irq_request(fore200e) < 0)
- return -EBUSY;
-
- fore200e_supply(fore200e);
-
- /* all done, board initialization is now complete */
- fore200e->state = FORE200E_STATE_COMPLETE;
- return 0;
-}
-
-#ifdef CONFIG_SBUS
-static int fore200e_sba_probe(struct platform_device *op)
-{
- struct fore200e *fore200e;
- static int index = 0;
- int err;
-
- fore200e = kzalloc_obj(struct fore200e);
- if (!fore200e)
- return -ENOMEM;
-
- fore200e->bus = &fore200e_sbus_ops;
- fore200e->dev = &op->dev;
- fore200e->irq = op->archdata.irqs[0];
- fore200e->phys_base = op->resource[0].start;
-
- sprintf(fore200e->name, "SBA-200E-%d", index);
-
- err = fore200e_init(fore200e, &op->dev);
- if (err < 0) {
- fore200e_shutdown(fore200e);
- kfree(fore200e);
- return err;
- }
-
- index++;
- dev_set_drvdata(&op->dev, fore200e);
-
- return 0;
-}
-
-static void fore200e_sba_remove(struct platform_device *op)
-{
- struct fore200e *fore200e = dev_get_drvdata(&op->dev);
-
- fore200e_shutdown(fore200e);
- kfree(fore200e);
-}
-
-static const struct of_device_id fore200e_sba_match[] = {
- {
- .name = SBA200E_PROM_NAME,
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, fore200e_sba_match);
-
-static struct platform_driver fore200e_sba_driver = {
- .driver = {
- .name = "fore_200e",
- .of_match_table = fore200e_sba_match,
- },
- .probe = fore200e_sba_probe,
- .remove = fore200e_sba_remove,
-};
-#endif
-
-#ifdef CONFIG_PCI
-static int fore200e_pca_detect(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_ent)
-{
- struct fore200e* fore200e;
- int err = 0;
- static int index = 0;
-
- if (pci_enable_device(pci_dev)) {
- err = -EINVAL;
- goto out;
- }
-
- if (dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32))) {
- err = -EINVAL;
- goto out;
- }
-
- fore200e = kzalloc_obj(struct fore200e);
- if (fore200e == NULL) {
- err = -ENOMEM;
- goto out_disable;
- }
-
- fore200e->bus = &fore200e_pci_ops;
- fore200e->dev = &pci_dev->dev;
- fore200e->irq = pci_dev->irq;
- fore200e->phys_base = pci_resource_start(pci_dev, 0);
-
- sprintf(fore200e->name, "PCA-200E-%d", index - 1);
-
- pci_set_master(pci_dev);
-
- printk(FORE200E "device PCA-200E found at 0x%lx, IRQ %s\n",
- fore200e->phys_base, fore200e_irq_itoa(fore200e->irq));
-
- sprintf(fore200e->name, "PCA-200E-%d", index);
-
- err = fore200e_init(fore200e, &pci_dev->dev);
- if (err < 0) {
- fore200e_shutdown(fore200e);
- goto out_free;
- }
-
- ++index;
- pci_set_drvdata(pci_dev, fore200e);
-
-out:
- return err;
-
-out_free:
- kfree(fore200e);
-out_disable:
- pci_disable_device(pci_dev);
- goto out;
-}
-
-
-static void fore200e_pca_remove_one(struct pci_dev *pci_dev)
-{
- struct fore200e *fore200e;
-
- fore200e = pci_get_drvdata(pci_dev);
-
- fore200e_shutdown(fore200e);
- kfree(fore200e);
- pci_disable_device(pci_dev);
-}
-
-
-static const struct pci_device_id fore200e_pca_tbl[] = {
- { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl);
-
-static struct pci_driver fore200e_pca_driver = {
- .name = "fore_200e",
- .probe = fore200e_pca_detect,
- .remove = fore200e_pca_remove_one,
- .id_table = fore200e_pca_tbl,
-};
-#endif
-
-static int __init fore200e_module_init(void)
-{
- int err = 0;
-
- printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
-
-#ifdef CONFIG_SBUS
- err = platform_driver_register(&fore200e_sba_driver);
- if (err)
- return err;
-#endif
-
-#ifdef CONFIG_PCI
- err = pci_register_driver(&fore200e_pca_driver);
-#endif
-
-#ifdef CONFIG_SBUS
- if (err)
- platform_driver_unregister(&fore200e_sba_driver);
-#endif
-
- return err;
-}
-
-static void __exit fore200e_module_cleanup(void)
-{
-#ifdef CONFIG_PCI
- pci_unregister_driver(&fore200e_pca_driver);
-#endif
-#ifdef CONFIG_SBUS
- platform_driver_unregister(&fore200e_sba_driver);
-#endif
-}
-
-static int
-fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
-{
- struct fore200e* fore200e = FORE200E_DEV(dev);
- struct fore200e_vcc* fore200e_vcc;
- struct atm_vcc* vcc;
- int i, len, left = *pos;
- unsigned long flags;
-
- if (!left--) {
-
- if (fore200e_getstats(fore200e) < 0)
- return -EIO;
-
- len = sprintf(page,"\n"
- " device:\n"
- " internal name:\t\t%s\n", fore200e->name);
-
- /* print bus-specific information */
- if (fore200e->bus->proc_read)
- len += fore200e->bus->proc_read(fore200e, page + len);
-
- len += sprintf(page + len,
- " interrupt line:\t\t%s\n"
- " physical base address:\t0x%p\n"
- " virtual base address:\t0x%p\n"
- " factory address (ESI):\t%pM\n"
- " board serial number:\t\t%d\n\n",
- fore200e_irq_itoa(fore200e->irq),
- (void*)fore200e->phys_base,
- fore200e->virt_base,
- fore200e->esi,
- fore200e->esi[4] * 256 + fore200e->esi[5]);
-
- return len;
- }
-
- if (!left--)
- return sprintf(page,
- " free small bufs, scheme 1:\t%d\n"
- " free large bufs, scheme 1:\t%d\n"
- " free small bufs, scheme 2:\t%d\n"
- " free large bufs, scheme 2:\t%d\n",
- fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_SMALL ].freebuf_count,
- fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_LARGE ].freebuf_count,
- fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_SMALL ].freebuf_count,
- fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_LARGE ].freebuf_count);
-
- if (!left--) {
- u32 hb = fore200e->bus->read(&fore200e->cp_queues->heartbeat);
-
- len = sprintf(page,"\n\n"
- " cell processor:\n"
- " heartbeat state:\t\t");
-
- if (hb >> 16 != 0xDEAD)
- len += sprintf(page + len, "0x%08x\n", hb);
- else
- len += sprintf(page + len, "*** FATAL ERROR %04x ***\n", hb & 0xFFFF);
-
- return len;
- }
-
- if (!left--) {
- static const char* media_name[] = {
- "unshielded twisted pair",
- "multimode optical fiber ST",
- "multimode optical fiber SC",
- "single-mode optical fiber ST",
- "single-mode optical fiber SC",
- "unknown"
- };
-
- static const char* oc3_mode[] = {
- "normal operation",
- "diagnostic loopback",
- "line loopback",
- "unknown"
- };
-
- u32 fw_release = fore200e->bus->read(&fore200e->cp_queues->fw_release);
- u32 mon960_release = fore200e->bus->read(&fore200e->cp_queues->mon960_release);
- u32 oc3_revision = fore200e->bus->read(&fore200e->cp_queues->oc3_revision);
- u32 media_index = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type));
- u32 oc3_index;
-
- if (media_index > 4)
- media_index = 5;
-
- switch (fore200e->loop_mode) {
- case ATM_LM_NONE: oc3_index = 0;
- break;
- case ATM_LM_LOC_PHY: oc3_index = 1;
- break;
- case ATM_LM_RMT_PHY: oc3_index = 2;
- break;
- default: oc3_index = 3;
- }
-
- return sprintf(page,
- " firmware release:\t\t%d.%d.%d\n"
- " monitor release:\t\t%d.%d\n"
- " media type:\t\t\t%s\n"
- " OC-3 revision:\t\t0x%x\n"
- " OC-3 mode:\t\t\t%s",
- fw_release >> 16, fw_release << 16 >> 24, fw_release << 24 >> 24,
- mon960_release >> 16, mon960_release << 16 >> 16,
- media_name[ media_index ],
- oc3_revision,
- oc3_mode[ oc3_index ]);
- }
-
- if (!left--) {
- struct cp_monitor __iomem * cp_monitor = fore200e->cp_monitor;
-
- return sprintf(page,
- "\n\n"
- " monitor:\n"
- " version number:\t\t%d\n"
- " boot status word:\t\t0x%08x\n",
- fore200e->bus->read(&cp_monitor->mon_version),
- fore200e->bus->read(&cp_monitor->bstat));
- }
-
- if (!left--)
- return sprintf(page,
- "\n"
- " device statistics:\n"
- " 4b5b:\n"
- " crc_header_errors:\t\t%10u\n"
- " framing_errors:\t\t%10u\n",
- be32_to_cpu(fore200e->stats->phy.crc_header_errors),
- be32_to_cpu(fore200e->stats->phy.framing_errors));
-
- if (!left--)
- return sprintf(page, "\n"
- " OC-3:\n"
- " section_bip8_errors:\t%10u\n"
- " path_bip8_errors:\t\t%10u\n"
- " line_bip24_errors:\t\t%10u\n"
- " line_febe_errors:\t\t%10u\n"
- " path_febe_errors:\t\t%10u\n"
- " corr_hcs_errors:\t\t%10u\n"
- " ucorr_hcs_errors:\t\t%10u\n",
- be32_to_cpu(fore200e->stats->oc3.section_bip8_errors),
- be32_to_cpu(fore200e->stats->oc3.path_bip8_errors),
- be32_to_cpu(fore200e->stats->oc3.line_bip24_errors),
- be32_to_cpu(fore200e->stats->oc3.line_febe_errors),
- be32_to_cpu(fore200e->stats->oc3.path_febe_errors),
- be32_to_cpu(fore200e->stats->oc3.corr_hcs_errors),
- be32_to_cpu(fore200e->stats->oc3.ucorr_hcs_errors));
-
- if (!left--)
- return sprintf(page,"\n"
- " ATM:\t\t\t\t cells\n"
- " TX:\t\t\t%10u\n"
- " RX:\t\t\t%10u\n"
- " vpi out of range:\t\t%10u\n"
- " vpi no conn:\t\t%10u\n"
- " vci out of range:\t\t%10u\n"
- " vci no conn:\t\t%10u\n",
- be32_to_cpu(fore200e->stats->atm.cells_transmitted),
- be32_to_cpu(fore200e->stats->atm.cells_received),
- be32_to_cpu(fore200e->stats->atm.vpi_bad_range),
- be32_to_cpu(fore200e->stats->atm.vpi_no_conn),
- be32_to_cpu(fore200e->stats->atm.vci_bad_range),
- be32_to_cpu(fore200e->stats->atm.vci_no_conn));
-
- if (!left--)
- return sprintf(page,"\n"
- " AAL0:\t\t\t cells\n"
- " TX:\t\t\t%10u\n"
- " RX:\t\t\t%10u\n"
- " dropped:\t\t\t%10u\n",
- be32_to_cpu(fore200e->stats->aal0.cells_transmitted),
- be32_to_cpu(fore200e->stats->aal0.cells_received),
- be32_to_cpu(fore200e->stats->aal0.cells_dropped));
-
- if (!left--)
- return sprintf(page,"\n"
- " AAL3/4:\n"
- " SAR sublayer:\t\t cells\n"
- " TX:\t\t\t%10u\n"
- " RX:\t\t\t%10u\n"
- " dropped:\t\t\t%10u\n"
- " CRC errors:\t\t%10u\n"
- " protocol errors:\t\t%10u\n\n"
- " CS sublayer:\t\t PDUs\n"
- " TX:\t\t\t%10u\n"
- " RX:\t\t\t%10u\n"
- " dropped:\t\t\t%10u\n"
- " protocol errors:\t\t%10u\n",
- be32_to_cpu(fore200e->stats->aal34.cells_transmitted),
- be32_to_cpu(fore200e->stats->aal34.cells_received),
- be32_to_cpu(fore200e->stats->aal34.cells_dropped),
- be32_to_cpu(fore200e->stats->aal34.cells_crc_errors),
- be32_to_cpu(fore200e->stats->aal34.cells_protocol_errors),
- be32_to_cpu(fore200e->stats->aal34.cspdus_transmitted),
- be32_to_cpu(fore200e->stats->aal34.cspdus_received),
- be32_to_cpu(fore200e->stats->aal34.cspdus_dropped),
- be32_to_cpu(fore200e->stats->aal34.cspdus_protocol_errors));
-
- if (!left--)
- return sprintf(page,"\n"
- " AAL5:\n"
- " SAR sublayer:\t\t cells\n"
- " TX:\t\t\t%10u\n"
- " RX:\t\t\t%10u\n"
- " dropped:\t\t\t%10u\n"
- " congestions:\t\t%10u\n\n"
- " CS sublayer:\t\t PDUs\n"
- " TX:\t\t\t%10u\n"
- " RX:\t\t\t%10u\n"
- " dropped:\t\t\t%10u\n"
- " CRC errors:\t\t%10u\n"
- " protocol errors:\t\t%10u\n",
- be32_to_cpu(fore200e->stats->aal5.cells_transmitted),
- be32_to_cpu(fore200e->stats->aal5.cells_received),
- be32_to_cpu(fore200e->stats->aal5.cells_dropped),
- be32_to_cpu(fore200e->stats->aal5.congestion_experienced),
- be32_to_cpu(fore200e->stats->aal5.cspdus_transmitted),
- be32_to_cpu(fore200e->stats->aal5.cspdus_received),
- be32_to_cpu(fore200e->stats->aal5.cspdus_dropped),
- be32_to_cpu(fore200e->stats->aal5.cspdus_crc_errors),
- be32_to_cpu(fore200e->stats->aal5.cspdus_protocol_errors));
-
- if (!left--)
- return sprintf(page,"\n"
- " AUX:\t\t allocation failures\n"
- " small b1:\t\t\t%10u\n"
- " large b1:\t\t\t%10u\n"
- " small b2:\t\t\t%10u\n"
- " large b2:\t\t\t%10u\n"
- " RX PDUs:\t\t\t%10u\n"
- " TX PDUs:\t\t\t%10lu\n",
- be32_to_cpu(fore200e->stats->aux.small_b1_failed),
- be32_to_cpu(fore200e->stats->aux.large_b1_failed),
- be32_to_cpu(fore200e->stats->aux.small_b2_failed),
- be32_to_cpu(fore200e->stats->aux.large_b2_failed),
- be32_to_cpu(fore200e->stats->aux.rpd_alloc_failed),
- fore200e->tx_sat);
-
- if (!left--)
- return sprintf(page,"\n"
- " receive carrier:\t\t\t%s\n",
- fore200e->stats->aux.receive_carrier ? "ON" : "OFF!");
-
- if (!left--) {
- return sprintf(page,"\n"
- " VCCs:\n address VPI VCI AAL "
- "TX PDUs TX min/max size RX PDUs RX min/max size\n");
- }
-
- for (i = 0; i < NBR_CONNECT; i++) {
-
- vcc = fore200e->vc_map[i].vcc;
-
- if (vcc == NULL)
- continue;
-
- spin_lock_irqsave(&fore200e->q_lock, flags);
-
- if (vcc && test_bit(ATM_VF_READY, &vcc->flags) && !left--) {
-
- fore200e_vcc = FORE200E_VCC(vcc);
- ASSERT(fore200e_vcc);
-
- len = sprintf(page,
- " %pK %03d %05d %1d %09lu %05d/%05d %09lu %05d/%05d\n",
- vcc,
- vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
- fore200e_vcc->tx_pdu,
- fore200e_vcc->tx_min_pdu > 0xFFFF ? 0 : fore200e_vcc->tx_min_pdu,
- fore200e_vcc->tx_max_pdu,
- fore200e_vcc->rx_pdu,
- fore200e_vcc->rx_min_pdu > 0xFFFF ? 0 : fore200e_vcc->rx_min_pdu,
- fore200e_vcc->rx_max_pdu);
-
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
- return len;
- }
-
- spin_unlock_irqrestore(&fore200e->q_lock, flags);
- }
-
- return 0;
-}
-
-module_init(fore200e_module_init);
-module_exit(fore200e_module_cleanup);
-
-
-static const struct atmdev_ops fore200e_ops = {
- .open = fore200e_open,
- .close = fore200e_close,
- .ioctl = fore200e_ioctl,
- .send = fore200e_send,
- .change_qos = fore200e_change_qos,
- .proc_read = fore200e_proc_read,
- .owner = THIS_MODULE
-};
-
-MODULE_LICENSE("GPL");
-#ifdef CONFIG_PCI
-#ifdef __LITTLE_ENDIAN__
-MODULE_FIRMWARE("pca200e.bin");
-#else
-MODULE_FIRMWARE("pca200e_ecd.bin2");
-#endif
-#endif /* CONFIG_PCI */
-#ifdef CONFIG_SBUS
-MODULE_FIRMWARE("sba200e_ecd.bin2");
-#endif
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
deleted file mode 100644
index bb9cb00f9585..000000000000
--- a/drivers/atm/he.c
+++ /dev/null
@@ -1,2861 +0,0 @@
-/*
-
- he.c
-
- ForeRunnerHE ATM Adapter driver for ATM on Linux
- Copyright (C) 1999-2001 Naval Research Laboratory
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-/*
-
- he.c
-
- ForeRunnerHE ATM Adapter driver for ATM on Linux
- Copyright (C) 1999-2001 Naval Research Laboratory
-
- Permission to use, copy, modify and distribute this software and its
- documentation is hereby granted, provided that both the copyright
- notice and this permission notice appear in all copies of the software,
- derivative works or modified versions, and any portions thereof, and
- that both notices appear in supporting documentation.
-
- NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
- DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
- RESULTING FROM THE USE OF THIS SOFTWARE.
-
- This driver was written using the "Programmer's Reference Manual for
- ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98.
-
- AUTHORS:
- chas williams <chas@cmf.nrl.navy.mil>
- eric kinzie <ekinzie@cmf.nrl.navy.mil>
-
- NOTES:
- 4096 supported 'connections'
- group 0 is used for all traffic
- interrupt queue 0 is used for all interrupts
- aal0 support (based on work from ulrich.u.muller@nokia.com)
-
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/bitmap.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <linux/uaccess.h>
-
-#include <linux/atmdev.h>
-#include <linux/atm.h>
-#include <linux/sonet.h>
-
-#undef USE_SCATTERGATHER
-#undef USE_CHECKSUM_HW /* still confused about this */
-/* #undef HE_DEBUG */
-
-#include "he.h"
-#include "suni.h"
-#include <linux/atm_he.h>
-
-#define hprintk(fmt,args...) printk(KERN_ERR DEV_LABEL "%d: " fmt, he_dev->number , ##args)
-
-#ifdef HE_DEBUG
-#define HPRINTK(fmt,args...) printk(KERN_DEBUG DEV_LABEL "%d: " fmt, he_dev->number , ##args)
-#else /* !HE_DEBUG */
-#define HPRINTK(fmt,args...) do { } while (0)
-#endif /* HE_DEBUG */
-
-/* declarations */
-
-static int he_open(struct atm_vcc *vcc);
-static void he_close(struct atm_vcc *vcc);
-static int he_send(struct atm_vcc *vcc, struct sk_buff *skb);
-static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg);
-static irqreturn_t he_irq_handler(int irq, void *dev_id);
-static void he_tasklet(unsigned long data);
-static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
-static int he_start(struct atm_dev *dev);
-static void he_stop(struct he_dev *dev);
-static void he_phy_put(struct atm_dev *, unsigned char, unsigned long);
-static unsigned char he_phy_get(struct atm_dev *, unsigned long);
-
-static u8 read_prom_byte(struct he_dev *he_dev, int addr);
-
-/* globals */
-
-static struct he_dev *he_devs;
-static bool disable64;
-static short nvpibits = -1;
-static short nvcibits = -1;
-static short rx_skb_reserve = 16;
-static bool irq_coalesce = true;
-static bool sdh;
-
-/* Read from EEPROM = 0000 0011b */
-static unsigned int readtab[] = {
- CS_HIGH | CLK_HIGH,
- CS_LOW | CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW | SI_HIGH,
- CLK_HIGH | SI_HIGH, /* 1 */
- CLK_LOW | SI_HIGH,
- CLK_HIGH | SI_HIGH /* 1 */
-};
-
-/* Clock to read from/write to the EEPROM */
-static unsigned int clocktab[] = {
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW
-};
-
-static const struct atmdev_ops he_ops =
-{
- .open = he_open,
- .close = he_close,
- .ioctl = he_ioctl,
- .send = he_send,
- .phy_put = he_phy_put,
- .phy_get = he_phy_get,
- .proc_read = he_proc_read,
- .owner = THIS_MODULE
-};
-
-#define he_writel(dev, val, reg) do { writel(val, (dev)->membase + (reg)); wmb(); } while (0)
-#define he_readl(dev, reg) readl((dev)->membase + (reg))
-
-/* section 2.12 connection memory access */
-
-static __inline__ void
-he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr,
- unsigned flags)
-{
- he_writel(he_dev, val, CON_DAT);
- (void) he_readl(he_dev, CON_DAT); /* flush posted writes */
- he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL);
- while (he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
-}
-
-#define he_writel_rcm(dev, val, reg) \
- he_writel_internal(dev, val, reg, CON_CTL_RCM)
-
-#define he_writel_tcm(dev, val, reg) \
- he_writel_internal(dev, val, reg, CON_CTL_TCM)
-
-#define he_writel_mbox(dev, val, reg) \
- he_writel_internal(dev, val, reg, CON_CTL_MBOX)
-
-static unsigned
-he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
-{
- he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL);
- while (he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
- return he_readl(he_dev, CON_DAT);
-}
-
-#define he_readl_rcm(dev, reg) \
- he_readl_internal(dev, reg, CON_CTL_RCM)
-
-#define he_readl_tcm(dev, reg) \
- he_readl_internal(dev, reg, CON_CTL_TCM)
-
-#define he_readl_mbox(dev, reg) \
- he_readl_internal(dev, reg, CON_CTL_MBOX)
-
-
-/* figure 2.2 connection id */
-
-#define he_mkcid(dev, vpi, vci) (((vpi << (dev)->vcibits) | vci) & 0x1fff)
-
-/* 2.5.1 per connection transmit state registers */
-
-#define he_writel_tsr0(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 0)
-#define he_readl_tsr0(dev, cid) \
- he_readl_tcm(dev, CONFIG_TSRA | (cid << 3) | 0)
-
-#define he_writel_tsr1(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 1)
-
-#define he_writel_tsr2(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 2)
-
-#define he_writel_tsr3(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 3)
-
-#define he_writel_tsr4(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 4)
-
- /* from page 2-20
- *
- * NOTE While the transmit connection is active, bits 23 through 0
- * of this register must not be written by the host. Byte
- * enables should be used during normal operation when writing
- * the most significant byte.
- */
-
-#define he_writel_tsr4_upper(dev, val, cid) \
- he_writel_internal(dev, val, CONFIG_TSRA | (cid << 3) | 4, \
- CON_CTL_TCM \
- | CON_BYTE_DISABLE_2 \
- | CON_BYTE_DISABLE_1 \
- | CON_BYTE_DISABLE_0)
-
-#define he_readl_tsr4(dev, cid) \
- he_readl_tcm(dev, CONFIG_TSRA | (cid << 3) | 4)
-
-#define he_writel_tsr5(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 5)
-
-#define he_writel_tsr6(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 6)
-
-#define he_writel_tsr7(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 7)
-
-
-#define he_writel_tsr8(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 0)
-
-#define he_writel_tsr9(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 1)
-
-#define he_writel_tsr10(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 2)
-
-#define he_writel_tsr11(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 3)
-
-
-#define he_writel_tsr12(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRC | (cid << 1) | 0)
-
-#define he_writel_tsr13(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRC | (cid << 1) | 1)
-
-
-#define he_writel_tsr14(dev, val, cid) \
- he_writel_tcm(dev, val, CONFIG_TSRD | cid)
-
-#define he_writel_tsr14_upper(dev, val, cid) \
- he_writel_internal(dev, val, CONFIG_TSRD | cid, \
- CON_CTL_TCM \
- | CON_BYTE_DISABLE_2 \
- | CON_BYTE_DISABLE_1 \
- | CON_BYTE_DISABLE_0)
-
-/* 2.7.1 per connection receive state registers */
-
-#define he_writel_rsr0(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 0)
-#define he_readl_rsr0(dev, cid) \
- he_readl_rcm(dev, 0x00000 | (cid << 3) | 0)
-
-#define he_writel_rsr1(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 1)
-
-#define he_writel_rsr2(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 2)
-
-#define he_writel_rsr3(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 3)
-
-#define he_writel_rsr4(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 4)
-
-#define he_writel_rsr5(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 5)
-
-#define he_writel_rsr6(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 6)
-
-#define he_writel_rsr7(dev, val, cid) \
- he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 7)
-
-static __inline__ struct atm_vcc*
-__find_vcc(struct he_dev *he_dev, unsigned cid)
-{
- struct hlist_head *head;
- struct atm_vcc *vcc;
- struct sock *s;
- short vpi;
- int vci;
-
- vpi = cid >> he_dev->vcibits;
- vci = cid & ((1 << he_dev->vcibits) - 1);
- head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
-
- sk_for_each(s, head) {
- vcc = atm_sk(s);
- if (vcc->dev == he_dev->atm_dev &&
- vcc->vci == vci && vcc->vpi == vpi &&
- vcc->qos.rxtp.traffic_class != ATM_NONE) {
- return vcc;
- }
- }
- return NULL;
-}
-
-static int he_init_one(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_ent)
-{
- struct atm_dev *atm_dev = NULL;
- struct he_dev *he_dev = NULL;
- int err = 0;
-
- printk(KERN_INFO "ATM he driver\n");
-
- if (pci_enable_device(pci_dev))
- return -EIO;
- if (dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32)) != 0) {
- printk(KERN_WARNING "he: no suitable dma available\n");
- err = -EIO;
- goto init_one_failure;
- }
-
- atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &he_ops, -1, NULL);
- if (!atm_dev) {
- err = -ENODEV;
- goto init_one_failure;
- }
- pci_set_drvdata(pci_dev, atm_dev);
-
- he_dev = kzalloc_obj(struct he_dev);
- if (!he_dev) {
- err = -ENOMEM;
- goto init_one_failure;
- }
- he_dev->pci_dev = pci_dev;
- he_dev->atm_dev = atm_dev;
- he_dev->atm_dev->dev_data = he_dev;
- atm_dev->dev_data = he_dev;
- he_dev->number = atm_dev->number;
- tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
- spin_lock_init(&he_dev->global_lock);
-
- if (he_start(atm_dev)) {
- he_stop(he_dev);
- err = -ENODEV;
- goto init_one_failure;
- }
- he_dev->next = NULL;
- if (he_devs)
- he_dev->next = he_devs;
- he_devs = he_dev;
- return 0;
-
-init_one_failure:
- if (atm_dev)
- atm_dev_deregister(atm_dev);
- kfree(he_dev);
- pci_disable_device(pci_dev);
- return err;
-}
-
-static void he_remove_one(struct pci_dev *pci_dev)
-{
- struct atm_dev *atm_dev;
- struct he_dev *he_dev;
-
- atm_dev = pci_get_drvdata(pci_dev);
- he_dev = HE_DEV(atm_dev);
-
- /* need to remove from he_devs */
-
- he_stop(he_dev);
- atm_dev_deregister(atm_dev);
- kfree(he_dev);
-
- pci_disable_device(pci_dev);
-}
-
-
-static unsigned
-rate_to_atmf(unsigned rate) /* cps to atm forum format */
-{
-#define NONZERO (1 << 14)
-
- unsigned exp = 0;
-
- if (rate == 0)
- return 0;
-
- rate <<= 9;
- while (rate > 0x3ff) {
- ++exp;
- rate >>= 1;
- }
-
- return (NONZERO | (exp << 9) | (rate & 0x1ff));
-}
-
-static void he_init_rx_lbfp0(struct he_dev *he_dev)
-{
- unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
- unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
- unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
- unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row;
-
- lbufd_index = 0;
- lbm_offset = he_readl(he_dev, RCMLBM_BA);
-
- he_writel(he_dev, lbufd_index, RLBF0_H);
-
- for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i) {
- lbufd_index += 2;
- lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
-
- he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
- he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
-
- if (++lbuf_count == lbufs_per_row) {
- lbuf_count = 0;
- row_offset += he_dev->bytes_per_row;
- }
- lbm_offset += 4;
- }
-
- he_writel(he_dev, lbufd_index - 2, RLBF0_T);
- he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
-}
-
-static void he_init_rx_lbfp1(struct he_dev *he_dev)
-{
- unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
- unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
- unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
- unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row;
-
- lbufd_index = 1;
- lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
-
- he_writel(he_dev, lbufd_index, RLBF1_H);
-
- for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i) {
- lbufd_index += 2;
- lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
-
- he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
- he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
-
- if (++lbuf_count == lbufs_per_row) {
- lbuf_count = 0;
- row_offset += he_dev->bytes_per_row;
- }
- lbm_offset += 4;
- }
-
- he_writel(he_dev, lbufd_index - 2, RLBF1_T);
- he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
-}
-
-static void he_init_tx_lbfp(struct he_dev *he_dev)
-{
- unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
- unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
- unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
- unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row;
-
- lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs;
- lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
-
- he_writel(he_dev, lbufd_index, TLBF_H);
-
- for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i) {
- lbufd_index += 1;
- lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
-
- he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
- he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
-
- if (++lbuf_count == lbufs_per_row) {
- lbuf_count = 0;
- row_offset += he_dev->bytes_per_row;
- }
- lbm_offset += 2;
- }
-
- he_writel(he_dev, lbufd_index - 1, TLBF_T);
-}
-
-static int he_init_tpdrq(struct he_dev *he_dev)
-{
- he_dev->tpdrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
- &he_dev->tpdrq_phys,
- GFP_KERNEL);
- if (he_dev->tpdrq_base == NULL) {
- hprintk("failed to alloc tpdrq\n");
- return -ENOMEM;
- }
-
- he_dev->tpdrq_tail = he_dev->tpdrq_base;
- he_dev->tpdrq_head = he_dev->tpdrq_base;
-
- he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H);
- he_writel(he_dev, 0, TPDRQ_T);
- he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S);
-
- return 0;
-}
-
-static void he_init_cs_block(struct he_dev *he_dev)
-{
- unsigned clock, rate, delta;
- int reg;
-
- /* 5.1.7 cs block initialization */
-
- for (reg = 0; reg < 0x20; ++reg)
- he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg);
-
- /* rate grid timer reload values */
-
- clock = he_is622(he_dev) ? 66667000 : 50000000;
- rate = he_dev->atm_dev->link_rate;
- delta = rate / 16 / 2;
-
- for (reg = 0; reg < 0x10; ++reg) {
- /* 2.4 internal transmit function
- *
- * we initialize the first row in the rate grid.
- * values are period (in clock cycles) of timer
- */
- unsigned period = clock / rate;
-
- he_writel_mbox(he_dev, period, CS_TGRLD0 + reg);
- rate -= delta;
- }
-
- if (he_is622(he_dev)) {
- /* table 5.2 (4 cells per lbuf) */
- he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0);
- he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1);
- he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2);
- he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3);
- he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4);
-
- /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
- he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0);
- he_writel_mbox(he_dev, 0x1801, CS_ERCTL1);
- he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2);
- he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
- he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1);
- he_writel_mbox(he_dev, 0x14585, CS_RTFWR);
-
- he_writel_mbox(he_dev, 0x4680, CS_RTATR);
-
- /* table 5.8 */
- he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET);
- he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX);
- he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN);
- he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC);
- he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC);
- he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL);
-
- /* table 5.9 */
- he_writel_mbox(he_dev, 0x5, CS_OTPPER);
- he_writel_mbox(he_dev, 0x14, CS_OTWPER);
- } else {
- /* table 5.1 (4 cells per lbuf) */
- he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0);
- he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1);
- he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2);
- he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3);
- he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4);
-
- /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
- he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0);
- he_writel_mbox(he_dev, 0x4701, CS_ERCTL1);
- he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2);
- he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
- he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1);
- he_writel_mbox(he_dev, 0xf424, CS_RTFWR);
-
- he_writel_mbox(he_dev, 0x4680, CS_RTATR);
-
- /* table 5.8 */
- he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET);
- he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX);
- he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN);
- he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC);
- he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC);
- he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL);
-
- /* table 5.9 */
- he_writel_mbox(he_dev, 0x6, CS_OTPPER);
- he_writel_mbox(he_dev, 0x1e, CS_OTWPER);
- }
-
- he_writel_mbox(he_dev, 0x8, CS_OTTLIM);
-
- for (reg = 0; reg < 0x8; ++reg)
- he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg);
-
-}
-
-static int he_init_cs_block_rcm(struct he_dev *he_dev)
-{
- unsigned (*rategrid)[16][16];
- unsigned rate, delta;
- int i, j, reg;
-
- unsigned rate_atmf, exp, man;
- unsigned long long rate_cps;
- int mult, buf, buf_limit = 4;
-
- rategrid = kmalloc( sizeof(unsigned) * 16 * 16, GFP_KERNEL);
- if (!rategrid)
- return -ENOMEM;
-
- /* initialize rate grid group table */
-
- for (reg = 0x0; reg < 0xff; ++reg)
- he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
-
- /* initialize rate controller groups */
-
- for (reg = 0x100; reg < 0x1ff; ++reg)
- he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
-
- /* initialize tNrm lookup table */
-
- /* the manual makes reference to a routine in a sample driver
- for proper configuration; fortunately, we only need this
- in order to support abr connection */
-
- /* initialize rate to group table */
-
- rate = he_dev->atm_dev->link_rate;
- delta = rate / 32;
-
- /*
- * 2.4 transmit internal functions
- *
- * we construct a copy of the rate grid used by the scheduler
- * in order to construct the rate to group table below
- */
-
- for (j = 0; j < 16; j++) {
- (*rategrid)[0][j] = rate;
- rate -= delta;
- }
-
- for (i = 1; i < 16; i++)
- for (j = 0; j < 16; j++)
- if (i > 14)
- (*rategrid)[i][j] = (*rategrid)[i - 1][j] / 4;
- else
- (*rategrid)[i][j] = (*rategrid)[i - 1][j] / 2;
-
- /*
- * 2.4 transmit internal function
- *
- * this table maps the upper 5 bits of exponent and mantissa
- * of the atm forum representation of the rate into an index
- * on rate grid
- */
-
- rate_atmf = 0;
- while (rate_atmf < 0x400) {
- man = (rate_atmf & 0x1f) << 4;
- exp = rate_atmf >> 5;
-
- /*
- instead of '/ 512', use '>> 9' to prevent a call
- to divdu3 on x86 platforms
- */
- rate_cps = (unsigned long long) (1UL << exp) * (man + 512) >> 9;
-
- if (rate_cps < 10)
- rate_cps = 10; /* 2.2.1 minimum payload rate is 10 cps */
-
- for (i = 255; i > 0; i--)
- if ((*rategrid)[i/16][i%16] >= rate_cps)
- break; /* pick nearest rate instead? */
-
- /*
- * each table entry is 16 bits: (rate grid index (8 bits)
- * and a buffer limit (8 bits)
- * there are two table entries in each 32-bit register
- */
-
-#ifdef notdef
- buf = rate_cps * he_dev->tx_numbuffs /
- (he_dev->atm_dev->link_rate * 2);
-#else
- /* this is pretty, but avoids _divdu3 and is mostly correct */
- mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR;
- if (rate_cps > (272ULL * mult))
- buf = 4;
- else if (rate_cps > (204ULL * mult))
- buf = 3;
- else if (rate_cps > (136ULL * mult))
- buf = 2;
- else if (rate_cps > (68ULL * mult))
- buf = 1;
- else
- buf = 0;
-#endif
- if (buf > buf_limit)
- buf = buf_limit;
- reg = (reg << 16) | ((i << 8) | buf);
-
-#define RTGTBL_OFFSET 0x400
-
- if (rate_atmf & 0x1)
- he_writel_rcm(he_dev, reg,
- CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf >> 1));
-
- ++rate_atmf;
- }
-
- kfree(rategrid);
- return 0;
-}
-
-static int he_init_group(struct he_dev *he_dev, int group)
-{
- struct he_buff *heb, *next;
- dma_addr_t mapping;
- int i;
-
- he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
- he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
- he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
- he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
- G0_RBPS_BS + (group * 32));
-
- /* bitmap table */
- he_dev->rbpl_table = bitmap_zalloc(RBPL_TABLE_SIZE, GFP_KERNEL);
- if (!he_dev->rbpl_table) {
- hprintk("unable to allocate rbpl bitmap table\n");
- return -ENOMEM;
- }
-
- /* rbpl_virt 64-bit pointers */
- he_dev->rbpl_virt = kmalloc_objs(*he_dev->rbpl_virt, RBPL_TABLE_SIZE);
- if (!he_dev->rbpl_virt) {
- hprintk("unable to allocate rbpl virt table\n");
- goto out_free_rbpl_table;
- }
-
- /* large buffer pool */
- he_dev->rbpl_pool = dma_pool_create("rbpl", &he_dev->pci_dev->dev,
- CONFIG_RBPL_BUFSIZE, 64, 0);
- if (he_dev->rbpl_pool == NULL) {
- hprintk("unable to create rbpl pool\n");
- goto out_free_rbpl_virt;
- }
-
- he_dev->rbpl_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
- &he_dev->rbpl_phys, GFP_KERNEL);
- if (he_dev->rbpl_base == NULL) {
- hprintk("failed to alloc rbpl_base\n");
- goto out_destroy_rbpl_pool;
- }
-
- INIT_LIST_HEAD(&he_dev->rbpl_outstanding);
-
- for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
-
- heb = dma_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL, &mapping);
- if (!heb)
- goto out_free_rbpl;
- heb->mapping = mapping;
- list_add(&heb->entry, &he_dev->rbpl_outstanding);
-
- set_bit(i, he_dev->rbpl_table);
- he_dev->rbpl_virt[i] = heb;
- he_dev->rbpl_hint = i + 1;
- he_dev->rbpl_base[i].idx = i << RBP_IDX_OFFSET;
- he_dev->rbpl_base[i].phys = mapping + offsetof(struct he_buff, data);
- }
- he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE - 1];
-
- he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32));
- he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail),
- G0_RBPL_T + (group * 32));
- he_writel(he_dev, (CONFIG_RBPL_BUFSIZE - sizeof(struct he_buff))/4,
- G0_RBPL_BS + (group * 32));
- he_writel(he_dev,
- RBP_THRESH(CONFIG_RBPL_THRESH) |
- RBP_QSIZE(CONFIG_RBPL_SIZE - 1) |
- RBP_INT_ENB,
- G0_RBPL_QI + (group * 32));
-
- /* rx buffer ready queue */
-
- he_dev->rbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
- &he_dev->rbrq_phys, GFP_KERNEL);
- if (he_dev->rbrq_base == NULL) {
- hprintk("failed to allocate rbrq\n");
- goto out_free_rbpl;
- }
-
- he_dev->rbrq_head = he_dev->rbrq_base;
- he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16));
- he_writel(he_dev, 0, G0_RBRQ_H + (group * 16));
- he_writel(he_dev,
- RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE - 1),
- G0_RBRQ_Q + (group * 16));
- if (irq_coalesce) {
- hprintk("coalescing interrupts\n");
- he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7),
- G0_RBRQ_I + (group * 16));
- } else
- he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1),
- G0_RBRQ_I + (group * 16));
-
- /* tx buffer ready queue */
-
- he_dev->tbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
- CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
- &he_dev->tbrq_phys, GFP_KERNEL);
- if (he_dev->tbrq_base == NULL) {
- hprintk("failed to allocate tbrq\n");
- goto out_free_rbpq_base;
- }
-
- he_dev->tbrq_head = he_dev->tbrq_base;
-
- he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16));
- he_writel(he_dev, 0, G0_TBRQ_H + (group * 16));
- he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16));
- he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
-
- return 0;
-
-out_free_rbpq_base:
- dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_RBRQ_SIZE *
- sizeof(struct he_rbrq), he_dev->rbrq_base,
- he_dev->rbrq_phys);
-out_free_rbpl:
- list_for_each_entry_safe(heb, next, &he_dev->rbpl_outstanding, entry)
- dma_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
-
- dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_RBPL_SIZE *
- sizeof(struct he_rbp), he_dev->rbpl_base,
- he_dev->rbpl_phys);
-out_destroy_rbpl_pool:
- dma_pool_destroy(he_dev->rbpl_pool);
-out_free_rbpl_virt:
- kfree(he_dev->rbpl_virt);
-out_free_rbpl_table:
- bitmap_free(he_dev->rbpl_table);
-
- return -ENOMEM;
-}
-
-static int he_init_irq(struct he_dev *he_dev)
-{
- int i;
-
- /* 2.9.3.5 tail offset for each interrupt queue is located after the
- end of the interrupt queue */
-
- he_dev->irq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
- (CONFIG_IRQ_SIZE + 1) * sizeof(struct he_irq),
- &he_dev->irq_phys, GFP_KERNEL);
- if (he_dev->irq_base == NULL) {
- hprintk("failed to allocate irq\n");
- return -ENOMEM;
- }
- he_dev->irq_tailoffset = (unsigned *)
- &he_dev->irq_base[CONFIG_IRQ_SIZE];
- *he_dev->irq_tailoffset = 0;
- he_dev->irq_head = he_dev->irq_base;
- he_dev->irq_tail = he_dev->irq_base;
-
- for (i = 0; i < CONFIG_IRQ_SIZE; ++i)
- he_dev->irq_base[i].isw = ITYPE_INVALID;
-
- he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE);
- he_writel(he_dev,
- IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH),
- IRQ0_HEAD);
- he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL);
- he_writel(he_dev, 0x0, IRQ0_DATA);
-
- he_writel(he_dev, 0x0, IRQ1_BASE);
- he_writel(he_dev, 0x0, IRQ1_HEAD);
- he_writel(he_dev, 0x0, IRQ1_CNTL);
- he_writel(he_dev, 0x0, IRQ1_DATA);
-
- he_writel(he_dev, 0x0, IRQ2_BASE);
- he_writel(he_dev, 0x0, IRQ2_HEAD);
- he_writel(he_dev, 0x0, IRQ2_CNTL);
- he_writel(he_dev, 0x0, IRQ2_DATA);
-
- he_writel(he_dev, 0x0, IRQ3_BASE);
- he_writel(he_dev, 0x0, IRQ3_HEAD);
- he_writel(he_dev, 0x0, IRQ3_CNTL);
- he_writel(he_dev, 0x0, IRQ3_DATA);
-
- /* 2.9.3.2 interrupt queue mapping registers */
-
- he_writel(he_dev, 0x0, GRP_10_MAP);
- he_writel(he_dev, 0x0, GRP_32_MAP);
- he_writel(he_dev, 0x0, GRP_54_MAP);
- he_writel(he_dev, 0x0, GRP_76_MAP);
-
- if (request_irq(he_dev->pci_dev->irq,
- he_irq_handler, IRQF_SHARED, DEV_LABEL, he_dev)) {
- hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
- return -EINVAL;
- }
-
- he_dev->irq = he_dev->pci_dev->irq;
-
- return 0;
-}
-
-static int he_start(struct atm_dev *dev)
-{
- struct he_dev *he_dev;
- struct pci_dev *pci_dev;
- unsigned long membase;
-
- u16 command;
- u32 gen_cntl_0, host_cntl, lb_swap;
- u8 cache_size, timer;
-
- unsigned err;
- unsigned int status, reg;
- int i, group;
-
- he_dev = HE_DEV(dev);
- pci_dev = he_dev->pci_dev;
-
- membase = pci_resource_start(pci_dev, 0);
- HPRINTK("membase = 0x%lx irq = %d.\n", membase, pci_dev->irq);
-
- /*
- * pci bus controller initialization
- */
-
- /* 4.3 pci bus controller-specific initialization */
- if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0) {
- hprintk("can't read GEN_CNTL_0\n");
- return -EINVAL;
- }
- gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT);
- if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0) {
- hprintk("can't write GEN_CNTL_0.\n");
- return -EINVAL;
- }
-
- if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0) {
- hprintk("can't read PCI_COMMAND.\n");
- return -EINVAL;
- }
-
- command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
- if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0) {
- hprintk("can't enable memory.\n");
- return -EINVAL;
- }
-
- if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size)) {
- hprintk("can't read cache line size?\n");
- return -EINVAL;
- }
-
- if (cache_size < 16) {
- cache_size = 16;
- if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size))
- hprintk("can't set cache line size to %d\n", cache_size);
- }
-
- if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer)) {
- hprintk("can't read latency timer?\n");
- return -EINVAL;
- }
-
- /* from table 3.9
- *
- * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE
- *
- * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles]
- * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles]
- *
- */
-#define LAT_TIMER 209
- if (timer < LAT_TIMER) {
- HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER);
- timer = LAT_TIMER;
- if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer))
- hprintk("can't set latency timer to %d\n", timer);
- }
-
- if (!(he_dev->membase = ioremap(membase, HE_REGMAP_SIZE))) {
- hprintk("can't set up page mapping\n");
- return -EINVAL;
- }
-
- /* 4.4 card reset */
- he_writel(he_dev, 0x0, RESET_CNTL);
- he_writel(he_dev, 0xff, RESET_CNTL);
-
- msleep(16); /* 16 ms */
- status = he_readl(he_dev, RESET_CNTL);
- if ((status & BOARD_RST_STATUS) == 0) {
- hprintk("reset failed\n");
- return -EINVAL;
- }
-
- /* 4.5 set bus width */
- host_cntl = he_readl(he_dev, HOST_CNTL);
- if (host_cntl & PCI_BUS_SIZE64)
- gen_cntl_0 |= ENBL_64;
- else
- gen_cntl_0 &= ~ENBL_64;
-
- if (disable64 == 1) {
- hprintk("disabling 64-bit pci bus transfers\n");
- gen_cntl_0 &= ~ENBL_64;
- }
-
- if (gen_cntl_0 & ENBL_64)
- hprintk("64-bit transfers enabled\n");
-
- pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
-
- /* 4.7 read prom contents */
- for (i = 0; i < PROD_ID_LEN; ++i)
- he_dev->prod_id[i] = read_prom_byte(he_dev, PROD_ID + i);
-
- he_dev->media = read_prom_byte(he_dev, MEDIA);
-
- for (i = 0; i < 6; ++i)
- dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i);
-
- hprintk("%s%s, %pM\n", he_dev->prod_id,
- he_dev->media & 0x40 ? "SM" : "MM", dev->esi);
- he_dev->atm_dev->link_rate = he_is622(he_dev) ?
- ATM_OC12_PCR : ATM_OC3_PCR;
-
- /* 4.6 set host endianess */
- lb_swap = he_readl(he_dev, LB_SWAP);
- if (he_is622(he_dev))
- lb_swap &= ~XFER_SIZE; /* 4 cells */
- else
- lb_swap |= XFER_SIZE; /* 8 cells */
-#ifdef __BIG_ENDIAN
- lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST;
-#else
- lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST |
- DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP);
-#endif /* __BIG_ENDIAN */
- he_writel(he_dev, lb_swap, LB_SWAP);
-
- /* 4.8 sdram controller initialization */
- he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL);
-
- /* 4.9 initialize rnum value */
- lb_swap |= SWAP_RNUM_MAX(0xf);
- he_writel(he_dev, lb_swap, LB_SWAP);
-
- /* 4.10 initialize the interrupt queues */
- if ((err = he_init_irq(he_dev)) != 0)
- return err;
-
- /* 4.11 enable pci bus controller state machines */
- host_cntl |= (OUTFF_ENB | CMDFF_ENB |
- QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB);
- he_writel(he_dev, host_cntl, HOST_CNTL);
-
- gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB;
- pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
-
- /*
- * atm network controller initialization
- */
-
- /* 5.1.1 generic configuration state */
-
- /*
- * local (cell) buffer memory map
- *
- * HE155 HE622
- *
- * 0 ____________1023 bytes 0 _______________________2047 bytes
- * | | | | |
- * | utility | | rx0 | |
- * 5|____________| 255|___________________| u |
- * 6| | 256| | t |
- * | | | | i |
- * | rx0 | row | tx | l |
- * | | | | i |
- * | | 767|___________________| t |
- * 517|____________| 768| | y |
- * row 518| | | rx1 | |
- * | | 1023|___________________|___|
- * | |
- * | tx |
- * | |
- * | |
- * 1535|____________|
- * 1536| |
- * | rx1 |
- * 2047|____________|
- *
- */
-
- /* total 4096 connections */
- he_dev->vcibits = CONFIG_DEFAULT_VCIBITS;
- he_dev->vpibits = CONFIG_DEFAULT_VPIBITS;
-
- if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS) {
- hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS);
- return -ENODEV;
- }
-
- if (nvpibits != -1) {
- he_dev->vpibits = nvpibits;
- he_dev->vcibits = HE_MAXCIDBITS - nvpibits;
- }
-
- if (nvcibits != -1) {
- he_dev->vcibits = nvcibits;
- he_dev->vpibits = HE_MAXCIDBITS - nvcibits;
- }
-
-
- if (he_is622(he_dev)) {
- he_dev->cells_per_row = 40;
- he_dev->bytes_per_row = 2048;
- he_dev->r0_numrows = 256;
- he_dev->tx_numrows = 512;
- he_dev->r1_numrows = 256;
- he_dev->r0_startrow = 0;
- he_dev->tx_startrow = 256;
- he_dev->r1_startrow = 768;
- } else {
- he_dev->cells_per_row = 20;
- he_dev->bytes_per_row = 1024;
- he_dev->r0_numrows = 512;
- he_dev->tx_numrows = 1018;
- he_dev->r1_numrows = 512;
- he_dev->r0_startrow = 6;
- he_dev->tx_startrow = 518;
- he_dev->r1_startrow = 1536;
- }
-
- he_dev->cells_per_lbuf = 4;
- he_dev->buffer_limit = 4;
- he_dev->r0_numbuffs = he_dev->r0_numrows *
- he_dev->cells_per_row / he_dev->cells_per_lbuf;
- if (he_dev->r0_numbuffs > 2560)
- he_dev->r0_numbuffs = 2560;
-
- he_dev->r1_numbuffs = he_dev->r1_numrows *
- he_dev->cells_per_row / he_dev->cells_per_lbuf;
- if (he_dev->r1_numbuffs > 2560)
- he_dev->r1_numbuffs = 2560;
-
- he_dev->tx_numbuffs = he_dev->tx_numrows *
- he_dev->cells_per_row / he_dev->cells_per_lbuf;
- if (he_dev->tx_numbuffs > 5120)
- he_dev->tx_numbuffs = 5120;
-
- /* 5.1.2 configure hardware dependent registers */
-
- he_writel(he_dev,
- SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) |
- RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) |
- (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) |
- (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)),
- LBARB);
-
- he_writel(he_dev, BANK_ON |
- (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)),
- SDRAMCON);
-
- he_writel(he_dev,
- (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) |
- RM_RW_WAIT(1), RCMCONFIG);
- he_writel(he_dev,
- (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) |
- TM_RW_WAIT(1), TCMCONFIG);
-
- he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG);
-
- he_writel(he_dev,
- (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) |
- (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) |
- RX_VALVP(he_dev->vpibits) |
- RX_VALVC(he_dev->vcibits), RC_CONFIG);
-
- he_writel(he_dev, DRF_THRESH(0x20) |
- (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) |
- TX_VCI_MASK(he_dev->vcibits) |
- LBFREE_CNT(he_dev->tx_numbuffs), TX_CONFIG);
-
- he_writel(he_dev, 0x0, TXAAL5_PROTO);
-
- he_writel(he_dev, PHY_INT_ENB |
- (he_is622(he_dev) ? PTMR_PRE(67 - 1) : PTMR_PRE(50 - 1)),
- RH_CONFIG);
-
- /* 5.1.3 initialize connection memory */
-
- for (i = 0; i < TCM_MEM_SIZE; ++i)
- he_writel_tcm(he_dev, 0, i);
-
- for (i = 0; i < RCM_MEM_SIZE; ++i)
- he_writel_rcm(he_dev, 0, i);
-
- /*
- * transmit connection memory map
- *
- * tx memory
- * 0x0 ___________________
- * | |
- * | |
- * | TSRa |
- * | |
- * | |
- * 0x8000|___________________|
- * | |
- * | TSRb |
- * 0xc000|___________________|
- * | |
- * | TSRc |
- * 0xe000|___________________|
- * | TSRd |
- * 0xf000|___________________|
- * | tmABR |
- * 0x10000|___________________|
- * | |
- * | tmTPD |
- * |___________________|
- * | |
- * ....
- * 0x1ffff|___________________|
- *
- *
- */
-
- he_writel(he_dev, CONFIG_TSRB, TSRB_BA);
- he_writel(he_dev, CONFIG_TSRC, TSRC_BA);
- he_writel(he_dev, CONFIG_TSRD, TSRD_BA);
- he_writel(he_dev, CONFIG_TMABR, TMABR_BA);
- he_writel(he_dev, CONFIG_TPDBA, TPD_BA);
-
-
- /*
- * receive connection memory map
- *
- * 0x0 ___________________
- * | |
- * | |
- * | RSRa |
- * | |
- * | |
- * 0x8000|___________________|
- * | |
- * | rx0/1 |
- * | LBM | link lists of local
- * | tx | buffer memory
- * | |
- * 0xd000|___________________|
- * | |
- * | rmABR |
- * 0xe000|___________________|
- * | |
- * | RSRb |
- * |___________________|
- * | |
- * ....
- * 0xffff|___________________|
- */
-
- he_writel(he_dev, 0x08000, RCMLBM_BA);
- he_writel(he_dev, 0x0e000, RCMRSRB_BA);
- he_writel(he_dev, 0x0d800, RCMABR_BA);
-
- /* 5.1.4 initialize local buffer free pools linked lists */
-
- he_init_rx_lbfp0(he_dev);
- he_init_rx_lbfp1(he_dev);
-
- he_writel(he_dev, 0x0, RLBC_H);
- he_writel(he_dev, 0x0, RLBC_T);
- he_writel(he_dev, 0x0, RLBC_H2);
-
- he_writel(he_dev, 512, RXTHRSH); /* 10% of r0+r1 buffers */
- he_writel(he_dev, 256, LITHRSH); /* 5% of r0+r1 buffers */
-
- he_init_tx_lbfp(he_dev);
-
- he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA);
-
- /* 5.1.5 initialize intermediate receive queues */
-
- if (he_is622(he_dev)) {
- he_writel(he_dev, 0x000f, G0_INMQ_S);
- he_writel(he_dev, 0x200f, G0_INMQ_L);
-
- he_writel(he_dev, 0x001f, G1_INMQ_S);
- he_writel(he_dev, 0x201f, G1_INMQ_L);
-
- he_writel(he_dev, 0x002f, G2_INMQ_S);
- he_writel(he_dev, 0x202f, G2_INMQ_L);
-
- he_writel(he_dev, 0x003f, G3_INMQ_S);
- he_writel(he_dev, 0x203f, G3_INMQ_L);
-
- he_writel(he_dev, 0x004f, G4_INMQ_S);
- he_writel(he_dev, 0x204f, G4_INMQ_L);
-
- he_writel(he_dev, 0x005f, G5_INMQ_S);
- he_writel(he_dev, 0x205f, G5_INMQ_L);
-
- he_writel(he_dev, 0x006f, G6_INMQ_S);
- he_writel(he_dev, 0x206f, G6_INMQ_L);
-
- he_writel(he_dev, 0x007f, G7_INMQ_S);
- he_writel(he_dev, 0x207f, G7_INMQ_L);
- } else {
- he_writel(he_dev, 0x0000, G0_INMQ_S);
- he_writel(he_dev, 0x0008, G0_INMQ_L);
-
- he_writel(he_dev, 0x0001, G1_INMQ_S);
- he_writel(he_dev, 0x0009, G1_INMQ_L);
-
- he_writel(he_dev, 0x0002, G2_INMQ_S);
- he_writel(he_dev, 0x000a, G2_INMQ_L);
-
- he_writel(he_dev, 0x0003, G3_INMQ_S);
- he_writel(he_dev, 0x000b, G3_INMQ_L);
-
- he_writel(he_dev, 0x0004, G4_INMQ_S);
- he_writel(he_dev, 0x000c, G4_INMQ_L);
-
- he_writel(he_dev, 0x0005, G5_INMQ_S);
- he_writel(he_dev, 0x000d, G5_INMQ_L);
-
- he_writel(he_dev, 0x0006, G6_INMQ_S);
- he_writel(he_dev, 0x000e, G6_INMQ_L);
-
- he_writel(he_dev, 0x0007, G7_INMQ_S);
- he_writel(he_dev, 0x000f, G7_INMQ_L);
- }
-
- /* 5.1.6 application tunable parameters */
-
- he_writel(he_dev, 0x0, MCC);
- he_writel(he_dev, 0x0, OEC);
- he_writel(he_dev, 0x0, DCC);
- he_writel(he_dev, 0x0, CEC);
-
- /* 5.1.7 cs block initialization */
-
- he_init_cs_block(he_dev);
-
- /* 5.1.8 cs block connection memory initialization */
-
- if (he_init_cs_block_rcm(he_dev) < 0)
- return -ENOMEM;
-
- /* 5.1.10 initialize host structures */
-
- he_init_tpdrq(he_dev);
-
- he_dev->tpd_pool = dma_pool_create("tpd", &he_dev->pci_dev->dev,
- sizeof(struct he_tpd), TPD_ALIGNMENT, 0);
- if (he_dev->tpd_pool == NULL) {
- hprintk("unable to create tpd dma_pool\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&he_dev->outstanding_tpds);
-
- if (he_init_group(he_dev, 0) != 0)
- return -ENOMEM;
-
- for (group = 1; group < HE_NUM_GROUPS; ++group) {
- he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
- he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
- he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
- he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
- G0_RBPS_BS + (group * 32));
-
- he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32));
- he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32));
- he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
- G0_RBPL_QI + (group * 32));
- he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32));
-
- he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16));
- he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16));
- he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0),
- G0_RBRQ_Q + (group * 16));
- he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16));
-
- he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16));
- he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16));
- he_writel(he_dev, TBRQ_THRESH(0x1),
- G0_TBRQ_THRESH + (group * 16));
- he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16));
- }
-
- /* host status page */
-
- he_dev->hsp = dma_alloc_coherent(&he_dev->pci_dev->dev,
- sizeof(struct he_hsp),
- &he_dev->hsp_phys, GFP_KERNEL);
- if (he_dev->hsp == NULL) {
- hprintk("failed to allocate host status page\n");
- return -ENOMEM;
- }
- he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
-
- /* initialize framer */
-
-#ifdef CONFIG_ATM_HE_USE_SUNI
- if (he_isMM(he_dev))
- suni_init(he_dev->atm_dev);
- if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start)
- he_dev->atm_dev->phy->start(he_dev->atm_dev);
-#endif /* CONFIG_ATM_HE_USE_SUNI */
-
- if (sdh) {
- /* this really should be in suni.c but for now... */
- int val;
-
- val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM);
- val = (val & ~SUNI_TPOP_APM_S) | (SUNI_TPOP_S_SDH << SUNI_TPOP_APM_S_SHIFT);
- he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);
- he_phy_put(he_dev->atm_dev, SUNI_TACP_IUCHP_CLP, SUNI_TACP_IUCHP);
- }
-
- /* 5.1.12 enable transmit and receive */
-
- reg = he_readl_mbox(he_dev, CS_ERCTL0);
- reg |= TX_ENABLE|ER_ENABLE;
- he_writel_mbox(he_dev, reg, CS_ERCTL0);
-
- reg = he_readl(he_dev, RC_CONFIG);
- reg |= RX_ENABLE;
- he_writel(he_dev, reg, RC_CONFIG);
-
- for (i = 0; i < HE_NUM_CS_STPER; ++i) {
- he_dev->cs_stper[i].inuse = 0;
- he_dev->cs_stper[i].pcr = -1;
- }
- he_dev->total_bw = 0;
-
-
- /* atm linux initialization */
-
- he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits;
- he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits;
-
- he_dev->irq_peak = 0;
- he_dev->rbrq_peak = 0;
- he_dev->rbpl_peak = 0;
- he_dev->tbrq_peak = 0;
-
- HPRINTK("hell bent for leather!\n");
-
- return 0;
-}
-
-static void
-he_stop(struct he_dev *he_dev)
-{
- struct he_buff *heb, *next;
- struct pci_dev *pci_dev;
- u32 gen_cntl_0, reg;
- u16 command;
-
- pci_dev = he_dev->pci_dev;
-
- /* disable interrupts */
-
- if (he_dev->membase) {
- pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0);
- gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB);
- pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
-
- tasklet_disable(&he_dev->tasklet);
-
- /* disable recv and transmit */
-
- reg = he_readl_mbox(he_dev, CS_ERCTL0);
- reg &= ~(TX_ENABLE|ER_ENABLE);
- he_writel_mbox(he_dev, reg, CS_ERCTL0);
-
- reg = he_readl(he_dev, RC_CONFIG);
- reg &= ~(RX_ENABLE);
- he_writel(he_dev, reg, RC_CONFIG);
- }
-
-#ifdef CONFIG_ATM_HE_USE_SUNI
- if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop)
- he_dev->atm_dev->phy->stop(he_dev->atm_dev);
-#endif /* CONFIG_ATM_HE_USE_SUNI */
-
- if (he_dev->irq)
- free_irq(he_dev->irq, he_dev);
-
- if (he_dev->irq_base)
- dma_free_coherent(&he_dev->pci_dev->dev, (CONFIG_IRQ_SIZE + 1)
- * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys);
-
- if (he_dev->hsp)
- dma_free_coherent(&he_dev->pci_dev->dev, sizeof(struct he_hsp),
- he_dev->hsp, he_dev->hsp_phys);
-
- if (he_dev->rbpl_base) {
- list_for_each_entry_safe(heb, next, &he_dev->rbpl_outstanding, entry)
- dma_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
-
- dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_RBPL_SIZE
- * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);
- }
-
- kfree(he_dev->rbpl_virt);
- bitmap_free(he_dev->rbpl_table);
- dma_pool_destroy(he_dev->rbpl_pool);
-
- if (he_dev->rbrq_base)
- dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
- he_dev->rbrq_base, he_dev->rbrq_phys);
-
- if (he_dev->tbrq_base)
- dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
- he_dev->tbrq_base, he_dev->tbrq_phys);
-
- if (he_dev->tpdrq_base)
- dma_free_coherent(&he_dev->pci_dev->dev,
- CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
- he_dev->tpdrq_base, he_dev->tpdrq_phys);
-
- dma_pool_destroy(he_dev->tpd_pool);
-
- if (he_dev->pci_dev) {
- pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command);
- command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command);
- }
-
- if (he_dev->membase)
- iounmap(he_dev->membase);
-}
-
-static struct he_tpd *
-__alloc_tpd(struct he_dev *he_dev)
-{
- struct he_tpd *tpd;
- dma_addr_t mapping;
-
- tpd = dma_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC, &mapping);
- if (tpd == NULL)
- return NULL;
-
- tpd->status = TPD_ADDR(mapping);
- tpd->reserved = 0;
- tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0;
- tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0;
- tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0;
-
- return tpd;
-}
-
-#define AAL5_LEN(buf,len) \
- ((((unsigned char *)(buf))[(len)-6] << 8) | \
- (((unsigned char *)(buf))[(len)-5]))
-
-/* 2.10.1.2 receive
- *
- * aal5 packets can optionally return the tcp checksum in the lower
- * 16 bits of the crc (RSR0_TCP_CKSUM)
- */
-
-#define TCP_CKSUM(buf,len) \
- ((((unsigned char *)(buf))[(len)-2] << 8) | \
- (((unsigned char *)(buf))[(len-1)]))
-
-static int
-he_service_rbrq(struct he_dev *he_dev, int group)
-{
- struct he_rbrq *rbrq_tail = (struct he_rbrq *)
- ((unsigned long)he_dev->rbrq_base |
- he_dev->hsp->group[group].rbrq_tail);
- unsigned cid, lastcid = -1;
- struct sk_buff *skb;
- struct atm_vcc *vcc = NULL;
- struct he_vcc *he_vcc;
- struct he_buff *heb, *next;
- int i;
- int pdus_assembled = 0;
- int updated = 0;
-
- read_lock(&vcc_sklist_lock);
- while (he_dev->rbrq_head != rbrq_tail) {
- ++updated;
-
- HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n",
- he_dev->rbrq_head, group,
- RBRQ_ADDR(he_dev->rbrq_head),
- RBRQ_BUFLEN(he_dev->rbrq_head),
- RBRQ_CID(he_dev->rbrq_head),
- RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "",
- RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "",
- RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "",
- RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "",
- RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "",
- RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");
-
- i = RBRQ_ADDR(he_dev->rbrq_head) >> RBP_IDX_OFFSET;
- heb = he_dev->rbpl_virt[i];
-
- cid = RBRQ_CID(he_dev->rbrq_head);
- if (cid != lastcid)
- vcc = __find_vcc(he_dev, cid);
- lastcid = cid;
-
- if (vcc == NULL || (he_vcc = HE_VCC(vcc)) == NULL) {
- hprintk("vcc/he_vcc == NULL (cid 0x%x)\n", cid);
- if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) {
- clear_bit(i, he_dev->rbpl_table);
- list_del(&heb->entry);
- dma_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
- }
-
- goto next_rbrq_entry;
- }
-
- if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) {
- hprintk("HBUF_ERR! (cid 0x%x)\n", cid);
- atomic_inc(&vcc->stats->rx_drop);
- goto return_host_buffers;
- }
-
- heb->len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
- clear_bit(i, he_dev->rbpl_table);
- list_move_tail(&heb->entry, &he_vcc->buffers);
- he_vcc->pdu_len += heb->len;
-
- if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) {
- lastcid = -1;
- HPRINTK("wake_up rx_waitq (cid 0x%x)\n", cid);
- wake_up(&he_vcc->rx_waitq);
- goto return_host_buffers;
- }
-
- if (!RBRQ_END_PDU(he_dev->rbrq_head))
- goto next_rbrq_entry;
-
- if (RBRQ_LEN_ERR(he_dev->rbrq_head)
- || RBRQ_CRC_ERR(he_dev->rbrq_head)) {
- HPRINTK("%s%s (%d.%d)\n",
- RBRQ_CRC_ERR(he_dev->rbrq_head)
- ? "CRC_ERR " : "",
- RBRQ_LEN_ERR(he_dev->rbrq_head)
- ? "LEN_ERR" : "",
- vcc->vpi, vcc->vci);
- atomic_inc(&vcc->stats->rx_err);
- goto return_host_buffers;
- }
-
- skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve,
- GFP_ATOMIC);
- if (!skb) {
- HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci);
- goto return_host_buffers;
- }
-
- if (rx_skb_reserve > 0)
- skb_reserve(skb, rx_skb_reserve);
-
- __net_timestamp(skb);
-
- list_for_each_entry(heb, &he_vcc->buffers, entry)
- skb_put_data(skb, &heb->data, heb->len);
-
- switch (vcc->qos.aal) {
- case ATM_AAL0:
- /* 2.10.1.5 raw cell receive */
- skb->len = ATM_AAL0_SDU;
- skb_set_tail_pointer(skb, skb->len);
- break;
- case ATM_AAL5:
- /* 2.10.1.2 aal5 receive */
-
- skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len);
- skb_set_tail_pointer(skb, skb->len);
-#ifdef USE_CHECKSUM_HW
- if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) {
- skb->ip_summed = CHECKSUM_COMPLETE;
- skb->csum = TCP_CKSUM(skb->data,
- he_vcc->pdu_len);
- }
-#endif
- break;
- }
-
-#ifdef should_never_happen
- if (skb->len > vcc->qos.rxtp.max_sdu)
- hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)! cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid);
-#endif
-
-#ifdef notdef
- ATM_SKB(skb)->vcc = vcc;
-#endif
- spin_unlock(&he_dev->global_lock);
- vcc->push(vcc, skb);
- spin_lock(&he_dev->global_lock);
-
- atomic_inc(&vcc->stats->rx);
-
-return_host_buffers:
- ++pdus_assembled;
-
- list_for_each_entry_safe(heb, next, &he_vcc->buffers, entry)
- dma_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
- INIT_LIST_HEAD(&he_vcc->buffers);
- he_vcc->pdu_len = 0;
-
-next_rbrq_entry:
- he_dev->rbrq_head = (struct he_rbrq *)
- ((unsigned long) he_dev->rbrq_base |
- RBRQ_MASK(he_dev->rbrq_head + 1));
-
- }
- read_unlock(&vcc_sklist_lock);
-
- if (updated) {
- if (updated > he_dev->rbrq_peak)
- he_dev->rbrq_peak = updated;
-
- he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head),
- G0_RBRQ_H + (group * 16));
- }
-
- return pdus_assembled;
-}
-
-static void
-he_service_tbrq(struct he_dev *he_dev, int group)
-{
- struct he_tbrq *tbrq_tail = (struct he_tbrq *)
- ((unsigned long)he_dev->tbrq_base |
- he_dev->hsp->group[group].tbrq_tail);
- struct he_tpd *tpd;
- int slot, updated = 0;
- struct he_tpd *__tpd;
-
- /* 2.1.6 transmit buffer return queue */
-
- while (he_dev->tbrq_head != tbrq_tail) {
- ++updated;
-
- HPRINTK("tbrq%d 0x%x%s%s\n",
- group,
- TBRQ_TPD(he_dev->tbrq_head),
- TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "",
- TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
- tpd = NULL;
- list_for_each_entry(__tpd, &he_dev->outstanding_tpds, entry) {
- if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) {
- tpd = __tpd;
- list_del(&__tpd->entry);
- break;
- }
- }
-
- if (tpd == NULL) {
- hprintk("unable to locate tpd for dma buffer %x\n",
- TBRQ_TPD(he_dev->tbrq_head));
- goto next_tbrq_entry;
- }
-
- if (TBRQ_EOS(he_dev->tbrq_head)) {
- HPRINTK("wake_up(tx_waitq) cid 0x%x\n",
- he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci));
- if (tpd->vcc)
- wake_up(&HE_VCC(tpd->vcc)->tx_waitq);
-
- goto next_tbrq_entry;
- }
-
- for (slot = 0; slot < TPD_MAXIOV; ++slot) {
- if (tpd->iovec[slot].addr)
- dma_unmap_single(&he_dev->pci_dev->dev,
- tpd->iovec[slot].addr,
- tpd->iovec[slot].len & TPD_LEN_MASK,
- DMA_TO_DEVICE);
- if (tpd->iovec[slot].len & TPD_LST)
- break;
-
- }
-
- if (tpd->skb) { /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */
- if (tpd->vcc && tpd->vcc->pop)
- tpd->vcc->pop(tpd->vcc, tpd->skb);
- else
- dev_kfree_skb_any(tpd->skb);
- }
-
-next_tbrq_entry:
- if (tpd)
- dma_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
- he_dev->tbrq_head = (struct he_tbrq *)
- ((unsigned long) he_dev->tbrq_base |
- TBRQ_MASK(he_dev->tbrq_head + 1));
- }
-
- if (updated) {
- if (updated > he_dev->tbrq_peak)
- he_dev->tbrq_peak = updated;
-
- he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head),
- G0_TBRQ_H + (group * 16));
- }
-}
-
-static void
-he_service_rbpl(struct he_dev *he_dev, int group)
-{
- struct he_rbp *new_tail;
- struct he_rbp *rbpl_head;
- struct he_buff *heb;
- dma_addr_t mapping;
- int i;
- int moved = 0;
-
- rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
- RBPL_MASK(he_readl(he_dev, G0_RBPL_S)));
-
- for (;;) {
- new_tail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
- RBPL_MASK(he_dev->rbpl_tail+1));
-
- /* table 3.42 -- rbpl_tail should never be set to rbpl_head */
- if (new_tail == rbpl_head)
- break;
-
- i = find_next_zero_bit(he_dev->rbpl_table, RBPL_TABLE_SIZE, he_dev->rbpl_hint);
- if (i > (RBPL_TABLE_SIZE - 1)) {
- i = find_first_zero_bit(he_dev->rbpl_table, RBPL_TABLE_SIZE);
- if (i > (RBPL_TABLE_SIZE - 1))
- break;
- }
- he_dev->rbpl_hint = i + 1;
-
- heb = dma_pool_alloc(he_dev->rbpl_pool, GFP_ATOMIC, &mapping);
- if (!heb)
- break;
- heb->mapping = mapping;
- list_add(&heb->entry, &he_dev->rbpl_outstanding);
- he_dev->rbpl_virt[i] = heb;
- set_bit(i, he_dev->rbpl_table);
- new_tail->idx = i << RBP_IDX_OFFSET;
- new_tail->phys = mapping + offsetof(struct he_buff, data);
-
- he_dev->rbpl_tail = new_tail;
- ++moved;
- }
-
- if (moved)
- he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
-}
-
-static void
-he_tasklet(unsigned long data)
-{
- unsigned long flags;
- struct he_dev *he_dev = (struct he_dev *) data;
- int group, type;
- int updated = 0;
-
- HPRINTK("tasklet (0x%lx)\n", data);
- spin_lock_irqsave(&he_dev->global_lock, flags);
-
- while (he_dev->irq_head != he_dev->irq_tail) {
- ++updated;
-
- type = ITYPE_TYPE(he_dev->irq_head->isw);
- group = ITYPE_GROUP(he_dev->irq_head->isw);
-
- switch (type) {
- case ITYPE_RBRQ_THRESH:
- HPRINTK("rbrq%d threshold\n", group);
- fallthrough;
- case ITYPE_RBRQ_TIMER:
- if (he_service_rbrq(he_dev, group))
- he_service_rbpl(he_dev, group);
- break;
- case ITYPE_TBRQ_THRESH:
- HPRINTK("tbrq%d threshold\n", group);
- fallthrough;
- case ITYPE_TPD_COMPLETE:
- he_service_tbrq(he_dev, group);
- break;
- case ITYPE_RBPL_THRESH:
- he_service_rbpl(he_dev, group);
- break;
- case ITYPE_RBPS_THRESH:
- /* shouldn't happen unless small buffers enabled */
- break;
- case ITYPE_PHY:
- HPRINTK("phy interrupt\n");
-#ifdef CONFIG_ATM_HE_USE_SUNI
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt)
- he_dev->atm_dev->phy->interrupt(he_dev->atm_dev);
- spin_lock_irqsave(&he_dev->global_lock, flags);
-#endif
- break;
- case ITYPE_OTHER:
- switch (type|group) {
- case ITYPE_PARITY:
- hprintk("parity error\n");
- break;
- case ITYPE_ABORT:
- hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR));
- break;
- }
- break;
- case ITYPE_TYPE(ITYPE_INVALID):
- /* see 8.1.1 -- check all queues */
-
- HPRINTK("isw not updated 0x%x\n", he_dev->irq_head->isw);
-
- he_service_rbrq(he_dev, 0);
- he_service_rbpl(he_dev, 0);
- he_service_tbrq(he_dev, 0);
- break;
- default:
- hprintk("bad isw 0x%x?\n", he_dev->irq_head->isw);
- }
-
- he_dev->irq_head->isw = ITYPE_INVALID;
-
- he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK);
- }
-
- if (updated) {
- if (updated > he_dev->irq_peak)
- he_dev->irq_peak = updated;
-
- he_writel(he_dev,
- IRQ_SIZE(CONFIG_IRQ_SIZE) |
- IRQ_THRESH(CONFIG_IRQ_THRESH) |
- IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD);
- (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata; flush posted writes */
- }
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-}
-
-static irqreturn_t
-he_irq_handler(int irq, void *dev_id)
-{
- unsigned long flags;
- struct he_dev *he_dev = (struct he_dev * )dev_id;
- int handled = 0;
-
- if (he_dev == NULL)
- return IRQ_NONE;
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
-
- he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) |
- (*he_dev->irq_tailoffset << 2));
-
- if (he_dev->irq_tail == he_dev->irq_head) {
- HPRINTK("tailoffset not updated?\n");
- he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base |
- ((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2));
- (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */
- }
-
-#ifdef DEBUG
- if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */)
- hprintk("spurious (or shared) interrupt?\n");
-#endif
-
- if (he_dev->irq_head != he_dev->irq_tail) {
- handled = 1;
- tasklet_schedule(&he_dev->tasklet);
- he_writel(he_dev, INT_CLEAR_A, INT_FIFO); /* clear interrupt */
- (void) he_readl(he_dev, INT_FIFO); /* flush posted writes */
- }
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- return IRQ_RETVAL(handled);
-
-}
-
-static __inline__ void
-__enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
-{
- struct he_tpdrq *new_tail;
-
- HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n",
- tpd, cid, he_dev->tpdrq_tail);
-
- /* new_tail = he_dev->tpdrq_tail; */
- new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base |
- TPDRQ_MASK(he_dev->tpdrq_tail+1));
-
- /*
- * check to see if we are about to set the tail == head
- * if true, update the head pointer from the adapter
- * to see if this is really the case (reading the queue
- * head for every enqueue would be unnecessarily slow)
- */
-
- if (new_tail == he_dev->tpdrq_head) {
- he_dev->tpdrq_head = (struct he_tpdrq *)
- (((unsigned long)he_dev->tpdrq_base) |
- TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H)));
-
- if (new_tail == he_dev->tpdrq_head) {
- int slot;
-
- hprintk("tpdrq full (cid 0x%x)\n", cid);
- /*
- * FIXME
- * push tpd onto a transmit backlog queue
- * after service_tbrq, service the backlog
- * for now, we just drop the pdu
- */
- for (slot = 0; slot < TPD_MAXIOV; ++slot) {
- if (tpd->iovec[slot].addr)
- dma_unmap_single(&he_dev->pci_dev->dev,
- tpd->iovec[slot].addr,
- tpd->iovec[slot].len & TPD_LEN_MASK,
- DMA_TO_DEVICE);
- }
- if (tpd->skb) {
- if (tpd->vcc->pop)
- tpd->vcc->pop(tpd->vcc, tpd->skb);
- else
- dev_kfree_skb_any(tpd->skb);
- atomic_inc(&tpd->vcc->stats->tx_err);
- }
- dma_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
- return;
- }
- }
-
- /* 2.1.5 transmit packet descriptor ready queue */
- list_add_tail(&tpd->entry, &he_dev->outstanding_tpds);
- he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status);
- he_dev->tpdrq_tail->cid = cid;
- wmb();
-
- he_dev->tpdrq_tail = new_tail;
-
- he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T);
- (void) he_readl(he_dev, TPDRQ_T); /* flush posted writes */
-}
-
-static int
-he_open(struct atm_vcc *vcc)
-{
- unsigned long flags;
- struct he_dev *he_dev = HE_DEV(vcc->dev);
- struct he_vcc *he_vcc;
- int err = 0;
- unsigned cid, rsr0, rsr1, rsr4, tsr0, tsr0_aal, tsr4, period, reg, clock;
- short vpi = vcc->vpi;
- int vci = vcc->vci;
-
- if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
- return 0;
-
- HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci);
-
- set_bit(ATM_VF_ADDR, &vcc->flags);
-
- cid = he_mkcid(he_dev, vpi, vci);
-
- he_vcc = kmalloc_obj(struct he_vcc, GFP_ATOMIC);
- if (he_vcc == NULL) {
- hprintk("unable to allocate he_vcc during open\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&he_vcc->buffers);
- he_vcc->pdu_len = 0;
- he_vcc->rc_index = -1;
-
- init_waitqueue_head(&he_vcc->rx_waitq);
- init_waitqueue_head(&he_vcc->tx_waitq);
-
- vcc->dev_data = he_vcc;
-
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
- int pcr_goal;
-
- pcr_goal = atm_pcr_goal(&vcc->qos.txtp);
- if (pcr_goal == 0)
- pcr_goal = he_dev->atm_dev->link_rate;
- if (pcr_goal < 0) /* means round down, technically */
- pcr_goal = -pcr_goal;
-
- HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal);
-
- switch (vcc->qos.aal) {
- case ATM_AAL5:
- tsr0_aal = TSR0_AAL5;
- tsr4 = TSR4_AAL5;
- break;
- case ATM_AAL0:
- tsr0_aal = TSR0_AAL0_SDU;
- tsr4 = TSR4_AAL0_SDU;
- break;
- default:
- err = -EINVAL;
- goto open_failed;
- }
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
- tsr0 = he_readl_tsr0(he_dev, cid);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- if (TSR0_CONN_STATE(tsr0) != 0) {
- hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0);
- err = -EBUSY;
- goto open_failed;
- }
-
- switch (vcc->qos.txtp.traffic_class) {
- case ATM_UBR:
- /* 2.3.3.1 open connection ubr */
-
- tsr0 = TSR0_UBR | TSR0_GROUP(0) | tsr0_aal |
- TSR0_USE_WMIN | TSR0_UPDATE_GER;
- break;
-
- case ATM_CBR:
- /* 2.3.3.2 open connection cbr */
-
- /* 8.2.3 cbr scheduler wrap problem -- limit to 90% total link rate */
- if ((he_dev->total_bw + pcr_goal)
- > (he_dev->atm_dev->link_rate * 9 / 10))
- {
- err = -EBUSY;
- goto open_failed;
- }
-
- spin_lock_irqsave(&he_dev->global_lock, flags); /* also protects he_dev->cs_stper[] */
-
- /* find an unused cs_stper register */
- for (reg = 0; reg < HE_NUM_CS_STPER; ++reg)
- if (he_dev->cs_stper[reg].inuse == 0 ||
- he_dev->cs_stper[reg].pcr == pcr_goal)
- break;
-
- if (reg == HE_NUM_CS_STPER) {
- err = -EBUSY;
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- goto open_failed;
- }
-
- he_dev->total_bw += pcr_goal;
-
- he_vcc->rc_index = reg;
- ++he_dev->cs_stper[reg].inuse;
- he_dev->cs_stper[reg].pcr = pcr_goal;
-
- clock = he_is622(he_dev) ? 66667000 : 50000000;
- period = clock / pcr_goal;
-
- HPRINTK("rc_index = %d period = %d\n",
- reg, period);
-
- he_writel_mbox(he_dev, rate_to_atmf(period/2),
- CS_STPER0 + reg);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- tsr0 = TSR0_CBR | TSR0_GROUP(0) | tsr0_aal |
- TSR0_RC_INDEX(reg);
-
- break;
- default:
- err = -EINVAL;
- goto open_failed;
- }
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
-
- he_writel_tsr0(he_dev, tsr0, cid);
- he_writel_tsr4(he_dev, tsr4 | 1, cid);
- he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) |
- TSR1_PCR(rate_to_atmf(pcr_goal)), cid);
- he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid);
- he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid);
-
- he_writel_tsr3(he_dev, 0x0, cid);
- he_writel_tsr5(he_dev, 0x0, cid);
- he_writel_tsr6(he_dev, 0x0, cid);
- he_writel_tsr7(he_dev, 0x0, cid);
- he_writel_tsr8(he_dev, 0x0, cid);
- he_writel_tsr10(he_dev, 0x0, cid);
- he_writel_tsr11(he_dev, 0x0, cid);
- he_writel_tsr12(he_dev, 0x0, cid);
- he_writel_tsr13(he_dev, 0x0, cid);
- he_writel_tsr14(he_dev, 0x0, cid);
- (void) he_readl_tsr0(he_dev, cid); /* flush posted writes */
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- }
-
- if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
- unsigned aal;
-
- HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid,
- &HE_VCC(vcc)->rx_waitq);
-
- switch (vcc->qos.aal) {
- case ATM_AAL5:
- aal = RSR0_AAL5;
- break;
- case ATM_AAL0:
- aal = RSR0_RAWCELL;
- break;
- default:
- err = -EINVAL;
- goto open_failed;
- }
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
-
- rsr0 = he_readl_rsr0(he_dev, cid);
- if (rsr0 & RSR0_OPEN_CONN) {
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0);
- err = -EBUSY;
- goto open_failed;
- }
-
- rsr1 = RSR1_GROUP(0) | RSR1_RBPL_ONLY;
- rsr4 = RSR4_GROUP(0) | RSR4_RBPL_ONLY;
- rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ?
- (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0;
-
-#ifdef USE_CHECKSUM_HW
- if (vpi == 0 && vci >= ATM_NOT_RSV_VCI)
- rsr0 |= RSR0_TCP_CKSUM;
-#endif
-
- he_writel_rsr4(he_dev, rsr4, cid);
- he_writel_rsr1(he_dev, rsr1, cid);
- /* 5.1.11 last parameter initialized should be
- the open/closed indication in rsr0 */
- he_writel_rsr0(he_dev,
- rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid);
- (void) he_readl_rsr0(he_dev, cid); /* flush posted writes */
-
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- }
-
-open_failed:
-
- if (err) {
- kfree(he_vcc);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- }
- else
- set_bit(ATM_VF_READY, &vcc->flags);
-
- return err;
-}
-
-static void
-he_close(struct atm_vcc *vcc)
-{
- unsigned long flags;
- DECLARE_WAITQUEUE(wait, current);
- struct he_dev *he_dev = HE_DEV(vcc->dev);
- struct he_tpd *tpd;
- unsigned cid;
- struct he_vcc *he_vcc = HE_VCC(vcc);
-#define MAX_RETRY 30
- int retry = 0, sleep = 1, tx_inuse;
-
- HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci);
-
- clear_bit(ATM_VF_READY, &vcc->flags);
- cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
-
- if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
- int timeout;
-
- HPRINTK("close rx cid 0x%x\n", cid);
-
- /* 2.7.2.2 close receive operation */
-
- /* wait for previous close (if any) to finish */
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
- while (he_readl(he_dev, RCC_STAT) & RCC_BUSY) {
- HPRINTK("close cid 0x%x RCC_BUSY\n", cid);
- udelay(250);
- }
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&he_vcc->rx_waitq, &wait);
-
- he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid);
- (void) he_readl_rsr0(he_dev, cid); /* flush posted writes */
- he_writel_mbox(he_dev, cid, RXCON_CLOSE);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- timeout = schedule_timeout(30*HZ);
-
- remove_wait_queue(&he_vcc->rx_waitq, &wait);
- set_current_state(TASK_RUNNING);
-
- if (timeout == 0)
- hprintk("close rx timeout cid 0x%x\n", cid);
-
- HPRINTK("close rx cid 0x%x complete\n", cid);
-
- }
-
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
- volatile unsigned tsr4, tsr0;
- int timeout;
-
- HPRINTK("close tx cid 0x%x\n", cid);
-
- /* 2.1.2
- *
- * ... the host must first stop queueing packets to the TPDRQ
- * on the connection to be closed, then wait for all outstanding
- * packets to be transmitted and their buffers returned to the
- * TBRQ. When the last packet on the connection arrives in the
- * TBRQ, the host issues the close command to the adapter.
- */
-
- while (((tx_inuse = refcount_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) &&
- (retry < MAX_RETRY)) {
- msleep(sleep);
- if (sleep < 250)
- sleep = sleep * 2;
-
- ++retry;
- }
-
- if (tx_inuse > 1)
- hprintk("close tx cid 0x%x tx_inuse = %d\n", cid, tx_inuse);
-
- /* 2.3.1.1 generic close operations with flush */
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
- he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid);
- /* also clears TSR4_SESSION_ENDED */
-
- switch (vcc->qos.txtp.traffic_class) {
- case ATM_UBR:
- he_writel_tsr1(he_dev,
- TSR1_MCR(rate_to_atmf(200000))
- | TSR1_PCR(0), cid);
- break;
- case ATM_CBR:
- he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid);
- break;
- }
- (void) he_readl_tsr4(he_dev, cid); /* flush posted writes */
-
- tpd = __alloc_tpd(he_dev);
- if (tpd == NULL) {
- hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid);
- goto close_tx_incomplete;
- }
- tpd->status |= TPD_EOS | TPD_INT;
- tpd->skb = NULL;
- tpd->vcc = vcc;
- wmb();
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&he_vcc->tx_waitq, &wait);
- __enqueue_tpd(he_dev, tpd, cid);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- timeout = schedule_timeout(30*HZ);
-
- remove_wait_queue(&he_vcc->tx_waitq, &wait);
- set_current_state(TASK_RUNNING);
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
-
- if (timeout == 0) {
- hprintk("close tx timeout cid 0x%x\n", cid);
- goto close_tx_incomplete;
- }
-
- while (!((tsr4 = he_readl_tsr4(he_dev, cid)) & TSR4_SESSION_ENDED)) {
- HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4);
- udelay(250);
- }
-
- while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0) {
- HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0);
- udelay(250);
- }
-
-close_tx_incomplete:
-
- if (vcc->qos.txtp.traffic_class == ATM_CBR) {
- int reg = he_vcc->rc_index;
-
- HPRINTK("cs_stper reg = %d\n", reg);
-
- if (he_dev->cs_stper[reg].inuse == 0)
- hprintk("cs_stper[%d].inuse = 0!\n", reg);
- else
- --he_dev->cs_stper[reg].inuse;
-
- he_dev->total_bw -= he_dev->cs_stper[reg].pcr;
- }
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- HPRINTK("close tx cid 0x%x complete\n", cid);
- }
-
- kfree(he_vcc);
-
- clear_bit(ATM_VF_ADDR, &vcc->flags);
-}
-
-static int
-he_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- unsigned long flags;
- struct he_dev *he_dev = HE_DEV(vcc->dev);
- unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
- struct he_tpd *tpd;
-#ifdef USE_SCATTERGATHER
- int i, slot = 0;
-#endif
-
-#define HE_TPD_BUFSIZE 0xffff
-
- HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci);
-
- if ((skb->len > HE_TPD_BUFSIZE) ||
- ((vcc->qos.aal == ATM_AAL0) && (skb->len != ATM_AAL0_SDU))) {
- hprintk("buffer too large (or small) -- %d bytes\n", skb->len );
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- atomic_inc(&vcc->stats->tx_err);
- return -EINVAL;
- }
-
-#ifndef USE_SCATTERGATHER
- if (skb_shinfo(skb)->nr_frags) {
- hprintk("no scatter/gather support\n");
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- atomic_inc(&vcc->stats->tx_err);
- return -EINVAL;
- }
-#endif
- spin_lock_irqsave(&he_dev->global_lock, flags);
-
- tpd = __alloc_tpd(he_dev);
- if (tpd == NULL) {
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- atomic_inc(&vcc->stats->tx_err);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- return -ENOMEM;
- }
-
- if (vcc->qos.aal == ATM_AAL5)
- tpd->status |= TPD_CELLTYPE(TPD_USERCELL);
- else {
- char *pti_clp = (void *) (skb->data + 3);
- int clp, pti;
-
- pti = (*pti_clp & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;
- clp = (*pti_clp & ATM_HDR_CLP);
- tpd->status |= TPD_CELLTYPE(pti);
- if (clp)
- tpd->status |= TPD_CLP;
-
- skb_pull(skb, ATM_AAL0_SDU - ATM_CELL_PAYLOAD);
- }
-
-#ifdef USE_SCATTERGATHER
- tpd->iovec[slot].addr = dma_map_single(&he_dev->pci_dev->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
- tpd->iovec[slot].len = skb_headlen(skb);
- ++slot;
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- if (slot == TPD_MAXIOV) { /* queue tpd; start new tpd */
- tpd->vcc = vcc;
- tpd->skb = NULL; /* not the last fragment
- so dont ->push() yet */
- wmb();
-
- __enqueue_tpd(he_dev, tpd, cid);
- tpd = __alloc_tpd(he_dev);
- if (tpd == NULL) {
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- atomic_inc(&vcc->stats->tx_err);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- return -ENOMEM;
- }
- tpd->status |= TPD_USERCELL;
- slot = 0;
- }
-
- tpd->iovec[slot].addr = skb_frag_dma_map(&he_dev->pci_dev->dev,
- frag, 0, skb_frag_size(frag), DMA_TO_DEVICE);
- tpd->iovec[slot].len = skb_frag_size(frag);
- ++slot;
-
- }
-
- tpd->iovec[slot - 1].len |= TPD_LST;
-#else
- tpd->address0 = dma_map_single(&he_dev->pci_dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
- tpd->length0 = skb->len | TPD_LST;
-#endif
- tpd->status |= TPD_INT;
-
- tpd->vcc = vcc;
- tpd->skb = skb;
- wmb();
- ATM_SKB(skb)->vcc = vcc;
-
- __enqueue_tpd(he_dev, tpd, cid);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- atomic_inc(&vcc->stats->tx);
-
- return 0;
-}
-
-static int
-he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg)
-{
- unsigned long flags;
- struct he_dev *he_dev = HE_DEV(atm_dev);
- struct he_ioctl_reg reg;
- int err = 0;
-
- switch (cmd) {
- case HE_GET_REG:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- if (copy_from_user(®, arg,
- sizeof(struct he_ioctl_reg)))
- return -EFAULT;
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
- switch (reg.type) {
- case HE_REGTYPE_PCI:
- if (reg.addr >= HE_REGMAP_SIZE) {
- err = -EINVAL;
- break;
- }
-
- reg.val = he_readl(he_dev, reg.addr);
- break;
- case HE_REGTYPE_RCM:
- reg.val =
- he_readl_rcm(he_dev, reg.addr);
- break;
- case HE_REGTYPE_TCM:
- reg.val =
- he_readl_tcm(he_dev, reg.addr);
- break;
- case HE_REGTYPE_MBOX:
- reg.val =
- he_readl_mbox(he_dev, reg.addr);
- break;
- default:
- err = -EINVAL;
- break;
- }
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
- if (err == 0)
- if (copy_to_user(arg, ®,
- sizeof(struct he_ioctl_reg)))
- return -EFAULT;
- break;
- default:
-#ifdef CONFIG_ATM_HE_USE_SUNI
- if (atm_dev->phy && atm_dev->phy->ioctl)
- err = atm_dev->phy->ioctl(atm_dev, cmd, arg);
-#else /* CONFIG_ATM_HE_USE_SUNI */
- err = -EINVAL;
-#endif /* CONFIG_ATM_HE_USE_SUNI */
- break;
- }
-
- return err;
-}
-
-static void
-he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr)
-{
- unsigned long flags;
- struct he_dev *he_dev = HE_DEV(atm_dev);
-
- HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr);
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
- he_writel(he_dev, val, FRAMER + (addr*4));
- (void) he_readl(he_dev, FRAMER + (addr*4)); /* flush posted writes */
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-}
-
-
-static unsigned char
-he_phy_get(struct atm_dev *atm_dev, unsigned long addr)
-{
- unsigned long flags;
- struct he_dev *he_dev = HE_DEV(atm_dev);
- unsigned reg;
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
- reg = he_readl(he_dev, FRAMER + (addr*4));
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- HPRINTK("phy_get(addr 0x%lx) =0x%x\n", addr, reg);
- return reg;
-}
-
-static int
-he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
-{
- unsigned long flags;
- struct he_dev *he_dev = HE_DEV(dev);
- int left, i;
-#ifdef notdef
- struct he_rbrq *rbrq_tail;
- struct he_tpdrq *tpdrq_head;
- int rbpl_head, rbpl_tail;
-#endif
- static long mcc = 0, oec = 0, dcc = 0, cec = 0;
-
-
- left = *pos;
- if (!left--)
- return sprintf(page, "ATM he driver\n");
-
- if (!left--)
- return sprintf(page, "%s%s\n\n",
- he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM");
-
- if (!left--)
- return sprintf(page, "Mismatched Cells VPI/VCI Not Open Dropped Cells RCM Dropped Cells\n");
-
- spin_lock_irqsave(&he_dev->global_lock, flags);
- mcc += he_readl(he_dev, MCC);
- oec += he_readl(he_dev, OEC);
- dcc += he_readl(he_dev, DCC);
- cec += he_readl(he_dev, CEC);
- spin_unlock_irqrestore(&he_dev->global_lock, flags);
-
- if (!left--)
- return sprintf(page, "%16ld %16ld %13ld %17ld\n\n",
- mcc, oec, dcc, cec);
-
- if (!left--)
- return sprintf(page, "irq_size = %d inuse = ? peak = %d\n",
- CONFIG_IRQ_SIZE, he_dev->irq_peak);
-
- if (!left--)
- return sprintf(page, "tpdrq_size = %d inuse = ?\n",
- CONFIG_TPDRQ_SIZE);
-
- if (!left--)
- return sprintf(page, "rbrq_size = %d inuse = ? peak = %d\n",
- CONFIG_RBRQ_SIZE, he_dev->rbrq_peak);
-
- if (!left--)
- return sprintf(page, "tbrq_size = %d peak = %d\n",
- CONFIG_TBRQ_SIZE, he_dev->tbrq_peak);
-
-
-#ifdef notdef
- rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S));
- rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T));
-
- inuse = rbpl_head - rbpl_tail;
- if (inuse < 0)
- inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp);
- inuse /= sizeof(struct he_rbp);
-
- if (!left--)
- return sprintf(page, "rbpl_size = %d inuse = %d\n\n",
- CONFIG_RBPL_SIZE, inuse);
-#endif
-
- if (!left--)
- return sprintf(page, "rate controller periods (cbr)\n pcr #vc\n");
-
- for (i = 0; i < HE_NUM_CS_STPER; ++i)
- if (!left--)
- return sprintf(page, "cs_stper%-2d %8ld %3d\n", i,
- he_dev->cs_stper[i].pcr,
- he_dev->cs_stper[i].inuse);
-
- if (!left--)
- return sprintf(page, "total bw (cbr): %d (limit %d)\n",
- he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9);
-
- return 0;
-}
-
-/* eeprom routines -- see 4.7 */
-
-static u8 read_prom_byte(struct he_dev *he_dev, int addr)
-{
- u32 val = 0, tmp_read = 0;
- int i, j = 0;
- u8 byte_read = 0;
-
- val = readl(he_dev->membase + HOST_CNTL);
- val &= 0xFFFFE0FF;
-
- /* Turn on write enable */
- val |= 0x800;
- he_writel(he_dev, val, HOST_CNTL);
-
- /* Send READ instruction */
- for (i = 0; i < ARRAY_SIZE(readtab); i++) {
- he_writel(he_dev, val | readtab[i], HOST_CNTL);
- udelay(EEPROM_DELAY);
- }
-
- /* Next, we need to send the byte address to read from */
- for (i = 7; i >= 0; i--) {
- he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL);
- udelay(EEPROM_DELAY);
- he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL);
- udelay(EEPROM_DELAY);
- }
-
- j = 0;
-
- val &= 0xFFFFF7FF; /* Turn off write enable */
- he_writel(he_dev, val, HOST_CNTL);
-
- /* Now, we can read data from the EEPROM by clocking it in */
- for (i = 7; i >= 0; i--) {
- he_writel(he_dev, val | clocktab[j++], HOST_CNTL);
- udelay(EEPROM_DELAY);
- tmp_read = he_readl(he_dev, HOST_CNTL);
- byte_read |= (unsigned char)
- ((tmp_read & ID_DOUT) >> ID_DOFFSET << i);
- he_writel(he_dev, val | clocktab[j++], HOST_CNTL);
- udelay(EEPROM_DELAY);
- }
-
- he_writel(he_dev, val | ID_CS, HOST_CNTL);
- udelay(EEPROM_DELAY);
-
- return byte_read;
-}
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>");
-MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver");
-module_param(disable64, bool, 0);
-MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers");
-module_param(nvpibits, short, 0);
-MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)");
-module_param(nvcibits, short, 0);
-MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)");
-module_param(rx_skb_reserve, short, 0);
-MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)");
-module_param(irq_coalesce, bool, 0);
-MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)");
-module_param(sdh, bool, 0);
-MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
-
-static const struct pci_device_id he_pci_tbl[] = {
- { PCI_VDEVICE(FORE, PCI_DEVICE_ID_FORE_HE), 0 },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, he_pci_tbl);
-
-static struct pci_driver he_driver = {
- .name = "he",
- .probe = he_init_one,
- .remove = he_remove_one,
- .id_table = he_pci_tbl,
-};
-
-module_pci_driver(he_driver);
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
deleted file mode 100644
index 4bbcca7f77c8..000000000000
--- a/drivers/atm/idt77105.c
+++ /dev/null
@@ -1,376 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* drivers/atm/idt77105.c - IDT77105 (PHY) driver */
-
-/* Written 1999 by Greg Banks, NEC Australia <gnb@linuxfan.com>. Based on suni.c */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/atmdev.h>
-#include <linux/sonet.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/capability.h>
-#include <linux/atm_idt77105.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <asm/param.h>
-#include <linux/uaccess.h>
-
-#include "idt77105.h"
-
-#undef GENERAL_DEBUG
-
-#ifdef GENERAL_DEBUG
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-
-struct idt77105_priv {
- struct idt77105_stats stats; /* link diagnostics */
- struct atm_dev *dev; /* device back-pointer */
- struct idt77105_priv *next;
- int loop_mode;
- unsigned char old_mcr; /* storage of MCR reg while signal lost */
-};
-
-static DEFINE_SPINLOCK(idt77105_priv_lock);
-
-#define PRIV(dev) ((struct idt77105_priv *) dev->phy_data)
-
-#define PUT(val,reg) dev->ops->phy_put(dev,val,IDT77105_##reg)
-#define GET(reg) dev->ops->phy_get(dev,IDT77105_##reg)
-
-static void idt77105_stats_timer_func(struct timer_list *);
-static void idt77105_restart_timer_func(struct timer_list *);
-
-
-static DEFINE_TIMER(stats_timer, idt77105_stats_timer_func);
-static DEFINE_TIMER(restart_timer, idt77105_restart_timer_func);
-static int start_timer = 1;
-static struct idt77105_priv *idt77105_all = NULL;
-
-/*
- * Retrieve the value of one of the IDT77105's counters.
- * `counter' is one of the IDT77105_CTRSEL_* constants.
- */
-static u16 get_counter(struct atm_dev *dev, int counter)
-{
- u16 val;
-
- /* write the counter bit into PHY register 6 */
- PUT(counter, CTRSEL);
- /* read the low 8 bits from register 4 */
- val = GET(CTRLO);
- /* read the high 8 bits from register 5 */
- val |= GET(CTRHI)<<8;
-
- return val;
-}
-
-/*
- * Timer function called every second to gather statistics
- * from the 77105. This is done because the h/w registers
- * will overflow if not read at least once per second. The
- * kernel's stats are much higher precision. Also, having
- * a separate copy of the stats allows implementation of
- * an ioctl which gathers the stats *without* zero'ing them.
- */
-static void idt77105_stats_timer_func(struct timer_list *unused)
-{
- struct idt77105_priv *walk;
- struct atm_dev *dev;
- struct idt77105_stats *stats;
-
- DPRINTK("IDT77105 gathering statistics\n");
- for (walk = idt77105_all; walk; walk = walk->next) {
- dev = walk->dev;
-
- stats = &walk->stats;
- stats->symbol_errors += get_counter(dev, IDT77105_CTRSEL_SEC);
- stats->tx_cells += get_counter(dev, IDT77105_CTRSEL_TCC);
- stats->rx_cells += get_counter(dev, IDT77105_CTRSEL_RCC);
- stats->rx_hec_errors += get_counter(dev, IDT77105_CTRSEL_RHEC);
- }
- if (!start_timer) mod_timer(&stats_timer,jiffies+IDT77105_STATS_TIMER_PERIOD);
-}
-
-
-/*
- * A separate timer func which handles restarting PHY chips which
- * have had the cable re-inserted after being pulled out. This is
- * done by polling the Good Signal Bit in the Interrupt Status
- * register every 5 seconds. The other technique (checking Good
- * Signal Bit in the interrupt handler) cannot be used because PHY
- * interrupts need to be disabled when the cable is pulled out
- * to avoid lots of spurious cell error interrupts.
- */
-static void idt77105_restart_timer_func(struct timer_list *unused)
-{
- struct idt77105_priv *walk;
- struct atm_dev *dev;
- unsigned char istat;
-
- DPRINTK("IDT77105 checking for cable re-insertion\n");
- for (walk = idt77105_all; walk; walk = walk->next) {
- dev = walk->dev;
-
- if (dev->signal != ATM_PHY_SIG_LOST)
- continue;
-
- istat = GET(ISTAT); /* side effect: clears all interrupt status bits */
- if (istat & IDT77105_ISTAT_GOODSIG) {
- /* Found signal again */
- atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND);
- printk(KERN_NOTICE "%s(itf %d): signal detected again\n",
- dev->type,dev->number);
- /* flush the receive FIFO */
- PUT( GET(DIAG) | IDT77105_DIAG_RFLUSH, DIAG);
- /* re-enable interrupts */
- PUT( walk->old_mcr ,MCR);
- }
- }
- if (!start_timer) mod_timer(&restart_timer,jiffies+IDT77105_RESTART_TIMER_PERIOD);
-}
-
-
-static int fetch_stats(struct atm_dev *dev,struct idt77105_stats __user *arg,int zero)
-{
- unsigned long flags;
- struct idt77105_stats stats;
-
- spin_lock_irqsave(&idt77105_priv_lock, flags);
- memcpy(&stats, &PRIV(dev)->stats, sizeof(struct idt77105_stats));
- if (zero)
- memset(&PRIV(dev)->stats, 0, sizeof(struct idt77105_stats));
- spin_unlock_irqrestore(&idt77105_priv_lock, flags);
- if (arg == NULL)
- return 0;
- return copy_to_user(arg, &stats,
- sizeof(struct idt77105_stats)) ? -EFAULT : 0;
-}
-
-
-static int set_loopback(struct atm_dev *dev,int mode)
-{
- int diag;
-
- diag = GET(DIAG) & ~IDT77105_DIAG_LCMASK;
- switch (mode) {
- case ATM_LM_NONE:
- break;
- case ATM_LM_LOC_ATM:
- diag |= IDT77105_DIAG_LC_PHY_LOOPBACK;
- break;
- case ATM_LM_RMT_ATM:
- diag |= IDT77105_DIAG_LC_LINE_LOOPBACK;
- break;
- default:
- return -EINVAL;
- }
- PUT(diag,DIAG);
- printk(KERN_NOTICE "%s(%d) Loopback mode is: %s\n", dev->type,
- dev->number,
- (mode == ATM_LM_NONE ? "NONE" :
- (mode == ATM_LM_LOC_ATM ? "DIAG (local)" :
- (mode == IDT77105_DIAG_LC_LINE_LOOPBACK ? "LOOP (remote)" :
- "unknown")))
- );
- PRIV(dev)->loop_mode = mode;
- return 0;
-}
-
-
-static int idt77105_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
-{
- printk(KERN_NOTICE "%s(%d) idt77105_ioctl() called\n",dev->type,dev->number);
- switch (cmd) {
- case IDT77105_GETSTATZ:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- fallthrough;
- case IDT77105_GETSTAT:
- return fetch_stats(dev, arg, cmd == IDT77105_GETSTATZ);
- case ATM_SETLOOP:
- return set_loopback(dev,(int)(unsigned long) arg);
- case ATM_GETLOOP:
- return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ?
- -EFAULT : 0;
- case ATM_QUERYLOOP:
- return put_user(ATM_LM_LOC_ATM | ATM_LM_RMT_ATM,
- (int __user *) arg) ? -EFAULT : 0;
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-
-
-static void idt77105_int(struct atm_dev *dev)
-{
- unsigned char istat;
-
- istat = GET(ISTAT); /* side effect: clears all interrupt status bits */
-
- DPRINTK("IDT77105 generated an interrupt, istat=%02x\n", (unsigned)istat);
-
- if (istat & IDT77105_ISTAT_RSCC) {
- /* Rx Signal Condition Change - line went up or down */
- if (istat & IDT77105_ISTAT_GOODSIG) { /* signal detected again */
- /* This should not happen (restart timer does it) but JIC */
- atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND);
- } else { /* signal lost */
- /*
- * Disable interrupts and stop all transmission and
- * reception - the restart timer will restore these.
- */
- PRIV(dev)->old_mcr = GET(MCR);
- PUT(
- (PRIV(dev)->old_mcr|
- IDT77105_MCR_DREC|
- IDT77105_MCR_DRIC|
- IDT77105_MCR_HALTTX
- ) & ~IDT77105_MCR_EIP, MCR);
- atm_dev_signal_change(dev, ATM_PHY_SIG_LOST);
- printk(KERN_NOTICE "%s(itf %d): signal lost\n",
- dev->type,dev->number);
- }
- }
-
- if (istat & IDT77105_ISTAT_RFO) {
- /* Rx FIFO Overrun -- perform a FIFO flush */
- PUT( GET(DIAG) | IDT77105_DIAG_RFLUSH, DIAG);
- printk(KERN_NOTICE "%s(itf %d): receive FIFO overrun\n",
- dev->type,dev->number);
- }
-#ifdef GENERAL_DEBUG
- if (istat & (IDT77105_ISTAT_HECERR | IDT77105_ISTAT_SCR |
- IDT77105_ISTAT_RSE)) {
- /* normally don't care - just report in stats */
- printk(KERN_NOTICE "%s(itf %d): received cell with error\n",
- dev->type,dev->number);
- }
-#endif
-}
-
-
-static int idt77105_start(struct atm_dev *dev)
-{
- unsigned long flags;
-
- if (!(dev->phy_data = kmalloc_obj(struct idt77105_priv)))
- return -ENOMEM;
- PRIV(dev)->dev = dev;
- spin_lock_irqsave(&idt77105_priv_lock, flags);
- PRIV(dev)->next = idt77105_all;
- idt77105_all = PRIV(dev);
- spin_unlock_irqrestore(&idt77105_priv_lock, flags);
- memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats));
-
- /* initialise dev->signal from Good Signal Bit */
- atm_dev_signal_change(dev,
- GET(ISTAT) & IDT77105_ISTAT_GOODSIG ?
- ATM_PHY_SIG_FOUND : ATM_PHY_SIG_LOST);
- if (dev->signal == ATM_PHY_SIG_LOST)
- printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type,
- dev->number);
-
- /* initialise loop mode from hardware */
- switch ( GET(DIAG) & IDT77105_DIAG_LCMASK ) {
- case IDT77105_DIAG_LC_NORMAL:
- PRIV(dev)->loop_mode = ATM_LM_NONE;
- break;
- case IDT77105_DIAG_LC_PHY_LOOPBACK:
- PRIV(dev)->loop_mode = ATM_LM_LOC_ATM;
- break;
- case IDT77105_DIAG_LC_LINE_LOOPBACK:
- PRIV(dev)->loop_mode = ATM_LM_RMT_ATM;
- break;
- }
-
- /* enable interrupts, e.g. on loss of signal */
- PRIV(dev)->old_mcr = GET(MCR);
- if (dev->signal == ATM_PHY_SIG_FOUND) {
- PRIV(dev)->old_mcr |= IDT77105_MCR_EIP;
- PUT(PRIV(dev)->old_mcr, MCR);
- }
-
-
- idt77105_stats_timer_func(0); /* clear 77105 counters */
- (void) fetch_stats(dev,NULL,1); /* clear kernel counters */
-
- spin_lock_irqsave(&idt77105_priv_lock, flags);
- if (start_timer) {
- start_timer = 0;
-
- stats_timer.expires = jiffies+IDT77105_STATS_TIMER_PERIOD;
- add_timer(&stats_timer);
-
- restart_timer.expires = jiffies+IDT77105_RESTART_TIMER_PERIOD;
- add_timer(&restart_timer);
- }
- spin_unlock_irqrestore(&idt77105_priv_lock, flags);
- return 0;
-}
-
-
-static int idt77105_stop(struct atm_dev *dev)
-{
- struct idt77105_priv *walk, *prev;
-
- DPRINTK("%s(itf %d): stopping IDT77105\n",dev->type,dev->number);
-
- /* disable interrupts */
- PUT( GET(MCR) & ~IDT77105_MCR_EIP, MCR );
-
- /* detach private struct from atm_dev & free */
- for (prev = NULL, walk = idt77105_all ;
- walk != NULL;
- prev = walk, walk = walk->next) {
- if (walk->dev == dev) {
- if (prev != NULL)
- prev->next = walk->next;
- else
- idt77105_all = walk->next;
- dev->phy = NULL;
- dev->phy_data = NULL;
- kfree(walk);
- break;
- }
- }
-
- return 0;
-}
-
-
-static const struct atmphy_ops idt77105_ops = {
- .start = idt77105_start,
- .ioctl = idt77105_ioctl,
- .interrupt = idt77105_int,
- .stop = idt77105_stop,
-};
-
-
-int idt77105_init(struct atm_dev *dev)
-{
- dev->phy = &idt77105_ops;
- return 0;
-}
-
-EXPORT_SYMBOL(idt77105_init);
-
-static void __exit idt77105_exit(void)
-{
- /* turn off timers */
- timer_delete_sync(&stats_timer);
- timer_delete_sync(&restart_timer);
-}
-
-module_exit(idt77105_exit);
-
-MODULE_DESCRIPTION("IDT77105 PHY driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
deleted file mode 100644
index 7f8aaf5e6e43..000000000000
--- a/drivers/atm/idt77252.c
+++ /dev/null
@@ -1,3797 +0,0 @@
-/*******************************************************************
- *
- * Copyright (c) 2000 ATecoM GmbH
- *
- * The author may be reached at ecd@atecom.com.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *******************************************************************/
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/poison.h>
-#include <linux/skbuff.h>
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-#include <linux/netdevice.h>
-#include <linux/atmdev.h>
-#include <linux/atm.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/wait.h>
-#include <linux/jiffies.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-#include <asm/byteorder.h>
-
-#ifdef CONFIG_ATM_IDT77252_USE_SUNI
-#include "suni.h"
-#endif /* CONFIG_ATM_IDT77252_USE_SUNI */
-
-
-#include "idt77252.h"
-#include "idt77252_tables.h"
-
-static unsigned int vpibits = 1;
-
-
-#define ATM_IDT77252_SEND_IDLE 1
-
-
-/*
- * Debug HACKs.
- */
-#define DEBUG_MODULE 1
-#undef HAVE_EEPROM /* does not work, yet. */
-
-#ifdef CONFIG_ATM_IDT77252_DEBUG
-static unsigned long debug = DBG_GENERAL;
-#endif
-
-
-#define SAR_RX_DELAY (SAR_CFG_RXINT_NODELAY)
-
-
-/*
- * SCQ Handling.
- */
-static struct scq_info *alloc_scq(struct idt77252_dev *, int);
-static void free_scq(struct idt77252_dev *, struct scq_info *);
-static int queue_skb(struct idt77252_dev *, struct vc_map *,
- struct sk_buff *, int oam);
-static void drain_scq(struct idt77252_dev *, struct vc_map *);
-static unsigned long get_free_scd(struct idt77252_dev *, struct vc_map *);
-static void fill_scd(struct idt77252_dev *, struct scq_info *, int);
-
-/*
- * FBQ Handling.
- */
-static int push_rx_skb(struct idt77252_dev *,
- struct sk_buff *, int queue);
-static void recycle_rx_skb(struct idt77252_dev *, struct sk_buff *);
-static void flush_rx_pool(struct idt77252_dev *, struct rx_pool *);
-static void recycle_rx_pool_skb(struct idt77252_dev *,
- struct rx_pool *);
-static void add_rx_skb(struct idt77252_dev *, int queue,
- unsigned int size, unsigned int count);
-
-/*
- * RSQ Handling.
- */
-static int init_rsq(struct idt77252_dev *);
-static void deinit_rsq(struct idt77252_dev *);
-static void idt77252_rx(struct idt77252_dev *);
-
-/*
- * TSQ handling.
- */
-static int init_tsq(struct idt77252_dev *);
-static void deinit_tsq(struct idt77252_dev *);
-static void idt77252_tx(struct idt77252_dev *);
-
-
-/*
- * ATM Interface.
- */
-static void idt77252_dev_close(struct atm_dev *dev);
-static int idt77252_open(struct atm_vcc *vcc);
-static void idt77252_close(struct atm_vcc *vcc);
-static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb);
-static int idt77252_send_oam(struct atm_vcc *vcc, void *cell,
- int flags);
-static void idt77252_phy_put(struct atm_dev *dev, unsigned char value,
- unsigned long addr);
-static unsigned char idt77252_phy_get(struct atm_dev *dev, unsigned long addr);
-static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos,
- int flags);
-static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos,
- char *page);
-static void idt77252_softint(struct work_struct *work);
-
-
-static const struct atmdev_ops idt77252_ops =
-{
- .dev_close = idt77252_dev_close,
- .open = idt77252_open,
- .close = idt77252_close,
- .send = idt77252_send,
- .send_oam = idt77252_send_oam,
- .phy_put = idt77252_phy_put,
- .phy_get = idt77252_phy_get,
- .change_qos = idt77252_change_qos,
- .proc_read = idt77252_proc_read,
- .owner = THIS_MODULE
-};
-
-static struct idt77252_dev *idt77252_chain = NULL;
-static unsigned int idt77252_sram_write_errors = 0;
-
-/*****************************************************************************/
-/* */
-/* I/O and Utility Bus */
-/* */
-/*****************************************************************************/
-
-static void
-waitfor_idle(struct idt77252_dev *card)
-{
- u32 stat;
-
- stat = readl(SAR_REG_STAT);
- while (stat & SAR_STAT_CMDBZ)
- stat = readl(SAR_REG_STAT);
-}
-
-static u32
-read_sram(struct idt77252_dev *card, unsigned long addr)
-{
- unsigned long flags;
- u32 value;
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(SAR_CMD_READ_SRAM | (addr << 2), SAR_REG_CMD);
- waitfor_idle(card);
- value = readl(SAR_REG_DR0);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
- return value;
-}
-
-static void
-write_sram(struct idt77252_dev *card, unsigned long addr, u32 value)
-{
- unsigned long flags;
-
- if ((idt77252_sram_write_errors == 0) &&
- (((addr > card->tst[0] + card->tst_size - 2) &&
- (addr < card->tst[0] + card->tst_size)) ||
- ((addr > card->tst[1] + card->tst_size - 2) &&
- (addr < card->tst[1] + card->tst_size)))) {
- printk("%s: ERROR: TST JMP section at %08lx written: %08x\n",
- card->name, addr, value);
- }
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(value, SAR_REG_DR0);
- writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD);
- waitfor_idle(card);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
-}
-
-static u8
-read_utility(void *dev, unsigned long ubus_addr)
-{
- struct idt77252_dev *card = dev;
- unsigned long flags;
- u8 value;
-
- if (!card) {
- printk("Error: No such device.\n");
- return -1;
- }
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(SAR_CMD_READ_UTILITY + ubus_addr, SAR_REG_CMD);
- waitfor_idle(card);
- value = readl(SAR_REG_DR0);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
- return value;
-}
-
-static void
-write_utility(void *dev, unsigned long ubus_addr, u8 value)
-{
- struct idt77252_dev *card = dev;
- unsigned long flags;
-
- if (!card) {
- printk("Error: No such device.\n");
- return;
- }
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel((u32) value, SAR_REG_DR0);
- writel(SAR_CMD_WRITE_UTILITY + ubus_addr, SAR_REG_CMD);
- waitfor_idle(card);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
-}
-
-#ifdef HAVE_EEPROM
-static u32 rdsrtab[] =
-{
- SAR_GP_EECS | SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- SAR_GP_EEDO,
- SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- SAR_GP_EEDO,
- SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */
-};
-
-static u32 wrentab[] =
-{
- SAR_GP_EECS | SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- SAR_GP_EEDO,
- SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
- SAR_GP_EEDO,
- SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK /* 0 */
-};
-
-static u32 rdtab[] =
-{
- SAR_GP_EECS | SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- SAR_GP_EEDO,
- SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
- SAR_GP_EEDO,
- SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */
-};
-
-static u32 wrtab[] =
-{
- SAR_GP_EECS | SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- 0,
- SAR_GP_EESCLK, /* 0 */
- SAR_GP_EEDO,
- SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */
- 0,
- SAR_GP_EESCLK /* 0 */
-};
-
-static u32 clktab[] =
-{
- 0,
- SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK,
- 0,
- SAR_GP_EESCLK,
- 0
-};
-
-static u32
-idt77252_read_gp(struct idt77252_dev *card)
-{
- u32 gp;
-
- gp = readl(SAR_REG_GP);
-#if 0
- printk("RD: %s\n", gp & SAR_GP_EEDI ? "1" : "0");
-#endif
- return gp;
-}
-
-static void
-idt77252_write_gp(struct idt77252_dev *card, u32 value)
-{
- unsigned long flags;
-
-#if 0
- printk("WR: %s %s %s\n", value & SAR_GP_EECS ? " " : "/CS",
- value & SAR_GP_EESCLK ? "HIGH" : "LOW ",
- value & SAR_GP_EEDO ? "1" : "0");
-#endif
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- waitfor_idle(card);
- writel(value, SAR_REG_GP);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
-}
-
-static u8
-idt77252_eeprom_read_status(struct idt77252_dev *card)
-{
- u8 byte;
- u32 gp;
- int i, j;
-
- gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
-
- for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
- idt77252_write_gp(card, gp | rdsrtab[i]);
- udelay(5);
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- byte = 0;
- for (i = 0, j = 0; i < 8; i++) {
- byte <<= 1;
-
- idt77252_write_gp(card, gp | clktab[j++]);
- udelay(5);
-
- byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
-
- idt77252_write_gp(card, gp | clktab[j++]);
- udelay(5);
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- return byte;
-}
-
-static u8
-idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset)
-{
- u8 byte;
- u32 gp;
- int i, j;
-
- gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
-
- for (i = 0; i < ARRAY_SIZE(rdtab); i++) {
- idt77252_write_gp(card, gp | rdtab[i]);
- udelay(5);
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- for (i = 0, j = 0; i < 8; i++) {
- idt77252_write_gp(card, gp | clktab[j++] |
- (offset & 1 ? SAR_GP_EEDO : 0));
- udelay(5);
-
- idt77252_write_gp(card, gp | clktab[j++] |
- (offset & 1 ? SAR_GP_EEDO : 0));
- udelay(5);
-
- offset >>= 1;
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- byte = 0;
- for (i = 0, j = 0; i < 8; i++) {
- byte <<= 1;
-
- idt77252_write_gp(card, gp | clktab[j++]);
- udelay(5);
-
- byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
-
- idt77252_write_gp(card, gp | clktab[j++]);
- udelay(5);
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- return byte;
-}
-
-static void
-idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data)
-{
- u32 gp;
- int i, j;
-
- gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
-
- for (i = 0; i < ARRAY_SIZE(wrentab); i++) {
- idt77252_write_gp(card, gp | wrentab[i]);
- udelay(5);
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- for (i = 0; i < ARRAY_SIZE(wrtab); i++) {
- idt77252_write_gp(card, gp | wrtab[i]);
- udelay(5);
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- for (i = 0, j = 0; i < 8; i++) {
- idt77252_write_gp(card, gp | clktab[j++] |
- (offset & 1 ? SAR_GP_EEDO : 0));
- udelay(5);
-
- idt77252_write_gp(card, gp | clktab[j++] |
- (offset & 1 ? SAR_GP_EEDO : 0));
- udelay(5);
-
- offset >>= 1;
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-
- for (i = 0, j = 0; i < 8; i++) {
- idt77252_write_gp(card, gp | clktab[j++] |
- (data & 1 ? SAR_GP_EEDO : 0));
- udelay(5);
-
- idt77252_write_gp(card, gp | clktab[j++] |
- (data & 1 ? SAR_GP_EEDO : 0));
- udelay(5);
-
- data >>= 1;
- }
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-}
-
-static void
-idt77252_eeprom_init(struct idt77252_dev *card)
-{
- u32 gp;
-
- gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
-
- idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
- udelay(5);
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
- idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
- udelay(5);
- idt77252_write_gp(card, gp | SAR_GP_EECS);
- udelay(5);
-}
-#endif /* HAVE_EEPROM */
-
-
-#ifdef CONFIG_ATM_IDT77252_DEBUG
-static void
-dump_tct(struct idt77252_dev *card, int index)
-{
- unsigned long tct;
- int i;
-
- tct = (unsigned long) (card->tct_base + index * SAR_SRAM_TCT_SIZE);
-
- printk("%s: TCT %x:", card->name, index);
- for (i = 0; i < 8; i++) {
- printk(" %08x", read_sram(card, tct + i));
- }
- printk("\n");
-}
-
-static void
-idt77252_tx_dump(struct idt77252_dev *card)
-{
- struct atm_vcc *vcc;
- struct vc_map *vc;
- int i;
-
- printk("%s\n", __func__);
- for (i = 0; i < card->tct_size; i++) {
- vc = card->vcs[i];
- if (!vc)
- continue;
-
- vcc = NULL;
- if (vc->rx_vcc)
- vcc = vc->rx_vcc;
- else if (vc->tx_vcc)
- vcc = vc->tx_vcc;
-
- if (!vcc)
- continue;
-
- printk("%s: Connection %d:\n", card->name, vc->index);
- dump_tct(card, vc->index);
- }
-}
-#endif
-
-
-/*****************************************************************************/
-/* */
-/* SCQ Handling */
-/* */
-/*****************************************************************************/
-
-static int
-sb_pool_add(struct idt77252_dev *card, struct sk_buff *skb, int queue)
-{
- struct sb_pool *pool = &card->sbpool[queue];
- int index;
-
- index = pool->index;
- while (pool->skb[index]) {
- index = (index + 1) & FBQ_MASK;
- if (index == pool->index)
- return -ENOBUFS;
- }
-
- pool->skb[index] = skb;
- IDT77252_PRV_POOL(skb) = POOL_HANDLE(queue, index);
-
- pool->index = (index + 1) & FBQ_MASK;
- return 0;
-}
-
-static void
-sb_pool_remove(struct idt77252_dev *card, struct sk_buff *skb)
-{
- unsigned int queue, index;
- u32 handle;
-
- handle = IDT77252_PRV_POOL(skb);
-
- queue = POOL_QUEUE(handle);
- if (queue > 3)
- return;
-
- index = POOL_INDEX(handle);
- if (index > FBQ_SIZE - 1)
- return;
-
- card->sbpool[queue].skb[index] = NULL;
-}
-
-static struct sk_buff *
-sb_pool_skb(struct idt77252_dev *card, u32 handle)
-{
- unsigned int queue, index;
-
- queue = POOL_QUEUE(handle);
- if (queue > 3)
- return NULL;
-
- index = POOL_INDEX(handle);
- if (index > FBQ_SIZE - 1)
- return NULL;
-
- return card->sbpool[queue].skb[index];
-}
-
-static struct scq_info *
-alloc_scq(struct idt77252_dev *card, int class)
-{
- struct scq_info *scq;
-
- scq = kzalloc_obj(struct scq_info);
- if (!scq)
- return NULL;
- scq->base = dma_alloc_coherent(&card->pcidev->dev, SCQ_SIZE,
- &scq->paddr, GFP_KERNEL);
- if (scq->base == NULL) {
- kfree(scq);
- return NULL;
- }
-
- scq->next = scq->base;
- scq->last = scq->base + (SCQ_ENTRIES - 1);
- atomic_set(&scq->used, 0);
-
- spin_lock_init(&scq->lock);
- spin_lock_init(&scq->skblock);
-
- skb_queue_head_init(&scq->transmit);
- skb_queue_head_init(&scq->pending);
-
- TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08llx\n",
- scq->base, scq->next, scq->last, (unsigned long long)scq->paddr);
-
- return scq;
-}
-
-static void
-free_scq(struct idt77252_dev *card, struct scq_info *scq)
-{
- struct sk_buff *skb;
- struct atm_vcc *vcc;
-
- dma_free_coherent(&card->pcidev->dev, SCQ_SIZE,
- scq->base, scq->paddr);
-
- while ((skb = skb_dequeue(&scq->transmit))) {
- dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb->len, DMA_TO_DEVICE);
-
- vcc = ATM_SKB(skb)->vcc;
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb(skb);
- }
-
- while ((skb = skb_dequeue(&scq->pending))) {
- dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb->len, DMA_TO_DEVICE);
-
- vcc = ATM_SKB(skb)->vcc;
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb(skb);
- }
-
- kfree(scq);
-}
-
-
-static int
-push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
-{
- struct scq_info *scq = vc->scq;
- unsigned long flags;
- struct scqe *tbd;
- int entries;
-
- TXPRINTK("%s: SCQ: next 0x%p\n", card->name, scq->next);
-
- atomic_inc(&scq->used);
- entries = atomic_read(&scq->used);
- if (entries > (SCQ_ENTRIES - 1)) {
- atomic_dec(&scq->used);
- goto out;
- }
-
- skb_queue_tail(&scq->transmit, skb);
-
- spin_lock_irqsave(&vc->lock, flags);
- if (vc->estimator) {
- struct atm_vcc *vcc = vc->tx_vcc;
- struct sock *sk = sk_atm(vcc);
-
- vc->estimator->cells += (skb->len + 47) / 48;
- if (refcount_read(&sk->sk_wmem_alloc) >
- (sk->sk_sndbuf >> 1)) {
- u32 cps = vc->estimator->maxcps;
-
- vc->estimator->cps = cps;
- vc->estimator->avcps = cps << 5;
- if (vc->lacr < vc->init_er) {
- vc->lacr = vc->init_er;
- writel(TCMDQ_LACR | (vc->lacr << 16) |
- vc->index, SAR_REG_TCMDQ);
- }
- }
- }
- spin_unlock_irqrestore(&vc->lock, flags);
-
- tbd = &IDT77252_PRV_TBD(skb);
-
- spin_lock_irqsave(&scq->lock, flags);
- scq->next->word_1 = cpu_to_le32(tbd->word_1 |
- SAR_TBD_TSIF | SAR_TBD_GTSI);
- scq->next->word_2 = cpu_to_le32(tbd->word_2);
- scq->next->word_3 = cpu_to_le32(tbd->word_3);
- scq->next->word_4 = cpu_to_le32(tbd->word_4);
-
- if (scq->next == scq->last)
- scq->next = scq->base;
- else
- scq->next++;
-
- write_sram(card, scq->scd,
- scq->paddr +
- (u32)((unsigned long)scq->next - (unsigned long)scq->base));
- spin_unlock_irqrestore(&scq->lock, flags);
-
- scq->trans_start = jiffies;
-
- if (test_and_clear_bit(VCF_IDLE, &vc->flags)) {
- writel(TCMDQ_START_LACR | (vc->lacr << 16) | vc->index,
- SAR_REG_TCMDQ);
- }
-
- TXPRINTK("%d entries in SCQ used (push).\n", atomic_read(&scq->used));
-
- XPRINTK("%s: SCQ (after push %2d) head = 0x%x, next = 0x%p.\n",
- card->name, atomic_read(&scq->used),
- read_sram(card, scq->scd + 1), scq->next);
-
- return 0;
-
-out:
- if (time_after(jiffies, scq->trans_start + HZ)) {
- printk("%s: Error pushing TBD for %d.%d\n",
- card->name, vc->tx_vcc->vpi, vc->tx_vcc->vci);
-#ifdef CONFIG_ATM_IDT77252_DEBUG
- idt77252_tx_dump(card);
-#endif
- scq->trans_start = jiffies;
- }
-
- return -ENOBUFS;
-}
-
-
-static void
-drain_scq(struct idt77252_dev *card, struct vc_map *vc)
-{
- struct scq_info *scq = vc->scq;
- struct sk_buff *skb;
- struct atm_vcc *vcc;
-
- TXPRINTK("%s: SCQ (before drain %2d) next = 0x%p.\n",
- card->name, atomic_read(&scq->used), scq->next);
-
- skb = skb_dequeue(&scq->transmit);
- if (skb) {
- TXPRINTK("%s: freeing skb at %p.\n", card->name, skb);
-
- dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb->len, DMA_TO_DEVICE);
-
- vcc = ATM_SKB(skb)->vcc;
-
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb(skb);
-
- atomic_inc(&vcc->stats->tx);
- }
-
- atomic_dec(&scq->used);
-
- spin_lock(&scq->skblock);
- while ((skb = skb_dequeue(&scq->pending))) {
- if (push_on_scq(card, vc, skb)) {
- skb_queue_head(&vc->scq->pending, skb);
- break;
- }
- }
- spin_unlock(&scq->skblock);
-}
-
-static int
-queue_skb(struct idt77252_dev *card, struct vc_map *vc,
- struct sk_buff *skb, int oam)
-{
- struct atm_vcc *vcc;
- struct scqe *tbd;
- unsigned long flags;
- int error;
- int aal;
- u32 word4;
-
- if (skb->len == 0) {
- printk("%s: invalid skb->len (%d)\n", card->name, skb->len);
- return -EINVAL;
- }
-
- TXPRINTK("%s: Sending %d bytes of data.\n",
- card->name, skb->len);
-
- tbd = &IDT77252_PRV_TBD(skb);
- vcc = ATM_SKB(skb)->vcc;
- word4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
- (skb->data[2] << 8) | (skb->data[3] << 0);
-
- IDT77252_PRV_PADDR(skb) = dma_map_single(&card->pcidev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
- if (dma_mapping_error(&card->pcidev->dev, IDT77252_PRV_PADDR(skb)))
- return -ENOMEM;
-
- error = -EINVAL;
-
- if (oam) {
- if (skb->len != 52)
- goto errout;
-
- tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU;
- tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
- tbd->word_3 = 0x00000000;
- tbd->word_4 = word4;
-
- if (test_bit(VCF_RSV, &vc->flags))
- vc = card->vcs[0];
-
- goto done;
- }
-
- if (test_bit(VCF_RSV, &vc->flags)) {
- printk("%s: Trying to transmit on reserved VC\n", card->name);
- goto errout;
- }
-
- aal = vcc->qos.aal;
-
- switch (aal) {
- case ATM_AAL0:
- case ATM_AAL34:
- if (skb->len > 52)
- goto errout;
-
- if (aal == ATM_AAL0)
- tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL0 |
- ATM_CELL_PAYLOAD;
- else
- tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL34 |
- ATM_CELL_PAYLOAD;
-
- tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
- tbd->word_3 = 0x00000000;
- tbd->word_4 = word4;
- break;
-
- case ATM_AAL5:
- tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL5 | skb->len;
- tbd->word_2 = IDT77252_PRV_PADDR(skb);
- tbd->word_3 = skb->len;
- tbd->word_4 = (vcc->vpi << SAR_TBD_VPI_SHIFT) |
- (vcc->vci << SAR_TBD_VCI_SHIFT);
- break;
-
- case ATM_AAL1:
- case ATM_AAL2:
- default:
- printk("%s: Traffic type not supported.\n", card->name);
- error = -EPROTONOSUPPORT;
- goto errout;
- }
-
-done:
- spin_lock_irqsave(&vc->scq->skblock, flags);
- skb_queue_tail(&vc->scq->pending, skb);
-
- while ((skb = skb_dequeue(&vc->scq->pending))) {
- if (push_on_scq(card, vc, skb)) {
- skb_queue_head(&vc->scq->pending, skb);
- break;
- }
- }
- spin_unlock_irqrestore(&vc->scq->skblock, flags);
-
- return 0;
-
-errout:
- dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb->len, DMA_TO_DEVICE);
- return error;
-}
-
-static unsigned long
-get_free_scd(struct idt77252_dev *card, struct vc_map *vc)
-{
- int i;
-
- for (i = 0; i < card->scd_size; i++) {
- if (!card->scd2vc[i]) {
- card->scd2vc[i] = vc;
- vc->scd_index = i;
- return card->scd_base + i * SAR_SRAM_SCD_SIZE;
- }
- }
- return 0;
-}
-
-static void
-fill_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
-{
- write_sram(card, scq->scd, scq->paddr);
- write_sram(card, scq->scd + 1, 0x00000000);
- write_sram(card, scq->scd + 2, 0xffffffff);
- write_sram(card, scq->scd + 3, 0x00000000);
-}
-
-static void
-clear_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
-{
- return;
-}
-
-/*****************************************************************************/
-/* */
-/* RSQ Handling */
-/* */
-/*****************************************************************************/
-
-static int
-init_rsq(struct idt77252_dev *card)
-{
- struct rsq_entry *rsqe;
-
- card->rsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE,
- &card->rsq.paddr, GFP_KERNEL);
- if (card->rsq.base == NULL) {
- printk("%s: can't allocate RSQ.\n", card->name);
- return -1;
- }
-
- card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1;
- card->rsq.next = card->rsq.last;
- for (rsqe = card->rsq.base; rsqe <= card->rsq.last; rsqe++)
- rsqe->word_4 = 0;
-
- writel((unsigned long) card->rsq.last - (unsigned long) card->rsq.base,
- SAR_REG_RSQH);
- writel(card->rsq.paddr, SAR_REG_RSQB);
-
- IPRINTK("%s: RSQ base at 0x%lx (0x%x).\n", card->name,
- (unsigned long) card->rsq.base,
- readl(SAR_REG_RSQB));
- IPRINTK("%s: RSQ head = 0x%x, base = 0x%x, tail = 0x%x.\n",
- card->name,
- readl(SAR_REG_RSQH),
- readl(SAR_REG_RSQB),
- readl(SAR_REG_RSQT));
-
- return 0;
-}
-
-static void
-deinit_rsq(struct idt77252_dev *card)
-{
- dma_free_coherent(&card->pcidev->dev, RSQSIZE,
- card->rsq.base, card->rsq.paddr);
-}
-
-static void
-dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
-{
- struct atm_vcc *vcc;
- struct sk_buff *skb;
- struct rx_pool *rpp;
- struct vc_map *vc;
- u32 header, vpi, vci;
- u32 stat;
- int i;
-
- stat = le32_to_cpu(rsqe->word_4);
-
- if (stat & SAR_RSQE_IDLE) {
- RXPRINTK("%s: message about inactive connection.\n",
- card->name);
- return;
- }
-
- skb = sb_pool_skb(card, le32_to_cpu(rsqe->word_2));
- if (skb == NULL) {
- printk("%s: NULL skb in %s, rsqe: %08x %08x %08x %08x\n",
- card->name, __func__,
- le32_to_cpu(rsqe->word_1), le32_to_cpu(rsqe->word_2),
- le32_to_cpu(rsqe->word_3), le32_to_cpu(rsqe->word_4));
- return;
- }
-
- header = le32_to_cpu(rsqe->word_1);
- vpi = (header >> 16) & 0x00ff;
- vci = (header >> 0) & 0xffff;
-
- RXPRINTK("%s: SDU for %d.%d received in buffer 0x%p (data 0x%p).\n",
- card->name, vpi, vci, skb, skb->data);
-
- if ((vpi >= (1 << card->vpibits)) || (vci != (vci & card->vcimask))) {
- printk("%s: SDU received for out-of-range vc %u.%u\n",
- card->name, vpi, vci);
- recycle_rx_skb(card, skb);
- return;
- }
-
- vc = card->vcs[VPCI2VC(card, vpi, vci)];
- if (!vc || !test_bit(VCF_RX, &vc->flags)) {
- printk("%s: SDU received on non RX vc %u.%u\n",
- card->name, vpi, vci);
- recycle_rx_skb(card, skb);
- return;
- }
-
- vcc = vc->rx_vcc;
-
- dma_sync_single_for_cpu(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb_end_pointer(skb) - skb->data,
- DMA_FROM_DEVICE);
-
- if ((vcc->qos.aal == ATM_AAL0) ||
- (vcc->qos.aal == ATM_AAL34)) {
- struct sk_buff *sb;
- unsigned char *cell;
- u32 aal0;
-
- cell = skb->data;
- for (i = (stat & SAR_RSQE_CELLCNT); i; i--) {
- if ((sb = dev_alloc_skb(64)) == NULL) {
- printk("%s: Can't allocate buffers for aal0.\n",
- card->name);
- atomic_add(i, &vcc->stats->rx_drop);
- break;
- }
- if (!atm_charge(vcc, sb->truesize)) {
- RXPRINTK("%s: atm_charge() dropped aal0 packets.\n",
- card->name);
- atomic_add(i - 1, &vcc->stats->rx_drop);
- dev_kfree_skb(sb);
- break;
- }
- aal0 = (vpi << ATM_HDR_VPI_SHIFT) |
- (vci << ATM_HDR_VCI_SHIFT);
- aal0 |= (stat & SAR_RSQE_EPDU) ? 0x00000002 : 0;
- aal0 |= (stat & SAR_RSQE_CLP) ? 0x00000001 : 0;
-
- *((u32 *) sb->data) = aal0;
- skb_put(sb, sizeof(u32));
- skb_put_data(sb, cell, ATM_CELL_PAYLOAD);
-
- ATM_SKB(sb)->vcc = vcc;
- __net_timestamp(sb);
- vcc->push(vcc, sb);
- atomic_inc(&vcc->stats->rx);
-
- cell += ATM_CELL_PAYLOAD;
- }
-
- recycle_rx_skb(card, skb);
- return;
- }
- if (vcc->qos.aal != ATM_AAL5) {
- printk("%s: Unexpected AAL type in dequeue_rx(): %d.\n",
- card->name, vcc->qos.aal);
- recycle_rx_skb(card, skb);
- return;
- }
- skb->len = (stat & SAR_RSQE_CELLCNT) * ATM_CELL_PAYLOAD;
-
- rpp = &vc->rcv.rx_pool;
-
- __skb_queue_tail(&rpp->queue, skb);
- rpp->len += skb->len;
-
- if (stat & SAR_RSQE_EPDU) {
- unsigned int len, truesize;
- unsigned char *l1l2;
-
- l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);
-
- len = (l1l2[0] << 8) | l1l2[1];
- len = len ? len : 0x10000;
-
- RXPRINTK("%s: PDU has %d bytes.\n", card->name, len);
-
- if ((len + 8 > rpp->len) || (len + (47 + 8) < rpp->len)) {
- RXPRINTK("%s: AAL5 PDU size mismatch: %d != %d. "
- "(CDC: %08x)\n",
- card->name, len, rpp->len, readl(SAR_REG_CDC));
- recycle_rx_pool_skb(card, rpp);
- atomic_inc(&vcc->stats->rx_err);
- return;
- }
- if (stat & SAR_RSQE_CRC) {
- RXPRINTK("%s: AAL5 CRC error.\n", card->name);
- recycle_rx_pool_skb(card, rpp);
- atomic_inc(&vcc->stats->rx_err);
- return;
- }
- if (skb_queue_len(&rpp->queue) > 1) {
- struct sk_buff *sb;
-
- skb = dev_alloc_skb(rpp->len);
- if (!skb) {
- RXPRINTK("%s: Can't alloc RX skb.\n",
- card->name);
- recycle_rx_pool_skb(card, rpp);
- atomic_inc(&vcc->stats->rx_err);
- return;
- }
- if (!atm_charge(vcc, skb->truesize)) {
- recycle_rx_pool_skb(card, rpp);
- dev_kfree_skb(skb);
- return;
- }
- skb_queue_walk(&rpp->queue, sb)
- skb_put_data(skb, sb->data, sb->len);
-
- recycle_rx_pool_skb(card, rpp);
-
- skb_trim(skb, len);
- ATM_SKB(skb)->vcc = vcc;
- __net_timestamp(skb);
-
- vcc->push(vcc, skb);
- atomic_inc(&vcc->stats->rx);
-
- return;
- }
-
- flush_rx_pool(card, rpp);
-
- if (!atm_charge(vcc, skb->truesize)) {
- recycle_rx_skb(card, skb);
- return;
- }
-
- dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb_end_pointer(skb) - skb->data,
- DMA_FROM_DEVICE);
- sb_pool_remove(card, skb);
-
- skb_trim(skb, len);
- ATM_SKB(skb)->vcc = vcc;
- __net_timestamp(skb);
-
- truesize = skb->truesize;
- vcc->push(vcc, skb);
- atomic_inc(&vcc->stats->rx);
-
- if (truesize > SAR_FB_SIZE_3)
- add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
- else if (truesize > SAR_FB_SIZE_2)
- add_rx_skb(card, 2, SAR_FB_SIZE_2, 1);
- else if (truesize > SAR_FB_SIZE_1)
- add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
- else
- add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
- return;
- }
-}
-
-static void
-idt77252_rx(struct idt77252_dev *card)
-{
- struct rsq_entry *rsqe;
-
- if (card->rsq.next == card->rsq.last)
- rsqe = card->rsq.base;
- else
- rsqe = card->rsq.next + 1;
-
- if (!(le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID)) {
- RXPRINTK("%s: no entry in RSQ.\n", card->name);
- return;
- }
-
- do {
- dequeue_rx(card, rsqe);
- rsqe->word_4 = 0;
- card->rsq.next = rsqe;
- if (card->rsq.next == card->rsq.last)
- rsqe = card->rsq.base;
- else
- rsqe = card->rsq.next + 1;
- } while (le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID);
-
- writel((unsigned long) card->rsq.next - (unsigned long) card->rsq.base,
- SAR_REG_RSQH);
-}
-
-static void
-idt77252_rx_raw(struct idt77252_dev *card)
-{
- struct sk_buff *queue;
- u32 head, tail;
- struct atm_vcc *vcc;
- struct vc_map *vc;
- struct sk_buff *sb;
-
- if (card->raw_cell_head == NULL) {
- u32 handle = le32_to_cpu(*(card->raw_cell_hnd + 1));
- card->raw_cell_head = sb_pool_skb(card, handle);
- }
-
- queue = card->raw_cell_head;
- if (!queue)
- return;
-
- head = IDT77252_PRV_PADDR(queue) + (queue->data - queue->head - 16);
- tail = readl(SAR_REG_RAWCT);
-
- dma_sync_single_for_cpu(&card->pcidev->dev, IDT77252_PRV_PADDR(queue),
- skb_end_offset(queue) - 16,
- DMA_FROM_DEVICE);
-
- while (head != tail) {
- unsigned int vpi, vci;
- u32 header;
-
- header = le32_to_cpu(*(u32 *) &queue->data[0]);
-
- vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;
- vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;
-
-#ifdef CONFIG_ATM_IDT77252_DEBUG
- if (debug & DBG_RAW_CELL) {
- int i;
-
- printk("%s: raw cell %x.%02x.%04x.%x.%x\n",
- card->name, (header >> 28) & 0x000f,
- (header >> 20) & 0x00ff,
- (header >> 4) & 0xffff,
- (header >> 1) & 0x0007,
- (header >> 0) & 0x0001);
- for (i = 16; i < 64; i++)
- printk(" %02x", queue->data[i]);
- printk("\n");
- }
-#endif
-
- if (vpi >= (1<<card->vpibits) || vci >= (1<<card->vcibits)) {
- RPRINTK("%s: SDU received for out-of-range vc %u.%u\n",
- card->name, vpi, vci);
- goto drop;
- }
-
- vc = card->vcs[VPCI2VC(card, vpi, vci)];
- if (!vc || !test_bit(VCF_RX, &vc->flags)) {
- RPRINTK("%s: SDU received on non RX vc %u.%u\n",
- card->name, vpi, vci);
- goto drop;
- }
-
- vcc = vc->rx_vcc;
-
- if (vcc->qos.aal != ATM_AAL0) {
- RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n",
- card->name, vpi, vci);
- atomic_inc(&vcc->stats->rx_drop);
- goto drop;
- }
-
- if ((sb = dev_alloc_skb(64)) == NULL) {
- printk("%s: Can't allocate buffers for AAL0.\n",
- card->name);
- atomic_inc(&vcc->stats->rx_err);
- goto drop;
- }
-
- if (!atm_charge(vcc, sb->truesize)) {
- RXPRINTK("%s: atm_charge() dropped AAL0 packets.\n",
- card->name);
- dev_kfree_skb(sb);
- goto drop;
- }
-
- *((u32 *) sb->data) = header;
- skb_put(sb, sizeof(u32));
- skb_put_data(sb, &(queue->data[16]), ATM_CELL_PAYLOAD);
-
- ATM_SKB(sb)->vcc = vcc;
- __net_timestamp(sb);
- vcc->push(vcc, sb);
- atomic_inc(&vcc->stats->rx);
-
-drop:
- skb_pull(queue, 64);
-
- head = IDT77252_PRV_PADDR(queue)
- + (queue->data - queue->head - 16);
-
- if (queue->len < 128) {
- struct sk_buff *next;
- u32 handle;
-
- head = le32_to_cpu(*(u32 *) &queue->data[0]);
- handle = le32_to_cpu(*(u32 *) &queue->data[4]);
-
- next = sb_pool_skb(card, handle);
- recycle_rx_skb(card, queue);
-
- if (next) {
- card->raw_cell_head = next;
- queue = card->raw_cell_head;
- dma_sync_single_for_cpu(&card->pcidev->dev,
- IDT77252_PRV_PADDR(queue),
- (skb_end_pointer(queue) -
- queue->data),
- DMA_FROM_DEVICE);
- } else {
- card->raw_cell_head = NULL;
- printk("%s: raw cell queue overrun\n",
- card->name);
- break;
- }
- }
- }
-}
-
-
-/*****************************************************************************/
-/* */
-/* TSQ Handling */
-/* */
-/*****************************************************************************/
-
-static int
-init_tsq(struct idt77252_dev *card)
-{
- struct tsq_entry *tsqe;
-
- card->tsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE,
- &card->tsq.paddr, GFP_KERNEL);
- if (card->tsq.base == NULL) {
- printk("%s: can't allocate TSQ.\n", card->name);
- return -1;
- }
-
- card->tsq.last = card->tsq.base + TSQ_NUM_ENTRIES - 1;
- card->tsq.next = card->tsq.last;
- for (tsqe = card->tsq.base; tsqe <= card->tsq.last; tsqe++)
- tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID);
-
- writel(card->tsq.paddr, SAR_REG_TSQB);
- writel((unsigned long) card->tsq.next - (unsigned long) card->tsq.base,
- SAR_REG_TSQH);
-
- return 0;
-}
-
-static void
-deinit_tsq(struct idt77252_dev *card)
-{
- dma_free_coherent(&card->pcidev->dev, TSQSIZE,
- card->tsq.base, card->tsq.paddr);
-}
-
-static void
-idt77252_tx(struct idt77252_dev *card)
-{
- struct tsq_entry *tsqe;
- unsigned int vpi, vci;
- struct vc_map *vc;
- u32 conn, stat;
-
- if (card->tsq.next == card->tsq.last)
- tsqe = card->tsq.base;
- else
- tsqe = card->tsq.next + 1;
-
- TXPRINTK("idt77252_tx: tsq %p: base %p, next %p, last %p\n", tsqe,
- card->tsq.base, card->tsq.next, card->tsq.last);
- TXPRINTK("idt77252_tx: tsqb %08x, tsqt %08x, tsqh %08x, \n",
- readl(SAR_REG_TSQB),
- readl(SAR_REG_TSQT),
- readl(SAR_REG_TSQH));
-
- stat = le32_to_cpu(tsqe->word_2);
-
- if (stat & SAR_TSQE_INVALID)
- return;
-
- do {
- TXPRINTK("tsqe: 0x%p [0x%08x 0x%08x]\n", tsqe,
- le32_to_cpu(tsqe->word_1),
- le32_to_cpu(tsqe->word_2));
-
- switch (stat & SAR_TSQE_TYPE) {
- case SAR_TSQE_TYPE_TIMER:
- TXPRINTK("%s: Timer RollOver detected.\n", card->name);
- break;
-
- case SAR_TSQE_TYPE_IDLE:
-
- conn = le32_to_cpu(tsqe->word_1);
-
- if (SAR_TSQE_TAG(stat) == 0x10) {
-#ifdef NOTDEF
- printk("%s: Connection %d halted.\n",
- card->name,
- le32_to_cpu(tsqe->word_1) & 0x1fff);
-#endif
- break;
- }
-
- vc = card->vcs[conn & 0x1fff];
- if (!vc) {
- printk("%s: could not find VC from conn %d\n",
- card->name, conn & 0x1fff);
- break;
- }
-
- printk("%s: Connection %d IDLE.\n",
- card->name, vc->index);
-
- set_bit(VCF_IDLE, &vc->flags);
- break;
-
- case SAR_TSQE_TYPE_TSR:
-
- conn = le32_to_cpu(tsqe->word_1);
-
- vc = card->vcs[conn & 0x1fff];
- if (!vc) {
- printk("%s: no VC at index %d\n",
- card->name,
- le32_to_cpu(tsqe->word_1) & 0x1fff);
- break;
- }
-
- drain_scq(card, vc);
- break;
-
- case SAR_TSQE_TYPE_TBD_COMP:
-
- conn = le32_to_cpu(tsqe->word_1);
-
- vpi = (conn >> SAR_TBD_VPI_SHIFT) & 0x00ff;
- vci = (conn >> SAR_TBD_VCI_SHIFT) & 0xffff;
-
- if (vpi >= (1 << card->vpibits) ||
- vci >= (1 << card->vcibits)) {
- printk("%s: TBD complete: "
- "out of range VPI.VCI %u.%u\n",
- card->name, vpi, vci);
- break;
- }
-
- vc = card->vcs[VPCI2VC(card, vpi, vci)];
- if (!vc) {
- printk("%s: TBD complete: "
- "no VC at VPI.VCI %u.%u\n",
- card->name, vpi, vci);
- break;
- }
-
- drain_scq(card, vc);
- break;
- }
-
- tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID);
-
- card->tsq.next = tsqe;
- if (card->tsq.next == card->tsq.last)
- tsqe = card->tsq.base;
- else
- tsqe = card->tsq.next + 1;
-
- TXPRINTK("tsqe: %p: base %p, next %p, last %p\n", tsqe,
- card->tsq.base, card->tsq.next, card->tsq.last);
-
- stat = le32_to_cpu(tsqe->word_2);
-
- } while (!(stat & SAR_TSQE_INVALID));
-
- writel((unsigned long)card->tsq.next - (unsigned long)card->tsq.base,
- SAR_REG_TSQH);
-
- XPRINTK("idt77252_tx-after writel%d: TSQ head = 0x%x, tail = 0x%x, next = 0x%p.\n",
- card->index, readl(SAR_REG_TSQH),
- readl(SAR_REG_TSQT), card->tsq.next);
-}
-
-
-static void
-tst_timer(struct timer_list *t)
-{
- struct idt77252_dev *card = timer_container_of(card, t, tst_timer);
- unsigned long base, idle, jump;
- unsigned long flags;
- u32 pc;
- int e;
-
- spin_lock_irqsave(&card->tst_lock, flags);
-
- base = card->tst[card->tst_index];
- idle = card->tst[card->tst_index ^ 1];
-
- if (test_bit(TST_SWITCH_WAIT, &card->tst_state)) {
- jump = base + card->tst_size - 2;
-
- pc = readl(SAR_REG_NOW) >> 2;
- if ((pc ^ idle) & ~(card->tst_size - 1)) {
- mod_timer(&card->tst_timer, jiffies + 1);
- goto out;
- }
-
- clear_bit(TST_SWITCH_WAIT, &card->tst_state);
-
- card->tst_index ^= 1;
- write_sram(card, jump, TSTE_OPC_JMP | (base << 2));
-
- base = card->tst[card->tst_index];
- idle = card->tst[card->tst_index ^ 1];
-
- for (e = 0; e < card->tst_size - 2; e++) {
- if (card->soft_tst[e].tste & TSTE_PUSH_IDLE) {
- write_sram(card, idle + e,
- card->soft_tst[e].tste & TSTE_MASK);
- card->soft_tst[e].tste &= ~(TSTE_PUSH_IDLE);
- }
- }
- }
-
- if (test_and_clear_bit(TST_SWITCH_PENDING, &card->tst_state)) {
-
- for (e = 0; e < card->tst_size - 2; e++) {
- if (card->soft_tst[e].tste & TSTE_PUSH_ACTIVE) {
- write_sram(card, idle + e,
- card->soft_tst[e].tste & TSTE_MASK);
- card->soft_tst[e].tste &= ~(TSTE_PUSH_ACTIVE);
- card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
- }
- }
-
- jump = base + card->tst_size - 2;
-
- write_sram(card, jump, TSTE_OPC_NULL);
- set_bit(TST_SWITCH_WAIT, &card->tst_state);
-
- mod_timer(&card->tst_timer, jiffies + 1);
- }
-
-out:
- spin_unlock_irqrestore(&card->tst_lock, flags);
-}
-
-static int
-__fill_tst(struct idt77252_dev *card, struct vc_map *vc,
- int n, unsigned int opc)
-{
- unsigned long cl, avail;
- unsigned long idle;
- int e, r;
- u32 data;
-
- avail = card->tst_size - 2;
- for (e = 0; e < avail; e++) {
- if (card->soft_tst[e].vc == NULL)
- break;
- }
- if (e >= avail) {
- printk("%s: No free TST entries found\n", card->name);
- return -1;
- }
-
- NPRINTK("%s: conn %d: first TST entry at %d.\n",
- card->name, vc ? vc->index : -1, e);
-
- r = n;
- cl = avail;
- data = opc & TSTE_OPC_MASK;
- if (vc && (opc != TSTE_OPC_NULL))
- data = opc | vc->index;
-
- idle = card->tst[card->tst_index ^ 1];
-
- /*
- * Fill Soft TST.
- */
- while (r > 0) {
- if ((cl >= avail) && (card->soft_tst[e].vc == NULL)) {
- if (vc)
- card->soft_tst[e].vc = vc;
- else
- card->soft_tst[e].vc = (void *)-1;
-
- card->soft_tst[e].tste = data;
- if (timer_pending(&card->tst_timer))
- card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE;
- else {
- write_sram(card, idle + e, data);
- card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
- }
-
- cl -= card->tst_size;
- r--;
- }
-
- if (++e == avail)
- e = 0;
- cl += n;
- }
-
- return 0;
-}
-
-static int
-fill_tst(struct idt77252_dev *card, struct vc_map *vc, int n, unsigned int opc)
-{
- unsigned long flags;
- int res;
-
- spin_lock_irqsave(&card->tst_lock, flags);
-
- res = __fill_tst(card, vc, n, opc);
-
- set_bit(TST_SWITCH_PENDING, &card->tst_state);
- if (!timer_pending(&card->tst_timer))
- mod_timer(&card->tst_timer, jiffies + 1);
-
- spin_unlock_irqrestore(&card->tst_lock, flags);
- return res;
-}
-
-static int
-__clear_tst(struct idt77252_dev *card, struct vc_map *vc)
-{
- unsigned long idle;
- int e;
-
- idle = card->tst[card->tst_index ^ 1];
-
- for (e = 0; e < card->tst_size - 2; e++) {
- if (card->soft_tst[e].vc == vc) {
- card->soft_tst[e].vc = NULL;
-
- card->soft_tst[e].tste = TSTE_OPC_VAR;
- if (timer_pending(&card->tst_timer))
- card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE;
- else {
- write_sram(card, idle + e, TSTE_OPC_VAR);
- card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
- }
- }
- }
-
- return 0;
-}
-
-static int
-clear_tst(struct idt77252_dev *card, struct vc_map *vc)
-{
- unsigned long flags;
- int res;
-
- spin_lock_irqsave(&card->tst_lock, flags);
-
- res = __clear_tst(card, vc);
-
- set_bit(TST_SWITCH_PENDING, &card->tst_state);
- if (!timer_pending(&card->tst_timer))
- mod_timer(&card->tst_timer, jiffies + 1);
-
- spin_unlock_irqrestore(&card->tst_lock, flags);
- return res;
-}
-
-static int
-change_tst(struct idt77252_dev *card, struct vc_map *vc,
- int n, unsigned int opc)
-{
- unsigned long flags;
- int res;
-
- spin_lock_irqsave(&card->tst_lock, flags);
-
- __clear_tst(card, vc);
- res = __fill_tst(card, vc, n, opc);
-
- set_bit(TST_SWITCH_PENDING, &card->tst_state);
- if (!timer_pending(&card->tst_timer))
- mod_timer(&card->tst_timer, jiffies + 1);
-
- spin_unlock_irqrestore(&card->tst_lock, flags);
- return res;
-}
-
-
-static int
-set_tct(struct idt77252_dev *card, struct vc_map *vc)
-{
- unsigned long tct;
-
- tct = (unsigned long) (card->tct_base + vc->index * SAR_SRAM_TCT_SIZE);
-
- switch (vc->class) {
- case SCHED_CBR:
- OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",
- card->name, tct, vc->scq->scd);
-
- write_sram(card, tct + 0, TCT_CBR | vc->scq->scd);
- write_sram(card, tct + 1, 0);
- write_sram(card, tct + 2, 0);
- write_sram(card, tct + 3, 0);
- write_sram(card, tct + 4, 0);
- write_sram(card, tct + 5, 0);
- write_sram(card, tct + 6, 0);
- write_sram(card, tct + 7, 0);
- break;
-
- case SCHED_UBR:
- OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",
- card->name, tct, vc->scq->scd);
-
- write_sram(card, tct + 0, TCT_UBR | vc->scq->scd);
- write_sram(card, tct + 1, 0);
- write_sram(card, tct + 2, TCT_TSIF);
- write_sram(card, tct + 3, TCT_HALT | TCT_IDLE);
- write_sram(card, tct + 4, 0);
- write_sram(card, tct + 5, vc->init_er);
- write_sram(card, tct + 6, 0);
- write_sram(card, tct + 7, TCT_FLAG_UBR);
- break;
-
- case SCHED_VBR:
- case SCHED_ABR:
- default:
- return -ENOSYS;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-/* */
-/* FBQ Handling */
-/* */
-/*****************************************************************************/
-
-static __inline__ int
-idt77252_fbq_full(struct idt77252_dev *card, int queue)
-{
- return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) == 0x0f;
-}
-
-static int
-push_rx_skb(struct idt77252_dev *card, struct sk_buff *skb, int queue)
-{
- unsigned long flags;
- u32 handle;
- u32 addr;
-
- skb->data = skb->head;
- skb_reset_tail_pointer(skb);
- skb->len = 0;
-
- skb_reserve(skb, 16);
-
- switch (queue) {
- case 0:
- skb_put(skb, SAR_FB_SIZE_0);
- break;
- case 1:
- skb_put(skb, SAR_FB_SIZE_1);
- break;
- case 2:
- skb_put(skb, SAR_FB_SIZE_2);
- break;
- case 3:
- skb_put(skb, SAR_FB_SIZE_3);
- break;
- default:
- return -1;
- }
-
- if (idt77252_fbq_full(card, queue))
- return -1;
-
- memset(&skb->data[(skb->len & ~(0x3f)) - 64], 0, 2 * sizeof(u32));
-
- handle = IDT77252_PRV_POOL(skb);
- addr = IDT77252_PRV_PADDR(skb);
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(handle, card->fbq[queue]);
- writel(addr, card->fbq[queue]);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
-
- return 0;
-}
-
-static void
-add_rx_skb(struct idt77252_dev *card, int queue,
- unsigned int size, unsigned int count)
-{
- struct sk_buff *skb;
- dma_addr_t paddr;
-
- while (count--) {
- skb = dev_alloc_skb(size);
- if (!skb)
- return;
-
- if (sb_pool_add(card, skb, queue)) {
- printk("%s: SB POOL full\n", __func__);
- goto outfree;
- }
-
- paddr = dma_map_single(&card->pcidev->dev, skb->data,
- skb_end_pointer(skb) - skb->data,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(&card->pcidev->dev, paddr))
- goto outpoolrm;
- IDT77252_PRV_PADDR(skb) = paddr;
-
- if (push_rx_skb(card, skb, queue)) {
- printk("%s: FB QUEUE full\n", __func__);
- goto outunmap;
- }
- }
-
- return;
-
-outunmap:
- dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb_end_pointer(skb) - skb->data, DMA_FROM_DEVICE);
-
-outpoolrm:
- sb_pool_remove(card, skb);
-
-outfree:
- dev_kfree_skb(skb);
-}
-
-
-static void
-recycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb)
-{
- u32 handle = IDT77252_PRV_POOL(skb);
- int err;
-
- dma_sync_single_for_device(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb_end_pointer(skb) - skb->data,
- DMA_FROM_DEVICE);
-
- err = push_rx_skb(card, skb, POOL_QUEUE(handle));
- if (err) {
- dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
- skb_end_pointer(skb) - skb->data,
- DMA_FROM_DEVICE);
- sb_pool_remove(card, skb);
- dev_kfree_skb(skb);
- }
-}
-
-static void
-flush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp)
-{
- skb_queue_head_init(&rpp->queue);
- rpp->len = 0;
-}
-
-static void
-recycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp)
-{
- struct sk_buff *skb, *tmp;
-
- skb_queue_walk_safe(&rpp->queue, skb, tmp)
- recycle_rx_skb(card, skb);
-
- flush_rx_pool(card, rpp);
-}
-
-/*****************************************************************************/
-/* */
-/* ATM Interface */
-/* */
-/*****************************************************************************/
-
-static void
-idt77252_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr)
-{
- write_utility(dev->dev_data, 0x100 + (addr & 0x1ff), value);
-}
-
-static unsigned char
-idt77252_phy_get(struct atm_dev *dev, unsigned long addr)
-{
- return read_utility(dev->dev_data, 0x100 + (addr & 0x1ff));
-}
-
-static inline int
-idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam)
-{
- struct atm_dev *dev = vcc->dev;
- struct idt77252_dev *card = dev->dev_data;
- struct vc_map *vc = vcc->dev_data;
- int err;
-
- if (vc == NULL) {
- printk("%s: NULL connection in send().\n", card->name);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb(skb);
- return -EINVAL;
- }
- if (!test_bit(VCF_TX, &vc->flags)) {
- printk("%s: Trying to transmit on a non-tx VC.\n", card->name);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb(skb);
- return -EINVAL;
- }
-
- switch (vcc->qos.aal) {
- case ATM_AAL0:
- case ATM_AAL1:
- case ATM_AAL5:
- break;
- default:
- printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb(skb);
- return -EINVAL;
- }
-
- if (skb_shinfo(skb)->nr_frags != 0) {
- printk("%s: No scatter-gather yet.\n", card->name);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb(skb);
- return -EINVAL;
- }
- ATM_SKB(skb)->vcc = vcc;
-
- err = queue_skb(card, vc, skb, oam);
- if (err) {
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb(skb);
- return err;
- }
-
- return 0;
-}
-
-static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- return idt77252_send_skb(vcc, skb, 0);
-}
-
-static int
-idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)
-{
- struct atm_dev *dev = vcc->dev;
- struct idt77252_dev *card = dev->dev_data;
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(64);
- if (!skb) {
- printk("%s: Out of memory in send_oam().\n", card->name);
- atomic_inc(&vcc->stats->tx_err);
- return -ENOMEM;
- }
- refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
-
- skb_put_data(skb, cell, 52);
-
- return idt77252_send_skb(vcc, skb, 1);
-}
-
-static __inline__ unsigned int
-idt77252_fls(unsigned int x)
-{
- int r = 1;
-
- if (x == 0)
- return 0;
- if (x & 0xffff0000) {
- x >>= 16;
- r += 16;
- }
- if (x & 0xff00) {
- x >>= 8;
- r += 8;
- }
- if (x & 0xf0) {
- x >>= 4;
- r += 4;
- }
- if (x & 0xc) {
- x >>= 2;
- r += 2;
- }
- if (x & 0x2)
- r += 1;
- return r;
-}
-
-static u16
-idt77252_int_to_atmfp(unsigned int rate)
-{
- u16 m, e;
-
- if (rate == 0)
- return 0;
- e = idt77252_fls(rate) - 1;
- if (e < 9)
- m = (rate - (1 << e)) << (9 - e);
- else if (e == 9)
- m = (rate - (1 << e));
- else /* e > 9 */
- m = (rate - (1 << e)) >> (e - 9);
- return 0x4000 | (e << 9) | m;
-}
-
-static u8
-idt77252_rate_logindex(struct idt77252_dev *card, int pcr)
-{
- u16 afp;
-
- afp = idt77252_int_to_atmfp(pcr < 0 ? -pcr : pcr);
- if (pcr < 0)
- return rate_to_log[(afp >> 5) & 0x1ff];
- return rate_to_log[((afp >> 5) + 1) & 0x1ff];
-}
-
-static void
-idt77252_est_timer(struct timer_list *t)
-{
- struct rate_estimator *est = timer_container_of(est, t, timer);
- struct vc_map *vc = est->vc;
- struct idt77252_dev *card = vc->card;
- unsigned long flags;
- u32 rate, cps;
- u64 ncells;
- u8 lacr;
-
- spin_lock_irqsave(&vc->lock, flags);
- if (!vc->estimator)
- goto out;
- ncells = est->cells;
-
- rate = ((u32)(ncells - est->last_cells)) << (7 - est->interval);
- est->last_cells = ncells;
- est->avcps += ((long)rate - (long)est->avcps) >> est->ewma_log;
- est->cps = (est->avcps + 0x1f) >> 5;
-
- cps = est->cps;
- if (cps < (est->maxcps >> 4))
- cps = est->maxcps >> 4;
-
- lacr = idt77252_rate_logindex(card, cps);
- if (lacr > vc->max_er)
- lacr = vc->max_er;
-
- if (lacr != vc->lacr) {
- vc->lacr = lacr;
- writel(TCMDQ_LACR|(vc->lacr << 16)|vc->index, SAR_REG_TCMDQ);
- }
-
- est->timer.expires = jiffies + ((HZ / 4) << est->interval);
- add_timer(&est->timer);
-
-out:
- spin_unlock_irqrestore(&vc->lock, flags);
-}
-
-static struct rate_estimator *
-idt77252_init_est(struct vc_map *vc, int pcr)
-{
- struct rate_estimator *est;
-
- est = kzalloc_obj(struct rate_estimator);
- if (!est)
- return NULL;
- est->maxcps = pcr < 0 ? -pcr : pcr;
- est->cps = est->maxcps;
- est->avcps = est->cps << 5;
- est->vc = vc;
-
- est->interval = 2; /* XXX: make this configurable */
- est->ewma_log = 2; /* XXX: make this configurable */
- timer_setup(&est->timer, idt77252_est_timer, 0);
- mod_timer(&est->timer, jiffies + ((HZ / 4) << est->interval));
-
- return est;
-}
-
-static int
-idt77252_init_cbr(struct idt77252_dev *card, struct vc_map *vc,
- struct atm_vcc *vcc, struct atm_qos *qos)
-{
- int tst_free, tst_used, tst_entries;
- unsigned long tmpl, modl;
- int tcr, tcra;
-
- if ((qos->txtp.max_pcr == 0) &&
- (qos->txtp.pcr == 0) && (qos->txtp.min_pcr == 0)) {
- printk("%s: trying to open a CBR VC with cell rate = 0\n",
- card->name);
- return -EINVAL;
- }
-
- tst_used = 0;
- tst_free = card->tst_free;
- if (test_bit(VCF_TX, &vc->flags))
- tst_used = vc->ntste;
- tst_free += tst_used;
-
- tcr = atm_pcr_goal(&qos->txtp);
- tcra = tcr >= 0 ? tcr : -tcr;
-
- TXPRINTK("%s: CBR target cell rate = %d\n", card->name, tcra);
-
- tmpl = (unsigned long) tcra * ((unsigned long) card->tst_size - 2);
- modl = tmpl % (unsigned long)card->utopia_pcr;
-
- tst_entries = (int) (tmpl / card->utopia_pcr);
- if (tcr > 0) {
- if (modl > 0)
- tst_entries++;
- } else if (tcr == 0) {
- tst_entries = tst_free - SAR_TST_RESERVED;
- if (tst_entries <= 0) {
- printk("%s: no CBR bandwidth free.\n", card->name);
- return -ENOSR;
- }
- }
-
- if (tst_entries == 0) {
- printk("%s: selected CBR bandwidth < granularity.\n",
- card->name);
- return -EINVAL;
- }
-
- if (tst_entries > (tst_free - SAR_TST_RESERVED)) {
- printk("%s: not enough CBR bandwidth free.\n", card->name);
- return -ENOSR;
- }
-
- vc->ntste = tst_entries;
-
- card->tst_free = tst_free - tst_entries;
- if (test_bit(VCF_TX, &vc->flags)) {
- if (tst_used == tst_entries)
- return 0;
-
- OPRINTK("%s: modify %d -> %d entries in TST.\n",
- card->name, tst_used, tst_entries);
- change_tst(card, vc, tst_entries, TSTE_OPC_CBR);
- return 0;
- }
-
- OPRINTK("%s: setting %d entries in TST.\n", card->name, tst_entries);
- fill_tst(card, vc, tst_entries, TSTE_OPC_CBR);
- return 0;
-}
-
-static int
-idt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc,
- struct atm_vcc *vcc, struct atm_qos *qos)
-{
- struct rate_estimator *est = NULL;
- unsigned long flags;
- int tcr;
-
- spin_lock_irqsave(&vc->lock, flags);
- if (vc->estimator) {
- est = vc->estimator;
- vc->estimator = NULL;
- }
- spin_unlock_irqrestore(&vc->lock, flags);
- if (est) {
- timer_shutdown_sync(&est->timer);
- kfree(est);
- }
-
- tcr = atm_pcr_goal(&qos->txtp);
- if (tcr == 0)
- tcr = card->link_pcr;
-
- vc->estimator = idt77252_init_est(vc, tcr);
-
- vc->class = SCHED_UBR;
- vc->init_er = idt77252_rate_logindex(card, tcr);
- vc->lacr = vc->init_er;
- if (tcr < 0)
- vc->max_er = vc->init_er;
- else
- vc->max_er = 0xff;
-
- return 0;
-}
-
-static int
-idt77252_init_tx(struct idt77252_dev *card, struct vc_map *vc,
- struct atm_vcc *vcc, struct atm_qos *qos)
-{
- int error;
-
- if (test_bit(VCF_TX, &vc->flags))
- return -EBUSY;
-
- switch (qos->txtp.traffic_class) {
- case ATM_CBR:
- vc->class = SCHED_CBR;
- break;
-
- case ATM_UBR:
- vc->class = SCHED_UBR;
- break;
-
- case ATM_VBR:
- case ATM_ABR:
- default:
- return -EPROTONOSUPPORT;
- }
-
- vc->scq = alloc_scq(card, vc->class);
- if (!vc->scq) {
- printk("%s: can't get SCQ.\n", card->name);
- return -ENOMEM;
- }
-
- vc->scq->scd = get_free_scd(card, vc);
- if (vc->scq->scd == 0) {
- printk("%s: no SCD available.\n", card->name);
- free_scq(card, vc->scq);
- return -ENOMEM;
- }
-
- fill_scd(card, vc->scq, vc->class);
-
- if (set_tct(card, vc)) {
- printk("%s: class %d not supported.\n",
- card->name, qos->txtp.traffic_class);
-
- card->scd2vc[vc->scd_index] = NULL;
- free_scq(card, vc->scq);
- return -EPROTONOSUPPORT;
- }
-
- switch (vc->class) {
- case SCHED_CBR:
- error = idt77252_init_cbr(card, vc, vcc, qos);
- if (error) {
- card->scd2vc[vc->scd_index] = NULL;
- free_scq(card, vc->scq);
- return error;
- }
-
- clear_bit(VCF_IDLE, &vc->flags);
- writel(TCMDQ_START | vc->index, SAR_REG_TCMDQ);
- break;
-
- case SCHED_UBR:
- error = idt77252_init_ubr(card, vc, vcc, qos);
- if (error) {
- card->scd2vc[vc->scd_index] = NULL;
- free_scq(card, vc->scq);
- return error;
- }
-
- set_bit(VCF_IDLE, &vc->flags);
- break;
- }
-
- vc->tx_vcc = vcc;
- set_bit(VCF_TX, &vc->flags);
- return 0;
-}
-
-static int
-idt77252_init_rx(struct idt77252_dev *card, struct vc_map *vc,
- struct atm_vcc *vcc, struct atm_qos *qos)
-{
- unsigned long flags;
- unsigned long addr;
- u32 rcte = 0;
-
- if (test_bit(VCF_RX, &vc->flags))
- return -EBUSY;
-
- vc->rx_vcc = vcc;
- set_bit(VCF_RX, &vc->flags);
-
- if ((vcc->vci == 3) || (vcc->vci == 4))
- return 0;
-
- flush_rx_pool(card, &vc->rcv.rx_pool);
-
- rcte |= SAR_RCTE_CONNECTOPEN;
- rcte |= SAR_RCTE_RAWCELLINTEN;
-
- switch (qos->aal) {
- case ATM_AAL0:
- rcte |= SAR_RCTE_RCQ;
- break;
- case ATM_AAL1:
- rcte |= SAR_RCTE_OAM; /* Let SAR drop Video */
- break;
- case ATM_AAL34:
- rcte |= SAR_RCTE_AAL34;
- break;
- case ATM_AAL5:
- rcte |= SAR_RCTE_AAL5;
- break;
- default:
- rcte |= SAR_RCTE_RCQ;
- break;
- }
-
- if (qos->aal != ATM_AAL5)
- rcte |= SAR_RCTE_FBP_1;
- else if (qos->rxtp.max_sdu > SAR_FB_SIZE_2)
- rcte |= SAR_RCTE_FBP_3;
- else if (qos->rxtp.max_sdu > SAR_FB_SIZE_1)
- rcte |= SAR_RCTE_FBP_2;
- else if (qos->rxtp.max_sdu > SAR_FB_SIZE_0)
- rcte |= SAR_RCTE_FBP_1;
- else
- rcte |= SAR_RCTE_FBP_01;
-
- addr = card->rct_base + (vc->index << 2);
-
- OPRINTK("%s: writing RCT at 0x%lx\n", card->name, addr);
- write_sram(card, addr, rcte);
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(SAR_CMD_OPEN_CONNECTION | (addr << 2), SAR_REG_CMD);
- waitfor_idle(card);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
-
- return 0;
-}
-
-static int
-idt77252_open(struct atm_vcc *vcc)
-{
- struct atm_dev *dev = vcc->dev;
- struct idt77252_dev *card = dev->dev_data;
- struct vc_map *vc;
- unsigned int index;
- unsigned int inuse;
- int error;
- int vci = vcc->vci;
- short vpi = vcc->vpi;
-
- if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
- return 0;
-
- if (vpi >= (1 << card->vpibits)) {
- printk("%s: unsupported VPI: %d\n", card->name, vpi);
- return -EINVAL;
- }
-
- if (vci >= (1 << card->vcibits)) {
- printk("%s: unsupported VCI: %d\n", card->name, vci);
- return -EINVAL;
- }
-
- set_bit(ATM_VF_ADDR, &vcc->flags);
-
- mutex_lock(&card->mutex);
-
- OPRINTK("%s: opening vpi.vci: %d.%d\n", card->name, vpi, vci);
-
- switch (vcc->qos.aal) {
- case ATM_AAL0:
- case ATM_AAL1:
- case ATM_AAL5:
- break;
- default:
- printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
- mutex_unlock(&card->mutex);
- return -EPROTONOSUPPORT;
- }
-
- index = VPCI2VC(card, vpi, vci);
- if (!card->vcs[index]) {
- card->vcs[index] = kzalloc_obj(struct vc_map);
- if (!card->vcs[index]) {
- printk("%s: can't alloc vc in open()\n", card->name);
- mutex_unlock(&card->mutex);
- return -ENOMEM;
- }
- card->vcs[index]->card = card;
- card->vcs[index]->index = index;
-
- spin_lock_init(&card->vcs[index]->lock);
- }
- vc = card->vcs[index];
-
- vcc->dev_data = vc;
-
- IPRINTK("%s: idt77252_open: vc = %d (%d.%d) %s/%s (max RX SDU: %u)\n",
- card->name, vc->index, vcc->vpi, vcc->vci,
- vcc->qos.rxtp.traffic_class != ATM_NONE ? "rx" : "--",
- vcc->qos.txtp.traffic_class != ATM_NONE ? "tx" : "--",
- vcc->qos.rxtp.max_sdu);
-
- inuse = 0;
- if (vcc->qos.txtp.traffic_class != ATM_NONE &&
- test_bit(VCF_TX, &vc->flags))
- inuse = 1;
- if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
- test_bit(VCF_RX, &vc->flags))
- inuse += 2;
-
- if (inuse) {
- printk("%s: %s vci already in use.\n", card->name,
- inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx");
- mutex_unlock(&card->mutex);
- return -EADDRINUSE;
- }
-
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
- error = idt77252_init_tx(card, vc, vcc, &vcc->qos);
- if (error) {
- mutex_unlock(&card->mutex);
- return error;
- }
- }
-
- if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
- error = idt77252_init_rx(card, vc, vcc, &vcc->qos);
- if (error) {
- mutex_unlock(&card->mutex);
- return error;
- }
- }
-
- set_bit(ATM_VF_READY, &vcc->flags);
-
- mutex_unlock(&card->mutex);
- return 0;
-}
-
-static void
-idt77252_close(struct atm_vcc *vcc)
-{
- struct atm_dev *dev = vcc->dev;
- struct idt77252_dev *card = dev->dev_data;
- struct vc_map *vc = vcc->dev_data;
- unsigned long flags;
- unsigned long addr;
- unsigned long timeout;
-
- mutex_lock(&card->mutex);
-
- IPRINTK("%s: idt77252_close: vc = %d (%d.%d)\n",
- card->name, vc->index, vcc->vpi, vcc->vci);
-
- clear_bit(ATM_VF_READY, &vcc->flags);
-
- if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
-
- spin_lock_irqsave(&vc->lock, flags);
- clear_bit(VCF_RX, &vc->flags);
- vc->rx_vcc = NULL;
- spin_unlock_irqrestore(&vc->lock, flags);
-
- if ((vcc->vci == 3) || (vcc->vci == 4))
- goto done;
-
- addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE;
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2), SAR_REG_CMD);
- waitfor_idle(card);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
-
- if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) {
- DPRINTK("%s: closing a VC with pending rx buffers.\n",
- card->name);
-
- recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
- }
- }
-
-done:
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
-
- spin_lock_irqsave(&vc->lock, flags);
- clear_bit(VCF_TX, &vc->flags);
- clear_bit(VCF_IDLE, &vc->flags);
- clear_bit(VCF_RSV, &vc->flags);
- vc->tx_vcc = NULL;
-
- if (vc->estimator) {
- timer_shutdown(&vc->estimator->timer);
- kfree(vc->estimator);
- vc->estimator = NULL;
- }
- spin_unlock_irqrestore(&vc->lock, flags);
-
- timeout = 5 * 1000;
- while (atomic_read(&vc->scq->used) > 0) {
- timeout = msleep_interruptible(timeout);
- if (!timeout) {
- pr_warn("%s: SCQ drain timeout: %u used\n",
- card->name, atomic_read(&vc->scq->used));
- break;
- }
- }
-
- writel(TCMDQ_HALT | vc->index, SAR_REG_TCMDQ);
- clear_scd(card, vc->scq, vc->class);
-
- if (vc->class == SCHED_CBR) {
- clear_tst(card, vc);
- card->tst_free += vc->ntste;
- vc->ntste = 0;
- }
-
- card->scd2vc[vc->scd_index] = NULL;
- free_scq(card, vc->scq);
- }
-
- mutex_unlock(&card->mutex);
-}
-
-static int
-idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
-{
- struct atm_dev *dev = vcc->dev;
- struct idt77252_dev *card = dev->dev_data;
- struct vc_map *vc = vcc->dev_data;
- int error = 0;
-
- mutex_lock(&card->mutex);
-
- if (qos->txtp.traffic_class != ATM_NONE) {
- if (!test_bit(VCF_TX, &vc->flags)) {
- error = idt77252_init_tx(card, vc, vcc, qos);
- if (error)
- goto out;
- } else {
- switch (qos->txtp.traffic_class) {
- case ATM_CBR:
- error = idt77252_init_cbr(card, vc, vcc, qos);
- if (error)
- goto out;
- break;
-
- case ATM_UBR:
- error = idt77252_init_ubr(card, vc, vcc, qos);
- if (error)
- goto out;
-
- if (!test_bit(VCF_IDLE, &vc->flags)) {
- writel(TCMDQ_LACR | (vc->lacr << 16) |
- vc->index, SAR_REG_TCMDQ);
- }
- break;
-
- case ATM_VBR:
- case ATM_ABR:
- error = -EOPNOTSUPP;
- goto out;
- }
- }
- }
-
- if ((qos->rxtp.traffic_class != ATM_NONE) &&
- !test_bit(VCF_RX, &vc->flags)) {
- error = idt77252_init_rx(card, vc, vcc, qos);
- if (error)
- goto out;
- }
-
- memcpy(&vcc->qos, qos, sizeof(struct atm_qos));
-
- set_bit(ATM_VF_HASQOS, &vcc->flags);
-
-out:
- mutex_unlock(&card->mutex);
- return error;
-}
-
-static int
-idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page)
-{
- struct idt77252_dev *card = dev->dev_data;
- int i, left;
-
- left = (int) *pos;
- if (!left--)
- return sprintf(page, "IDT77252 Interrupts:\n");
- if (!left--)
- return sprintf(page, "TSIF: %lu\n", card->irqstat[15]);
- if (!left--)
- return sprintf(page, "TXICP: %lu\n", card->irqstat[14]);
- if (!left--)
- return sprintf(page, "TSQF: %lu\n", card->irqstat[12]);
- if (!left--)
- return sprintf(page, "TMROF: %lu\n", card->irqstat[11]);
- if (!left--)
- return sprintf(page, "PHYI: %lu\n", card->irqstat[10]);
- if (!left--)
- return sprintf(page, "FBQ3A: %lu\n", card->irqstat[8]);
- if (!left--)
- return sprintf(page, "FBQ2A: %lu\n", card->irqstat[7]);
- if (!left--)
- return sprintf(page, "RSQF: %lu\n", card->irqstat[6]);
- if (!left--)
- return sprintf(page, "EPDU: %lu\n", card->irqstat[5]);
- if (!left--)
- return sprintf(page, "RAWCF: %lu\n", card->irqstat[4]);
- if (!left--)
- return sprintf(page, "FBQ1A: %lu\n", card->irqstat[3]);
- if (!left--)
- return sprintf(page, "FBQ0A: %lu\n", card->irqstat[2]);
- if (!left--)
- return sprintf(page, "RSQAF: %lu\n", card->irqstat[1]);
- if (!left--)
- return sprintf(page, "IDT77252 Transmit Connection Table:\n");
-
- for (i = 0; i < card->tct_size; i++) {
- unsigned long tct;
- struct atm_vcc *vcc;
- struct vc_map *vc;
- char *p;
-
- vc = card->vcs[i];
- if (!vc)
- continue;
-
- vcc = NULL;
- if (vc->tx_vcc)
- vcc = vc->tx_vcc;
- if (!vcc)
- continue;
- if (left--)
- continue;
-
- p = page;
- p += sprintf(p, " %4u: %u.%u: ", i, vcc->vpi, vcc->vci);
- tct = (unsigned long) (card->tct_base + i * SAR_SRAM_TCT_SIZE);
-
- for (i = 0; i < 8; i++)
- p += sprintf(p, " %08x", read_sram(card, tct + i));
- p += sprintf(p, "\n");
- return p - page;
- }
- return 0;
-}
-
-/*****************************************************************************/
-/* */
-/* Interrupt handler */
-/* */
-/*****************************************************************************/
-
-static void
-idt77252_collect_stat(struct idt77252_dev *card)
-{
- (void) readl(SAR_REG_CDC);
- (void) readl(SAR_REG_VPEC);
- (void) readl(SAR_REG_ICC);
-
-}
-
-static irqreturn_t
-idt77252_interrupt(int irq, void *dev_id)
-{
- struct idt77252_dev *card = dev_id;
- u32 stat;
-
- stat = readl(SAR_REG_STAT) & 0xffff;
- if (!stat) /* no interrupt for us */
- return IRQ_NONE;
-
- if (test_and_set_bit(IDT77252_BIT_INTERRUPT, &card->flags)) {
- printk("%s: Re-entering irq_handler()\n", card->name);
- goto out;
- }
-
- writel(stat, SAR_REG_STAT); /* reset interrupt */
-
- if (stat & SAR_STAT_TSIF) { /* entry written to TSQ */
- INTPRINTK("%s: TSIF\n", card->name);
- card->irqstat[15]++;
- idt77252_tx(card);
- }
- if (stat & SAR_STAT_TXICP) { /* Incomplete CS-PDU has */
- INTPRINTK("%s: TXICP\n", card->name);
- card->irqstat[14]++;
-#ifdef CONFIG_ATM_IDT77252_DEBUG
- idt77252_tx_dump(card);
-#endif
- }
- if (stat & SAR_STAT_TSQF) { /* TSQ 7/8 full */
- INTPRINTK("%s: TSQF\n", card->name);
- card->irqstat[12]++;
- idt77252_tx(card);
- }
- if (stat & SAR_STAT_TMROF) { /* Timer overflow */
- INTPRINTK("%s: TMROF\n", card->name);
- card->irqstat[11]++;
- idt77252_collect_stat(card);
- }
-
- if (stat & SAR_STAT_EPDU) { /* Got complete CS-PDU */
- INTPRINTK("%s: EPDU\n", card->name);
- card->irqstat[5]++;
- idt77252_rx(card);
- }
- if (stat & SAR_STAT_RSQAF) { /* RSQ is 7/8 full */
- INTPRINTK("%s: RSQAF\n", card->name);
- card->irqstat[1]++;
- idt77252_rx(card);
- }
- if (stat & SAR_STAT_RSQF) { /* RSQ is full */
- INTPRINTK("%s: RSQF\n", card->name);
- card->irqstat[6]++;
- idt77252_rx(card);
- }
- if (stat & SAR_STAT_RAWCF) { /* Raw cell received */
- INTPRINTK("%s: RAWCF\n", card->name);
- card->irqstat[4]++;
- idt77252_rx_raw(card);
- }
-
- if (stat & SAR_STAT_PHYI) { /* PHY device interrupt */
- INTPRINTK("%s: PHYI", card->name);
- card->irqstat[10]++;
- if (card->atmdev->phy && card->atmdev->phy->interrupt)
- card->atmdev->phy->interrupt(card->atmdev);
- }
-
- if (stat & (SAR_STAT_FBQ0A | SAR_STAT_FBQ1A |
- SAR_STAT_FBQ2A | SAR_STAT_FBQ3A)) {
-
- writel(readl(SAR_REG_CFG) & ~(SAR_CFG_FBIE), SAR_REG_CFG);
-
- INTPRINTK("%s: FBQA: %04x\n", card->name, stat);
-
- if (stat & SAR_STAT_FBQ0A)
- card->irqstat[2]++;
- if (stat & SAR_STAT_FBQ1A)
- card->irqstat[3]++;
- if (stat & SAR_STAT_FBQ2A)
- card->irqstat[7]++;
- if (stat & SAR_STAT_FBQ3A)
- card->irqstat[8]++;
-
- schedule_work(&card->tqueue);
- }
-
-out:
- clear_bit(IDT77252_BIT_INTERRUPT, &card->flags);
- return IRQ_HANDLED;
-}
-
-static void
-idt77252_softint(struct work_struct *work)
-{
- struct idt77252_dev *card =
- container_of(work, struct idt77252_dev, tqueue);
- u32 stat;
- int done;
-
- for (done = 1; ; done = 1) {
- stat = readl(SAR_REG_STAT) >> 16;
-
- if ((stat & 0x0f) < SAR_FBQ0_HIGH) {
- add_rx_skb(card, 0, SAR_FB_SIZE_0, 32);
- done = 0;
- }
-
- stat >>= 4;
- if ((stat & 0x0f) < SAR_FBQ1_HIGH) {
- add_rx_skb(card, 1, SAR_FB_SIZE_1, 32);
- done = 0;
- }
-
- stat >>= 4;
- if ((stat & 0x0f) < SAR_FBQ2_HIGH) {
- add_rx_skb(card, 2, SAR_FB_SIZE_2, 32);
- done = 0;
- }
-
- stat >>= 4;
- if ((stat & 0x0f) < SAR_FBQ3_HIGH) {
- add_rx_skb(card, 3, SAR_FB_SIZE_3, 32);
- done = 0;
- }
-
- if (done)
- break;
- }
-
- writel(readl(SAR_REG_CFG) | SAR_CFG_FBIE, SAR_REG_CFG);
-}
-
-
-static int
-open_card_oam(struct idt77252_dev *card)
-{
- unsigned long flags;
- unsigned long addr;
- struct vc_map *vc;
- int vpi, vci;
- int index;
- u32 rcte;
-
- for (vpi = 0; vpi < (1 << card->vpibits); vpi++) {
- for (vci = 3; vci < 5; vci++) {
- index = VPCI2VC(card, vpi, vci);
-
- vc = kzalloc_obj(struct vc_map);
- if (!vc) {
- printk("%s: can't alloc vc\n", card->name);
- return -ENOMEM;
- }
- vc->index = index;
- card->vcs[index] = vc;
-
- flush_rx_pool(card, &vc->rcv.rx_pool);
-
- rcte = SAR_RCTE_CONNECTOPEN |
- SAR_RCTE_RAWCELLINTEN |
- SAR_RCTE_RCQ |
- SAR_RCTE_FBP_1;
-
- addr = card->rct_base + (vc->index << 2);
- write_sram(card, addr, rcte);
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(SAR_CMD_OPEN_CONNECTION | (addr << 2),
- SAR_REG_CMD);
- waitfor_idle(card);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
- }
- }
-
- return 0;
-}
-
-static void
-close_card_oam(struct idt77252_dev *card)
-{
- unsigned long flags;
- unsigned long addr;
- struct vc_map *vc;
- int vpi, vci;
- int index;
-
- for (vpi = 0; vpi < (1 << card->vpibits); vpi++) {
- for (vci = 3; vci < 5; vci++) {
- index = VPCI2VC(card, vpi, vci);
- vc = card->vcs[index];
-
- addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE;
-
- spin_lock_irqsave(&card->cmd_lock, flags);
- writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2),
- SAR_REG_CMD);
- waitfor_idle(card);
- spin_unlock_irqrestore(&card->cmd_lock, flags);
-
- if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) {
- DPRINTK("%s: closing a VC "
- "with pending rx buffers.\n",
- card->name);
-
- recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
- }
- kfree(vc);
- }
- }
-}
-
-static int
-open_card_ubr0(struct idt77252_dev *card)
-{
- struct vc_map *vc;
-
- vc = kzalloc_obj(struct vc_map);
- if (!vc) {
- printk("%s: can't alloc vc\n", card->name);
- return -ENOMEM;
- }
- card->vcs[0] = vc;
- vc->class = SCHED_UBR0;
-
- vc->scq = alloc_scq(card, vc->class);
- if (!vc->scq) {
- printk("%s: can't get SCQ.\n", card->name);
- kfree(card->vcs[0]);
- card->vcs[0] = NULL;
- return -ENOMEM;
- }
-
- card->scd2vc[0] = vc;
- vc->scd_index = 0;
- vc->scq->scd = card->scd_base;
-
- fill_scd(card, vc->scq, vc->class);
-
- write_sram(card, card->tct_base + 0, TCT_UBR | card->scd_base);
- write_sram(card, card->tct_base + 1, 0);
- write_sram(card, card->tct_base + 2, 0);
- write_sram(card, card->tct_base + 3, 0);
- write_sram(card, card->tct_base + 4, 0);
- write_sram(card, card->tct_base + 5, 0);
- write_sram(card, card->tct_base + 6, 0);
- write_sram(card, card->tct_base + 7, TCT_FLAG_UBR);
-
- clear_bit(VCF_IDLE, &vc->flags);
- writel(TCMDQ_START | 0, SAR_REG_TCMDQ);
- return 0;
-}
-
-static void
-close_card_ubr0(struct idt77252_dev *card)
-{
- struct vc_map *vc = card->vcs[0];
-
- free_scq(card, vc->scq);
- kfree(vc);
-}
-
-static int
-idt77252_dev_open(struct idt77252_dev *card)
-{
- u32 conf;
-
- if (!test_bit(IDT77252_BIT_INIT, &card->flags)) {
- printk("%s: SAR not yet initialized.\n", card->name);
- return -1;
- }
-
- conf = SAR_CFG_RXPTH| /* enable receive path */
- SAR_RX_DELAY | /* interrupt on complete PDU */
- SAR_CFG_RAWIE | /* interrupt enable on raw cells */
- SAR_CFG_RQFIE | /* interrupt on RSQ almost full */
- SAR_CFG_TMOIE | /* interrupt on timer overflow */
- SAR_CFG_FBIE | /* interrupt on low free buffers */
- SAR_CFG_TXEN | /* transmit operation enable */
- SAR_CFG_TXINT | /* interrupt on transmit status */
- SAR_CFG_TXUIE | /* interrupt on transmit underrun */
- SAR_CFG_TXSFI | /* interrupt on TSQ almost full */
- SAR_CFG_PHYIE /* enable PHY interrupts */
- ;
-
-#ifdef CONFIG_ATM_IDT77252_RCV_ALL
- /* Test RAW cell receive. */
- conf |= SAR_CFG_VPECA;
-#endif
-
- writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
-
- if (open_card_oam(card)) {
- printk("%s: Error initializing OAM.\n", card->name);
- return -1;
- }
-
- if (open_card_ubr0(card)) {
- printk("%s: Error initializing UBR0.\n", card->name);
- return -1;
- }
-
- IPRINTK("%s: opened IDT77252 ABR SAR.\n", card->name);
- return 0;
-}
-
-static void idt77252_dev_close(struct atm_dev *dev)
-{
- struct idt77252_dev *card = dev->dev_data;
- u32 conf;
-
- close_card_ubr0(card);
- close_card_oam(card);
-
- conf = SAR_CFG_RXPTH | /* enable receive path */
- SAR_RX_DELAY | /* interrupt on complete PDU */
- SAR_CFG_RAWIE | /* interrupt enable on raw cells */
- SAR_CFG_RQFIE | /* interrupt on RSQ almost full */
- SAR_CFG_TMOIE | /* interrupt on timer overflow */
- SAR_CFG_FBIE | /* interrupt on low free buffers */
- SAR_CFG_TXEN | /* transmit operation enable */
- SAR_CFG_TXINT | /* interrupt on transmit status */
- SAR_CFG_TXUIE | /* interrupt on xmit underrun */
- SAR_CFG_TXSFI /* interrupt on TSQ almost full */
- ;
-
- writel(readl(SAR_REG_CFG) & ~(conf), SAR_REG_CFG);
-
- DIPRINTK("%s: closed IDT77252 ABR SAR.\n", card->name);
-}
-
-
-/*****************************************************************************/
-/* */
-/* Initialisation and Deinitialization of IDT77252 */
-/* */
-/*****************************************************************************/
-
-
-static void
-deinit_card(struct idt77252_dev *card)
-{
- struct sk_buff *skb;
- int i, j;
-
- if (!test_bit(IDT77252_BIT_INIT, &card->flags)) {
- printk("%s: SAR not yet initialized.\n", card->name);
- return;
- }
- DIPRINTK("idt77252: deinitialize card %u\n", card->index);
-
- writel(0, SAR_REG_CFG);
-
- if (card->atmdev)
- atm_dev_deregister(card->atmdev);
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < FBQ_SIZE; j++) {
- skb = card->sbpool[i].skb[j];
- if (skb) {
- dma_unmap_single(&card->pcidev->dev,
- IDT77252_PRV_PADDR(skb),
- (skb_end_pointer(skb) -
- skb->data),
- DMA_FROM_DEVICE);
- card->sbpool[i].skb[j] = NULL;
- dev_kfree_skb(skb);
- }
- }
- }
-
- vfree(card->soft_tst);
-
- vfree(card->scd2vc);
-
- vfree(card->vcs);
-
- if (card->raw_cell_hnd) {
- dma_free_coherent(&card->pcidev->dev, 2 * sizeof(u32),
- card->raw_cell_hnd, card->raw_cell_paddr);
- }
-
- if (card->rsq.base) {
- DIPRINTK("%s: Release RSQ ...\n", card->name);
- deinit_rsq(card);
- }
-
- if (card->tsq.base) {
- DIPRINTK("%s: Release TSQ ...\n", card->name);
- deinit_tsq(card);
- }
-
- DIPRINTK("idt77252: Release IRQ.\n");
- free_irq(card->pcidev->irq, card);
-
- for (i = 0; i < 4; i++) {
- if (card->fbq[i])
- iounmap(card->fbq[i]);
- }
-
- if (card->membase)
- iounmap(card->membase);
-
- clear_bit(IDT77252_BIT_INIT, &card->flags);
- DIPRINTK("%s: Card deinitialized.\n", card->name);
-}
-
-
-static void init_sram(struct idt77252_dev *card)
-{
- int i;
-
- for (i = 0; i < card->sramsize; i += 4)
- write_sram(card, (i >> 2), 0);
-
- /* set SRAM layout for THIS card */
- if (card->sramsize == (512 * 1024)) {
- card->tct_base = SAR_SRAM_TCT_128_BASE;
- card->tct_size = (SAR_SRAM_TCT_128_TOP - card->tct_base + 1)
- / SAR_SRAM_TCT_SIZE;
- card->rct_base = SAR_SRAM_RCT_128_BASE;
- card->rct_size = (SAR_SRAM_RCT_128_TOP - card->rct_base + 1)
- / SAR_SRAM_RCT_SIZE;
- card->rt_base = SAR_SRAM_RT_128_BASE;
- card->scd_base = SAR_SRAM_SCD_128_BASE;
- card->scd_size = (SAR_SRAM_SCD_128_TOP - card->scd_base + 1)
- / SAR_SRAM_SCD_SIZE;
- card->tst[0] = SAR_SRAM_TST1_128_BASE;
- card->tst[1] = SAR_SRAM_TST2_128_BASE;
- card->tst_size = SAR_SRAM_TST1_128_TOP - card->tst[0] + 1;
- card->abrst_base = SAR_SRAM_ABRSTD_128_BASE;
- card->abrst_size = SAR_ABRSTD_SIZE_8K;
- card->fifo_base = SAR_SRAM_FIFO_128_BASE;
- card->fifo_size = SAR_RXFD_SIZE_32K;
- } else {
- card->tct_base = SAR_SRAM_TCT_32_BASE;
- card->tct_size = (SAR_SRAM_TCT_32_TOP - card->tct_base + 1)
- / SAR_SRAM_TCT_SIZE;
- card->rct_base = SAR_SRAM_RCT_32_BASE;
- card->rct_size = (SAR_SRAM_RCT_32_TOP - card->rct_base + 1)
- / SAR_SRAM_RCT_SIZE;
- card->rt_base = SAR_SRAM_RT_32_BASE;
- card->scd_base = SAR_SRAM_SCD_32_BASE;
- card->scd_size = (SAR_SRAM_SCD_32_TOP - card->scd_base + 1)
- / SAR_SRAM_SCD_SIZE;
- card->tst[0] = SAR_SRAM_TST1_32_BASE;
- card->tst[1] = SAR_SRAM_TST2_32_BASE;
- card->tst_size = (SAR_SRAM_TST1_32_TOP - card->tst[0] + 1);
- card->abrst_base = SAR_SRAM_ABRSTD_32_BASE;
- card->abrst_size = SAR_ABRSTD_SIZE_1K;
- card->fifo_base = SAR_SRAM_FIFO_32_BASE;
- card->fifo_size = SAR_RXFD_SIZE_4K;
- }
-
- /* Initialize TCT */
- for (i = 0; i < card->tct_size; i++) {
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 0, 0);
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 1, 0);
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 2, 0);
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 3, 0);
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 4, 0);
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 5, 0);
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 6, 0);
- write_sram(card, i * SAR_SRAM_TCT_SIZE + 7, 0);
- }
-
- /* Initialize RCT */
- for (i = 0; i < card->rct_size; i++) {
- write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE,
- (u32) SAR_RCTE_RAWCELLINTEN);
- write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 1,
- (u32) 0);
- write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 2,
- (u32) 0);
- write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 3,
- (u32) 0xffffffff);
- }
-
- writel((SAR_FBQ0_LOW << 28) | (SAR_FB_SIZE_0 / 48), SAR_REG_FBQS0);
- writel((SAR_FBQ1_LOW << 28) | (SAR_FB_SIZE_1 / 48), SAR_REG_FBQS1);
- writel((SAR_FBQ2_LOW << 28) | (SAR_FB_SIZE_2 / 48), SAR_REG_FBQS2);
- writel((SAR_FBQ3_LOW << 28) | (SAR_FB_SIZE_3 / 48), SAR_REG_FBQS3);
-
- /* Initialize rate table */
- for (i = 0; i < 256; i++) {
- write_sram(card, card->rt_base + i, log_to_rate[i]);
- }
-
- for (i = 0; i < 128; i++) {
- unsigned int tmp;
-
- tmp = rate_to_log[(i << 2) + 0] << 0;
- tmp |= rate_to_log[(i << 2) + 1] << 8;
- tmp |= rate_to_log[(i << 2) + 2] << 16;
- tmp |= rate_to_log[(i << 2) + 3] << 24;
- write_sram(card, card->rt_base + 256 + i, tmp);
- }
-
-#if 0 /* Fill RDF and AIR tables. */
- for (i = 0; i < 128; i++) {
- unsigned int tmp;
-
- tmp = RDF[0][(i << 1) + 0] << 16;
- tmp |= RDF[0][(i << 1) + 1] << 0;
- write_sram(card, card->rt_base + 512 + i, tmp);
- }
-
- for (i = 0; i < 128; i++) {
- unsigned int tmp;
-
- tmp = AIR[0][(i << 1) + 0] << 16;
- tmp |= AIR[0][(i << 1) + 1] << 0;
- write_sram(card, card->rt_base + 640 + i, tmp);
- }
-#endif
-
- IPRINTK("%s: initialize rate table ...\n", card->name);
- writel(card->rt_base << 2, SAR_REG_RTBL);
-
- /* Initialize TSTs */
- IPRINTK("%s: initialize TST ...\n", card->name);
- card->tst_free = card->tst_size - 2; /* last two are jumps */
-
- for (i = card->tst[0]; i < card->tst[0] + card->tst_size - 2; i++)
- write_sram(card, i, TSTE_OPC_VAR);
- write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2));
- idt77252_sram_write_errors = 1;
- write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2));
- idt77252_sram_write_errors = 0;
- for (i = card->tst[1]; i < card->tst[1] + card->tst_size - 2; i++)
- write_sram(card, i, TSTE_OPC_VAR);
- write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2));
- idt77252_sram_write_errors = 1;
- write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2));
- idt77252_sram_write_errors = 0;
-
- card->tst_index = 0;
- writel(card->tst[0] << 2, SAR_REG_TSTB);
-
- /* Initialize ABRSTD and Receive FIFO */
- IPRINTK("%s: initialize ABRSTD ...\n", card->name);
- writel(card->abrst_size | (card->abrst_base << 2),
- SAR_REG_ABRSTD);
-
- IPRINTK("%s: initialize receive fifo ...\n", card->name);
- writel(card->fifo_size | (card->fifo_base << 2),
- SAR_REG_RXFD);
-
- IPRINTK("%s: SRAM initialization complete.\n", card->name);
-}
-
-static int init_card(struct atm_dev *dev)
-{
- struct idt77252_dev *card = dev->dev_data;
- struct pci_dev *pcidev = card->pcidev;
- unsigned long tmpl, modl;
- unsigned int linkrate, rsvdcr;
- unsigned int tst_entries;
- struct net_device *tmp;
- char tname[10];
-
- u32 size;
- u_char pci_byte;
- u32 conf;
- int i, k;
-
- if (test_bit(IDT77252_BIT_INIT, &card->flags)) {
- printk("Error: SAR already initialized.\n");
- return -1;
- }
-
-/*****************************************************************/
-/* P C I C O N F I G U R A T I O N */
-/*****************************************************************/
-
- /* Set PCI Retry-Timeout and TRDY timeout */
- IPRINTK("%s: Checking PCI retries.\n", card->name);
- if (pci_read_config_byte(pcidev, 0x40, &pci_byte) != 0) {
- printk("%s: can't read PCI retry timeout.\n", card->name);
- deinit_card(card);
- return -1;
- }
- if (pci_byte != 0) {
- IPRINTK("%s: PCI retry timeout: %d, set to 0.\n",
- card->name, pci_byte);
- if (pci_write_config_byte(pcidev, 0x40, 0) != 0) {
- printk("%s: can't set PCI retry timeout.\n",
- card->name);
- deinit_card(card);
- return -1;
- }
- }
- IPRINTK("%s: Checking PCI TRDY.\n", card->name);
- if (pci_read_config_byte(pcidev, 0x41, &pci_byte) != 0) {
- printk("%s: can't read PCI TRDY timeout.\n", card->name);
- deinit_card(card);
- return -1;
- }
- if (pci_byte != 0) {
- IPRINTK("%s: PCI TRDY timeout: %d, set to 0.\n",
- card->name, pci_byte);
- if (pci_write_config_byte(pcidev, 0x41, 0) != 0) {
- printk("%s: can't set PCI TRDY timeout.\n", card->name);
- deinit_card(card);
- return -1;
- }
- }
- /* Reset Timer register */
- if (readl(SAR_REG_STAT) & SAR_STAT_TMROF) {
- printk("%s: resetting timer overflow.\n", card->name);
- writel(SAR_STAT_TMROF, SAR_REG_STAT);
- }
- IPRINTK("%s: Request IRQ ... ", card->name);
- if (request_irq(pcidev->irq, idt77252_interrupt, IRQF_SHARED,
- card->name, card) != 0) {
- printk("%s: can't allocate IRQ.\n", card->name);
- deinit_card(card);
- return -1;
- }
- IPRINTK("got %d.\n", pcidev->irq);
-
-/*****************************************************************/
-/* C H E C K A N D I N I T S R A M */
-/*****************************************************************/
-
- IPRINTK("%s: Initializing SRAM\n", card->name);
-
- /* preset size of connecton table, so that init_sram() knows about it */
- conf = SAR_CFG_TX_FIFO_SIZE_9 | /* Use maximum fifo size */
- SAR_CFG_RXSTQ_SIZE_8k | /* Receive Status Queue is 8k */
- SAR_CFG_IDLE_CLP | /* Set CLP on idle cells */
-#ifndef ATM_IDT77252_SEND_IDLE
- SAR_CFG_NO_IDLE | /* Do not send idle cells */
-#endif
- 0;
-
- if (card->sramsize == (512 * 1024))
- conf |= SAR_CFG_CNTBL_1k;
- else
- conf |= SAR_CFG_CNTBL_512;
-
- switch (vpibits) {
- case 0:
- conf |= SAR_CFG_VPVCS_0;
- break;
- default:
- case 1:
- conf |= SAR_CFG_VPVCS_1;
- break;
- case 2:
- conf |= SAR_CFG_VPVCS_2;
- break;
- case 8:
- conf |= SAR_CFG_VPVCS_8;
- break;
- }
-
- writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
-
- init_sram(card);
-
-/********************************************************************/
-/* A L L O C R A M A N D S E T V A R I O U S T H I N G S */
-/********************************************************************/
- /* Initialize TSQ */
- if (0 != init_tsq(card)) {
- deinit_card(card);
- return -1;
- }
- /* Initialize RSQ */
- if (0 != init_rsq(card)) {
- deinit_card(card);
- return -1;
- }
-
- card->vpibits = vpibits;
- if (card->sramsize == (512 * 1024)) {
- card->vcibits = 10 - card->vpibits;
- } else {
- card->vcibits = 9 - card->vpibits;
- }
-
- card->vcimask = 0;
- for (k = 0, i = 1; k < card->vcibits; k++) {
- card->vcimask |= i;
- i <<= 1;
- }
-
- IPRINTK("%s: Setting VPI/VCI mask to zero.\n", card->name);
- writel(0, SAR_REG_VPM);
-
- /* Little Endian Order */
- writel(0, SAR_REG_GP);
-
- /* Initialize RAW Cell Handle Register */
- card->raw_cell_hnd = dma_alloc_coherent(&card->pcidev->dev,
- 2 * sizeof(u32),
- &card->raw_cell_paddr,
- GFP_KERNEL);
- if (!card->raw_cell_hnd) {
- printk("%s: memory allocation failure.\n", card->name);
- deinit_card(card);
- return -1;
- }
- writel(card->raw_cell_paddr, SAR_REG_RAWHND);
- IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name,
- card->raw_cell_hnd);
-
- size = sizeof(struct vc_map *) * card->tct_size;
- IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size);
- card->vcs = vzalloc(size);
- if (!card->vcs) {
- printk("%s: memory allocation failure.\n", card->name);
- deinit_card(card);
- return -1;
- }
-
- size = sizeof(struct vc_map *) * card->scd_size;
- IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n",
- card->name, size);
- card->scd2vc = vzalloc(size);
- if (!card->scd2vc) {
- printk("%s: memory allocation failure.\n", card->name);
- deinit_card(card);
- return -1;
- }
-
- size = sizeof(struct tst_info) * (card->tst_size - 2);
- IPRINTK("%s: allocate %d byte for TST to VC mapping.\n",
- card->name, size);
- card->soft_tst = vmalloc(size);
- if (!card->soft_tst) {
- printk("%s: memory allocation failure.\n", card->name);
- deinit_card(card);
- return -1;
- }
- for (i = 0; i < card->tst_size - 2; i++) {
- card->soft_tst[i].tste = TSTE_OPC_VAR;
- card->soft_tst[i].vc = NULL;
- }
-
- if (dev->phy == NULL) {
- printk("%s: No LT device defined.\n", card->name);
- deinit_card(card);
- return -1;
- }
- if (dev->phy->ioctl == NULL) {
- printk("%s: LT had no IOCTL function defined.\n", card->name);
- deinit_card(card);
- return -1;
- }
-
-#ifdef CONFIG_ATM_IDT77252_USE_SUNI
- /*
- * this is a jhs hack to get around special functionality in the
- * phy driver for the atecom hardware; the functionality doesn't
- * exist in the linux atm suni driver
- *
- * it isn't the right way to do things, but as the guy from NIST
- * said, talking about their measurement of the fine structure
- * constant, "it's good enough for government work."
- */
- linkrate = 149760000;
-#endif
-
- card->link_pcr = (linkrate / 8 / 53);
- printk("%s: Linkrate on ATM line : %u bit/s, %u cell/s.\n",
- card->name, linkrate, card->link_pcr);
-
-#ifdef ATM_IDT77252_SEND_IDLE
- card->utopia_pcr = card->link_pcr;
-#else
- card->utopia_pcr = (160000000 / 8 / 54);
-#endif
-
- rsvdcr = 0;
- if (card->utopia_pcr > card->link_pcr)
- rsvdcr = card->utopia_pcr - card->link_pcr;
-
- tmpl = (unsigned long) rsvdcr * ((unsigned long) card->tst_size - 2);
- modl = tmpl % (unsigned long)card->utopia_pcr;
- tst_entries = (int) (tmpl / (unsigned long)card->utopia_pcr);
- if (modl)
- tst_entries++;
- card->tst_free -= tst_entries;
- fill_tst(card, NULL, tst_entries, TSTE_OPC_NULL);
-
-#ifdef HAVE_EEPROM
- idt77252_eeprom_init(card);
- printk("%s: EEPROM: %02x:", card->name,
- idt77252_eeprom_read_status(card));
-
- for (i = 0; i < 0x80; i++) {
- printk(" %02x",
- idt77252_eeprom_read_byte(card, i)
- );
- }
- printk("\n");
-#endif /* HAVE_EEPROM */
-
- /*
- * XXX: <hack>
- */
- sprintf(tname, "eth%d", card->index);
- tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */
- if (tmp) {
- memcpy(card->atmdev->esi, tmp->dev_addr, 6);
- dev_put(tmp);
- printk("%s: ESI %pM\n", card->name, card->atmdev->esi);
- }
- /*
- * XXX: </hack>
- */
-
- /* Set Maximum Deficit Count for now. */
- writel(0xffff, SAR_REG_MDFCT);
-
- set_bit(IDT77252_BIT_INIT, &card->flags);
-
- XPRINTK("%s: IDT77252 ABR SAR initialization complete.\n", card->name);
- return 0;
-}
-
-
-/*****************************************************************************/
-/* */
-/* Probing of IDT77252 ABR SAR */
-/* */
-/*****************************************************************************/
-
-
-static int idt77252_preset(struct idt77252_dev *card)
-{
- u16 pci_command;
-
-/*****************************************************************/
-/* P C I C O N F I G U R A T I O N */
-/*****************************************************************/
-
- XPRINTK("%s: Enable PCI master and memory access for SAR.\n",
- card->name);
- if (pci_read_config_word(card->pcidev, PCI_COMMAND, &pci_command)) {
- printk("%s: can't read PCI_COMMAND.\n", card->name);
- deinit_card(card);
- return -1;
- }
- if (!(pci_command & PCI_COMMAND_IO)) {
- printk("%s: PCI_COMMAND: %04x (?)\n",
- card->name, pci_command);
- deinit_card(card);
- return (-1);
- }
- pci_command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- if (pci_write_config_word(card->pcidev, PCI_COMMAND, pci_command)) {
- printk("%s: can't write PCI_COMMAND.\n", card->name);
- deinit_card(card);
- return -1;
- }
-/*****************************************************************/
-/* G E N E R I C R E S E T */
-/*****************************************************************/
-
- /* Software reset */
- writel(SAR_CFG_SWRST, SAR_REG_CFG);
- mdelay(1);
- writel(0, SAR_REG_CFG);
-
- IPRINTK("%s: Software resetted.\n", card->name);
- return 0;
-}
-
-
-static unsigned long probe_sram(struct idt77252_dev *card)
-{
- u32 data, addr;
-
- writel(0, SAR_REG_DR0);
- writel(SAR_CMD_WRITE_SRAM | (0 << 2), SAR_REG_CMD);
-
- for (addr = 0x4000; addr < 0x80000; addr += 0x4000) {
- writel(ATM_POISON, SAR_REG_DR0);
- writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD);
-
- writel(SAR_CMD_READ_SRAM | (0 << 2), SAR_REG_CMD);
- data = readl(SAR_REG_DR0);
-
- if (data != 0)
- break;
- }
-
- return addr * sizeof(u32);
-}
-
-static int idt77252_init_one(struct pci_dev *pcidev,
- const struct pci_device_id *id)
-{
- static struct idt77252_dev **last = &idt77252_chain;
- static int index = 0;
-
- unsigned long membase, srambase;
- struct idt77252_dev *card;
- struct atm_dev *dev;
- int i, err;
-
-
- if ((err = pci_enable_device(pcidev))) {
- printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev));
- return err;
- }
-
- if ((err = dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(32)))) {
- printk("idt77252: can't enable DMA for PCI device at %s\n", pci_name(pcidev));
- goto err_out_disable_pdev;
- }
-
- card = kzalloc_obj(struct idt77252_dev);
- if (!card) {
- printk("idt77252-%d: can't allocate private data\n", index);
- err = -ENOMEM;
- goto err_out_disable_pdev;
- }
- card->revision = pcidev->revision;
- card->index = index;
- card->pcidev = pcidev;
- sprintf(card->name, "idt77252-%d", card->index);
-
- INIT_WORK(&card->tqueue, idt77252_softint);
-
- membase = pci_resource_start(pcidev, 1);
- srambase = pci_resource_start(pcidev, 2);
-
- mutex_init(&card->mutex);
- spin_lock_init(&card->cmd_lock);
- spin_lock_init(&card->tst_lock);
-
- timer_setup(&card->tst_timer, tst_timer, 0);
-
- /* Do the I/O remapping... */
- card->membase = ioremap(membase, 1024);
- if (!card->membase) {
- printk("%s: can't ioremap() membase\n", card->name);
- err = -EIO;
- goto err_out_free_card;
- }
-
- if (idt77252_preset(card)) {
- printk("%s: preset failed\n", card->name);
- err = -EIO;
- goto err_out_iounmap;
- }
-
- dev = atm_dev_register("idt77252", &pcidev->dev, &idt77252_ops, -1,
- NULL);
- if (!dev) {
- printk("%s: can't register atm device\n", card->name);
- err = -EIO;
- goto err_out_iounmap;
- }
- dev->dev_data = card;
- card->atmdev = dev;
-
-#ifdef CONFIG_ATM_IDT77252_USE_SUNI
- suni_init(dev);
- if (!dev->phy) {
- printk("%s: can't init SUNI\n", card->name);
- err = -EIO;
- goto err_out_deinit_card;
- }
-#endif /* CONFIG_ATM_IDT77252_USE_SUNI */
-
- card->sramsize = probe_sram(card);
-
- for (i = 0; i < 4; i++) {
- card->fbq[i] = ioremap(srambase | 0x200000 | (i << 18), 4);
- if (!card->fbq[i]) {
- printk("%s: can't ioremap() FBQ%d\n", card->name, i);
- err = -EIO;
- goto err_out_deinit_card;
- }
- }
-
- printk("%s: ABR SAR (Rev %c): MEM %08lx SRAM %08lx [%u KB]\n",
- card->name, ((card->revision > 1) && (card->revision < 25)) ?
- 'A' + card->revision - 1 : '?', membase, srambase,
- card->sramsize / 1024);
-
- if (init_card(dev)) {
- printk("%s: init_card failed\n", card->name);
- err = -EIO;
- goto err_out_deinit_card;
- }
-
- dev->ci_range.vpi_bits = card->vpibits;
- dev->ci_range.vci_bits = card->vcibits;
- dev->link_rate = card->link_pcr;
-
- if (dev->phy->start)
- dev->phy->start(dev);
-
- if (idt77252_dev_open(card)) {
- printk("%s: dev_open failed\n", card->name);
- err = -EIO;
- goto err_out_stop;
- }
-
- *last = card;
- last = &card->next;
- index++;
-
- return 0;
-
-err_out_stop:
- if (dev->phy->stop)
- dev->phy->stop(dev);
-
-err_out_deinit_card:
- deinit_card(card);
-
-err_out_iounmap:
- iounmap(card->membase);
-
-err_out_free_card:
- kfree(card);
-
-err_out_disable_pdev:
- pci_disable_device(pcidev);
- return err;
-}
-
-static const struct pci_device_id idt77252_pci_tbl[] =
-{
- { PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77252), 0 },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, idt77252_pci_tbl);
-
-static struct pci_driver idt77252_driver = {
- .name = "idt77252",
- .id_table = idt77252_pci_tbl,
- .probe = idt77252_init_one,
-};
-
-static int __init idt77252_init(void)
-{
- struct sk_buff *skb;
-
- printk("%s: at %p\n", __func__, idt77252_init);
- BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct idt77252_skb_prv) + sizeof(struct atm_skb_data));
- return pci_register_driver(&idt77252_driver);
-}
-
-static void __exit idt77252_exit(void)
-{
- struct idt77252_dev *card;
- struct atm_dev *dev;
-
- pci_unregister_driver(&idt77252_driver);
-
- while (idt77252_chain) {
- card = idt77252_chain;
- dev = card->atmdev;
- idt77252_chain = card->next;
- timer_shutdown_sync(&card->tst_timer);
-
- if (dev->phy->stop)
- dev->phy->stop(dev);
- deinit_card(card);
- pci_disable_device(card->pcidev);
- kfree(card);
- }
-
- DIPRINTK("idt77252: finished cleanup-module().\n");
-}
-
-module_init(idt77252_init);
-module_exit(idt77252_exit);
-
-MODULE_LICENSE("GPL");
-
-module_param(vpibits, uint, 0);
-MODULE_PARM_DESC(vpibits, "number of VPI bits supported (0, 1, or 2)");
-#ifdef CONFIG_ATM_IDT77252_DEBUG
-module_param(debug, ulong, 0644);
-MODULE_PARM_DESC(debug, "debug bitmap, see drivers/atm/idt77252.h");
-#endif
-
-MODULE_AUTHOR("Eddie C. Dost <ecd@atecom.com>");
-MODULE_DESCRIPTION("IDT77252 ABR SAR Driver");
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
deleted file mode 100644
index 0d38e93772c2..000000000000
--- a/drivers/atm/iphase.c
+++ /dev/null
@@ -1,3283 +0,0 @@
-/******************************************************************************
- iphase.c: Device driver for Interphase ATM PCI adapter cards
- Author: Peter Wang <pwang@iphase.com>
- Some fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- Interphase Corporation <www.iphase.com>
- Version: 1.0
-*******************************************************************************
-
- This software may be used and distributed according to the terms
- of the GNU General Public License (GPL), incorporated herein by reference.
- Drivers based on this skeleton fall under the GPL and must retain
- the authorship (implicit copyright) notice.
-
- 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.
-
- Modified from an incomplete driver for Interphase 5575 1KVC 1M card which
- was originally written by Monalisa Agrawal at UNH. Now this driver
- supports a variety of varients of Interphase ATM PCI (i)Chip adapter
- card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM)
- in terms of PHY type, the size of control memory and the size of
- packet memory. The following are the change log and history:
-
- Bugfix the Mona's UBR driver.
- Modify the basic memory allocation and dma logic.
- Port the driver to the latest kernel from 2.0.46.
- Complete the ABR logic of the driver, and added the ABR work-
- around for the hardware anormalies.
- Add the CBR support.
- Add the flow control logic to the driver to allow rate-limit VC.
- Add 4K VC support to the board with 512K control memory.
- Add the support of all the variants of the Interphase ATM PCI
- (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525
- (25M UTP25) and x531 (DS3 and E3).
- Add SMP support.
-
- Support and updates available at: ftp://ftp.iphase.com/pub/atm
-
-*******************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/ctype.h>
-#include <linux/sonet.h>
-#include <linux/skbuff.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/uio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <linux/atomic.h>
-#include <linux/uaccess.h>
-#include <asm/string.h>
-#include <asm/byteorder.h>
-#include <linux/vmalloc.h>
-#include <linux/jiffies.h>
-#include <linux/nospec.h>
-#include "iphase.h"
-#include "suni.h"
-#define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
-
-#define PRIV(dev) ((struct suni_priv *) dev->phy_data)
-
-static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr);
-static void desc_dbg(IADEV *iadev);
-
-static IADEV *ia_dev[8];
-static struct atm_dev *_ia_dev[8];
-static int iadev_count;
-static void ia_led_timer(struct timer_list *unused);
-static DEFINE_TIMER(ia_timer, ia_led_timer);
-static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
-static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;
-static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER
- |IF_IADBG_ABR | IF_IADBG_EVENT*/ 0;
-
-module_param(IA_TX_BUF, int, 0);
-module_param(IA_TX_BUF_SZ, int, 0);
-module_param(IA_RX_BUF, int, 0);
-module_param(IA_RX_BUF_SZ, int, 0);
-module_param(IADebugFlag, uint, 0644);
-
-MODULE_DESCRIPTION("Driver for Interphase ATM PCI NICs");
-MODULE_LICENSE("GPL");
-
-/**************************** IA_LIB **********************************/
-
-static void ia_init_rtn_q (IARTN_Q *que)
-{
- que->next = NULL;
- que->tail = NULL;
-}
-
-static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data)
-{
- data->next = NULL;
- if (que->next == NULL)
- que->next = que->tail = data;
- else {
- data->next = que->next;
- que->next = data;
- }
- return;
-}
-
-static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) {
- IARTN_Q *entry = kmalloc_obj(*entry, GFP_ATOMIC);
- if (!entry)
- return -ENOMEM;
- entry->data = data;
- entry->next = NULL;
- if (que->next == NULL)
- que->next = que->tail = entry;
- else {
- que->tail->next = entry;
- que->tail = que->tail->next;
- }
- return 1;
-}
-
-static IARTN_Q * ia_deque_rtn_q (IARTN_Q *que) {
- IARTN_Q *tmpdata;
- if (que->next == NULL)
- return NULL;
- tmpdata = que->next;
- if ( que->next == que->tail)
- que->next = que->tail = NULL;
- else
- que->next = que->next->next;
- return tmpdata;
-}
-
-static void ia_hack_tcq(IADEV *dev) {
-
- u_short desc1;
- u_short tcq_wr;
- struct ia_vcc *iavcc_r = NULL;
-
- tcq_wr = readl(dev->seg_reg+TCQ_WR_PTR) & 0xffff;
- while (dev->host_tcq_wr != tcq_wr) {
- desc1 = *(u_short *)(dev->seg_ram + dev->host_tcq_wr);
- if (!desc1) ;
- else if (!dev->desc_tbl[desc1 -1].timestamp) {
- IF_ABR(printk(" Desc %d is reset at %ld\n", desc1 -1, jiffies);)
- *(u_short *) (dev->seg_ram + dev->host_tcq_wr) = 0;
- }
- else if (dev->desc_tbl[desc1 -1].timestamp) {
- if (!(iavcc_r = dev->desc_tbl[desc1 -1].iavcc)) {
- printk("IA: Fatal err in get_desc\n");
- continue;
- }
- iavcc_r->vc_desc_cnt--;
- dev->desc_tbl[desc1 -1].timestamp = 0;
- IF_EVENT(printk("ia_hack: return_q skb = 0x%p desc = %d\n",
- dev->desc_tbl[desc1 -1].txskb, desc1);)
- if (iavcc_r->pcr < dev->rate_limit) {
- IA_SKB_STATE (dev->desc_tbl[desc1-1].txskb) |= IA_TX_DONE;
- if (ia_enque_rtn_q(&dev->tx_return_q, dev->desc_tbl[desc1 -1]) < 0)
- printk("ia_hack_tcq: No memory available\n");
- }
- dev->desc_tbl[desc1 -1].iavcc = NULL;
- dev->desc_tbl[desc1 -1].txskb = NULL;
- }
- dev->host_tcq_wr += 2;
- if (dev->host_tcq_wr > dev->ffL.tcq_ed)
- dev->host_tcq_wr = dev->ffL.tcq_st;
- }
-} /* ia_hack_tcq */
-
-static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
- u_short desc_num, i;
- struct ia_vcc *iavcc_r = NULL;
- unsigned long delta;
- static unsigned long timer = 0;
- int ltimeout;
-
- ia_hack_tcq (dev);
- if((time_after(jiffies,timer+50)) || ((dev->ffL.tcq_rd==dev->host_tcq_wr))) {
- timer = jiffies;
- i=0;
- while (i < dev->num_tx_desc) {
- if (!dev->desc_tbl[i].timestamp) {
- i++;
- continue;
- }
- ltimeout = dev->desc_tbl[i].iavcc->ltimeout;
- delta = jiffies - dev->desc_tbl[i].timestamp;
- if (delta >= ltimeout) {
- IF_ABR(printk("RECOVER run!! desc_tbl %d = %d delta = %ld, time = %ld\n", i,dev->desc_tbl[i].timestamp, delta, jiffies);)
- if (dev->ffL.tcq_rd == dev->ffL.tcq_st)
- dev->ffL.tcq_rd = dev->ffL.tcq_ed;
- else
- dev->ffL.tcq_rd -= 2;
- *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd) = i+1;
- if (!dev->desc_tbl[i].txskb || !(iavcc_r = dev->desc_tbl[i].iavcc))
- printk("Fatal err, desc table vcc or skb is NULL\n");
- else
- iavcc_r->vc_desc_cnt--;
- dev->desc_tbl[i].timestamp = 0;
- dev->desc_tbl[i].iavcc = NULL;
- dev->desc_tbl[i].txskb = NULL;
- }
- i++;
- } /* while */
- }
- if (dev->ffL.tcq_rd == dev->host_tcq_wr)
- return 0xFFFF;
-
- /* Get the next available descriptor number from TCQ */
- desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
-
- while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) {
- dev->ffL.tcq_rd += 2;
- if (dev->ffL.tcq_rd > dev->ffL.tcq_ed)
- dev->ffL.tcq_rd = dev->ffL.tcq_st;
- if (dev->ffL.tcq_rd == dev->host_tcq_wr)
- return 0xFFFF;
- desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
- }
-
- /* get system time */
- dev->desc_tbl[desc_num -1].timestamp = jiffies;
- return desc_num;
-}
-
-static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) {
- u_char foundLockUp;
- vcstatus_t *vcstatus;
- u_short *shd_tbl;
- u_short tempCellSlot, tempFract;
- struct main_vc *abr_vc = (struct main_vc *)dev->MAIN_VC_TABLE_ADDR;
- struct ext_vc *eabr_vc = (struct ext_vc *)dev->EXT_VC_TABLE_ADDR;
- u_int i;
-
- if (vcc->qos.txtp.traffic_class == ATM_ABR) {
- vcstatus = (vcstatus_t *) &(dev->testTable[vcc->vci]->vc_status);
- vcstatus->cnt++;
- foundLockUp = 0;
- if( vcstatus->cnt == 0x05 ) {
- abr_vc += vcc->vci;
- eabr_vc += vcc->vci;
- if( eabr_vc->last_desc ) {
- if( (abr_vc->status & 0x07) == ABR_STATE /* 0x2 */ ) {
- /* Wait for 10 Micro sec */
- udelay(10);
- if ((eabr_vc->last_desc)&&((abr_vc->status & 0x07)==ABR_STATE))
- foundLockUp = 1;
- }
- else {
- tempCellSlot = abr_vc->last_cell_slot;
- tempFract = abr_vc->fraction;
- if((tempCellSlot == dev->testTable[vcc->vci]->lastTime)
- && (tempFract == dev->testTable[vcc->vci]->fract))
- foundLockUp = 1;
- dev->testTable[vcc->vci]->lastTime = tempCellSlot;
- dev->testTable[vcc->vci]->fract = tempFract;
- }
- } /* last descriptor */
- vcstatus->cnt = 0;
- } /* vcstatus->cnt */
-
- if (foundLockUp) {
- IF_ABR(printk("LOCK UP found\n");)
- writew(0xFFFD, dev->seg_reg+MODE_REG_0);
- /* Wait for 10 Micro sec */
- udelay(10);
- abr_vc->status &= 0xFFF8;
- abr_vc->status |= 0x0001; /* state is idle */
- shd_tbl = (u_short *)dev->ABR_SCHED_TABLE_ADDR;
- for( i = 0; ((i < dev->num_vc) && (shd_tbl[i])); i++ );
- if (i < dev->num_vc)
- shd_tbl[i] = vcc->vci;
- else
- IF_ERR(printk("ABR Seg. may not continue on VC %x\n",vcc->vci);)
- writew(T_ONLINE, dev->seg_reg+MODE_REG_0);
- writew(~(TRANSMIT_DONE|TCQ_NOT_EMPTY), dev->seg_reg+SEG_MASK_REG);
- writew(TRANSMIT_DONE, dev->seg_reg+SEG_INTR_STATUS_REG);
- vcstatus->cnt = 0;
- } /* foundLockUp */
-
- } /* if an ABR VC */
-
-
-}
-
-/*
-** Conversion of 24-bit cellrate (cells/sec) to 16-bit floating point format.
-**
-** +----+----+------------------+-------------------------------+
-** | R | NZ | 5-bit exponent | 9-bit mantissa |
-** +----+----+------------------+-------------------------------+
-**
-** R = reserved (written as 0)
-** NZ = 0 if 0 cells/sec; 1 otherwise
-**
-** if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec
-*/
-static u16
-cellrate_to_float(u32 cr)
-{
-
-#define NZ 0x4000
-#define M_BITS 9 /* Number of bits in mantissa */
-#define E_BITS 5 /* Number of bits in exponent */
-#define M_MASK 0x1ff
-#define E_MASK 0x1f
- u16 flot;
- u32 tmp = cr & 0x00ffffff;
- int i = 0;
- if (cr == 0)
- return 0;
- while (tmp != 1) {
- tmp >>= 1;
- i++;
- }
- if (i == M_BITS)
- flot = NZ | (i << M_BITS) | (cr & M_MASK);
- else if (i < M_BITS)
- flot = NZ | (i << M_BITS) | ((cr << (M_BITS - i)) & M_MASK);
- else
- flot = NZ | (i << M_BITS) | ((cr >> (i - M_BITS)) & M_MASK);
- return flot;
-}
-
-#if 0
-/*
-** Conversion of 16-bit floating point format to 24-bit cellrate (cells/sec).
-*/
-static u32
-float_to_cellrate(u16 rate)
-{
- u32 exp, mantissa, cps;
- if ((rate & NZ) == 0)
- return 0;
- exp = (rate >> M_BITS) & E_MASK;
- mantissa = rate & M_MASK;
- if (exp == 0)
- return 1;
- cps = (1 << M_BITS) | mantissa;
- if (exp == M_BITS)
- cps = cps;
- else if (exp > M_BITS)
- cps <<= (exp - M_BITS);
- else
- cps >>= (M_BITS - exp);
- return cps;
-}
-#endif
-
-static void init_abr_vc (IADEV *dev, srv_cls_param_t *srv_p) {
- srv_p->class_type = ATM_ABR;
- srv_p->pcr = dev->LineRate;
- srv_p->mcr = 0;
- srv_p->icr = 0x055cb7;
- srv_p->tbe = 0xffffff;
- srv_p->frtt = 0x3a;
- srv_p->rif = 0xf;
- srv_p->rdf = 0xb;
- srv_p->nrm = 0x4;
- srv_p->trm = 0x7;
- srv_p->cdf = 0x3;
- srv_p->adtf = 50;
-}
-
-static int
-ia_open_abr_vc(IADEV *dev, srv_cls_param_t *srv_p,
- struct atm_vcc *vcc, u8 flag)
-{
- f_vc_abr_entry *f_abr_vc;
- r_vc_abr_entry *r_abr_vc;
- u32 icr;
- u8 trm, nrm, crm;
- u16 adtf, air, *ptr16;
- f_abr_vc =(f_vc_abr_entry *)dev->MAIN_VC_TABLE_ADDR;
- f_abr_vc += vcc->vci;
- switch (flag) {
- case 1: /* FFRED initialization */
-#if 0 /* sanity check */
- if (srv_p->pcr == 0)
- return INVALID_PCR;
- if (srv_p->pcr > dev->LineRate)
- srv_p->pcr = dev->LineRate;
- if ((srv_p->mcr + dev->sum_mcr) > dev->LineRate)
- return MCR_UNAVAILABLE;
- if (srv_p->mcr > srv_p->pcr)
- return INVALID_MCR;
- if (!(srv_p->icr))
- srv_p->icr = srv_p->pcr;
- if ((srv_p->icr < srv_p->mcr) || (srv_p->icr > srv_p->pcr))
- return INVALID_ICR;
- if ((srv_p->tbe < MIN_TBE) || (srv_p->tbe > MAX_TBE))
- return INVALID_TBE;
- if ((srv_p->frtt < MIN_FRTT) || (srv_p->frtt > MAX_FRTT))
- return INVALID_FRTT;
- if (srv_p->nrm > MAX_NRM)
- return INVALID_NRM;
- if (srv_p->trm > MAX_TRM)
- return INVALID_TRM;
- if (srv_p->adtf > MAX_ADTF)
- return INVALID_ADTF;
- else if (srv_p->adtf == 0)
- srv_p->adtf = 1;
- if (srv_p->cdf > MAX_CDF)
- return INVALID_CDF;
- if (srv_p->rif > MAX_RIF)
- return INVALID_RIF;
- if (srv_p->rdf > MAX_RDF)
- return INVALID_RDF;
-#endif
- memset ((caddr_t)f_abr_vc, 0, sizeof(*f_abr_vc));
- f_abr_vc->f_vc_type = ABR;
- nrm = 2 << srv_p->nrm; /* (2 ** (srv_p->nrm +1)) */
- /* i.e 2**n = 2 << (n-1) */
- f_abr_vc->f_nrm = nrm << 8 | nrm;
- trm = 100000/(2 << (16 - srv_p->trm));
- if ( trm == 0) trm = 1;
- f_abr_vc->f_nrmexp =(((srv_p->nrm +1) & 0x0f) << 12)|(MRM << 8) | trm;
- crm = srv_p->tbe / nrm;
- if (crm == 0) crm = 1;
- f_abr_vc->f_crm = crm & 0xff;
- f_abr_vc->f_pcr = cellrate_to_float(srv_p->pcr);
- icr = min( srv_p->icr, (srv_p->tbe > srv_p->frtt) ?
- ((srv_p->tbe/srv_p->frtt)*1000000) :
- (1000000/(srv_p->frtt/srv_p->tbe)));
- f_abr_vc->f_icr = cellrate_to_float(icr);
- adtf = (10000 * srv_p->adtf)/8192;
- if (adtf == 0) adtf = 1;
- f_abr_vc->f_cdf = ((7 - srv_p->cdf) << 12 | adtf) & 0xfff;
- f_abr_vc->f_mcr = cellrate_to_float(srv_p->mcr);
- f_abr_vc->f_acr = f_abr_vc->f_icr;
- f_abr_vc->f_status = 0x0042;
- break;
- case 0: /* RFRED initialization */
- ptr16 = (u_short *)(dev->reass_ram + REASS_TABLE*dev->memSize);
- *(ptr16 + vcc->vci) = NO_AAL5_PKT | REASS_ABR;
- r_abr_vc = (r_vc_abr_entry*)(dev->reass_ram+ABR_VC_TABLE*dev->memSize);
- r_abr_vc += vcc->vci;
- r_abr_vc->r_status_rdf = (15 - srv_p->rdf) & 0x000f;
- air = srv_p->pcr << (15 - srv_p->rif);
- if (air == 0) air = 1;
- r_abr_vc->r_air = cellrate_to_float(air);
- dev->testTable[vcc->vci]->vc_status = VC_ACTIVE | VC_ABR;
- dev->sum_mcr += srv_p->mcr;
- dev->n_abr++;
- break;
- default:
- break;
- }
- return 0;
-}
-static int ia_cbr_setup (IADEV *dev, struct atm_vcc *vcc) {
- u32 rateLow=0, rateHigh, rate;
- int entries;
- struct ia_vcc *ia_vcc;
-
- int idealSlot =0, testSlot, toBeAssigned, inc;
- u32 spacing;
- u16 *SchedTbl, *TstSchedTbl;
- u16 cbrVC, vcIndex;
- u32 fracSlot = 0;
- u32 sp_mod = 0;
- u32 sp_mod2 = 0;
-
- /* IpAdjustTrafficParams */
- if (vcc->qos.txtp.max_pcr <= 0) {
- IF_ERR(printk("PCR for CBR not defined\n");)
- return -1;
- }
- rate = vcc->qos.txtp.max_pcr;
- entries = rate / dev->Granularity;
- IF_CBR(printk("CBR: CBR entries=0x%x for rate=0x%x & Gran=0x%x\n",
- entries, rate, dev->Granularity);)
- if (entries < 1)
- IF_CBR(printk("CBR: Bandwidth smaller than granularity of CBR table\n");)
- rateLow = entries * dev->Granularity;
- rateHigh = (entries + 1) * dev->Granularity;
- if (3*(rate - rateLow) > (rateHigh - rate))
- entries++;
- if (entries > dev->CbrRemEntries) {
- IF_CBR(printk("CBR: Not enough bandwidth to support this PCR.\n");)
- IF_CBR(printk("Entries = 0x%x, CbrRemEntries = 0x%x.\n",
- entries, dev->CbrRemEntries);)
- return -EBUSY;
- }
-
- ia_vcc = INPH_IA_VCC(vcc);
- ia_vcc->NumCbrEntry = entries;
- dev->sum_mcr += entries * dev->Granularity;
- /* IaFFrednInsertCbrSched */
- // Starting at an arbitrary location, place the entries into the table
- // as smoothly as possible
- cbrVC = 0;
- spacing = dev->CbrTotEntries / entries;
- sp_mod = dev->CbrTotEntries % entries; // get modulo
- toBeAssigned = entries;
- fracSlot = 0;
- vcIndex = vcc->vci;
- IF_CBR(printk("Vci=0x%x,Spacing=0x%x,Sp_mod=0x%x\n",vcIndex,spacing,sp_mod);)
- while (toBeAssigned)
- {
- // If this is the first time, start the table loading for this connection
- // as close to entryPoint as possible.
- if (toBeAssigned == entries)
- {
- idealSlot = dev->CbrEntryPt;
- dev->CbrEntryPt += 2; // Adding 2 helps to prevent clumping
- if (dev->CbrEntryPt >= dev->CbrTotEntries)
- dev->CbrEntryPt -= dev->CbrTotEntries;// Wrap if necessary
- } else {
- idealSlot += (u32)(spacing + fracSlot); // Point to the next location
- // in the table that would be smoothest
- fracSlot = ((sp_mod + sp_mod2) / entries); // get new integer part
- sp_mod2 = ((sp_mod + sp_mod2) % entries); // calc new fractional part
- }
- if (idealSlot >= (int)dev->CbrTotEntries)
- idealSlot -= dev->CbrTotEntries;
- // Continuously check around this ideal value until a null
- // location is encountered.
- SchedTbl = (u16*)(dev->seg_ram+CBR_SCHED_TABLE*dev->memSize);
- inc = 0;
- testSlot = idealSlot;
- TstSchedTbl = (u16*)(SchedTbl+testSlot); //set index and read in value
- IF_CBR(printk("CBR Testslot 0x%x AT Location 0x%p, NumToAssign=%d\n",
- testSlot, TstSchedTbl,toBeAssigned);)
- memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
- while (cbrVC) // If another VC at this location, we have to keep looking
- {
- inc++;
- testSlot = idealSlot - inc;
- if (testSlot < 0) { // Wrap if necessary
- testSlot += dev->CbrTotEntries;
- IF_CBR(printk("Testslot Wrap. STable Start=0x%p,Testslot=%d\n",
- SchedTbl,testSlot);)
- }
- TstSchedTbl = (u16 *)(SchedTbl + testSlot); // set table index
- memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
- if (!cbrVC)
- break;
- testSlot = idealSlot + inc;
- if (testSlot >= (int)dev->CbrTotEntries) { // Wrap if necessary
- testSlot -= dev->CbrTotEntries;
- IF_CBR(printk("TotCbrEntries=%d",dev->CbrTotEntries);)
- IF_CBR(printk(" Testslot=0x%x ToBeAssgned=%d\n",
- testSlot, toBeAssigned);)
- }
- // set table index and read in value
- TstSchedTbl = (u16*)(SchedTbl + testSlot);
- IF_CBR(printk("Reading CBR Tbl from 0x%p, CbrVal=0x%x Iteration %d\n",
- TstSchedTbl,cbrVC,inc);)
- memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
- } /* while */
- // Move this VCI number into this location of the CBR Sched table.
- memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex, sizeof(*TstSchedTbl));
- dev->CbrRemEntries--;
- toBeAssigned--;
- } /* while */
-
- /* IaFFrednCbrEnable */
- dev->NumEnabledCBR++;
- if (dev->NumEnabledCBR == 1) {
- writew((CBR_EN | UBR_EN | ABR_EN | (0x23 << 2)), dev->seg_reg+STPARMS);
- IF_CBR(printk("CBR is enabled\n");)
- }
- return 0;
-}
-static void ia_cbrVc_close (struct atm_vcc *vcc) {
- IADEV *iadev;
- u16 *SchedTbl, NullVci = 0;
- u32 i, NumFound;
-
- iadev = INPH_IA_DEV(vcc->dev);
- iadev->NumEnabledCBR--;
- SchedTbl = (u16*)(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize);
- if (iadev->NumEnabledCBR == 0) {
- writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);
- IF_CBR (printk("CBR support disabled\n");)
- }
- NumFound = 0;
- for (i=0; i < iadev->CbrTotEntries; i++)
- {
- if (*SchedTbl == vcc->vci) {
- iadev->CbrRemEntries++;
- *SchedTbl = NullVci;
- IF_CBR(NumFound++;)
- }
- SchedTbl++;
- }
- IF_CBR(printk("Exit ia_cbrVc_close, NumRemoved=%d\n",NumFound);)
-}
-
-static int ia_avail_descs(IADEV *iadev) {
- int tmp = 0;
- ia_hack_tcq(iadev);
- if (iadev->host_tcq_wr >= iadev->ffL.tcq_rd)
- tmp = (iadev->host_tcq_wr - iadev->ffL.tcq_rd) / 2;
- else
- tmp = (iadev->ffL.tcq_ed - iadev->ffL.tcq_rd + 2 + iadev->host_tcq_wr -
- iadev->ffL.tcq_st) / 2;
- return tmp;
-}
-
-static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb);
-
-static int ia_que_tx (IADEV *iadev) {
- struct sk_buff *skb;
- int num_desc;
- struct atm_vcc *vcc;
- num_desc = ia_avail_descs(iadev);
-
- while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) {
- if (!(vcc = ATM_SKB(skb)->vcc)) {
- dev_kfree_skb_any(skb);
- printk("ia_que_tx: Null vcc\n");
- break;
- }
- if (!test_bit(ATM_VF_READY,&vcc->flags)) {
- dev_kfree_skb_any(skb);
- printk("Free the SKB on closed vci %d \n", vcc->vci);
- break;
- }
- if (ia_pkt_tx (vcc, skb)) {
- skb_queue_head(&iadev->tx_backlog, skb);
- }
- num_desc--;
- }
- return 0;
-}
-
-static void ia_tx_poll (IADEV *iadev) {
- struct atm_vcc *vcc = NULL;
- struct sk_buff *skb = NULL, *skb1 = NULL;
- struct ia_vcc *iavcc;
- IARTN_Q * rtne;
-
- ia_hack_tcq(iadev);
- while ( (rtne = ia_deque_rtn_q(&iadev->tx_return_q))) {
- skb = rtne->data.txskb;
- if (!skb) {
- printk("ia_tx_poll: skb is null\n");
- goto out;
- }
- vcc = ATM_SKB(skb)->vcc;
- if (!vcc) {
- printk("ia_tx_poll: vcc is null\n");
- dev_kfree_skb_any(skb);
- goto out;
- }
-
- iavcc = INPH_IA_VCC(vcc);
- if (!iavcc) {
- printk("ia_tx_poll: iavcc is null\n");
- dev_kfree_skb_any(skb);
- goto out;
- }
-
- skb1 = skb_dequeue(&iavcc->txing_skb);
- while (skb1 && (skb1 != skb)) {
- if (!(IA_SKB_STATE(skb1) & IA_TX_DONE)) {
- printk("IA_tx_intr: Vci %d lost pkt!!!\n", vcc->vci);
- }
- IF_ERR(printk("Release the SKB not match\n");)
- if ((vcc->pop) && (skb1->len != 0))
- {
- vcc->pop(vcc, skb1);
- IF_EVENT(printk("Transmit Done - skb 0x%lx return\n",
- (long)skb1);)
- }
- else
- dev_kfree_skb_any(skb1);
- skb1 = skb_dequeue(&iavcc->txing_skb);
- }
- if (!skb1) {
- IF_EVENT(printk("IA: Vci %d - skb not found requeued\n",vcc->vci);)
- ia_enque_head_rtn_q (&iadev->tx_return_q, rtne);
- break;
- }
- if ((vcc->pop) && (skb->len != 0))
- {
- vcc->pop(vcc, skb);
- IF_EVENT(printk("Tx Done - skb 0x%lx return\n",(long)skb);)
- }
- else
- dev_kfree_skb_any(skb);
- kfree(rtne);
- }
- ia_que_tx(iadev);
-out:
- return;
-}
-#if 0
-static void ia_eeprom_put (IADEV *iadev, u32 addr, u_short val)
-{
- u32 t;
- int i;
- /*
- * Issue a command to enable writes to the NOVRAM
- */
- NVRAM_CMD (EXTEND + EWEN);
- NVRAM_CLR_CE;
- /*
- * issue the write command
- */
- NVRAM_CMD(IAWRITE + addr);
- /*
- * Send the data, starting with D15, then D14, and so on for 16 bits
- */
- for (i=15; i>=0; i--) {
- NVRAM_CLKOUT (val & 0x8000);
- val <<= 1;
- }
- NVRAM_CLR_CE;
- CFG_OR(NVCE);
- t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS);
- while (!(t & NVDO))
- t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS);
-
- NVRAM_CLR_CE;
- /*
- * disable writes again
- */
- NVRAM_CMD(EXTEND + EWDS)
- NVRAM_CLR_CE;
- CFG_AND(~NVDI);
-}
-#endif
-
-static u16 ia_eeprom_get (IADEV *iadev, u32 addr)
-{
- u_short val;
- u32 t;
- int i;
- /*
- * Read the first bit that was clocked with the falling edge of
- * the last command data clock
- */
- NVRAM_CMD(IAREAD + addr);
- /*
- * Now read the rest of the bits, the next bit read is D14, then D13,
- * and so on.
- */
- val = 0;
- for (i=15; i>=0; i--) {
- NVRAM_CLKIN(t);
- val |= (t << i);
- }
- NVRAM_CLR_CE;
- CFG_AND(~NVDI);
- return val;
-}
-
-static void ia_hw_type(IADEV *iadev) {
- u_short memType = ia_eeprom_get(iadev, 25);
- iadev->memType = memType;
- if ((memType & MEM_SIZE_MASK) == MEM_SIZE_1M) {
- iadev->num_tx_desc = IA_TX_BUF;
- iadev->tx_buf_sz = IA_TX_BUF_SZ;
- iadev->num_rx_desc = IA_RX_BUF;
- iadev->rx_buf_sz = IA_RX_BUF_SZ;
- } else if ((memType & MEM_SIZE_MASK) == MEM_SIZE_512K) {
- if (IA_TX_BUF == DFL_TX_BUFFERS)
- iadev->num_tx_desc = IA_TX_BUF / 2;
- else
- iadev->num_tx_desc = IA_TX_BUF;
- iadev->tx_buf_sz = IA_TX_BUF_SZ;
- if (IA_RX_BUF == DFL_RX_BUFFERS)
- iadev->num_rx_desc = IA_RX_BUF / 2;
- else
- iadev->num_rx_desc = IA_RX_BUF;
- iadev->rx_buf_sz = IA_RX_BUF_SZ;
- }
- else {
- if (IA_TX_BUF == DFL_TX_BUFFERS)
- iadev->num_tx_desc = IA_TX_BUF / 8;
- else
- iadev->num_tx_desc = IA_TX_BUF;
- iadev->tx_buf_sz = IA_TX_BUF_SZ;
- if (IA_RX_BUF == DFL_RX_BUFFERS)
- iadev->num_rx_desc = IA_RX_BUF / 8;
- else
- iadev->num_rx_desc = IA_RX_BUF;
- iadev->rx_buf_sz = IA_RX_BUF_SZ;
- }
- iadev->rx_pkt_ram = TX_PACKET_RAM + (iadev->num_tx_desc * iadev->tx_buf_sz);
- IF_INIT(printk("BUF: tx=%d,sz=%d rx=%d sz= %d rx_pkt_ram=%d\n",
- iadev->num_tx_desc, iadev->tx_buf_sz, iadev->num_rx_desc,
- iadev->rx_buf_sz, iadev->rx_pkt_ram);)
-
-#if 0
- if ((memType & FE_MASK) == FE_SINGLE_MODE) {
- iadev->phy_type = PHY_OC3C_S;
- else if ((memType & FE_MASK) == FE_UTP_OPTION)
- iadev->phy_type = PHY_UTP155;
- else
- iadev->phy_type = PHY_OC3C_M;
-#endif
-
- iadev->phy_type = memType & FE_MASK;
- IF_INIT(printk("memType = 0x%x iadev->phy_type = 0x%x\n",
- memType,iadev->phy_type);)
- if (iadev->phy_type == FE_25MBIT_PHY)
- iadev->LineRate = (u32)(((25600000/8)*26)/(27*53));
- else if (iadev->phy_type == FE_DS3_PHY)
- iadev->LineRate = (u32)(((44736000/8)*26)/(27*53));
- else if (iadev->phy_type == FE_E3_PHY)
- iadev->LineRate = (u32)(((34368000/8)*26)/(27*53));
- else
- iadev->LineRate = (u32)(ATM_OC3_PCR);
- IF_INIT(printk("iadev->LineRate = %d \n", iadev->LineRate);)
-
-}
-
-static u32 ia_phy_read32(struct iadev_priv *ia, unsigned int reg)
-{
- return readl(ia->phy + (reg >> 2));
-}
-
-static void ia_phy_write32(struct iadev_priv *ia, unsigned int reg, u32 val)
-{
- writel(val, ia->phy + (reg >> 2));
-}
-
-static void ia_frontend_intr(struct iadev_priv *iadev)
-{
- u32 status;
-
- if (iadev->phy_type & FE_25MBIT_PHY) {
- status = ia_phy_read32(iadev, MB25_INTR_STATUS);
- iadev->carrier_detect = (status & MB25_IS_GSB) ? 1 : 0;
- } else if (iadev->phy_type & FE_DS3_PHY) {
- ia_phy_read32(iadev, SUNI_DS3_FRM_INTR_STAT);
- status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
- iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
- } else if (iadev->phy_type & FE_E3_PHY) {
- ia_phy_read32(iadev, SUNI_E3_FRM_MAINT_INTR_IND);
- status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
- iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
- } else {
- status = ia_phy_read32(iadev, SUNI_RSOP_STATUS);
- iadev->carrier_detect = (status & SUNI_LOSV) ? 0 : 1;
- }
-
- printk(KERN_INFO "IA: SUNI carrier %s\n",
- iadev->carrier_detect ? "detected" : "lost signal");
-}
-
-static void ia_mb25_init(struct iadev_priv *iadev)
-{
-#if 0
- mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED;
-#endif
- ia_phy_write32(iadev, MB25_MASTER_CTRL, MB25_MC_DRIC | MB25_MC_DREC);
- ia_phy_write32(iadev, MB25_DIAG_CONTROL, 0);
-
- iadev->carrier_detect =
- (ia_phy_read32(iadev, MB25_INTR_STATUS) & MB25_IS_GSB) ? 1 : 0;
-}
-
-struct ia_reg {
- u16 reg;
- u16 val;
-};
-
-static void ia_phy_write(struct iadev_priv *iadev,
- const struct ia_reg *regs, int len)
-{
- while (len--) {
- ia_phy_write32(iadev, regs->reg, regs->val);
- regs++;
- }
-}
-
-static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
-{
- static const struct ia_reg suni_ds3_init[] = {
- { SUNI_DS3_FRM_INTR_ENBL, 0x17 },
- { SUNI_DS3_FRM_CFG, 0x01 },
- { SUNI_DS3_TRAN_CFG, 0x01 },
- { SUNI_CONFIG, 0 },
- { SUNI_SPLR_CFG, 0 },
- { SUNI_SPLT_CFG, 0 }
- };
- u32 status;
-
- status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
- iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
-
- ia_phy_write(iadev, suni_ds3_init, ARRAY_SIZE(suni_ds3_init));
-}
-
-static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
-{
- static const struct ia_reg suni_e3_init[] = {
- { SUNI_E3_FRM_FRAM_OPTIONS, 0x04 },
- { SUNI_E3_FRM_MAINT_OPTIONS, 0x20 },
- { SUNI_E3_FRM_FRAM_INTR_ENBL, 0x1d },
- { SUNI_E3_FRM_MAINT_INTR_ENBL, 0x30 },
- { SUNI_E3_TRAN_STAT_DIAG_OPTIONS, 0 },
- { SUNI_E3_TRAN_FRAM_OPTIONS, 0x01 },
- { SUNI_CONFIG, SUNI_PM7345_E3ENBL },
- { SUNI_SPLR_CFG, 0x41 },
- { SUNI_SPLT_CFG, 0x41 }
- };
- u32 status;
-
- status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
- iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
- ia_phy_write(iadev, suni_e3_init, ARRAY_SIZE(suni_e3_init));
-}
-
-static void ia_suni_pm7345_init(struct iadev_priv *iadev)
-{
- static const struct ia_reg suni_init[] = {
- /* Enable RSOP loss of signal interrupt. */
- { SUNI_INTR_ENBL, 0x28 },
- /* Clear error counters. */
- { SUNI_ID_RESET, 0 },
- /* Clear "PMCTST" in master test register. */
- { SUNI_MASTER_TEST, 0 },
-
- { SUNI_RXCP_CTRL, 0x2c },
- { SUNI_RXCP_FCTRL, 0x81 },
-
- { SUNI_RXCP_IDLE_PAT_H1, 0 },
- { SUNI_RXCP_IDLE_PAT_H2, 0 },
- { SUNI_RXCP_IDLE_PAT_H3, 0 },
- { SUNI_RXCP_IDLE_PAT_H4, 0x01 },
-
- { SUNI_RXCP_IDLE_MASK_H1, 0xff },
- { SUNI_RXCP_IDLE_MASK_H2, 0xff },
- { SUNI_RXCP_IDLE_MASK_H3, 0xff },
- { SUNI_RXCP_IDLE_MASK_H4, 0xfe },
-
- { SUNI_RXCP_CELL_PAT_H1, 0 },
- { SUNI_RXCP_CELL_PAT_H2, 0 },
- { SUNI_RXCP_CELL_PAT_H3, 0 },
- { SUNI_RXCP_CELL_PAT_H4, 0x01 },
-
- { SUNI_RXCP_CELL_MASK_H1, 0xff },
- { SUNI_RXCP_CELL_MASK_H2, 0xff },
- { SUNI_RXCP_CELL_MASK_H3, 0xff },
- { SUNI_RXCP_CELL_MASK_H4, 0xff },
-
- { SUNI_TXCP_CTRL, 0xa4 },
- { SUNI_TXCP_INTR_EN_STS, 0x10 },
- { SUNI_TXCP_IDLE_PAT_H5, 0x55 }
- };
-
- if (iadev->phy_type & FE_DS3_PHY)
- ia_suni_pm7345_init_ds3(iadev);
- else
- ia_suni_pm7345_init_e3(iadev);
-
- ia_phy_write(iadev, suni_init, ARRAY_SIZE(suni_init));
-
- ia_phy_write32(iadev, SUNI_CONFIG, ia_phy_read32(iadev, SUNI_CONFIG) &
- ~(SUNI_PM7345_LLB | SUNI_PM7345_CLB |
- SUNI_PM7345_DLB | SUNI_PM7345_PLB));
-#ifdef __SNMP__
- suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE;
-#endif /* __SNMP__ */
- return;
-}
-
-
-/***************************** IA_LIB END *****************************/
-
-#ifdef CONFIG_ATM_IA_DEBUG
-static int tcnter = 0;
-static void xdump( u_char* cp, int length, char* prefix )
-{
- int col, count;
- u_char prntBuf[120];
- u_char* pBuf = prntBuf;
- count = 0;
- while(count < length){
- pBuf += sprintf( pBuf, "%s", prefix );
- for(col = 0;count + col < length && col < 16; col++){
- if (col != 0 && (col % 4) == 0)
- pBuf += sprintf( pBuf, " " );
- pBuf += sprintf( pBuf, "%02X ", cp[count + col] );
- }
- while(col++ < 16){ /* pad end of buffer with blanks */
- if ((col % 4) == 0)
- sprintf( pBuf, " " );
- pBuf += sprintf( pBuf, " " );
- }
- pBuf += sprintf( pBuf, " " );
- for(col = 0;count + col < length && col < 16; col++){
- u_char c = cp[count + col];
-
- if (isascii(c) && isprint(c))
- pBuf += sprintf(pBuf, "%c", c);
- else
- pBuf += sprintf(pBuf, ".");
- }
- printk("%s\n", prntBuf);
- count += col;
- pBuf = prntBuf;
- }
-
-} /* close xdump(... */
-#endif /* CONFIG_ATM_IA_DEBUG */
-
-
-static struct atm_dev *ia_boards = NULL;
-
-#define ACTUAL_RAM_BASE \
- RAM_BASE*((iadev->mem)/(128 * 1024))
-#define ACTUAL_SEG_RAM_BASE \
- IPHASE5575_FRAG_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024))
-#define ACTUAL_REASS_RAM_BASE \
- IPHASE5575_REASS_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024))
-
-
-/*-- some utilities and memory allocation stuff will come here -------------*/
-
-static void desc_dbg(IADEV *iadev) {
-
- u_short tcq_wr_ptr, tcq_st_ptr, tcq_ed_ptr;
- u32 i;
- void __iomem *tmp;
- // regval = readl((u32)ia_cmds->maddr);
- tcq_wr_ptr = readw(iadev->seg_reg+TCQ_WR_PTR);
- printk("B_tcq_wr = 0x%x desc = %d last desc = %d\n",
- tcq_wr_ptr, readw(iadev->seg_ram+tcq_wr_ptr),
- readw(iadev->seg_ram+tcq_wr_ptr-2));
- printk(" host_tcq_wr = 0x%x host_tcq_rd = 0x%x \n", iadev->host_tcq_wr,
- iadev->ffL.tcq_rd);
- tcq_st_ptr = readw(iadev->seg_reg+TCQ_ST_ADR);
- tcq_ed_ptr = readw(iadev->seg_reg+TCQ_ED_ADR);
- printk("tcq_st_ptr = 0x%x tcq_ed_ptr = 0x%x \n", tcq_st_ptr, tcq_ed_ptr);
- i = 0;
- while (tcq_st_ptr != tcq_ed_ptr) {
- tmp = iadev->seg_ram+tcq_st_ptr;
- printk("TCQ slot %d desc = %d Addr = %p\n", i++, readw(tmp), tmp);
- tcq_st_ptr += 2;
- }
- for(i=0; i <iadev->num_tx_desc; i++)
- printk("Desc_tbl[%d] = %d \n", i, iadev->desc_tbl[i].timestamp);
-}
-
-
-/*----------------------------- Receiving side stuff --------------------------*/
-
-static void rx_excp_rcvd(struct atm_dev *dev)
-{
-#if 0 /* closing the receiving size will cause too many excp int */
- IADEV *iadev;
- u_short state;
- u_short excpq_rd_ptr;
- //u_short *ptr;
- int vci, error = 1;
- iadev = INPH_IA_DEV(dev);
- state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
- while((state & EXCPQ_EMPTY) != EXCPQ_EMPTY)
- { printk("state = %x \n", state);
- excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_RD_PTR) & 0xffff;
- printk("state = %x excpq_rd_ptr = %x \n", state, excpq_rd_ptr);
- if (excpq_rd_ptr == *(u16*)(iadev->reass_reg + EXCP_Q_WR_PTR))
- IF_ERR(printk("excpq_rd_ptr is wrong!!!\n");)
- // TODO: update exception stat
- vci = readw(iadev->reass_ram+excpq_rd_ptr);
- error = readw(iadev->reass_ram+excpq_rd_ptr+2) & 0x0007;
- // pwang_test
- excpq_rd_ptr += 4;
- if (excpq_rd_ptr > (readw(iadev->reass_reg + EXCP_Q_ED_ADR)& 0xffff))
- excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_ST_ADR)& 0xffff;
- writew( excpq_rd_ptr, iadev->reass_reg + EXCP_Q_RD_PTR);
- state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
- }
-#endif
-}
-
-static void free_desc(struct atm_dev *dev, int desc)
-{
- IADEV *iadev;
- iadev = INPH_IA_DEV(dev);
- writew(desc, iadev->reass_ram+iadev->rfL.fdq_wr);
- iadev->rfL.fdq_wr +=2;
- if (iadev->rfL.fdq_wr > iadev->rfL.fdq_ed)
- iadev->rfL.fdq_wr = iadev->rfL.fdq_st;
- writew(iadev->rfL.fdq_wr, iadev->reass_reg+FREEQ_WR_PTR);
-}
-
-
-static int rx_pkt(struct atm_dev *dev)
-{
- IADEV *iadev;
- struct atm_vcc *vcc;
- unsigned short status;
- struct rx_buf_desc __iomem *buf_desc_ptr;
- int desc;
- struct dle* wr_ptr;
- int len;
- struct sk_buff *skb;
- u_int buf_addr, dma_addr;
-
- iadev = INPH_IA_DEV(dev);
- if (iadev->rfL.pcq_rd == (readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff))
- {
- printk(KERN_ERR DEV_LABEL "(itf %d) Receive queue empty\n", dev->number);
- return -EINVAL;
- }
- /* mask 1st 3 bits to get the actual descno. */
- desc = readw(iadev->reass_ram+iadev->rfL.pcq_rd) & 0x1fff;
- IF_RX(printk("reass_ram = %p iadev->rfL.pcq_rd = 0x%x desc = %d\n",
- iadev->reass_ram, iadev->rfL.pcq_rd, desc);
- printk(" pcq_wr_ptr = 0x%x\n",
- readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff);)
- /* update the read pointer - maybe we shud do this in the end*/
- if ( iadev->rfL.pcq_rd== iadev->rfL.pcq_ed)
- iadev->rfL.pcq_rd = iadev->rfL.pcq_st;
- else
- iadev->rfL.pcq_rd += 2;
- writew(iadev->rfL.pcq_rd, iadev->reass_reg+PCQ_RD_PTR);
-
- /* get the buffer desc entry.
- update stuff. - doesn't seem to be any update necessary
- */
- buf_desc_ptr = iadev->RX_DESC_BASE_ADDR;
- /* make the ptr point to the corresponding buffer desc entry */
- buf_desc_ptr += desc;
- if (!desc || (desc > iadev->num_rx_desc) ||
- ((buf_desc_ptr->vc_index & 0xffff) >= iadev->num_vc)) {
- free_desc(dev, desc);
- IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
- return -1;
- }
- vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];
- if (!vcc)
- {
- free_desc(dev, desc);
- printk("IA: null vcc, drop PDU\n");
- return -1;
- }
-
-
- /* might want to check the status bits for errors */
- status = (u_short) (buf_desc_ptr->desc_mode);
- if (status & (RX_CER | RX_PTE | RX_OFL))
- {
- atomic_inc(&vcc->stats->rx_err);
- IF_ERR(printk("IA: bad packet, dropping it");)
- if (status & RX_CER) {
- IF_ERR(printk(" cause: packet CRC error\n");)
- }
- else if (status & RX_PTE) {
- IF_ERR(printk(" cause: packet time out\n");)
- }
- else {
- IF_ERR(printk(" cause: buffer overflow\n");)
- }
- goto out_free_desc;
- }
-
- /*
- build DLE.
- */
-
- buf_addr = (buf_desc_ptr->buf_start_hi << 16) | buf_desc_ptr->buf_start_lo;
- dma_addr = (buf_desc_ptr->dma_start_hi << 16) | buf_desc_ptr->dma_start_lo;
- len = dma_addr - buf_addr;
- if (len > iadev->rx_buf_sz) {
- printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz);
- atomic_inc(&vcc->stats->rx_err);
- goto out_free_desc;
- }
-
- if (!(skb = atm_alloc_charge(vcc, len, GFP_ATOMIC))) {
- if (vcc->vci < 32)
- printk("Drop control packets\n");
- goto out_free_desc;
- }
- skb_put(skb,len);
- // pwang_test
- ATM_SKB(skb)->vcc = vcc;
- ATM_DESC(skb) = desc;
- skb_queue_tail(&iadev->rx_dma_q, skb);
-
- /* Build the DLE structure */
- wr_ptr = iadev->rx_dle_q.write;
- wr_ptr->sys_pkt_addr = dma_map_single(&iadev->pci->dev, skb->data,
- len, DMA_FROM_DEVICE);
- wr_ptr->local_pkt_addr = buf_addr;
- wr_ptr->bytes = len; /* We don't know this do we ?? */
- wr_ptr->mode = DMA_INT_ENABLE;
-
- /* shud take care of wrap around here too. */
- if(++wr_ptr == iadev->rx_dle_q.end)
- wr_ptr = iadev->rx_dle_q.start;
- iadev->rx_dle_q.write = wr_ptr;
- udelay(1);
- /* Increment transaction counter */
- writel(1, iadev->dma+IPHASE5575_RX_COUNTER);
-out: return 0;
-out_free_desc:
- free_desc(dev, desc);
- goto out;
-}
-
-static void rx_intr(struct atm_dev *dev)
-{
- IADEV *iadev;
- u_short status;
- u_short state, i;
-
- iadev = INPH_IA_DEV(dev);
- status = readl(iadev->reass_reg+REASS_INTR_STATUS_REG) & 0xffff;
- IF_EVENT(printk("rx_intr: status = 0x%x\n", status);)
- if (status & RX_PKT_RCVD)
- {
- /* do something */
- /* Basically recvd an interrupt for receiving a packet.
- A descriptor would have been written to the packet complete
- queue. Get all the descriptors and set up dma to move the
- packets till the packet complete queue is empty..
- */
- state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
- IF_EVENT(printk("Rx intr status: RX_PKT_RCVD %08x\n", status);)
- while(!(state & PCQ_EMPTY))
- {
- rx_pkt(dev);
- state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
- }
- iadev->rxing = 1;
- }
- if (status & RX_FREEQ_EMPT)
- {
- if (iadev->rxing) {
- iadev->rx_tmp_cnt = iadev->rx_pkt_cnt;
- iadev->rx_tmp_jif = jiffies;
- iadev->rxing = 0;
- }
- else if ((time_after(jiffies, iadev->rx_tmp_jif + 50)) &&
- ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) {
- for (i = 1; i <= iadev->num_rx_desc; i++)
- free_desc(dev, i);
-printk("Test logic RUN!!!!\n");
- writew( ~(RX_FREEQ_EMPT|RX_EXCP_RCVD),iadev->reass_reg+REASS_MASK_REG);
- iadev->rxing = 1;
- }
- IF_EVENT(printk("Rx intr status: RX_FREEQ_EMPT %08x\n", status);)
- }
-
- if (status & RX_EXCP_RCVD)
- {
- /* probably need to handle the exception queue also. */
- IF_EVENT(printk("Rx intr status: RX_EXCP_RCVD %08x\n", status);)
- rx_excp_rcvd(dev);
- }
-
-
- if (status & RX_RAW_RCVD)
- {
- /* need to handle the raw incoming cells. This deepnds on
- whether we have programmed to receive the raw cells or not.
- Else ignore. */
- IF_EVENT(printk("Rx intr status: RX_RAW_RCVD %08x\n", status);)
- }
-}
-
-
-static void rx_dle_intr(struct atm_dev *dev)
-{
- IADEV *iadev;
- struct atm_vcc *vcc;
- struct sk_buff *skb;
- int desc;
- u_short state;
- struct dle *dle, *cur_dle;
- u_int dle_lp;
- int len;
- iadev = INPH_IA_DEV(dev);
-
- /* free all the dles done, that is just update our own dle read pointer
- - do we really need to do this. Think not. */
- /* DMA is done, just get all the recevie buffers from the rx dma queue
- and push them up to the higher layer protocol. Also free the desc
- associated with the buffer. */
- dle = iadev->rx_dle_q.read;
- dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1);
- cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4));
- while(dle != cur_dle)
- {
- /* free the DMAed skb */
- skb = skb_dequeue(&iadev->rx_dma_q);
- if (!skb)
- goto INCR_DLE;
- desc = ATM_DESC(skb);
- free_desc(dev, desc);
-
- if (!(len = skb->len))
- {
- printk("rx_dle_intr: skb len 0\n");
- dev_kfree_skb_any(skb);
- }
- else
- {
- struct cpcs_trailer *trailer;
- u_short length;
- struct ia_vcc *ia_vcc;
-
- dma_unmap_single(&iadev->pci->dev, iadev->rx_dle_q.write->sys_pkt_addr,
- len, DMA_FROM_DEVICE);
- /* no VCC related housekeeping done as yet. lets see */
- vcc = ATM_SKB(skb)->vcc;
- if (!vcc) {
- printk("IA: null vcc\n");
- dev_kfree_skb_any(skb);
- goto INCR_DLE;
- }
- ia_vcc = INPH_IA_VCC(vcc);
- if (ia_vcc == NULL)
- {
- atomic_inc(&vcc->stats->rx_err);
- atm_return(vcc, skb->truesize);
- dev_kfree_skb_any(skb);
- goto INCR_DLE;
- }
- // get real pkt length pwang_test
- trailer = (struct cpcs_trailer*)((u_char *)skb->data +
- skb->len - sizeof(*trailer));
- length = swap_byte_order(trailer->length);
- if ((length > iadev->rx_buf_sz) || (length >
- (skb->len - sizeof(struct cpcs_trailer))))
- {
- atomic_inc(&vcc->stats->rx_err);
- IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)",
- length, skb->len);)
- atm_return(vcc, skb->truesize);
- dev_kfree_skb_any(skb);
- goto INCR_DLE;
- }
- skb_trim(skb, length);
-
- /* Display the packet */
- IF_RXPKT(printk("\nDmad Recvd data: len = %d \n", skb->len);
- xdump(skb->data, skb->len, "RX: ");
- printk("\n");)
-
- IF_RX(printk("rx_dle_intr: skb push");)
- vcc->push(vcc,skb);
- atomic_inc(&vcc->stats->rx);
- iadev->rx_pkt_cnt++;
- }
-INCR_DLE:
- if (++dle == iadev->rx_dle_q.end)
- dle = iadev->rx_dle_q.start;
- }
- iadev->rx_dle_q.read = dle;
-
- /* if the interrupts are masked because there were no free desc available,
- unmask them now. */
- if (!iadev->rxing) {
- state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
- if (!(state & FREEQ_EMPTY)) {
- state = readl(iadev->reass_reg + REASS_MASK_REG) & 0xffff;
- writel(state & ~(RX_FREEQ_EMPT |/* RX_EXCP_RCVD |*/ RX_PKT_RCVD),
- iadev->reass_reg+REASS_MASK_REG);
- iadev->rxing++;
- }
- }
-}
-
-
-static int open_rx(struct atm_vcc *vcc)
-{
- IADEV *iadev;
- u_short __iomem *vc_table;
- u_short __iomem *reass_ptr;
- IF_EVENT(printk("iadev: open_rx %d.%d\n", vcc->vpi, vcc->vci);)
-
- if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0;
- iadev = INPH_IA_DEV(vcc->dev);
- if (vcc->qos.rxtp.traffic_class == ATM_ABR) {
- if (iadev->phy_type & FE_25MBIT_PHY) {
- printk("IA: ABR not support\n");
- return -EINVAL;
- }
- }
- /* Make only this VCI in the vc table valid and let all
- others be invalid entries */
- vc_table = iadev->reass_ram+RX_VC_TABLE*iadev->memSize;
- vc_table += vcc->vci;
- /* mask the last 6 bits and OR it with 3 for 1K VCs */
-
- *vc_table = vcc->vci << 6;
- /* Also keep a list of open rx vcs so that we can attach them with
- incoming PDUs later. */
- if ((vcc->qos.rxtp.traffic_class == ATM_ABR) ||
- (vcc->qos.txtp.traffic_class == ATM_ABR))
- {
- srv_cls_param_t srv_p;
- init_abr_vc(iadev, &srv_p);
- ia_open_abr_vc(iadev, &srv_p, vcc, 0);
- }
- else { /* for UBR later may need to add CBR logic */
- reass_ptr = iadev->reass_ram+REASS_TABLE*iadev->memSize;
- reass_ptr += vcc->vci;
- *reass_ptr = NO_AAL5_PKT;
- }
-
- if (iadev->rx_open[vcc->vci])
- printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d already open\n",
- vcc->dev->number, vcc->vci);
- iadev->rx_open[vcc->vci] = vcc;
- return 0;
-}
-
-static int rx_init(struct atm_dev *dev)
-{
- IADEV *iadev;
- struct rx_buf_desc __iomem *buf_desc_ptr;
- unsigned long rx_pkt_start = 0;
- void *dle_addr;
- struct abr_vc_table *abr_vc_table;
- u16 *vc_table;
- u16 *reass_table;
- int i,j, vcsize_sel;
- u_short freeq_st_adr;
- u_short *freeq_start;
-
- iadev = INPH_IA_DEV(dev);
- // spin_lock_init(&iadev->rx_lock);
-
- /* Allocate 4k bytes - more aligned than needed (4k boundary) */
- dle_addr = dma_alloc_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE,
- &iadev->rx_dle_dma, GFP_KERNEL);
- if (!dle_addr) {
- printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");
- goto err_out;
- }
- iadev->rx_dle_q.start = (struct dle *)dle_addr;
- iadev->rx_dle_q.read = iadev->rx_dle_q.start;
- iadev->rx_dle_q.write = iadev->rx_dle_q.start;
- iadev->rx_dle_q.end = (struct dle*)((unsigned long)dle_addr+sizeof(struct dle)*DLE_ENTRIES);
- /* the end of the dle q points to the entry after the last
- DLE that can be used. */
-
- /* write the upper 20 bits of the start address to rx list address register */
- /* We know this is 32bit bus addressed so the following is safe */
- writel(iadev->rx_dle_dma & 0xfffff000,
- iadev->dma + IPHASE5575_RX_LIST_ADDR);
- IF_INIT(printk("Tx Dle list addr: 0x%p value: 0x%0x\n",
- iadev->dma+IPHASE5575_TX_LIST_ADDR,
- readl(iadev->dma + IPHASE5575_TX_LIST_ADDR));
- printk("Rx Dle list addr: 0x%p value: 0x%0x\n",
- iadev->dma+IPHASE5575_RX_LIST_ADDR,
- readl(iadev->dma + IPHASE5575_RX_LIST_ADDR));)
-
- writew(0xffff, iadev->reass_reg+REASS_MASK_REG);
- writew(0, iadev->reass_reg+MODE_REG);
- writew(RESET_REASS, iadev->reass_reg+REASS_COMMAND_REG);
-
- /* Receive side control memory map
- -------------------------------
-
- Buffer descr 0x0000 (736 - 23K)
- VP Table 0x5c00 (256 - 512)
- Except q 0x5e00 (128 - 512)
- Free buffer q 0x6000 (1K - 2K)
- Packet comp q 0x6800 (1K - 2K)
- Reass Table 0x7000 (1K - 2K)
- VC Table 0x7800 (1K - 2K)
- ABR VC Table 0x8000 (1K - 32K)
- */
-
- /* Base address for Buffer Descriptor Table */
- writew(RX_DESC_BASE >> 16, iadev->reass_reg+REASS_DESC_BASE);
- /* Set the buffer size register */
- writew(iadev->rx_buf_sz, iadev->reass_reg+BUF_SIZE);
-
- /* Initialize each entry in the Buffer Descriptor Table */
- iadev->RX_DESC_BASE_ADDR = iadev->reass_ram+RX_DESC_BASE*iadev->memSize;
- buf_desc_ptr = iadev->RX_DESC_BASE_ADDR;
- memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
- buf_desc_ptr++;
- rx_pkt_start = iadev->rx_pkt_ram;
- for(i=1; i<=iadev->num_rx_desc; i++)
- {
- memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
- buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16;
- buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff;
- buf_desc_ptr++;
- rx_pkt_start += iadev->rx_buf_sz;
- }
- IF_INIT(printk("Rx Buffer desc ptr: 0x%p\n", buf_desc_ptr);)
- i = FREE_BUF_DESC_Q*iadev->memSize;
- writew(i >> 16, iadev->reass_reg+REASS_QUEUE_BASE);
- writew(i, iadev->reass_reg+FREEQ_ST_ADR);
- writew(i+iadev->num_rx_desc*sizeof(u_short),
- iadev->reass_reg+FREEQ_ED_ADR);
- writew(i, iadev->reass_reg+FREEQ_RD_PTR);
- writew(i+iadev->num_rx_desc*sizeof(u_short),
- iadev->reass_reg+FREEQ_WR_PTR);
- /* Fill the FREEQ with all the free descriptors. */
- freeq_st_adr = readw(iadev->reass_reg+FREEQ_ST_ADR);
- freeq_start = (u_short *)(iadev->reass_ram+freeq_st_adr);
- for(i=1; i<=iadev->num_rx_desc; i++)
- {
- *freeq_start = (u_short)i;
- freeq_start++;
- }
- IF_INIT(printk("freeq_start: 0x%p\n", freeq_start);)
- /* Packet Complete Queue */
- i = (PKT_COMP_Q * iadev->memSize) & 0xffff;
- writew(i, iadev->reass_reg+PCQ_ST_ADR);
- writew(i+iadev->num_vc*sizeof(u_short), iadev->reass_reg+PCQ_ED_ADR);
- writew(i, iadev->reass_reg+PCQ_RD_PTR);
- writew(i, iadev->reass_reg+PCQ_WR_PTR);
-
- /* Exception Queue */
- i = (EXCEPTION_Q * iadev->memSize) & 0xffff;
- writew(i, iadev->reass_reg+EXCP_Q_ST_ADR);
- writew(i + NUM_RX_EXCP * sizeof(RX_ERROR_Q),
- iadev->reass_reg+EXCP_Q_ED_ADR);
- writew(i, iadev->reass_reg+EXCP_Q_RD_PTR);
- writew(i, iadev->reass_reg+EXCP_Q_WR_PTR);
-
- /* Load local copy of FREEQ and PCQ ptrs */
- iadev->rfL.fdq_st = readw(iadev->reass_reg+FREEQ_ST_ADR) & 0xffff;
- iadev->rfL.fdq_ed = readw(iadev->reass_reg+FREEQ_ED_ADR) & 0xffff ;
- iadev->rfL.fdq_rd = readw(iadev->reass_reg+FREEQ_RD_PTR) & 0xffff;
- iadev->rfL.fdq_wr = readw(iadev->reass_reg+FREEQ_WR_PTR) & 0xffff;
- iadev->rfL.pcq_st = readw(iadev->reass_reg+PCQ_ST_ADR) & 0xffff;
- iadev->rfL.pcq_ed = readw(iadev->reass_reg+PCQ_ED_ADR) & 0xffff;
- iadev->rfL.pcq_rd = readw(iadev->reass_reg+PCQ_RD_PTR) & 0xffff;
- iadev->rfL.pcq_wr = readw(iadev->reass_reg+PCQ_WR_PTR) & 0xffff;
-
- IF_INIT(printk("INIT:pcq_st:0x%x pcq_ed:0x%x pcq_rd:0x%x pcq_wr:0x%x",
- iadev->rfL.pcq_st, iadev->rfL.pcq_ed, iadev->rfL.pcq_rd,
- iadev->rfL.pcq_wr);)
- /* just for check - no VP TBL */
- /* VP Table */
- /* writew(0x0b80, iadev->reass_reg+VP_LKUP_BASE); */
- /* initialize VP Table for invalid VPIs
- - I guess we can write all 1s or 0x000f in the entire memory
- space or something similar.
- */
-
- /* This seems to work and looks right to me too !!! */
- i = REASS_TABLE * iadev->memSize;
- writew((i >> 3), iadev->reass_reg+REASS_TABLE_BASE);
- /* initialize Reassembly table to I don't know what ???? */
- reass_table = (u16 *)(iadev->reass_ram+i);
- j = REASS_TABLE_SZ * iadev->memSize;
- for(i=0; i < j; i++)
- *reass_table++ = NO_AAL5_PKT;
- i = 8*1024;
- vcsize_sel = 0;
- while (i != iadev->num_vc) {
- i /= 2;
- vcsize_sel++;
- }
- i = RX_VC_TABLE * iadev->memSize;
- writew(((i>>3) & 0xfff8) | vcsize_sel, iadev->reass_reg+VC_LKUP_BASE);
- vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);
- j = RX_VC_TABLE_SZ * iadev->memSize;
- for(i = 0; i < j; i++)
- {
- /* shift the reassembly pointer by 3 + lower 3 bits of
- vc_lkup_base register (=3 for 1K VCs) and the last byte
- is those low 3 bits.
- Shall program this later.
- */
- *vc_table = (i << 6) | 15; /* for invalid VCI */
- vc_table++;
- }
- /* ABR VC table */
- i = ABR_VC_TABLE * iadev->memSize;
- writew(i >> 3, iadev->reass_reg+ABR_LKUP_BASE);
-
- i = ABR_VC_TABLE * iadev->memSize;
- abr_vc_table = (struct abr_vc_table *)(iadev->reass_ram+i);
- j = REASS_TABLE_SZ * iadev->memSize;
- memset ((char*)abr_vc_table, 0, j * sizeof(*abr_vc_table));
- for(i = 0; i < j; i++) {
- abr_vc_table->rdf = 0x0003;
- abr_vc_table->air = 0x5eb1;
- abr_vc_table++;
- }
-
- /* Initialize other registers */
-
- /* VP Filter Register set for VC Reassembly only */
- writew(0xff00, iadev->reass_reg+VP_FILTER);
- writew(0, iadev->reass_reg+XTRA_RM_OFFSET);
- writew(0x1, iadev->reass_reg+PROTOCOL_ID);
-
- /* Packet Timeout Count related Registers :
- Set packet timeout to occur in about 3 seconds
- Set Packet Aging Interval count register to overflow in about 4 us
- */
- writew(0xF6F8, iadev->reass_reg+PKT_TM_CNT );
-
- i = (j >> 6) & 0xFF;
- j += 2 * (j - 1);
- i |= ((j << 2) & 0xFF00);
- writew(i, iadev->reass_reg+TMOUT_RANGE);
-
- /* initiate the desc_tble */
- for(i=0; i<iadev->num_tx_desc;i++)
- iadev->desc_tbl[i].timestamp = 0;
-
- /* to clear the interrupt status register - read it */
- readw(iadev->reass_reg+REASS_INTR_STATUS_REG);
-
- /* Mask Register - clear it */
- writew(~(RX_FREEQ_EMPT|RX_PKT_RCVD), iadev->reass_reg+REASS_MASK_REG);
-
- skb_queue_head_init(&iadev->rx_dma_q);
- iadev->rx_free_desc_qhead = NULL;
-
- iadev->rx_open = kcalloc(iadev->num_vc, sizeof(void *), GFP_KERNEL);
- if (!iadev->rx_open) {
- printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n",
- dev->number);
- goto err_free_dle;
- }
-
- iadev->rxing = 1;
- iadev->rx_pkt_cnt = 0;
- /* Mode Register */
- writew(R_ONLINE, iadev->reass_reg+MODE_REG);
- return 0;
-
-err_free_dle:
- dma_free_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE, iadev->rx_dle_q.start,
- iadev->rx_dle_dma);
-err_out:
- return -ENOMEM;
-}
-
-
-/*
- The memory map suggested in appendix A and the coding for it.
- Keeping it around just in case we change our mind later.
-
- Buffer descr 0x0000 (128 - 4K)
- UBR sched 0x1000 (1K - 4K)
- UBR Wait q 0x2000 (1K - 4K)
- Commn queues 0x3000 Packet Ready, Trasmit comp(0x3100)
- (128 - 256) each
- extended VC 0x4000 (1K - 8K)
- ABR sched 0x6000 and ABR wait queue (1K - 2K) each
- CBR sched 0x7000 (as needed)
- VC table 0x8000 (1K - 32K)
-*/
-
-static void tx_intr(struct atm_dev *dev)
-{
- IADEV *iadev;
- unsigned short status;
- unsigned long flags;
-
- iadev = INPH_IA_DEV(dev);
-
- status = readl(iadev->seg_reg+SEG_INTR_STATUS_REG);
- if (status & TRANSMIT_DONE){
-
- IF_EVENT(printk("Transmit Done Intr logic run\n");)
- spin_lock_irqsave(&iadev->tx_lock, flags);
- ia_tx_poll(iadev);
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
- writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
- if (iadev->close_pending)
- wake_up(&iadev->close_wait);
- }
- if (status & TCQ_NOT_EMPTY)
- {
- IF_EVENT(printk("TCQ_NOT_EMPTY int received\n");)
- }
-}
-
-static void tx_dle_intr(struct atm_dev *dev)
-{
- IADEV *iadev;
- struct dle *dle, *cur_dle;
- struct sk_buff *skb;
- struct atm_vcc *vcc;
- struct ia_vcc *iavcc;
- u_int dle_lp;
- unsigned long flags;
-
- iadev = INPH_IA_DEV(dev);
- spin_lock_irqsave(&iadev->tx_lock, flags);
- dle = iadev->tx_dle_q.read;
- dle_lp = readl(iadev->dma+IPHASE5575_TX_LIST_ADDR) &
- (sizeof(struct dle)*DLE_ENTRIES - 1);
- cur_dle = (struct dle*)(iadev->tx_dle_q.start + (dle_lp >> 4));
- while (dle != cur_dle)
- {
- /* free the DMAed skb */
- skb = skb_dequeue(&iadev->tx_dma_q);
- if (!skb) break;
-
- /* Revenge of the 2 dle (skb + trailer) used in ia_pkt_tx() */
- if (!((dle - iadev->tx_dle_q.start)%(2*sizeof(struct dle)))) {
- dma_unmap_single(&iadev->pci->dev, dle->sys_pkt_addr, skb->len,
- DMA_TO_DEVICE);
- }
- vcc = ATM_SKB(skb)->vcc;
- if (!vcc) {
- printk("tx_dle_intr: vcc is null\n");
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
- dev_kfree_skb_any(skb);
-
- return;
- }
- iavcc = INPH_IA_VCC(vcc);
- if (!iavcc) {
- printk("tx_dle_intr: iavcc is null\n");
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
- dev_kfree_skb_any(skb);
- return;
- }
- if (vcc->qos.txtp.pcr >= iadev->rate_limit) {
- if ((vcc->pop) && (skb->len != 0))
- {
- vcc->pop(vcc, skb);
- }
- else {
- dev_kfree_skb_any(skb);
- }
- }
- else { /* Hold the rate-limited skb for flow control */
- IA_SKB_STATE(skb) |= IA_DLED;
- skb_queue_tail(&iavcc->txing_skb, skb);
- }
- IF_EVENT(printk("tx_dle_intr: enque skb = 0x%p \n", skb);)
- if (++dle == iadev->tx_dle_q.end)
- dle = iadev->tx_dle_q.start;
- }
- iadev->tx_dle_q.read = dle;
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
-}
-
-static int open_tx(struct atm_vcc *vcc)
-{
- struct ia_vcc *ia_vcc;
- IADEV *iadev;
- struct main_vc *vc;
- struct ext_vc *evc;
- int ret;
- IF_EVENT(printk("iadev: open_tx entered vcc->vci = %d\n", vcc->vci);)
- if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;
- iadev = INPH_IA_DEV(vcc->dev);
-
- if (iadev->phy_type & FE_25MBIT_PHY) {
- if (vcc->qos.txtp.traffic_class == ATM_ABR) {
- printk("IA: ABR not support\n");
- return -EINVAL;
- }
- if (vcc->qos.txtp.traffic_class == ATM_CBR) {
- printk("IA: CBR not support\n");
- return -EINVAL;
- }
- }
- ia_vcc = INPH_IA_VCC(vcc);
- memset((caddr_t)ia_vcc, 0, sizeof(*ia_vcc));
- if (vcc->qos.txtp.max_sdu >
- (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){
- printk("IA: SDU size over (%d) the configured SDU size %d\n",
- vcc->qos.txtp.max_sdu,iadev->tx_buf_sz);
- vcc->dev_data = NULL;
- kfree(ia_vcc);
- return -EINVAL;
- }
- ia_vcc->vc_desc_cnt = 0;
- ia_vcc->txing = 1;
-
- /* find pcr */
- if (vcc->qos.txtp.max_pcr == ATM_MAX_PCR)
- vcc->qos.txtp.pcr = iadev->LineRate;
- else if ((vcc->qos.txtp.max_pcr == 0)&&( vcc->qos.txtp.pcr <= 0))
- vcc->qos.txtp.pcr = iadev->LineRate;
- else if ((vcc->qos.txtp.max_pcr > vcc->qos.txtp.pcr) && (vcc->qos.txtp.max_pcr> 0))
- vcc->qos.txtp.pcr = vcc->qos.txtp.max_pcr;
- if (vcc->qos.txtp.pcr > iadev->LineRate)
- vcc->qos.txtp.pcr = iadev->LineRate;
- ia_vcc->pcr = vcc->qos.txtp.pcr;
-
- if (ia_vcc->pcr > (iadev->LineRate / 6) ) ia_vcc->ltimeout = HZ / 10;
- else if (ia_vcc->pcr > (iadev->LineRate / 130)) ia_vcc->ltimeout = HZ;
- else if (ia_vcc->pcr <= 170) ia_vcc->ltimeout = 16 * HZ;
- else ia_vcc->ltimeout = 2700 * HZ / ia_vcc->pcr;
- if (ia_vcc->pcr < iadev->rate_limit)
- skb_queue_head_init (&ia_vcc->txing_skb);
- if (ia_vcc->pcr < iadev->rate_limit) {
- struct sock *sk = sk_atm(vcc);
-
- if (vcc->qos.txtp.max_sdu != 0) {
- if (ia_vcc->pcr > 60000)
- sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5;
- else if (ia_vcc->pcr > 2000)
- sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4;
- else
- sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3;
- }
- else
- sk->sk_sndbuf = 24576;
- }
-
- vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;
- evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR;
- vc += vcc->vci;
- evc += vcc->vci;
- memset((caddr_t)vc, 0, sizeof(*vc));
- memset((caddr_t)evc, 0, sizeof(*evc));
-
- /* store the most significant 4 bits of vci as the last 4 bits
- of first part of atm header.
- store the last 12 bits of vci as first 12 bits of the second
- part of the atm header.
- */
- evc->atm_hdr1 = (vcc->vci >> 12) & 0x000f;
- evc->atm_hdr2 = (vcc->vci & 0x0fff) << 4;
-
- /* check the following for different traffic classes */
- if (vcc->qos.txtp.traffic_class == ATM_UBR)
- {
- vc->type = UBR;
- vc->status = CRC_APPEND;
- vc->acr = cellrate_to_float(iadev->LineRate);
- if (vcc->qos.txtp.pcr > 0)
- vc->acr = cellrate_to_float(vcc->qos.txtp.pcr);
- IF_UBR(printk("UBR: txtp.pcr = 0x%x f_rate = 0x%x\n",
- vcc->qos.txtp.max_pcr,vc->acr);)
- }
- else if (vcc->qos.txtp.traffic_class == ATM_ABR)
- { srv_cls_param_t srv_p;
- IF_ABR(printk("Tx ABR VCC\n");)
- init_abr_vc(iadev, &srv_p);
- if (vcc->qos.txtp.pcr > 0)
- srv_p.pcr = vcc->qos.txtp.pcr;
- if (vcc->qos.txtp.min_pcr > 0) {
- int tmpsum = iadev->sum_mcr+iadev->sum_cbr+vcc->qos.txtp.min_pcr;
- if (tmpsum > iadev->LineRate)
- return -EBUSY;
- srv_p.mcr = vcc->qos.txtp.min_pcr;
- iadev->sum_mcr += vcc->qos.txtp.min_pcr;
- }
- else srv_p.mcr = 0;
- if (vcc->qos.txtp.icr)
- srv_p.icr = vcc->qos.txtp.icr;
- if (vcc->qos.txtp.tbe)
- srv_p.tbe = vcc->qos.txtp.tbe;
- if (vcc->qos.txtp.frtt)
- srv_p.frtt = vcc->qos.txtp.frtt;
- if (vcc->qos.txtp.rif)
- srv_p.rif = vcc->qos.txtp.rif;
- if (vcc->qos.txtp.rdf)
- srv_p.rdf = vcc->qos.txtp.rdf;
- if (vcc->qos.txtp.nrm_pres)
- srv_p.nrm = vcc->qos.txtp.nrm;
- if (vcc->qos.txtp.trm_pres)
- srv_p.trm = vcc->qos.txtp.trm;
- if (vcc->qos.txtp.adtf_pres)
- srv_p.adtf = vcc->qos.txtp.adtf;
- if (vcc->qos.txtp.cdf_pres)
- srv_p.cdf = vcc->qos.txtp.cdf;
- if (srv_p.icr > srv_p.pcr)
- srv_p.icr = srv_p.pcr;
- IF_ABR(printk("ABR:vcc->qos.txtp.max_pcr = %d mcr = %d\n",
- srv_p.pcr, srv_p.mcr);)
- ia_open_abr_vc(iadev, &srv_p, vcc, 1);
- } else if (vcc->qos.txtp.traffic_class == ATM_CBR) {
- if (iadev->phy_type & FE_25MBIT_PHY) {
- printk("IA: CBR not support\n");
- return -EINVAL;
- }
- if (vcc->qos.txtp.max_pcr > iadev->LineRate) {
- IF_CBR(printk("PCR is not available\n");)
- return -1;
- }
- vc->type = CBR;
- vc->status = CRC_APPEND;
- if ((ret = ia_cbr_setup (iadev, vcc)) < 0) {
- return ret;
- }
- } else {
- printk("iadev: Non UBR, ABR and CBR traffic not supported\n");
- }
-
- iadev->testTable[vcc->vci]->vc_status |= VC_ACTIVE;
- IF_EVENT(printk("ia open_tx returning \n");)
- return 0;
-}
-
-
-static int tx_init(struct atm_dev *dev)
-{
- IADEV *iadev;
- struct tx_buf_desc *buf_desc_ptr;
- unsigned int tx_pkt_start;
- void *dle_addr;
- int i;
- u_short tcq_st_adr;
- u_short *tcq_start;
- u_short prq_st_adr;
- u_short *prq_start;
- struct main_vc *vc;
- struct ext_vc *evc;
- u_short tmp16;
- u32 vcsize_sel;
-
- iadev = INPH_IA_DEV(dev);
- spin_lock_init(&iadev->tx_lock);
-
- IF_INIT(printk("Tx MASK REG: 0x%0x\n",
- readw(iadev->seg_reg+SEG_MASK_REG));)
-
- /* Allocate 4k (boundary aligned) bytes */
- dle_addr = dma_alloc_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE,
- &iadev->tx_dle_dma, GFP_KERNEL);
- if (!dle_addr) {
- printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");
- goto err_out;
- }
- iadev->tx_dle_q.start = (struct dle*)dle_addr;
- iadev->tx_dle_q.read = iadev->tx_dle_q.start;
- iadev->tx_dle_q.write = iadev->tx_dle_q.start;
- iadev->tx_dle_q.end = (struct dle*)((unsigned long)dle_addr+sizeof(struct dle)*DLE_ENTRIES);
-
- /* write the upper 20 bits of the start address to tx list address register */
- writel(iadev->tx_dle_dma & 0xfffff000,
- iadev->dma + IPHASE5575_TX_LIST_ADDR);
- writew(0xffff, iadev->seg_reg+SEG_MASK_REG);
- writew(0, iadev->seg_reg+MODE_REG_0);
- writew(RESET_SEG, iadev->seg_reg+SEG_COMMAND_REG);
- iadev->MAIN_VC_TABLE_ADDR = iadev->seg_ram+MAIN_VC_TABLE*iadev->memSize;
- iadev->EXT_VC_TABLE_ADDR = iadev->seg_ram+EXT_VC_TABLE*iadev->memSize;
- iadev->ABR_SCHED_TABLE_ADDR=iadev->seg_ram+ABR_SCHED_TABLE*iadev->memSize;
-
- /*
- Transmit side control memory map
- --------------------------------
- Buffer descr 0x0000 (128 - 4K)
- Commn queues 0x1000 Transmit comp, Packet ready(0x1400)
- (512 - 1K) each
- TCQ - 4K, PRQ - 5K
- CBR Table 0x1800 (as needed) - 6K
- UBR Table 0x3000 (1K - 4K) - 12K
- UBR Wait queue 0x4000 (1K - 4K) - 16K
- ABR sched 0x5000 and ABR wait queue (1K - 2K) each
- ABR Tbl - 20K, ABR Wq - 22K
- extended VC 0x6000 (1K - 8K) - 24K
- VC Table 0x8000 (1K - 32K) - 32K
-
- Between 0x2000 (8K) and 0x3000 (12K) there is 4K space left for VBR Tbl
- and Wait q, which can be allotted later.
- */
-
- /* Buffer Descriptor Table Base address */
- writew(TX_DESC_BASE, iadev->seg_reg+SEG_DESC_BASE);
-
- /* initialize each entry in the buffer descriptor table */
- buf_desc_ptr =(struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE);
- memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
- buf_desc_ptr++;
- tx_pkt_start = TX_PACKET_RAM;
- for(i=1; i<=iadev->num_tx_desc; i++)
- {
- memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
- buf_desc_ptr->desc_mode = AAL5;
- buf_desc_ptr->buf_start_hi = tx_pkt_start >> 16;
- buf_desc_ptr->buf_start_lo = tx_pkt_start & 0x0000ffff;
- buf_desc_ptr++;
- tx_pkt_start += iadev->tx_buf_sz;
- }
- iadev->tx_buf = kmalloc_objs(*iadev->tx_buf, iadev->num_tx_desc);
- if (!iadev->tx_buf) {
- printk(KERN_ERR DEV_LABEL " couldn't get mem\n");
- goto err_free_dle;
- }
- for (i= 0; i< iadev->num_tx_desc; i++)
- {
- struct cpcs_trailer *cpcs;
-
- cpcs = kmalloc_obj(*cpcs, GFP_KERNEL | GFP_DMA);
- if(!cpcs) {
- printk(KERN_ERR DEV_LABEL " couldn't get freepage\n");
- goto err_free_tx_bufs;
- }
- iadev->tx_buf[i].cpcs = cpcs;
- iadev->tx_buf[i].dma_addr = dma_map_single(&iadev->pci->dev,
- cpcs,
- sizeof(*cpcs),
- DMA_TO_DEVICE);
- }
- iadev->desc_tbl = kmalloc_objs(*iadev->desc_tbl, iadev->num_tx_desc);
- if (!iadev->desc_tbl) {
- printk(KERN_ERR DEV_LABEL " couldn't get mem\n");
- goto err_free_all_tx_bufs;
- }
-
- /* Communication Queues base address */
- i = TX_COMP_Q * iadev->memSize;
- writew(i >> 16, iadev->seg_reg+SEG_QUEUE_BASE);
-
- /* Transmit Complete Queue */
- writew(i, iadev->seg_reg+TCQ_ST_ADR);
- writew(i, iadev->seg_reg+TCQ_RD_PTR);
- writew(i+iadev->num_tx_desc*sizeof(u_short),iadev->seg_reg+TCQ_WR_PTR);
- iadev->host_tcq_wr = i + iadev->num_tx_desc*sizeof(u_short);
- writew(i+2 * iadev->num_tx_desc * sizeof(u_short),
- iadev->seg_reg+TCQ_ED_ADR);
- /* Fill the TCQ with all the free descriptors. */
- tcq_st_adr = readw(iadev->seg_reg+TCQ_ST_ADR);
- tcq_start = (u_short *)(iadev->seg_ram+tcq_st_adr);
- for(i=1; i<=iadev->num_tx_desc; i++)
- {
- *tcq_start = (u_short)i;
- tcq_start++;
- }
-
- /* Packet Ready Queue */
- i = PKT_RDY_Q * iadev->memSize;
- writew(i, iadev->seg_reg+PRQ_ST_ADR);
- writew(i+2 * iadev->num_tx_desc * sizeof(u_short),
- iadev->seg_reg+PRQ_ED_ADR);
- writew(i, iadev->seg_reg+PRQ_RD_PTR);
- writew(i, iadev->seg_reg+PRQ_WR_PTR);
-
- /* Load local copy of PRQ and TCQ ptrs */
- iadev->ffL.prq_st = readw(iadev->seg_reg+PRQ_ST_ADR) & 0xffff;
- iadev->ffL.prq_ed = readw(iadev->seg_reg+PRQ_ED_ADR) & 0xffff;
- iadev->ffL.prq_wr = readw(iadev->seg_reg+PRQ_WR_PTR) & 0xffff;
-
- iadev->ffL.tcq_st = readw(iadev->seg_reg+TCQ_ST_ADR) & 0xffff;
- iadev->ffL.tcq_ed = readw(iadev->seg_reg+TCQ_ED_ADR) & 0xffff;
- iadev->ffL.tcq_rd = readw(iadev->seg_reg+TCQ_RD_PTR) & 0xffff;
-
- /* Just for safety initializing the queue to have desc 1 always */
- /* Fill the PRQ with all the free descriptors. */
- prq_st_adr = readw(iadev->seg_reg+PRQ_ST_ADR);
- prq_start = (u_short *)(iadev->seg_ram+prq_st_adr);
- for(i=1; i<=iadev->num_tx_desc; i++)
- {
- *prq_start = (u_short)0; /* desc 1 in all entries */
- prq_start++;
- }
- /* CBR Table */
- IF_INIT(printk("Start CBR Init\n");)
-#if 1 /* for 1K VC board, CBR_PTR_BASE is 0 */
- writew(0,iadev->seg_reg+CBR_PTR_BASE);
-#else /* Charlie's logic is wrong ? */
- tmp16 = (iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize)>>17;
- IF_INIT(printk("cbr_ptr_base = 0x%x ", tmp16);)
- writew(tmp16,iadev->seg_reg+CBR_PTR_BASE);
-#endif
-
- IF_INIT(printk("value in register = 0x%x\n",
- readw(iadev->seg_reg+CBR_PTR_BASE));)
- tmp16 = (CBR_SCHED_TABLE*iadev->memSize) >> 1;
- writew(tmp16, iadev->seg_reg+CBR_TAB_BEG);
- IF_INIT(printk("cbr_tab_beg = 0x%x in reg = 0x%x \n", tmp16,
- readw(iadev->seg_reg+CBR_TAB_BEG));)
- writew(tmp16, iadev->seg_reg+CBR_TAB_END+1); // CBR_PTR;
- tmp16 = (CBR_SCHED_TABLE*iadev->memSize + iadev->num_vc*6 - 2) >> 1;
- writew(tmp16, iadev->seg_reg+CBR_TAB_END);
- IF_INIT(printk("iadev->seg_reg = 0x%p CBR_PTR_BASE = 0x%x\n",
- iadev->seg_reg, readw(iadev->seg_reg+CBR_PTR_BASE));)
- IF_INIT(printk("CBR_TAB_BEG = 0x%x, CBR_TAB_END = 0x%x, CBR_PTR = 0x%x\n",
- readw(iadev->seg_reg+CBR_TAB_BEG), readw(iadev->seg_reg+CBR_TAB_END),
- readw(iadev->seg_reg+CBR_TAB_END+1));)
-
- /* Initialize the CBR Schedualing Table */
- memset_io(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize,
- 0, iadev->num_vc*6);
- iadev->CbrRemEntries = iadev->CbrTotEntries = iadev->num_vc*3;
- iadev->CbrEntryPt = 0;
- iadev->Granularity = MAX_ATM_155 / iadev->CbrTotEntries;
- iadev->NumEnabledCBR = 0;
-
- /* UBR scheduling Table and wait queue */
- /* initialize all bytes of UBR scheduler table and wait queue to 0
- - SCHEDSZ is 1K (# of entries).
- - UBR Table size is 4K
- - UBR wait queue is 4K
- since the table and wait queues are contiguous, all the bytes
- can be initialized by one memeset.
- */
-
- vcsize_sel = 0;
- i = 8*1024;
- while (i != iadev->num_vc) {
- i /= 2;
- vcsize_sel++;
- }
-
- i = MAIN_VC_TABLE * iadev->memSize;
- writew(vcsize_sel | ((i >> 8) & 0xfff8),iadev->seg_reg+VCT_BASE);
- i = EXT_VC_TABLE * iadev->memSize;
- writew((i >> 8) & 0xfffe, iadev->seg_reg+VCTE_BASE);
- i = UBR_SCHED_TABLE * iadev->memSize;
- writew((i & 0xffff) >> 11, iadev->seg_reg+UBR_SBPTR_BASE);
- i = UBR_WAIT_Q * iadev->memSize;
- writew((i >> 7) & 0xffff, iadev->seg_reg+UBRWQ_BASE);
- memset((caddr_t)(iadev->seg_ram+UBR_SCHED_TABLE*iadev->memSize),
- 0, iadev->num_vc*8);
- /* ABR scheduling Table(0x5000-0x57ff) and wait queue(0x5800-0x5fff)*/
- /* initialize all bytes of ABR scheduler table and wait queue to 0
- - SCHEDSZ is 1K (# of entries).
- - ABR Table size is 2K
- - ABR wait queue is 2K
- since the table and wait queues are contiguous, all the bytes
- can be initialized by one memeset.
- */
- i = ABR_SCHED_TABLE * iadev->memSize;
- writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE);
- i = ABR_WAIT_Q * iadev->memSize;
- writew((i >> 7) & 0xffff, iadev->seg_reg+ABRWQ_BASE);
-
- i = ABR_SCHED_TABLE*iadev->memSize;
- memset((caddr_t)(iadev->seg_ram+i), 0, iadev->num_vc*4);
- vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;
- evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR;
- iadev->testTable = kmalloc_objs(*iadev->testTable, iadev->num_vc);
- if (!iadev->testTable) {
- printk("Get freepage failed\n");
- goto err_free_desc_tbl;
- }
- for(i=0; i<iadev->num_vc; i++)
- {
- memset((caddr_t)vc, 0, sizeof(*vc));
- memset((caddr_t)evc, 0, sizeof(*evc));
- iadev->testTable[i] = kmalloc_obj(struct testTable_t);
- if (!iadev->testTable[i])
- goto err_free_test_tables;
- iadev->testTable[i]->lastTime = 0;
- iadev->testTable[i]->fract = 0;
- iadev->testTable[i]->vc_status = VC_UBR;
- vc++;
- evc++;
- }
-
- /* Other Initialization */
-
- /* Max Rate Register */
- if (iadev->phy_type & FE_25MBIT_PHY) {
- writew(RATE25, iadev->seg_reg+MAXRATE);
- writew((UBR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);
- }
- else {
- writew(cellrate_to_float(iadev->LineRate),iadev->seg_reg+MAXRATE);
- writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);
- }
- /* Set Idle Header Reigisters to be sure */
- writew(0, iadev->seg_reg+IDLEHEADHI);
- writew(0, iadev->seg_reg+IDLEHEADLO);
-
- /* Program ABR UBR Priority Register as PRI_ABR_UBR_EQUAL */
- writew(0xaa00, iadev->seg_reg+ABRUBR_ARB);
-
- iadev->close_pending = 0;
- init_waitqueue_head(&iadev->close_wait);
- init_waitqueue_head(&iadev->timeout_wait);
- skb_queue_head_init(&iadev->tx_dma_q);
- ia_init_rtn_q(&iadev->tx_return_q);
-
- /* RM Cell Protocol ID and Message Type */
- writew(RM_TYPE_4_0, iadev->seg_reg+RM_TYPE);
- skb_queue_head_init (&iadev->tx_backlog);
-
- /* Mode Register 1 */
- writew(MODE_REG_1_VAL, iadev->seg_reg+MODE_REG_1);
-
- /* Mode Register 0 */
- writew(T_ONLINE, iadev->seg_reg+MODE_REG_0);
-
- /* Interrupt Status Register - read to clear */
- readw(iadev->seg_reg+SEG_INTR_STATUS_REG);
-
- /* Interrupt Mask Reg- don't mask TCQ_NOT_EMPTY interrupt generation */
- writew(~(TRANSMIT_DONE | TCQ_NOT_EMPTY), iadev->seg_reg+SEG_MASK_REG);
- writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
- iadev->tx_pkt_cnt = 0;
- iadev->rate_limit = iadev->LineRate / 3;
-
- return 0;
-
-err_free_test_tables:
- while (--i >= 0)
- kfree(iadev->testTable[i]);
- kfree(iadev->testTable);
-err_free_desc_tbl:
- kfree(iadev->desc_tbl);
-err_free_all_tx_bufs:
- i = iadev->num_tx_desc;
-err_free_tx_bufs:
- while (--i >= 0) {
- struct cpcs_trailer_desc *desc = iadev->tx_buf + i;
-
- dma_unmap_single(&iadev->pci->dev, desc->dma_addr,
- sizeof(*desc->cpcs), DMA_TO_DEVICE);
- kfree(desc->cpcs);
- }
- kfree(iadev->tx_buf);
-err_free_dle:
- dma_free_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE, iadev->tx_dle_q.start,
- iadev->tx_dle_dma);
-err_out:
- return -ENOMEM;
-}
-
-static irqreturn_t ia_int(int irq, void *dev_id)
-{
- struct atm_dev *dev;
- IADEV *iadev;
- unsigned int status;
- int handled = 0;
-
- dev = dev_id;
- iadev = INPH_IA_DEV(dev);
- while( (status = readl(iadev->reg+IPHASE5575_BUS_STATUS_REG) & 0x7f))
- {
- handled = 1;
- IF_EVENT(printk("ia_int: status = 0x%x\n", status);)
- if (status & STAT_REASSINT)
- {
- /* do something */
- IF_EVENT(printk("REASSINT Bus status reg: %08x\n", status);)
- rx_intr(dev);
- }
- if (status & STAT_DLERINT)
- {
- /* Clear this bit by writing a 1 to it. */
- writel(STAT_DLERINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
- rx_dle_intr(dev);
- }
- if (status & STAT_SEGINT)
- {
- /* do something */
- IF_EVENT(printk("IA: tx_intr \n");)
- tx_intr(dev);
- }
- if (status & STAT_DLETINT)
- {
- writel(STAT_DLETINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
- tx_dle_intr(dev);
- }
- if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT))
- {
- if (status & STAT_FEINT)
- ia_frontend_intr(iadev);
- }
- }
- return IRQ_RETVAL(handled);
-}
-
-
-
-/*----------------------------- entries --------------------------------*/
-static int get_esi(struct atm_dev *dev)
-{
- IADEV *iadev;
- int i;
- u32 mac1;
- u16 mac2;
-
- iadev = INPH_IA_DEV(dev);
- mac1 = cpu_to_be32(le32_to_cpu(readl(
- iadev->reg+IPHASE5575_MAC1)));
- mac2 = cpu_to_be16(le16_to_cpu(readl(iadev->reg+IPHASE5575_MAC2)));
- IF_INIT(printk("ESI: 0x%08x%04x\n", mac1, mac2);)
- for (i=0; i<MAC1_LEN; i++)
- dev->esi[i] = mac1 >>(8*(MAC1_LEN-1-i));
-
- for (i=0; i<MAC2_LEN; i++)
- dev->esi[i+MAC1_LEN] = mac2 >>(8*(MAC2_LEN - 1 -i));
- return 0;
-}
-
-static int reset_sar(struct atm_dev *dev)
-{
- IADEV *iadev;
- int i, error;
- unsigned int pci[64];
-
- iadev = INPH_IA_DEV(dev);
- for (i = 0; i < 64; i++) {
- error = pci_read_config_dword(iadev->pci, i * 4, &pci[i]);
- if (error != PCIBIOS_SUCCESSFUL)
- return error;
- }
- writel(0, iadev->reg+IPHASE5575_EXT_RESET);
- for (i = 0; i < 64; i++) {
- error = pci_write_config_dword(iadev->pci, i * 4, pci[i]);
- if (error != PCIBIOS_SUCCESSFUL)
- return error;
- }
- udelay(5);
- return 0;
-}
-
-
-static int ia_init(struct atm_dev *dev)
-{
- IADEV *iadev;
- unsigned long real_base;
- void __iomem *base;
- unsigned short command;
- int error, i;
-
- /* The device has been identified and registered. Now we read
- necessary configuration info like memory base address,
- interrupt number etc */
-
- IF_INIT(printk(">ia_init\n");)
- dev->ci_range.vpi_bits = 0;
- dev->ci_range.vci_bits = NR_VCI_LD;
-
- iadev = INPH_IA_DEV(dev);
- real_base = pci_resource_start (iadev->pci, 0);
- iadev->irq = iadev->pci->irq;
-
- error = pci_read_config_word(iadev->pci, PCI_COMMAND, &command);
- if (error) {
- printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%x\n",
- dev->number,error);
- return -EINVAL;
- }
- IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n",
- dev->number, iadev->pci->revision, real_base, iadev->irq);)
-
- /* find mapping size of board */
-
- iadev->pci_map_size = pci_resource_len(iadev->pci, 0);
-
- if (iadev->pci_map_size == 0x100000){
- iadev->num_vc = 4096;
- dev->ci_range.vci_bits = NR_VCI_4K_LD;
- iadev->memSize = 4;
- }
- else if (iadev->pci_map_size == 0x40000) {
- iadev->num_vc = 1024;
- iadev->memSize = 1;
- }
- else {
- printk("Unknown pci_map_size = 0x%x\n", iadev->pci_map_size);
- return -EINVAL;
- }
- IF_INIT(printk (DEV_LABEL "map size: %i\n", iadev->pci_map_size);)
-
- /* enable bus mastering */
- pci_set_master(iadev->pci);
-
- /*
- * Delay at least 1us before doing any mem accesses (how 'bout 10?)
- */
- udelay(10);
-
- /* mapping the physical address to a virtual address in address space */
- base = ioremap(real_base,iadev->pci_map_size); /* ioremap is not resolved ??? */
-
- if (!base)
- {
- printk(DEV_LABEL " (itf %d): can't set up page mapping\n",
- dev->number);
- return -ENOMEM;
- }
- IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n",
- dev->number, iadev->pci->revision, base, iadev->irq);)
-
- /* filling the iphase dev structure */
- iadev->mem = iadev->pci_map_size /2;
- iadev->real_base = real_base;
- iadev->base = base;
-
- /* Bus Interface Control Registers */
- iadev->reg = base + REG_BASE;
- /* Segmentation Control Registers */
- iadev->seg_reg = base + SEG_BASE;
- /* Reassembly Control Registers */
- iadev->reass_reg = base + REASS_BASE;
- /* Front end/ DMA control registers */
- iadev->phy = base + PHY_BASE;
- iadev->dma = base + PHY_BASE;
- /* RAM - Segmentation RAm and Reassembly RAM */
- iadev->ram = base + ACTUAL_RAM_BASE;
- iadev->seg_ram = base + ACTUAL_SEG_RAM_BASE;
- iadev->reass_ram = base + ACTUAL_REASS_RAM_BASE;
-
- /* lets print out the above */
- IF_INIT(printk("Base addrs: %p %p %p \n %p %p %p %p\n",
- iadev->reg,iadev->seg_reg,iadev->reass_reg,
- iadev->phy, iadev->ram, iadev->seg_ram,
- iadev->reass_ram);)
-
- /* lets try reading the MAC address */
- error = get_esi(dev);
- if (error) {
- iounmap(iadev->base);
- return error;
- }
- printk("IA: ");
- for (i=0; i < ESI_LEN; i++)
- printk("%s%02X",i ? "-" : "",dev->esi[i]);
- printk("\n");
-
- /* reset SAR */
- if (reset_sar(dev)) {
- iounmap(iadev->base);
- printk("IA: reset SAR fail, please try again\n");
- return 1;
- }
- return 0;
-}
-
-static void ia_update_stats(IADEV *iadev) {
- if (!iadev->carrier_detect)
- return;
- iadev->rx_cell_cnt += readw(iadev->reass_reg+CELL_CTR0)&0xffff;
- iadev->rx_cell_cnt += (readw(iadev->reass_reg+CELL_CTR1) & 0xffff) << 16;
- iadev->drop_rxpkt += readw(iadev->reass_reg + DRP_PKT_CNTR ) & 0xffff;
- iadev->drop_rxcell += readw(iadev->reass_reg + ERR_CNTR) & 0xffff;
- iadev->tx_cell_cnt += readw(iadev->seg_reg + CELL_CTR_LO_AUTO)&0xffff;
- iadev->tx_cell_cnt += (readw(iadev->seg_reg+CELL_CTR_HIGH_AUTO)&0xffff)<<16;
- return;
-}
-
-static void ia_led_timer(struct timer_list *unused) {
- unsigned long flags;
- static u_char blinking[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- u_char i;
- static u32 ctrl_reg;
- for (i = 0; i < iadev_count; i++) {
- if (ia_dev[i]) {
- ctrl_reg = readl(ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
- if (blinking[i] == 0) {
- blinking[i]++;
- ctrl_reg &= (~CTRL_LED);
- writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
- ia_update_stats(ia_dev[i]);
- }
- else {
- blinking[i] = 0;
- ctrl_reg |= CTRL_LED;
- writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
- spin_lock_irqsave(&ia_dev[i]->tx_lock, flags);
- if (ia_dev[i]->close_pending)
- wake_up(&ia_dev[i]->close_wait);
- ia_tx_poll(ia_dev[i]);
- spin_unlock_irqrestore(&ia_dev[i]->tx_lock, flags);
- }
- }
- }
- mod_timer(&ia_timer, jiffies + HZ / 4);
- return;
-}
-
-static void ia_phy_put(struct atm_dev *dev, unsigned char value,
- unsigned long addr)
-{
- writel(value, INPH_IA_DEV(dev)->phy+addr);
-}
-
-static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr)
-{
- return readl(INPH_IA_DEV(dev)->phy+addr);
-}
-
-static void ia_free_tx(IADEV *iadev)
-{
- int i;
-
- kfree(iadev->desc_tbl);
- for (i = 0; i < iadev->num_vc; i++)
- kfree(iadev->testTable[i]);
- kfree(iadev->testTable);
- for (i = 0; i < iadev->num_tx_desc; i++) {
- struct cpcs_trailer_desc *desc = iadev->tx_buf + i;
-
- dma_unmap_single(&iadev->pci->dev, desc->dma_addr,
- sizeof(*desc->cpcs), DMA_TO_DEVICE);
- kfree(desc->cpcs);
- }
- kfree(iadev->tx_buf);
- dma_free_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE, iadev->tx_dle_q.start,
- iadev->tx_dle_dma);
-}
-
-static void ia_free_rx(IADEV *iadev)
-{
- kfree(iadev->rx_open);
- dma_free_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE, iadev->rx_dle_q.start,
- iadev->rx_dle_dma);
-}
-
-static int ia_start(struct atm_dev *dev)
-{
- IADEV *iadev;
- int error;
- unsigned char phy;
- u32 ctrl_reg;
- IF_EVENT(printk(">ia_start\n");)
- iadev = INPH_IA_DEV(dev);
- if (request_irq(iadev->irq, &ia_int, IRQF_SHARED, DEV_LABEL, dev)) {
- printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
- dev->number, iadev->irq);
- error = -EAGAIN;
- goto err_out;
- }
- /* @@@ should release IRQ on error */
- /* enabling memory + master */
- if ((error = pci_write_config_word(iadev->pci,
- PCI_COMMAND,
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER )))
- {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
- "master (0x%x)\n",dev->number, error);
- error = -EIO;
- goto err_free_irq;
- }
- udelay(10);
-
- /* Maybe we should reset the front end, initialize Bus Interface Control
- Registers and see. */
-
- IF_INIT(printk("Bus ctrl reg: %08x\n",
- readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));)
- ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG);
- ctrl_reg = (ctrl_reg & (CTRL_LED | CTRL_FE_RST))
- | CTRL_B8
- | CTRL_B16
- | CTRL_B32
- | CTRL_B48
- | CTRL_B64
- | CTRL_B128
- | CTRL_ERRMASK
- | CTRL_DLETMASK /* shud be removed l8r */
- | CTRL_DLERMASK
- | CTRL_SEGMASK
- | CTRL_REASSMASK
- | CTRL_FEMASK
- | CTRL_CSPREEMPT;
-
- writel(ctrl_reg, iadev->reg+IPHASE5575_BUS_CONTROL_REG);
-
- IF_INIT(printk("Bus ctrl reg after initializing: %08x\n",
- readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));
- printk("Bus status reg after init: %08x\n",
- readl(iadev->reg+IPHASE5575_BUS_STATUS_REG));)
-
- ia_hw_type(iadev);
- error = tx_init(dev);
- if (error)
- goto err_free_irq;
- error = rx_init(dev);
- if (error)
- goto err_free_tx;
-
- ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG);
- writel(ctrl_reg | CTRL_FE_RST, iadev->reg+IPHASE5575_BUS_CONTROL_REG);
- IF_INIT(printk("Bus ctrl reg after initializing: %08x\n",
- readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));)
- phy = 0; /* resolve compiler complaint */
- IF_INIT (
- if ((phy=ia_phy_get(dev,0)) == 0x30)
- printk("IA: pm5346,rev.%d\n",phy&0x0f);
- else
- printk("IA: utopia,rev.%0x\n",phy);)
-
- if (iadev->phy_type & FE_25MBIT_PHY)
- ia_mb25_init(iadev);
- else if (iadev->phy_type & (FE_DS3_PHY | FE_E3_PHY))
- ia_suni_pm7345_init(iadev);
- else {
- error = suni_init(dev);
- if (error)
- goto err_free_rx;
- if (dev->phy->start) {
- error = dev->phy->start(dev);
- if (error)
- goto err_free_rx;
- }
- /* Get iadev->carrier_detect status */
- ia_frontend_intr(iadev);
- }
- return 0;
-
-err_free_rx:
- ia_free_rx(iadev);
-err_free_tx:
- ia_free_tx(iadev);
-err_free_irq:
- free_irq(iadev->irq, dev);
-err_out:
- return error;
-}
-
-static void ia_close(struct atm_vcc *vcc)
-{
- DEFINE_WAIT(wait);
- u16 *vc_table;
- IADEV *iadev;
- struct ia_vcc *ia_vcc;
- struct sk_buff *skb = NULL;
- struct sk_buff_head tmp_tx_backlog, tmp_vcc_backlog;
- unsigned long closetime, flags;
-
- iadev = INPH_IA_DEV(vcc->dev);
- ia_vcc = INPH_IA_VCC(vcc);
- if (!ia_vcc) return;
-
- IF_EVENT(printk("ia_close: ia_vcc->vc_desc_cnt = %d vci = %d\n",
- ia_vcc->vc_desc_cnt,vcc->vci);)
- clear_bit(ATM_VF_READY,&vcc->flags);
- skb_queue_head_init (&tmp_tx_backlog);
- skb_queue_head_init (&tmp_vcc_backlog);
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
- iadev->close_pending++;
- prepare_to_wait(&iadev->timeout_wait, &wait, TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(500));
- finish_wait(&iadev->timeout_wait, &wait);
- spin_lock_irqsave(&iadev->tx_lock, flags);
- while((skb = skb_dequeue(&iadev->tx_backlog))) {
- if (ATM_SKB(skb)->vcc == vcc){
- if (vcc->pop) vcc->pop(vcc, skb);
- else dev_kfree_skb_any(skb);
- }
- else
- skb_queue_tail(&tmp_tx_backlog, skb);
- }
- while((skb = skb_dequeue(&tmp_tx_backlog)))
- skb_queue_tail(&iadev->tx_backlog, skb);
- IF_EVENT(printk("IA TX Done decs_cnt = %d\n", ia_vcc->vc_desc_cnt);)
- closetime = 300000 / ia_vcc->pcr;
- if (closetime == 0)
- closetime = 1;
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
- wait_event_timeout(iadev->close_wait, (ia_vcc->vc_desc_cnt <= 0), closetime);
- spin_lock_irqsave(&iadev->tx_lock, flags);
- iadev->close_pending--;
- iadev->testTable[vcc->vci]->lastTime = 0;
- iadev->testTable[vcc->vci]->fract = 0;
- iadev->testTable[vcc->vci]->vc_status = VC_UBR;
- if (vcc->qos.txtp.traffic_class == ATM_ABR) {
- if (vcc->qos.txtp.min_pcr > 0)
- iadev->sum_mcr -= vcc->qos.txtp.min_pcr;
- }
- if (vcc->qos.txtp.traffic_class == ATM_CBR) {
- ia_vcc = INPH_IA_VCC(vcc);
- iadev->sum_mcr -= ia_vcc->NumCbrEntry*iadev->Granularity;
- ia_cbrVc_close (vcc);
- }
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
- }
-
- if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
- // reset reass table
- vc_table = (u16 *)(iadev->reass_ram+REASS_TABLE*iadev->memSize);
- vc_table += vcc->vci;
- *vc_table = NO_AAL5_PKT;
- // reset vc table
- vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);
- vc_table += vcc->vci;
- *vc_table = (vcc->vci << 6) | 15;
- if (vcc->qos.rxtp.traffic_class == ATM_ABR) {
- struct abr_vc_table __iomem *abr_vc_table =
- (iadev->reass_ram+ABR_VC_TABLE*iadev->memSize);
- abr_vc_table += vcc->vci;
- abr_vc_table->rdf = 0x0003;
- abr_vc_table->air = 0x5eb1;
- }
- // Drain the packets
- rx_dle_intr(vcc->dev);
- iadev->rx_open[vcc->vci] = NULL;
- }
- kfree(INPH_IA_VCC(vcc));
- ia_vcc = NULL;
- vcc->dev_data = NULL;
- clear_bit(ATM_VF_ADDR,&vcc->flags);
- return;
-}
-
-static int ia_open(struct atm_vcc *vcc)
-{
- struct ia_vcc *ia_vcc;
- int error;
- if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
- {
- IF_EVENT(printk("ia: not partially allocated resources\n");)
- vcc->dev_data = NULL;
- }
- if (vcc->vci != ATM_VPI_UNSPEC && vcc->vpi != ATM_VCI_UNSPEC)
- {
- IF_EVENT(printk("iphase open: unspec part\n");)
- set_bit(ATM_VF_ADDR,&vcc->flags);
- }
- if (vcc->qos.aal != ATM_AAL5)
- return -EINVAL;
- IF_EVENT(printk(DEV_LABEL "(itf %d): open %d.%d\n",
- vcc->dev->number, vcc->vpi, vcc->vci);)
-
- /* Device dependent initialization */
- ia_vcc = kmalloc_obj(*ia_vcc);
- if (!ia_vcc) return -ENOMEM;
- vcc->dev_data = ia_vcc;
-
- if ((error = open_rx(vcc)))
- {
- IF_EVENT(printk("iadev: error in open_rx, closing\n");)
- ia_close(vcc);
- return error;
- }
-
- if ((error = open_tx(vcc)))
- {
- IF_EVENT(printk("iadev: error in open_tx, closing\n");)
- ia_close(vcc);
- return error;
- }
-
- set_bit(ATM_VF_READY,&vcc->flags);
-
-#if 0
- {
- static u8 first = 1;
- if (first) {
- ia_timer.expires = jiffies + 3*HZ;
- add_timer(&ia_timer);
- first = 0;
- }
- }
-#endif
- IF_EVENT(printk("ia open returning\n");)
- return 0;
-}
-
-static int ia_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
-{
- IF_EVENT(printk(">ia_change_qos\n");)
- return 0;
-}
-
-static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
-{
- IA_CMDBUF ia_cmds;
- IADEV *iadev;
- int i, board;
- u16 __user *tmps;
- IF_EVENT(printk(">ia_ioctl\n");)
- if (cmd != IA_CMD) {
- if (!dev->phy->ioctl) return -EINVAL;
- return dev->phy->ioctl(dev,cmd,arg);
- }
- if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT;
- board = ia_cmds.status;
-
- if ((board < 0) || (board > iadev_count))
- board = 0;
- board = array_index_nospec(board, iadev_count + 1);
-
- iadev = ia_dev[board];
- switch (ia_cmds.cmd) {
- case MEMDUMP:
- {
- switch (ia_cmds.sub_cmd) {
- case MEMDUMP_SEGREG:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- tmps = (u16 __user *)ia_cmds.buf;
- for(i=0; i<0x80; i+=2, tmps++)
- if(put_user((u16)(readl(iadev->seg_reg+i) & 0xffff), tmps)) return -EFAULT;
- ia_cmds.status = 0;
- ia_cmds.len = 0x80;
- break;
- case MEMDUMP_REASSREG:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- tmps = (u16 __user *)ia_cmds.buf;
- for(i=0; i<0x80; i+=2, tmps++)
- if(put_user((u16)(readl(iadev->reass_reg+i) & 0xffff), tmps)) return -EFAULT;
- ia_cmds.status = 0;
- ia_cmds.len = 0x80;
- break;
- case MEMDUMP_FFL:
- {
- ia_regs_t *regs_local;
- ffredn_t *ffL;
- rfredn_t *rfL;
-
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- regs_local = kmalloc_obj(*regs_local);
- if (!regs_local) return -ENOMEM;
- ffL = ®s_local->ffredn;
- rfL = ®s_local->rfredn;
- /* Copy real rfred registers into the local copy */
- for (i=0; i<(sizeof (rfredn_t))/4; i++)
- ((u_int *)rfL)[i] = readl(iadev->reass_reg + i) & 0xffff;
- /* Copy real ffred registers into the local copy */
- for (i=0; i<(sizeof (ffredn_t))/4; i++)
- ((u_int *)ffL)[i] = readl(iadev->seg_reg + i) & 0xffff;
-
- if (copy_to_user(ia_cmds.buf, regs_local,sizeof(ia_regs_t))) {
- kfree(regs_local);
- return -EFAULT;
- }
- kfree(regs_local);
- printk("Board %d registers dumped\n", board);
- ia_cmds.status = 0;
- }
- break;
- case READ_REG:
- {
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- desc_dbg(iadev);
- ia_cmds.status = 0;
- }
- break;
- case 0x6:
- {
- ia_cmds.status = 0;
- printk("skb = 0x%p\n", skb_peek(&iadev->tx_backlog));
- printk("rtn_q: 0x%p\n",ia_deque_rtn_q(&iadev->tx_return_q));
- }
- break;
- case 0x8:
- {
- struct k_sonet_stats *stats;
- stats = &PRIV(_ia_dev[board])->sonet_stats;
- printk("section_bip: %d\n", atomic_read(&stats->section_bip));
- printk("line_bip : %d\n", atomic_read(&stats->line_bip));
- printk("path_bip : %d\n", atomic_read(&stats->path_bip));
- printk("line_febe : %d\n", atomic_read(&stats->line_febe));
- printk("path_febe : %d\n", atomic_read(&stats->path_febe));
- printk("corr_hcs : %d\n", atomic_read(&stats->corr_hcs));
- printk("uncorr_hcs : %d\n", atomic_read(&stats->uncorr_hcs));
- printk("tx_cells : %d\n", atomic_read(&stats->tx_cells));
- printk("rx_cells : %d\n", atomic_read(&stats->rx_cells));
- }
- ia_cmds.status = 0;
- break;
- case 0x9:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- for (i = 1; i <= iadev->num_rx_desc; i++)
- free_desc(_ia_dev[board], i);
- writew( ~(RX_FREEQ_EMPT | RX_EXCP_RCVD),
- iadev->reass_reg+REASS_MASK_REG);
- iadev->rxing = 1;
-
- ia_cmds.status = 0;
- break;
-
- case 0xb:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- ia_frontend_intr(iadev);
- break;
- case 0xa:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- {
- ia_cmds.status = 0;
- IADebugFlag = ia_cmds.maddr;
- printk("New debug option loaded\n");
- }
- break;
- default:
- ia_cmds.status = 0;
- break;
- }
- }
- break;
- default:
- break;
-
- }
- return 0;
-}
-
-static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
- IADEV *iadev;
- struct dle *wr_ptr;
- struct tx_buf_desc __iomem *buf_desc_ptr;
- int desc;
- int comp_code;
- int total_len;
- struct cpcs_trailer *trailer;
- struct ia_vcc *iavcc;
-
- iadev = INPH_IA_DEV(vcc->dev);
- iavcc = INPH_IA_VCC(vcc);
- if (!iavcc->txing) {
- printk("discard packet on closed VC\n");
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- return 0;
- }
-
- if (skb->len > iadev->tx_buf_sz - 8) {
- printk("Transmit size over tx buffer size\n");
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- return 0;
- }
- if ((unsigned long)skb->data & 3) {
- printk("Misaligned SKB\n");
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- return 0;
- }
- /* Get a descriptor number from our free descriptor queue
- We get the descr number from the TCQ now, since I am using
- the TCQ as a free buffer queue. Initially TCQ will be
- initialized with all the descriptors and is hence, full.
- */
- desc = get_desc (iadev, iavcc);
- if (desc == 0xffff)
- return 1;
- comp_code = desc >> 13;
- desc &= 0x1fff;
-
- if ((desc == 0) || (desc > iadev->num_tx_desc))
- {
- IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);)
- atomic_inc(&vcc->stats->tx);
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
- return 0; /* return SUCCESS */
- }
-
- if (comp_code)
- {
- IF_ERR(printk(DEV_LABEL "send desc:%d completion code %d error\n",
- desc, comp_code);)
- }
-
- /* remember the desc and vcc mapping */
- iavcc->vc_desc_cnt++;
- iadev->desc_tbl[desc-1].iavcc = iavcc;
- iadev->desc_tbl[desc-1].txskb = skb;
- IA_SKB_STATE(skb) = 0;
-
- iadev->ffL.tcq_rd += 2;
- if (iadev->ffL.tcq_rd > iadev->ffL.tcq_ed)
- iadev->ffL.tcq_rd = iadev->ffL.tcq_st;
- writew(iadev->ffL.tcq_rd, iadev->seg_reg+TCQ_RD_PTR);
-
- /* Put the descriptor number in the packet ready queue
- and put the updated write pointer in the DLE field
- */
- *(u16*)(iadev->seg_ram+iadev->ffL.prq_wr) = desc;
-
- iadev->ffL.prq_wr += 2;
- if (iadev->ffL.prq_wr > iadev->ffL.prq_ed)
- iadev->ffL.prq_wr = iadev->ffL.prq_st;
-
- /* Figure out the exact length of the packet and padding required to
- make it aligned on a 48 byte boundary. */
- total_len = skb->len + sizeof(struct cpcs_trailer);
- total_len = ((total_len + 47) / 48) * 48;
- IF_TX(printk("ia packet len:%d padding:%d\n", total_len, total_len - skb->len);)
-
- /* Put the packet in a tx buffer */
- trailer = iadev->tx_buf[desc-1].cpcs;
- IF_TX(printk("Sent: skb = 0x%p skb->data: 0x%p len: %d, desc: %d\n",
- skb, skb->data, skb->len, desc);)
- trailer->control = 0;
- /*big endian*/
- trailer->length = ((skb->len & 0xff) << 8) | ((skb->len & 0xff00) >> 8);
- trailer->crc32 = 0; /* not needed - dummy bytes */
-
- /* Display the packet */
- IF_TXPKT(printk("Sent data: len = %d MsgNum = %d\n",
- skb->len, tcnter++);
- xdump(skb->data, skb->len, "TX: ");
- printk("\n");)
-
- /* Build the buffer descriptor */
- buf_desc_ptr = iadev->seg_ram+TX_DESC_BASE;
- buf_desc_ptr += desc; /* points to the corresponding entry */
- buf_desc_ptr->desc_mode = AAL5 | EOM_EN | APP_CRC32 | CMPL_INT;
- /* Huh ? p.115 of users guide describes this as a read-only register */
- writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
- buf_desc_ptr->vc_index = vcc->vci;
- buf_desc_ptr->bytes = total_len;
-
- if (vcc->qos.txtp.traffic_class == ATM_ABR)
- clear_lockup (vcc, iadev);
-
- /* Build the DLE structure */
- wr_ptr = iadev->tx_dle_q.write;
- memset((caddr_t)wr_ptr, 0, sizeof(*wr_ptr));
- wr_ptr->sys_pkt_addr = dma_map_single(&iadev->pci->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
- wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) |
- buf_desc_ptr->buf_start_lo;
- /* wr_ptr->bytes = swap_byte_order(total_len); didn't seem to affect?? */
- wr_ptr->bytes = skb->len;
-
- /* hw bug - DLEs of 0x2d, 0x2e, 0x2f cause DMA lockup */
- if ((wr_ptr->bytes >> 2) == 0xb)
- wr_ptr->bytes = 0x30;
-
- wr_ptr->mode = TX_DLE_PSI;
- wr_ptr->prq_wr_ptr_data = 0;
-
- /* end is not to be used for the DLE q */
- if (++wr_ptr == iadev->tx_dle_q.end)
- wr_ptr = iadev->tx_dle_q.start;
-
- /* Build trailer dle */
- wr_ptr->sys_pkt_addr = iadev->tx_buf[desc-1].dma_addr;
- wr_ptr->local_pkt_addr = ((buf_desc_ptr->buf_start_hi << 16) |
- buf_desc_ptr->buf_start_lo) + total_len - sizeof(struct cpcs_trailer);
-
- wr_ptr->bytes = sizeof(struct cpcs_trailer);
- wr_ptr->mode = DMA_INT_ENABLE;
- wr_ptr->prq_wr_ptr_data = iadev->ffL.prq_wr;
-
- /* end is not to be used for the DLE q */
- if (++wr_ptr == iadev->tx_dle_q.end)
- wr_ptr = iadev->tx_dle_q.start;
-
- iadev->tx_dle_q.write = wr_ptr;
- ATM_DESC(skb) = vcc->vci;
- skb_queue_tail(&iadev->tx_dma_q, skb);
-
- atomic_inc(&vcc->stats->tx);
- iadev->tx_pkt_cnt++;
- /* Increment transaction counter */
- writel(2, iadev->dma+IPHASE5575_TX_COUNTER);
-
-#if 0
- /* add flow control logic */
- if (atomic_read(&vcc->stats->tx) % 20 == 0) {
- if (iavcc->vc_desc_cnt > 10) {
- vcc->tx_quota = vcc->tx_quota * 3 / 4;
- printk("Tx1: vcc->tx_quota = %d \n", (u32)vcc->tx_quota );
- iavcc->flow_inc = -1;
- iavcc->saved_tx_quota = vcc->tx_quota;
- } else if ((iavcc->flow_inc < 0) && (iavcc->vc_desc_cnt < 3)) {
- // vcc->tx_quota = 3 * iavcc->saved_tx_quota / 4;
- printk("Tx2: vcc->tx_quota = %d \n", (u32)vcc->tx_quota );
- iavcc->flow_inc = 0;
- }
- }
-#endif
- IF_TX(printk("ia send done\n");)
- return 0;
-}
-
-static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- IADEV *iadev;
- unsigned long flags;
-
- iadev = INPH_IA_DEV(vcc->dev);
- if ((!skb)||(skb->len>(iadev->tx_buf_sz-sizeof(struct cpcs_trailer))))
- {
- if (!skb)
- printk(KERN_CRIT "null skb in ia_send\n");
- else dev_kfree_skb_any(skb);
- return -EINVAL;
- }
- spin_lock_irqsave(&iadev->tx_lock, flags);
- if (!test_bit(ATM_VF_READY,&vcc->flags)){
- dev_kfree_skb_any(skb);
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
- return -EINVAL;
- }
- ATM_SKB(skb)->vcc = vcc;
-
- if (skb_peek(&iadev->tx_backlog)) {
- skb_queue_tail(&iadev->tx_backlog, skb);
- }
- else {
- if (ia_pkt_tx (vcc, skb)) {
- skb_queue_tail(&iadev->tx_backlog, skb);
- }
- }
- spin_unlock_irqrestore(&iadev->tx_lock, flags);
- return 0;
-
-}
-
-static int ia_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
-{
- int left = *pos, n;
- char *tmpPtr;
- IADEV *iadev = INPH_IA_DEV(dev);
- if(!left--) {
- if (iadev->phy_type == FE_25MBIT_PHY) {
- n = sprintf(page, " Board Type : Iphase5525-1KVC-128K\n");
- return n;
- }
- if (iadev->phy_type == FE_DS3_PHY)
- n = sprintf(page, " Board Type : Iphase-ATM-DS3");
- else if (iadev->phy_type == FE_E3_PHY)
- n = sprintf(page, " Board Type : Iphase-ATM-E3");
- else if (iadev->phy_type == FE_UTP_OPTION)
- n = sprintf(page, " Board Type : Iphase-ATM-UTP155");
- else
- n = sprintf(page, " Board Type : Iphase-ATM-OC3");
- tmpPtr = page + n;
- if (iadev->pci_map_size == 0x40000)
- n += sprintf(tmpPtr, "-1KVC-");
- else
- n += sprintf(tmpPtr, "-4KVC-");
- tmpPtr = page + n;
- if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_1M)
- n += sprintf(tmpPtr, "1M \n");
- else if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_512K)
- n += sprintf(tmpPtr, "512K\n");
- else
- n += sprintf(tmpPtr, "128K\n");
- return n;
- }
- if (!left) {
- return sprintf(page, " Number of Tx Buffer: %u\n"
- " Size of Tx Buffer : %u\n"
- " Number of Rx Buffer: %u\n"
- " Size of Rx Buffer : %u\n"
- " Packets Received : %u\n"
- " Packets Transmitted: %u\n"
- " Cells Received : %u\n"
- " Cells Transmitted : %u\n"
- " Board Dropped Cells: %u\n"
- " Board Dropped Pkts : %u\n",
- iadev->num_tx_desc, iadev->tx_buf_sz,
- iadev->num_rx_desc, iadev->rx_buf_sz,
- iadev->rx_pkt_cnt, iadev->tx_pkt_cnt,
- iadev->rx_cell_cnt, iadev->tx_cell_cnt,
- iadev->drop_rxcell, iadev->drop_rxpkt);
- }
- return 0;
-}
-
-static const struct atmdev_ops ops = {
- .open = ia_open,
- .close = ia_close,
- .ioctl = ia_ioctl,
- .send = ia_send,
- .phy_put = ia_phy_put,
- .phy_get = ia_phy_get,
- .change_qos = ia_change_qos,
- .proc_read = ia_proc_read,
- .owner = THIS_MODULE,
-};
-
-static int ia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- struct atm_dev *dev;
- IADEV *iadev;
- int ret;
-
- iadev = kzalloc_obj(*iadev);
- if (!iadev) {
- ret = -ENOMEM;
- goto err_out;
- }
-
- iadev->pci = pdev;
-
- IF_INIT(printk("ia detected at bus:%d dev: %d function:%d\n",
- pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));)
- if (pci_enable_device(pdev)) {
- ret = -ENODEV;
- goto err_out_free_iadev;
- }
- dev = atm_dev_register(DEV_LABEL, &pdev->dev, &ops, -1, NULL);
- if (!dev) {
- ret = -ENOMEM;
- goto err_out_disable_dev;
- }
- dev->dev_data = iadev;
- IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", dev->number);)
- IF_INIT(printk("dev_id = 0x%p iadev->LineRate = %d \n", dev,
- iadev->LineRate);)
-
- pci_set_drvdata(pdev, dev);
-
- ia_dev[iadev_count] = iadev;
- _ia_dev[iadev_count] = dev;
- iadev_count++;
- if (ia_init(dev) || ia_start(dev)) {
- IF_INIT(printk("IA register failed!\n");)
- iadev_count--;
- ia_dev[iadev_count] = NULL;
- _ia_dev[iadev_count] = NULL;
- ret = -EINVAL;
- goto err_out_deregister_dev;
- }
- IF_EVENT(printk("iadev_count = %d\n", iadev_count);)
-
- iadev->next_board = ia_boards;
- ia_boards = dev;
-
- return 0;
-
-err_out_deregister_dev:
- atm_dev_deregister(dev);
-err_out_disable_dev:
- pci_disable_device(pdev);
-err_out_free_iadev:
- kfree(iadev);
-err_out:
- return ret;
-}
-
-static void ia_remove_one(struct pci_dev *pdev)
-{
- struct atm_dev *dev = pci_get_drvdata(pdev);
- IADEV *iadev = INPH_IA_DEV(dev);
-
- /* Disable phy interrupts */
- ia_phy_put(dev, ia_phy_get(dev, SUNI_RSOP_CIE) & ~(SUNI_RSOP_CIE_LOSE),
- SUNI_RSOP_CIE);
- udelay(1);
-
- if (dev->phy && dev->phy->stop)
- dev->phy->stop(dev);
-
- /* De-register device */
- free_irq(iadev->irq, dev);
- iadev_count--;
- ia_dev[iadev_count] = NULL;
- _ia_dev[iadev_count] = NULL;
- IF_EVENT(printk("deregistering iav at (itf:%d)\n", dev->number);)
- atm_dev_deregister(dev);
-
- iounmap(iadev->base);
- pci_disable_device(pdev);
-
- ia_free_rx(iadev);
- ia_free_tx(iadev);
-
- kfree(iadev);
-}
-
-static const struct pci_device_id ia_pci_tbl[] = {
- { PCI_VENDOR_ID_IPHASE, 0x0008, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_IPHASE, 0x0009, PCI_ANY_ID, PCI_ANY_ID, },
- { 0,}
-};
-MODULE_DEVICE_TABLE(pci, ia_pci_tbl);
-
-static struct pci_driver ia_driver = {
- .name = DEV_LABEL,
- .id_table = ia_pci_tbl,
- .probe = ia_init_one,
- .remove = ia_remove_one,
-};
-
-static int __init ia_module_init(void)
-{
- int ret;
-
- ret = pci_register_driver(&ia_driver);
- if (ret >= 0) {
- ia_timer.expires = jiffies + 3*HZ;
- add_timer(&ia_timer);
- } else
- printk(KERN_ERR DEV_LABEL ": no adapter found\n");
- return ret;
-}
-
-static void __exit ia_module_exit(void)
-{
- pci_unregister_driver(&ia_driver);
-
- timer_delete_sync(&ia_timer);
-}
-
-module_init(ia_module_init);
-module_exit(ia_module_exit);
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
deleted file mode 100644
index d6af999a9ebb..000000000000
--- a/drivers/atm/lanai.c
+++ /dev/null
@@ -1,2603 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* lanai.c -- Copyright 1999-2003 by Mitchell Blank Jr <mitch@sfgoth.com>
- *
- * This driver supports ATM cards based on the Efficient "Lanai"
- * chipset such as the Speedstream 3010 and the ENI-25p. The
- * Speedstream 3060 is currently not supported since we don't
- * have the code to drive the on-board Alcatel DSL chipset (yet).
- *
- * Thanks to Efficient for supporting this project with hardware,
- * documentation, and by answering my questions.
- *
- * Things not working yet:
- *
- * o We don't support the Speedstream 3060 yet - this card has
- * an on-board DSL modem chip by Alcatel and the driver will
- * need some extra code added to handle it
- *
- * o Note that due to limitations of the Lanai only one VCC can be
- * in CBR at once
- *
- * o We don't currently parse the EEPROM at all. The code is all
- * there as per the spec, but it doesn't actually work. I think
- * there may be some issues with the docs. Anyway, do NOT
- * enable it yet - bugs in that code may actually damage your
- * hardware! Because of this you should hardware an ESI before
- * trying to use this in a LANE or MPOA environment.
- *
- * o AAL0 is stubbed in but the actual rx/tx path isn't written yet:
- * vcc_tx_aal0() needs to send or queue a SKB
- * vcc_tx_unqueue_aal0() needs to attempt to send queued SKBs
- * vcc_rx_aal0() needs to handle AAL0 interrupts
- * This isn't too much work - I just wanted to get other things
- * done first.
- *
- * o lanai_change_qos() isn't written yet
- *
- * o There aren't any ioctl's yet -- I'd like to eventually support
- * setting loopback and LED modes that way.
- *
- * o If the segmentation engine or DMA gets shut down we should restart
- * card as per section 17.0i. (see lanai_reset)
- *
- * o setsockopt(SO_CIRANGE) isn't done (although despite what the
- * API says it isn't exactly commonly implemented)
- */
-
-/* Version history:
- * v.1.00 -- 26-JUL-2003 -- PCI/DMA updates
- * v.0.02 -- 11-JAN-2000 -- Endian fixes
- * v.0.01 -- 30-NOV-1999 -- Initial release
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/atmdev.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-
-/* -------------------- TUNABLE PARAMATERS: */
-
-/*
- * Maximum number of VCIs per card. Setting it lower could theoretically
- * save some memory, but since we allocate our vcc list with get_free_pages,
- * it's not really likely for most architectures
- */
-#define NUM_VCI (1024)
-
-/*
- * Enable extra debugging
- */
-#define DEBUG
-/*
- * Debug _all_ register operations with card, except the memory test.
- * Also disables the timed poll to prevent extra chattiness. This
- * isn't for normal use
- */
-#undef DEBUG_RW
-
-/*
- * The programming guide specifies a full test of the on-board SRAM
- * at initialization time. Undefine to remove this
- */
-#define FULL_MEMORY_TEST
-
-/*
- * This is the number of (4 byte) service entries that we will
- * try to allocate at startup. Note that we will end up with
- * one PAGE_SIZE's worth regardless of what this is set to
- */
-#define SERVICE_ENTRIES (1024)
-/* TODO: make above a module load-time option */
-
-/*
- * We normally read the onboard EEPROM in order to discover our MAC
- * address. Undefine to _not_ do this
- */
-/* #define READ_EEPROM */ /* ***DONT ENABLE YET*** */
-/* TODO: make above a module load-time option (also) */
-
-/*
- * Depth of TX fifo (in 128 byte units; range 2-31)
- * Smaller numbers are better for network latency
- * Larger numbers are better for PCI latency
- * I'm really sure where the best tradeoff is, but the BSD driver uses
- * 7 and it seems to work ok.
- */
-#define TX_FIFO_DEPTH (7)
-/* TODO: make above a module load-time option */
-
-/*
- * How often (in jiffies) we will try to unstick stuck connections -
- * shouldn't need to happen much
- */
-#define LANAI_POLL_PERIOD (10*HZ)
-/* TODO: make above a module load-time option */
-
-/*
- * When allocating an AAL5 receiving buffer, try to make it at least
- * large enough to hold this many max_sdu sized PDUs
- */
-#define AAL5_RX_MULTIPLIER (3)
-/* TODO: make above a module load-time option */
-
-/*
- * Same for transmitting buffer
- */
-#define AAL5_TX_MULTIPLIER (3)
-/* TODO: make above a module load-time option */
-
-/*
- * When allocating an AAL0 transmiting buffer, how many cells should fit.
- * Remember we'll end up with a PAGE_SIZE of them anyway, so this isn't
- * really critical
- */
-#define AAL0_TX_MULTIPLIER (40)
-/* TODO: make above a module load-time option */
-
-/*
- * How large should we make the AAL0 receiving buffer. Remember that this
- * is shared between all AAL0 VC's
- */
-#define AAL0_RX_BUFFER_SIZE (PAGE_SIZE)
-/* TODO: make above a module load-time option */
-
-/*
- * Should we use Lanai's "powerdown" feature when no vcc's are bound?
- */
-/* #define USE_POWERDOWN */
-/* TODO: make above a module load-time option (also) */
-
-/* -------------------- DEBUGGING AIDS: */
-
-#define DEV_LABEL "lanai"
-
-#ifdef DEBUG
-
-#define DPRINTK(format, args...) \
- printk(KERN_DEBUG DEV_LABEL ": " format, ##args)
-#define APRINTK(truth, format, args...) \
- do { \
- if (unlikely(!(truth))) \
- printk(KERN_ERR DEV_LABEL ": " format, ##args); \
- } while (0)
-
-#else /* !DEBUG */
-
-#define DPRINTK(format, args...)
-#define APRINTK(truth, format, args...)
-
-#endif /* DEBUG */
-
-#ifdef DEBUG_RW
-#define RWDEBUG(format, args...) \
- printk(KERN_DEBUG DEV_LABEL ": " format, ##args)
-#else /* !DEBUG_RW */
-#define RWDEBUG(format, args...)
-#endif
-
-/* -------------------- DATA DEFINITIONS: */
-
-#define LANAI_MAPPING_SIZE (0x40000)
-#define LANAI_EEPROM_SIZE (128)
-
-typedef int vci_t;
-typedef void __iomem *bus_addr_t;
-
-/* DMA buffer in host memory for TX, RX, or service list. */
-struct lanai_buffer {
- u32 *start; /* From get_free_pages */
- u32 *end; /* One past last byte */
- u32 *ptr; /* Pointer to current host location */
- dma_addr_t dmaaddr;
-};
-
-struct lanai_vcc_stats {
- unsigned rx_nomem;
- union {
- struct {
- unsigned rx_badlen;
- unsigned service_trash;
- unsigned service_stream;
- unsigned service_rxcrc;
- } aal5;
- struct {
- } aal0;
- } x;
-};
-
-struct lanai_dev; /* Forward declaration */
-
-/*
- * This is the card-specific per-vcc data. Note that unlike some other
- * drivers there is NOT a 1-to-1 correspondance between these and
- * atm_vcc's - each one of these represents an actual 2-way vcc, but
- * an atm_vcc can be 1-way and share with a 1-way vcc in the other
- * direction. To make it weirder, there can even be 0-way vccs
- * bound to us, waiting to do a change_qos
- */
-struct lanai_vcc {
- bus_addr_t vbase; /* Base of VCC's registers */
- struct lanai_vcc_stats stats;
- int nref; /* # of atm_vcc's who reference us */
- vci_t vci;
- struct {
- struct lanai_buffer buf;
- struct atm_vcc *atmvcc; /* atm_vcc who is receiver */
- } rx;
- struct {
- struct lanai_buffer buf;
- struct atm_vcc *atmvcc; /* atm_vcc who is transmitter */
- int endptr; /* last endptr from service entry */
- struct sk_buff_head backlog;
- void (*unqueue)(struct lanai_dev *, struct lanai_vcc *, int);
- } tx;
-};
-
-enum lanai_type {
- lanai2 = PCI_DEVICE_ID_EF_ATM_LANAI2,
- lanaihb = PCI_DEVICE_ID_EF_ATM_LANAIHB
-};
-
-struct lanai_dev_stats {
- unsigned ovfl_trash; /* # of cells dropped - buffer overflow */
- unsigned vci_trash; /* # of cells dropped - closed vci */
- unsigned hec_err; /* # of cells dropped - bad HEC */
- unsigned atm_ovfl; /* # of cells dropped - rx fifo overflow */
- unsigned pcierr_parity_detect;
- unsigned pcierr_serr_set;
- unsigned pcierr_master_abort;
- unsigned pcierr_m_target_abort;
- unsigned pcierr_s_target_abort;
- unsigned pcierr_master_parity;
- unsigned service_notx;
- unsigned service_norx;
- unsigned service_rxnotaal5;
- unsigned dma_reenable;
- unsigned card_reset;
-};
-
-struct lanai_dev {
- bus_addr_t base;
- struct lanai_dev_stats stats;
- struct lanai_buffer service;
- struct lanai_vcc **vccs;
-#ifdef USE_POWERDOWN
- int nbound; /* number of bound vccs */
-#endif
- enum lanai_type type;
- vci_t num_vci; /* Currently just NUM_VCI */
- u8 eeprom[LANAI_EEPROM_SIZE];
- u32 serialno, magicno;
- struct pci_dev *pci;
- DECLARE_BITMAP(backlog_vccs, NUM_VCI); /* VCCs with tx backlog */
- DECLARE_BITMAP(transmit_ready, NUM_VCI); /* VCCs with transmit space */
- struct timer_list timer;
- int naal0;
- struct lanai_buffer aal0buf; /* AAL0 RX buffers */
- u32 conf1, conf2; /* CONFIG[12] registers */
- u32 status; /* STATUS register */
- spinlock_t endtxlock;
- spinlock_t servicelock;
- struct atm_vcc *cbrvcc;
- int number;
- int board_rev;
-/* TODO - look at race conditions with maintence of conf1/conf2 */
-/* TODO - transmit locking: should we use _irq not _irqsave? */
-/* TODO - organize above in some rational fashion (see <asm/cache.h>) */
-};
-
-/*
- * Each device has two bitmaps for each VCC (baclog_vccs and transmit_ready)
- * This function iterates one of these, calling a given function for each
- * vci with their bit set
- */
-static void vci_bitfield_iterate(struct lanai_dev *lanai,
- const unsigned long *lp,
- void (*func)(struct lanai_dev *,vci_t vci))
-{
- vci_t vci;
-
- for_each_set_bit(vci, lp, NUM_VCI)
- func(lanai, vci);
-}
-
-/* -------------------- BUFFER UTILITIES: */
-
-/*
- * Lanai needs DMA buffers aligned to 256 bytes of at least 1024 bytes -
- * usually any page allocation will do. Just to be safe in case
- * PAGE_SIZE is insanely tiny, though...
- */
-#define LANAI_PAGE_SIZE ((PAGE_SIZE >= 1024) ? PAGE_SIZE : 1024)
-
-/*
- * Allocate a buffer in host RAM for service list, RX, or TX
- * Returns buf->start==NULL if no memory
- * Note that the size will be rounded up 2^n bytes, and
- * if we can't allocate that we'll settle for something smaller
- * until minbytes
- */
-static void lanai_buf_allocate(struct lanai_buffer *buf,
- size_t bytes, size_t minbytes, struct pci_dev *pci)
-{
- int size;
-
- if (bytes > (128 * 1024)) /* max lanai buffer size */
- bytes = 128 * 1024;
- for (size = LANAI_PAGE_SIZE; size < bytes; size *= 2)
- ;
- if (minbytes < LANAI_PAGE_SIZE)
- minbytes = LANAI_PAGE_SIZE;
- do {
- /*
- * Technically we could use non-consistent mappings for
- * everything, but the way the lanai uses DMA memory would
- * make that a terrific pain. This is much simpler.
- */
- buf->start = dma_alloc_coherent(&pci->dev,
- size, &buf->dmaaddr, GFP_KERNEL);
- if (buf->start != NULL) { /* Success */
- /* Lanai requires 256-byte alignment of DMA bufs */
- APRINTK((buf->dmaaddr & ~0xFFFFFF00) == 0,
- "bad dmaaddr: 0x%lx\n",
- (unsigned long) buf->dmaaddr);
- buf->ptr = buf->start;
- buf->end = (u32 *)
- (&((unsigned char *) buf->start)[size]);
- memset(buf->start, 0, size);
- break;
- }
- size /= 2;
- } while (size >= minbytes);
-}
-
-/* size of buffer in bytes */
-static inline size_t lanai_buf_size(const struct lanai_buffer *buf)
-{
- return ((unsigned long) buf->end) - ((unsigned long) buf->start);
-}
-
-static void lanai_buf_deallocate(struct lanai_buffer *buf,
- struct pci_dev *pci)
-{
- if (buf->start != NULL) {
- dma_free_coherent(&pci->dev, lanai_buf_size(buf),
- buf->start, buf->dmaaddr);
- buf->start = buf->end = buf->ptr = NULL;
- }
-}
-
-/* size of buffer as "card order" (0=1k .. 7=128k) */
-static int lanai_buf_size_cardorder(const struct lanai_buffer *buf)
-{
- int order = get_order(lanai_buf_size(buf)) + (PAGE_SHIFT - 10);
-
- /* This can only happen if PAGE_SIZE is gigantic, but just in case */
- if (order > 7)
- order = 7;
- return order;
-}
-
-/* -------------------- PORT I/O UTILITIES: */
-
-/* Registers (and their bit-fields) */
-enum lanai_register {
- Reset_Reg = 0x00, /* Reset; read for chip type; bits: */
-#define RESET_GET_BOARD_REV(x) (((x)>> 0)&0x03) /* Board revision */
-#define RESET_GET_BOARD_ID(x) (((x)>> 2)&0x03) /* Board ID */
-#define BOARD_ID_LANAI256 (0) /* 25.6M adapter card */
- Endian_Reg = 0x04, /* Endian setting */
- IntStatus_Reg = 0x08, /* Interrupt status */
- IntStatusMasked_Reg = 0x0C, /* Interrupt status (masked) */
- IntAck_Reg = 0x10, /* Interrupt acknowledge */
- IntAckMasked_Reg = 0x14, /* Interrupt acknowledge (masked) */
- IntStatusSet_Reg = 0x18, /* Get status + enable/disable */
- IntStatusSetMasked_Reg = 0x1C, /* Get status + en/di (masked) */
- IntControlEna_Reg = 0x20, /* Interrupt control enable */
- IntControlDis_Reg = 0x24, /* Interrupt control disable */
- Status_Reg = 0x28, /* Status */
-#define STATUS_PROMDATA (0x00000001) /* PROM_DATA pin */
-#define STATUS_WAITING (0x00000002) /* Interrupt being delayed */
-#define STATUS_SOOL (0x00000004) /* SOOL alarm */
-#define STATUS_LOCD (0x00000008) /* LOCD alarm */
-#define STATUS_LED (0x00000010) /* LED (HAPPI) output */
-#define STATUS_GPIN (0x00000020) /* GPIN pin */
-#define STATUS_BUTTBUSY (0x00000040) /* Butt register is pending */
- Config1_Reg = 0x2C, /* Config word 1; bits: */
-#define CONFIG1_PROMDATA (0x00000001) /* PROM_DATA pin */
-#define CONFIG1_PROMCLK (0x00000002) /* PROM_CLK pin */
-#define CONFIG1_SET_READMODE(x) ((x)*0x004) /* PCI BM reads; values: */
-#define READMODE_PLAIN (0) /* Plain memory read */
-#define READMODE_LINE (2) /* Memory read line */
-#define READMODE_MULTIPLE (3) /* Memory read multiple */
-#define CONFIG1_DMA_ENABLE (0x00000010) /* Turn on DMA */
-#define CONFIG1_POWERDOWN (0x00000020) /* Turn off clocks */
-#define CONFIG1_SET_LOOPMODE(x) ((x)*0x080) /* Clock&loop mode; values: */
-#define LOOPMODE_NORMAL (0) /* Normal - no loop */
-#define LOOPMODE_TIME (1)
-#define LOOPMODE_DIAG (2)
-#define LOOPMODE_LINE (3)
-#define CONFIG1_MASK_LOOPMODE (0x00000180)
-#define CONFIG1_SET_LEDMODE(x) ((x)*0x0200) /* Mode of LED; values: */
-#define LEDMODE_NOT_SOOL (0) /* !SOOL */
-#define LEDMODE_OFF (1) /* 0 */
-#define LEDMODE_ON (2) /* 1 */
-#define LEDMODE_NOT_LOCD (3) /* !LOCD */
-#define LEDMORE_GPIN (4) /* GPIN */
-#define LEDMODE_NOT_GPIN (7) /* !GPIN */
-#define CONFIG1_MASK_LEDMODE (0x00000E00)
-#define CONFIG1_GPOUT1 (0x00001000) /* Toggle for reset */
-#define CONFIG1_GPOUT2 (0x00002000) /* Loopback PHY */
-#define CONFIG1_GPOUT3 (0x00004000) /* Loopback lanai */
- Config2_Reg = 0x30, /* Config word 2; bits: */
-#define CONFIG2_HOWMANY (0x00000001) /* >512 VCIs? */
-#define CONFIG2_PTI7_MODE (0x00000002) /* Make PTI=7 RM, not OAM */
-#define CONFIG2_VPI_CHK_DIS (0x00000004) /* Ignore RX VPI value */
-#define CONFIG2_HEC_DROP (0x00000008) /* Drop cells w/ HEC errors */
-#define CONFIG2_VCI0_NORMAL (0x00000010) /* Treat VCI=0 normally */
-#define CONFIG2_CBR_ENABLE (0x00000020) /* Deal with CBR traffic */
-#define CONFIG2_TRASH_ALL (0x00000040) /* Trashing incoming cells */
-#define CONFIG2_TX_DISABLE (0x00000080) /* Trashing outgoing cells */
-#define CONFIG2_SET_TRASH (0x00000100) /* Turn trashing on */
- Statistics_Reg = 0x34, /* Statistics; bits: */
-#define STATS_GET_FIFO_OVFL(x) (((x)>> 0)&0xFF) /* FIFO overflowed */
-#define STATS_GET_HEC_ERR(x) (((x)>> 8)&0xFF) /* HEC was bad */
-#define STATS_GET_BAD_VCI(x) (((x)>>16)&0xFF) /* VCI not open */
-#define STATS_GET_BUF_OVFL(x) (((x)>>24)&0xFF) /* VCC buffer full */
- ServiceStuff_Reg = 0x38, /* Service stuff; bits: */
-#define SSTUFF_SET_SIZE(x) ((x)*0x20000000) /* size of service buffer */
-#define SSTUFF_SET_ADDR(x) ((x)>>8) /* set address of buffer */
- ServWrite_Reg = 0x3C, /* ServWrite Pointer */
- ServRead_Reg = 0x40, /* ServRead Pointer */
- TxDepth_Reg = 0x44, /* FIFO Transmit Depth */
- Butt_Reg = 0x48, /* Butt register */
- CBR_ICG_Reg = 0x50,
- CBR_PTR_Reg = 0x54,
- PingCount_Reg = 0x58, /* Ping count */
- DMA_Addr_Reg = 0x5C /* DMA address */
-};
-
-static inline bus_addr_t reg_addr(const struct lanai_dev *lanai,
- enum lanai_register reg)
-{
- return lanai->base + reg;
-}
-
-static inline u32 reg_read(const struct lanai_dev *lanai,
- enum lanai_register reg)
-{
- u32 t;
- t = readl(reg_addr(lanai, reg));
- RWDEBUG("R [0x%08X] 0x%02X = 0x%08X\n", (unsigned int) lanai->base,
- (int) reg, t);
- return t;
-}
-
-static inline void reg_write(const struct lanai_dev *lanai, u32 val,
- enum lanai_register reg)
-{
- RWDEBUG("W [0x%08X] 0x%02X < 0x%08X\n", (unsigned int) lanai->base,
- (int) reg, val);
- writel(val, reg_addr(lanai, reg));
-}
-
-static inline void conf1_write(const struct lanai_dev *lanai)
-{
- reg_write(lanai, lanai->conf1, Config1_Reg);
-}
-
-static inline void conf2_write(const struct lanai_dev *lanai)
-{
- reg_write(lanai, lanai->conf2, Config2_Reg);
-}
-
-/* Same as conf2_write(), but defers I/O if we're powered down */
-static inline void conf2_write_if_powerup(const struct lanai_dev *lanai)
-{
-#ifdef USE_POWERDOWN
- if (unlikely((lanai->conf1 & CONFIG1_POWERDOWN) != 0))
- return;
-#endif /* USE_POWERDOWN */
- conf2_write(lanai);
-}
-
-static inline void reset_board(const struct lanai_dev *lanai)
-{
- DPRINTK("about to reset board\n");
- reg_write(lanai, 0, Reset_Reg);
- /*
- * If we don't delay a little while here then we can end up
- * leaving the card in a VERY weird state and lock up the
- * PCI bus. This isn't documented anywhere but I've convinced
- * myself after a lot of painful experimentation
- */
- udelay(5);
-}
-
-/* -------------------- CARD SRAM UTILITIES: */
-
-/* The SRAM is mapped into normal PCI memory space - the only catch is
- * that it is only 16-bits wide but must be accessed as 32-bit. The
- * 16 high bits will be zero. We don't hide this, since they get
- * programmed mostly like discrete registers anyway
- */
-#define SRAM_START (0x20000)
-#define SRAM_BYTES (0x20000) /* Again, half don't really exist */
-
-static inline bus_addr_t sram_addr(const struct lanai_dev *lanai, int offset)
-{
- return lanai->base + SRAM_START + offset;
-}
-
-static inline u32 sram_read(const struct lanai_dev *lanai, int offset)
-{
- return readl(sram_addr(lanai, offset));
-}
-
-static inline void sram_write(const struct lanai_dev *lanai,
- u32 val, int offset)
-{
- writel(val, sram_addr(lanai, offset));
-}
-
-static int sram_test_word(const struct lanai_dev *lanai, int offset,
- u32 pattern)
-{
- u32 readback;
- sram_write(lanai, pattern, offset);
- readback = sram_read(lanai, offset);
- if (likely(readback == pattern))
- return 0;
- printk(KERN_ERR DEV_LABEL
- "(itf %d): SRAM word at %d bad: wrote 0x%X, read 0x%X\n",
- lanai->number, offset,
- (unsigned int) pattern, (unsigned int) readback);
- return -EIO;
-}
-
-static int sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
-{
- int offset, result = 0;
- for (offset = 0; offset < SRAM_BYTES && result == 0; offset += 4)
- result = sram_test_word(lanai, offset, pattern);
- return result;
-}
-
-static int sram_test_and_clear(const struct lanai_dev *lanai)
-{
-#ifdef FULL_MEMORY_TEST
- int result;
- DPRINTK("testing SRAM\n");
- if ((result = sram_test_pass(lanai, 0x5555)) != 0)
- return result;
- if ((result = sram_test_pass(lanai, 0xAAAA)) != 0)
- return result;
-#endif
- DPRINTK("clearing SRAM\n");
- return sram_test_pass(lanai, 0x0000);
-}
-
-/* -------------------- CARD-BASED VCC TABLE UTILITIES: */
-
-/* vcc table */
-enum lanai_vcc_offset {
- vcc_rxaddr1 = 0x00, /* Location1, plus bits: */
-#define RXADDR1_SET_SIZE(x) ((x)*0x0000100) /* size of RX buffer */
-#define RXADDR1_SET_RMMODE(x) ((x)*0x00800) /* RM cell action; values: */
-#define RMMODE_TRASH (0) /* discard */
-#define RMMODE_PRESERVE (1) /* input as AAL0 */
-#define RMMODE_PIPE (2) /* pipe to coscheduler */
-#define RMMODE_PIPEALL (3) /* pipe non-RM too */
-#define RXADDR1_OAM_PRESERVE (0x00002000) /* Input OAM cells as AAL0 */
-#define RXADDR1_SET_MODE(x) ((x)*0x0004000) /* Reassembly mode */
-#define RXMODE_TRASH (0) /* discard */
-#define RXMODE_AAL0 (1) /* non-AAL5 mode */
-#define RXMODE_AAL5 (2) /* AAL5, intr. each PDU */
-#define RXMODE_AAL5_STREAM (3) /* AAL5 w/o per-PDU intr */
- vcc_rxaddr2 = 0x04, /* Location2 */
- vcc_rxcrc1 = 0x08, /* RX CRC claculation space */
- vcc_rxcrc2 = 0x0C,
- vcc_rxwriteptr = 0x10, /* RX writeptr, plus bits: */
-#define RXWRITEPTR_LASTEFCI (0x00002000) /* Last PDU had EFCI bit */
-#define RXWRITEPTR_DROPPING (0x00004000) /* Had error, dropping */
-#define RXWRITEPTR_TRASHING (0x00008000) /* Trashing */
- vcc_rxbufstart = 0x14, /* RX bufstart, plus bits: */
-#define RXBUFSTART_CLP (0x00004000)
-#define RXBUFSTART_CI (0x00008000)
- vcc_rxreadptr = 0x18, /* RX readptr */
- vcc_txicg = 0x1C, /* TX ICG */
- vcc_txaddr1 = 0x20, /* Location1, plus bits: */
-#define TXADDR1_SET_SIZE(x) ((x)*0x0000100) /* size of TX buffer */
-#define TXADDR1_ABR (0x00008000) /* use ABR (doesn't work) */
- vcc_txaddr2 = 0x24, /* Location2 */
- vcc_txcrc1 = 0x28, /* TX CRC claculation space */
- vcc_txcrc2 = 0x2C,
- vcc_txreadptr = 0x30, /* TX Readptr, plus bits: */
-#define TXREADPTR_GET_PTR(x) ((x)&0x01FFF)
-#define TXREADPTR_MASK_DELTA (0x0000E000) /* ? */
- vcc_txendptr = 0x34, /* TX Endptr, plus bits: */
-#define TXENDPTR_CLP (0x00002000)
-#define TXENDPTR_MASK_PDUMODE (0x0000C000) /* PDU mode; values: */
-#define PDUMODE_AAL0 (0*0x04000)
-#define PDUMODE_AAL5 (2*0x04000)
-#define PDUMODE_AAL5STREAM (3*0x04000)
- vcc_txwriteptr = 0x38, /* TX Writeptr */
-#define TXWRITEPTR_GET_PTR(x) ((x)&0x1FFF)
- vcc_txcbr_next = 0x3C /* # of next CBR VCI in ring */
-#define TXCBR_NEXT_BOZO (0x00008000) /* "bozo bit" */
-};
-
-#define CARDVCC_SIZE (0x40)
-
-static inline bus_addr_t cardvcc_addr(const struct lanai_dev *lanai,
- vci_t vci)
-{
- return sram_addr(lanai, vci * CARDVCC_SIZE);
-}
-
-static inline u32 cardvcc_read(const struct lanai_vcc *lvcc,
- enum lanai_vcc_offset offset)
-{
- u32 val;
- APRINTK(lvcc->vbase != NULL, "cardvcc_read: unbound vcc!\n");
- val= readl(lvcc->vbase + offset);
- RWDEBUG("VR vci=%04d 0x%02X = 0x%08X\n",
- lvcc->vci, (int) offset, val);
- return val;
-}
-
-static inline void cardvcc_write(const struct lanai_vcc *lvcc,
- u32 val, enum lanai_vcc_offset offset)
-{
- APRINTK(lvcc->vbase != NULL, "cardvcc_write: unbound vcc!\n");
- APRINTK((val & ~0xFFFF) == 0,
- "cardvcc_write: bad val 0x%X (vci=%d, addr=0x%02X)\n",
- (unsigned int) val, lvcc->vci, (unsigned int) offset);
- RWDEBUG("VW vci=%04d 0x%02X > 0x%08X\n",
- lvcc->vci, (unsigned int) offset, (unsigned int) val);
- writel(val, lvcc->vbase + offset);
-}
-
-/* -------------------- COMPUTE SIZE OF AN AAL5 PDU: */
-
-/* How many bytes will an AAL5 PDU take to transmit - remember that:
- * o we need to add 8 bytes for length, CPI, UU, and CRC
- * o we need to round up to 48 bytes for cells
- */
-static inline int aal5_size(int size)
-{
- int cells = (size + 8 + 47) / 48;
- return cells * 48;
-}
-
-/* -------------------- FREE AN ATM SKB: */
-
-static inline void lanai_free_skb(struct atm_vcc *atmvcc, struct sk_buff *skb)
-{
- if (atmvcc->pop != NULL)
- atmvcc->pop(atmvcc, skb);
- else
- dev_kfree_skb_any(skb);
-}
-
-/* -------------------- TURN VCCS ON AND OFF: */
-
-static void host_vcc_start_rx(const struct lanai_vcc *lvcc)
-{
- u32 addr1;
- if (lvcc->rx.atmvcc->qos.aal == ATM_AAL5) {
- dma_addr_t dmaaddr = lvcc->rx.buf.dmaaddr;
- cardvcc_write(lvcc, 0xFFFF, vcc_rxcrc1);
- cardvcc_write(lvcc, 0xFFFF, vcc_rxcrc2);
- cardvcc_write(lvcc, 0, vcc_rxwriteptr);
- cardvcc_write(lvcc, 0, vcc_rxbufstart);
- cardvcc_write(lvcc, 0, vcc_rxreadptr);
- cardvcc_write(lvcc, (dmaaddr >> 16) & 0xFFFF, vcc_rxaddr2);
- addr1 = ((dmaaddr >> 8) & 0xFF) |
- RXADDR1_SET_SIZE(lanai_buf_size_cardorder(&lvcc->rx.buf))|
- RXADDR1_SET_RMMODE(RMMODE_TRASH) | /* ??? */
- /* RXADDR1_OAM_PRESERVE | --- no OAM support yet */
- RXADDR1_SET_MODE(RXMODE_AAL5);
- } else
- addr1 = RXADDR1_SET_RMMODE(RMMODE_PRESERVE) | /* ??? */
- RXADDR1_OAM_PRESERVE | /* ??? */
- RXADDR1_SET_MODE(RXMODE_AAL0);
- /* This one must be last! */
- cardvcc_write(lvcc, addr1, vcc_rxaddr1);
-}
-
-static void host_vcc_start_tx(const struct lanai_vcc *lvcc)
-{
- dma_addr_t dmaaddr = lvcc->tx.buf.dmaaddr;
- cardvcc_write(lvcc, 0, vcc_txicg);
- cardvcc_write(lvcc, 0xFFFF, vcc_txcrc1);
- cardvcc_write(lvcc, 0xFFFF, vcc_txcrc2);
- cardvcc_write(lvcc, 0, vcc_txreadptr);
- cardvcc_write(lvcc, 0, vcc_txendptr);
- cardvcc_write(lvcc, 0, vcc_txwriteptr);
- cardvcc_write(lvcc,
- (lvcc->tx.atmvcc->qos.txtp.traffic_class == ATM_CBR) ?
- TXCBR_NEXT_BOZO | lvcc->vci : 0, vcc_txcbr_next);
- cardvcc_write(lvcc, (dmaaddr >> 16) & 0xFFFF, vcc_txaddr2);
- cardvcc_write(lvcc,
- ((dmaaddr >> 8) & 0xFF) |
- TXADDR1_SET_SIZE(lanai_buf_size_cardorder(&lvcc->tx.buf)),
- vcc_txaddr1);
-}
-
-/* Shutdown receiving on card */
-static void lanai_shutdown_rx_vci(const struct lanai_vcc *lvcc)
-{
- if (lvcc->vbase == NULL) /* We were never bound to a VCI */
- return;
- /* 15.1.1 - set to trashing, wait one cell time (15us) */
- cardvcc_write(lvcc,
- RXADDR1_SET_RMMODE(RMMODE_TRASH) |
- RXADDR1_SET_MODE(RXMODE_TRASH), vcc_rxaddr1);
- udelay(15);
- /* 15.1.2 - clear rest of entries */
- cardvcc_write(lvcc, 0, vcc_rxaddr2);
- cardvcc_write(lvcc, 0, vcc_rxcrc1);
- cardvcc_write(lvcc, 0, vcc_rxcrc2);
- cardvcc_write(lvcc, 0, vcc_rxwriteptr);
- cardvcc_write(lvcc, 0, vcc_rxbufstart);
- cardvcc_write(lvcc, 0, vcc_rxreadptr);
-}
-
-/* Shutdown transmitting on card.
- * Unfortunately the lanai needs us to wait until all the data
- * drains out of the buffer before we can dealloc it, so this
- * can take a while -- up to 370ms for a full 128KB buffer
- * assuming everone else is quiet. In theory the time is
- * boundless if there's a CBR VCC holding things up.
- */
-static void lanai_shutdown_tx_vci(struct lanai_dev *lanai,
- struct lanai_vcc *lvcc)
-{
- struct sk_buff *skb;
- unsigned long flags, timeout;
- int read, write, lastread = -1;
-
- if (lvcc->vbase == NULL) /* We were never bound to a VCI */
- return;
- /* 15.2.1 - wait for queue to drain */
- while ((skb = skb_dequeue(&lvcc->tx.backlog)) != NULL)
- lanai_free_skb(lvcc->tx.atmvcc, skb);
- read_lock_irqsave(&vcc_sklist_lock, flags);
- __clear_bit(lvcc->vci, lanai->backlog_vccs);
- read_unlock_irqrestore(&vcc_sklist_lock, flags);
- /*
- * We need to wait for the VCC to drain but don't wait forever. We
- * give each 1K of buffer size 1/128th of a second to clear out.
- * TODO: maybe disable CBR if we're about to timeout?
- */
- timeout = jiffies +
- (((lanai_buf_size(&lvcc->tx.buf) / 1024) * HZ) >> 7);
- write = TXWRITEPTR_GET_PTR(cardvcc_read(lvcc, vcc_txwriteptr));
- for (;;) {
- read = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr));
- if (read == write && /* Is TX buffer empty? */
- (lvcc->tx.atmvcc->qos.txtp.traffic_class != ATM_CBR ||
- (cardvcc_read(lvcc, vcc_txcbr_next) &
- TXCBR_NEXT_BOZO) == 0))
- break;
- if (read != lastread) { /* Has there been any progress? */
- lastread = read;
- timeout += HZ / 10;
- }
- if (unlikely(time_after(jiffies, timeout))) {
- printk(KERN_ERR DEV_LABEL "(itf %d): Timed out on "
- "backlog closing vci %d\n",
- lvcc->tx.atmvcc->dev->number, lvcc->vci);
- DPRINTK("read, write = %d, %d\n", read, write);
- break;
- }
- msleep(40);
- }
- /* 15.2.2 - clear out all tx registers */
- cardvcc_write(lvcc, 0, vcc_txreadptr);
- cardvcc_write(lvcc, 0, vcc_txwriteptr);
- cardvcc_write(lvcc, 0, vcc_txendptr);
- cardvcc_write(lvcc, 0, vcc_txcrc1);
- cardvcc_write(lvcc, 0, vcc_txcrc2);
- cardvcc_write(lvcc, 0, vcc_txaddr2);
- cardvcc_write(lvcc, 0, vcc_txaddr1);
-}
-
-/* -------------------- MANAGING AAL0 RX BUFFER: */
-
-static inline int aal0_buffer_allocate(struct lanai_dev *lanai)
-{
- DPRINTK("aal0_buffer_allocate: allocating AAL0 RX buffer\n");
- lanai_buf_allocate(&lanai->aal0buf, AAL0_RX_BUFFER_SIZE, 80,
- lanai->pci);
- return (lanai->aal0buf.start == NULL) ? -ENOMEM : 0;
-}
-
-static inline void aal0_buffer_free(struct lanai_dev *lanai)
-{
- DPRINTK("aal0_buffer_allocate: freeing AAL0 RX buffer\n");
- lanai_buf_deallocate(&lanai->aal0buf, lanai->pci);
-}
-
-/* -------------------- EEPROM UTILITIES: */
-
-/* Offsets of data in the EEPROM */
-#define EEPROM_COPYRIGHT (0)
-#define EEPROM_COPYRIGHT_LEN (44)
-#define EEPROM_CHECKSUM (62)
-#define EEPROM_CHECKSUM_REV (63)
-#define EEPROM_MAC (64)
-#define EEPROM_MAC_REV (70)
-#define EEPROM_SERIAL (112)
-#define EEPROM_SERIAL_REV (116)
-#define EEPROM_MAGIC (120)
-#define EEPROM_MAGIC_REV (124)
-
-#define EEPROM_MAGIC_VALUE (0x5AB478D2)
-
-#ifndef READ_EEPROM
-
-/* Stub functions to use if EEPROM reading is disabled */
-static int eeprom_read(struct lanai_dev *lanai)
-{
- printk(KERN_INFO DEV_LABEL "(itf %d): *NOT* reading EEPROM\n",
- lanai->number);
- memset(&lanai->eeprom[EEPROM_MAC], 0, 6);
- return 0;
-}
-
-static int eeprom_validate(struct lanai_dev *lanai)
-{
- lanai->serialno = 0;
- lanai->magicno = EEPROM_MAGIC_VALUE;
- return 0;
-}
-
-#else /* READ_EEPROM */
-
-static int eeprom_read(struct lanai_dev *lanai)
-{
- int i, address;
- u8 data;
- u32 tmp;
-#define set_config1(x) do { lanai->conf1 = x; conf1_write(lanai); \
- } while (0)
-#define clock_h() set_config1(lanai->conf1 | CONFIG1_PROMCLK)
-#define clock_l() set_config1(lanai->conf1 &~ CONFIG1_PROMCLK)
-#define data_h() set_config1(lanai->conf1 | CONFIG1_PROMDATA)
-#define data_l() set_config1(lanai->conf1 &~ CONFIG1_PROMDATA)
-#define pre_read() do { data_h(); clock_h(); udelay(5); } while (0)
-#define read_pin() (reg_read(lanai, Status_Reg) & STATUS_PROMDATA)
-#define send_stop() do { data_l(); udelay(5); clock_h(); udelay(5); \
- data_h(); udelay(5); } while (0)
- /* start with both clock and data high */
- data_h(); clock_h(); udelay(5);
- for (address = 0; address < LANAI_EEPROM_SIZE; address++) {
- data = (address << 1) | 1; /* Command=read + address */
- /* send start bit */
- data_l(); udelay(5);
- clock_l(); udelay(5);
- for (i = 128; i != 0; i >>= 1) { /* write command out */
- tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) |
- ((data & i) ? CONFIG1_PROMDATA : 0);
- if (lanai->conf1 != tmp) {
- set_config1(tmp);
- udelay(5); /* Let new data settle */
- }
- clock_h(); udelay(5); clock_l(); udelay(5);
- }
- /* look for ack */
- data_h(); clock_h(); udelay(5);
- if (read_pin() != 0)
- goto error; /* No ack seen */
- clock_l(); udelay(5);
- /* read back result */
- for (data = 0, i = 7; i >= 0; i--) {
- data_h(); clock_h(); udelay(5);
- data = (data << 1) | !!read_pin();
- clock_l(); udelay(5);
- }
- /* look again for ack */
- data_h(); clock_h(); udelay(5);
- if (read_pin() == 0)
- goto error; /* Spurious ack */
- clock_l(); udelay(5);
- send_stop();
- lanai->eeprom[address] = data;
- DPRINTK("EEPROM 0x%04X %02X\n",
- (unsigned int) address, (unsigned int) data);
- }
- return 0;
- error:
- clock_l(); udelay(5); /* finish read */
- send_stop();
- printk(KERN_ERR DEV_LABEL "(itf %d): error reading EEPROM byte %d\n",
- lanai->number, address);
- return -EIO;
-#undef set_config1
-#undef clock_h
-#undef clock_l
-#undef data_h
-#undef data_l
-#undef pre_read
-#undef read_pin
-#undef send_stop
-}
-
-/* read a big-endian 4-byte value out of eeprom */
-static inline u32 eeprom_be4(const struct lanai_dev *lanai, int address)
-{
- return be32_to_cpup((const u32 *) &lanai->eeprom[address]);
-}
-
-/* Checksum/validate EEPROM contents */
-static int eeprom_validate(struct lanai_dev *lanai)
-{
- int i, s;
- u32 v;
- const u8 *e = lanai->eeprom;
-#ifdef DEBUG
- /* First, see if we can get an ASCIIZ string out of the copyright */
- for (i = EEPROM_COPYRIGHT;
- i < (EEPROM_COPYRIGHT + EEPROM_COPYRIGHT_LEN); i++)
- if (e[i] < 0x20 || e[i] > 0x7E)
- break;
- if ( i != EEPROM_COPYRIGHT &&
- i != EEPROM_COPYRIGHT + EEPROM_COPYRIGHT_LEN && e[i] == '\0')
- DPRINTK("eeprom: copyright = \"%s\"\n",
- (char *) &e[EEPROM_COPYRIGHT]);
- else
- DPRINTK("eeprom: copyright not found\n");
-#endif
- /* Validate checksum */
- for (i = s = 0; i < EEPROM_CHECKSUM; i++)
- s += e[i];
- s &= 0xFF;
- if (s != e[EEPROM_CHECKSUM]) {
- printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM checksum bad "
- "(wanted 0x%02X, got 0x%02X)\n", lanai->number,
- (unsigned int) s, (unsigned int) e[EEPROM_CHECKSUM]);
- return -EIO;
- }
- s ^= 0xFF;
- if (s != e[EEPROM_CHECKSUM_REV]) {
- printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM inverse checksum "
- "bad (wanted 0x%02X, got 0x%02X)\n", lanai->number,
- (unsigned int) s, (unsigned int) e[EEPROM_CHECKSUM_REV]);
- return -EIO;
- }
- /* Verify MAC address */
- for (i = 0; i < 6; i++)
- if ((e[EEPROM_MAC + i] ^ e[EEPROM_MAC_REV + i]) != 0xFF) {
- printk(KERN_ERR DEV_LABEL
- "(itf %d) : EEPROM MAC addresses don't match "
- "(0x%02X, inverse 0x%02X)\n", lanai->number,
- (unsigned int) e[EEPROM_MAC + i],
- (unsigned int) e[EEPROM_MAC_REV + i]);
- return -EIO;
- }
- DPRINTK("eeprom: MAC address = %pM\n", &e[EEPROM_MAC]);
- /* Verify serial number */
- lanai->serialno = eeprom_be4(lanai, EEPROM_SERIAL);
- v = eeprom_be4(lanai, EEPROM_SERIAL_REV);
- if ((lanai->serialno ^ v) != 0xFFFFFFFF) {
- printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM serial numbers "
- "don't match (0x%08X, inverse 0x%08X)\n", lanai->number,
- (unsigned int) lanai->serialno, (unsigned int) v);
- return -EIO;
- }
- DPRINTK("eeprom: Serial number = %d\n", (unsigned int) lanai->serialno);
- /* Verify magic number */
- lanai->magicno = eeprom_be4(lanai, EEPROM_MAGIC);
- v = eeprom_be4(lanai, EEPROM_MAGIC_REV);
- if ((lanai->magicno ^ v) != 0xFFFFFFFF) {
- printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM magic numbers "
- "don't match (0x%08X, inverse 0x%08X)\n", lanai->number,
- lanai->magicno, v);
- return -EIO;
- }
- DPRINTK("eeprom: Magic number = 0x%08X\n", lanai->magicno);
- if (lanai->magicno != EEPROM_MAGIC_VALUE)
- printk(KERN_WARNING DEV_LABEL "(itf %d): warning - EEPROM "
- "magic not what expected (got 0x%08X, not 0x%08X)\n",
- lanai->number, (unsigned int) lanai->magicno,
- (unsigned int) EEPROM_MAGIC_VALUE);
- return 0;
-}
-
-#endif /* READ_EEPROM */
-
-static inline const u8 *eeprom_mac(const struct lanai_dev *lanai)
-{
- return &lanai->eeprom[EEPROM_MAC];
-}
-
-/* -------------------- INTERRUPT HANDLING UTILITIES: */
-
-/* Interrupt types */
-#define INT_STATS (0x00000002) /* Statistics counter overflow */
-#define INT_SOOL (0x00000004) /* SOOL changed state */
-#define INT_LOCD (0x00000008) /* LOCD changed state */
-#define INT_LED (0x00000010) /* LED (HAPPI) changed state */
-#define INT_GPIN (0x00000020) /* GPIN changed state */
-#define INT_PING (0x00000040) /* PING_COUNT fulfilled */
-#define INT_WAKE (0x00000080) /* Lanai wants bus */
-#define INT_CBR0 (0x00000100) /* CBR sched hit VCI 0 */
-#define INT_LOCK (0x00000200) /* Service list overflow */
-#define INT_MISMATCH (0x00000400) /* TX magic list mismatch */
-#define INT_AAL0_STR (0x00000800) /* Non-AAL5 buffer half filled */
-#define INT_AAL0 (0x00001000) /* Non-AAL5 data available */
-#define INT_SERVICE (0x00002000) /* Service list entries available */
-#define INT_TABORTSENT (0x00004000) /* Target abort sent by lanai */
-#define INT_TABORTBM (0x00008000) /* Abort rcv'd as bus master */
-#define INT_TIMEOUTBM (0x00010000) /* No response to bus master */
-#define INT_PCIPARITY (0x00020000) /* Parity error on PCI */
-
-/* Sets of the above */
-#define INT_ALL (0x0003FFFE) /* All interrupts */
-#define INT_STATUS (0x0000003C) /* Some status pin changed */
-#define INT_DMASHUT (0x00038000) /* DMA engine got shut down */
-#define INT_SEGSHUT (0x00000700) /* Segmentation got shut down */
-
-static inline u32 intr_pending(const struct lanai_dev *lanai)
-{
- return reg_read(lanai, IntStatusMasked_Reg);
-}
-
-static inline void intr_enable(const struct lanai_dev *lanai, u32 i)
-{
- reg_write(lanai, i, IntControlEna_Reg);
-}
-
-static inline void intr_disable(const struct lanai_dev *lanai, u32 i)
-{
- reg_write(lanai, i, IntControlDis_Reg);
-}
-
-/* -------------------- CARD/PCI STATUS: */
-
-static void status_message(int itf, const char *name, int status)
-{
- static const char *onoff[2] = { "off to on", "on to off" };
- printk(KERN_INFO DEV_LABEL "(itf %d): %s changed from %s\n",
- itf, name, onoff[!status]);
-}
-
-static void lanai_check_status(struct lanai_dev *lanai)
-{
- u32 new = reg_read(lanai, Status_Reg);
- u32 changes = new ^ lanai->status;
- lanai->status = new;
-#define e(flag, name) \
- if (changes & flag) \
- status_message(lanai->number, name, new & flag)
- e(STATUS_SOOL, "SOOL");
- e(STATUS_LOCD, "LOCD");
- e(STATUS_LED, "LED");
- e(STATUS_GPIN, "GPIN");
-#undef e
-}
-
-static void pcistatus_got(int itf, const char *name)
-{
- printk(KERN_INFO DEV_LABEL "(itf %d): PCI got %s error\n", itf, name);
-}
-
-static void pcistatus_check(struct lanai_dev *lanai, int clearonly)
-{
- u16 s;
- int result;
- result = pci_read_config_word(lanai->pci, PCI_STATUS, &s);
- if (result != PCIBIOS_SUCCESSFUL) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't read PCI_STATUS: "
- "%d\n", lanai->number, result);
- return;
- }
- s &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
- PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT |
- PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_PARITY;
- if (s == 0)
- return;
- result = pci_write_config_word(lanai->pci, PCI_STATUS, s);
- if (result != PCIBIOS_SUCCESSFUL)
- printk(KERN_ERR DEV_LABEL "(itf %d): can't write PCI_STATUS: "
- "%d\n", lanai->number, result);
- if (clearonly)
- return;
-#define e(flag, name, stat) \
- if (s & flag) { \
- pcistatus_got(lanai->number, name); \
- ++lanai->stats.pcierr_##stat; \
- }
- e(PCI_STATUS_DETECTED_PARITY, "parity", parity_detect);
- e(PCI_STATUS_SIG_SYSTEM_ERROR, "signalled system", serr_set);
- e(PCI_STATUS_REC_MASTER_ABORT, "master", master_abort);
- e(PCI_STATUS_REC_TARGET_ABORT, "master target", m_target_abort);
- e(PCI_STATUS_SIG_TARGET_ABORT, "slave", s_target_abort);
- e(PCI_STATUS_PARITY, "master parity", master_parity);
-#undef e
-}
-
-/* -------------------- VCC TX BUFFER UTILITIES: */
-
-/* space left in tx buffer in bytes */
-static inline int vcc_tx_space(const struct lanai_vcc *lvcc, int endptr)
-{
- int r;
- r = endptr * 16;
- r -= ((unsigned long) lvcc->tx.buf.ptr) -
- ((unsigned long) lvcc->tx.buf.start);
- r -= 16; /* Leave "bubble" - if start==end it looks empty */
- if (r < 0)
- r += lanai_buf_size(&lvcc->tx.buf);
- return r;
-}
-
-/* test if VCC is currently backlogged */
-static inline int vcc_is_backlogged(const struct lanai_vcc *lvcc)
-{
- return !skb_queue_empty(&lvcc->tx.backlog);
-}
-
-/* Bit fields in the segmentation buffer descriptor */
-#define DESCRIPTOR_MAGIC (0xD0000000)
-#define DESCRIPTOR_AAL5 (0x00008000)
-#define DESCRIPTOR_AAL5_STREAM (0x00004000)
-#define DESCRIPTOR_CLP (0x00002000)
-
-/* Add 32-bit descriptor with its padding */
-static inline void vcc_tx_add_aal5_descriptor(struct lanai_vcc *lvcc,
- u32 flags, int len)
-{
- int pos;
- APRINTK((((unsigned long) lvcc->tx.buf.ptr) & 15) == 0,
- "vcc_tx_add_aal5_descriptor: bad ptr=%p\n", lvcc->tx.buf.ptr);
- lvcc->tx.buf.ptr += 4; /* Hope the values REALLY don't matter */
- pos = ((unsigned char *) lvcc->tx.buf.ptr) -
- (unsigned char *) lvcc->tx.buf.start;
- APRINTK((pos & ~0x0001FFF0) == 0,
- "vcc_tx_add_aal5_descriptor: bad pos (%d) before, vci=%d, "
- "start,ptr,end=%p,%p,%p\n", pos, lvcc->vci,
- lvcc->tx.buf.start, lvcc->tx.buf.ptr, lvcc->tx.buf.end);
- pos = (pos + len) & (lanai_buf_size(&lvcc->tx.buf) - 1);
- APRINTK((pos & ~0x0001FFF0) == 0,
- "vcc_tx_add_aal5_descriptor: bad pos (%d) after, vci=%d, "
- "start,ptr,end=%p,%p,%p\n", pos, lvcc->vci,
- lvcc->tx.buf.start, lvcc->tx.buf.ptr, lvcc->tx.buf.end);
- lvcc->tx.buf.ptr[-1] =
- cpu_to_le32(DESCRIPTOR_MAGIC | DESCRIPTOR_AAL5 |
- ((lvcc->tx.atmvcc->atm_options & ATM_ATMOPT_CLP) ?
- DESCRIPTOR_CLP : 0) | flags | pos >> 4);
- if (lvcc->tx.buf.ptr >= lvcc->tx.buf.end)
- lvcc->tx.buf.ptr = lvcc->tx.buf.start;
-}
-
-/* Add 32-bit AAL5 trailer and leave room for its CRC */
-static inline void vcc_tx_add_aal5_trailer(struct lanai_vcc *lvcc,
- int len, int cpi, int uu)
-{
- APRINTK((((unsigned long) lvcc->tx.buf.ptr) & 15) == 8,
- "vcc_tx_add_aal5_trailer: bad ptr=%p\n", lvcc->tx.buf.ptr);
- lvcc->tx.buf.ptr += 2;
- lvcc->tx.buf.ptr[-2] = cpu_to_be32((uu << 24) | (cpi << 16) | len);
- if (lvcc->tx.buf.ptr >= lvcc->tx.buf.end)
- lvcc->tx.buf.ptr = lvcc->tx.buf.start;
-}
-
-static inline void vcc_tx_memcpy(struct lanai_vcc *lvcc,
- const unsigned char *src, int n)
-{
- unsigned char *e;
- int m;
- e = ((unsigned char *) lvcc->tx.buf.ptr) + n;
- m = e - (unsigned char *) lvcc->tx.buf.end;
- if (m < 0)
- m = 0;
- memcpy(lvcc->tx.buf.ptr, src, n - m);
- if (m != 0) {
- memcpy(lvcc->tx.buf.start, src + n - m, m);
- e = ((unsigned char *) lvcc->tx.buf.start) + m;
- }
- lvcc->tx.buf.ptr = (u32 *) e;
-}
-
-static inline void vcc_tx_memzero(struct lanai_vcc *lvcc, int n)
-{
- unsigned char *e;
- int m;
- if (n == 0)
- return;
- e = ((unsigned char *) lvcc->tx.buf.ptr) + n;
- m = e - (unsigned char *) lvcc->tx.buf.end;
- if (m < 0)
- m = 0;
- memset(lvcc->tx.buf.ptr, 0, n - m);
- if (m != 0) {
- memset(lvcc->tx.buf.start, 0, m);
- e = ((unsigned char *) lvcc->tx.buf.start) + m;
- }
- lvcc->tx.buf.ptr = (u32 *) e;
-}
-
-/* Update "butt" register to specify new WritePtr */
-static inline void lanai_endtx(struct lanai_dev *lanai,
- const struct lanai_vcc *lvcc)
-{
- int i, ptr = ((unsigned char *) lvcc->tx.buf.ptr) -
- (unsigned char *) lvcc->tx.buf.start;
- APRINTK((ptr & ~0x0001FFF0) == 0,
- "lanai_endtx: bad ptr (%d), vci=%d, start,ptr,end=%p,%p,%p\n",
- ptr, lvcc->vci, lvcc->tx.buf.start, lvcc->tx.buf.ptr,
- lvcc->tx.buf.end);
-
- /*
- * Since the "butt register" is a shared resounce on the card we
- * serialize all accesses to it through this spinlock. This is
- * mostly just paranoia since the register is rarely "busy" anyway
- * but is needed for correctness.
- */
- spin_lock(&lanai->endtxlock);
- /*
- * We need to check if the "butt busy" bit is set before
- * updating the butt register. In theory this should
- * never happen because the ATM card is plenty fast at
- * updating the register. Still, we should make sure
- */
- for (i = 0; reg_read(lanai, Status_Reg) & STATUS_BUTTBUSY; i++) {
- if (unlikely(i > 50)) {
- printk(KERN_ERR DEV_LABEL "(itf %d): butt register "
- "always busy!\n", lanai->number);
- break;
- }
- udelay(5);
- }
- /*
- * Before we tall the card to start work we need to be sure 100% of
- * the info in the service buffer has been written before we tell
- * the card about it
- */
- wmb();
- reg_write(lanai, (ptr << 12) | lvcc->vci, Butt_Reg);
- spin_unlock(&lanai->endtxlock);
-}
-
-/*
- * Add one AAL5 PDU to lvcc's transmit buffer. Caller garauntees there's
- * space available. "pdusize" is the number of bytes the PDU will take
- */
-static void lanai_send_one_aal5(struct lanai_dev *lanai,
- struct lanai_vcc *lvcc, struct sk_buff *skb, int pdusize)
-{
- int pad;
- APRINTK(pdusize == aal5_size(skb->len),
- "lanai_send_one_aal5: wrong size packet (%d != %d)\n",
- pdusize, aal5_size(skb->len));
- vcc_tx_add_aal5_descriptor(lvcc, 0, pdusize);
- pad = pdusize - skb->len - 8;
- APRINTK(pad >= 0, "pad is negative (%d)\n", pad);
- APRINTK(pad < 48, "pad is too big (%d)\n", pad);
- vcc_tx_memcpy(lvcc, skb->data, skb->len);
- vcc_tx_memzero(lvcc, pad);
- vcc_tx_add_aal5_trailer(lvcc, skb->len, 0, 0);
- lanai_endtx(lanai, lvcc);
- lanai_free_skb(lvcc->tx.atmvcc, skb);
- atomic_inc(&lvcc->tx.atmvcc->stats->tx);
-}
-
-/* Try to fill the buffer - don't call unless there is backlog */
-static void vcc_tx_unqueue_aal5(struct lanai_dev *lanai,
- struct lanai_vcc *lvcc, int endptr)
-{
- int n;
- struct sk_buff *skb;
- int space = vcc_tx_space(lvcc, endptr);
- APRINTK(vcc_is_backlogged(lvcc),
- "vcc_tx_unqueue() called with empty backlog (vci=%d)\n",
- lvcc->vci);
- while (space >= 64) {
- skb = skb_dequeue(&lvcc->tx.backlog);
- if (skb == NULL)
- goto no_backlog;
- n = aal5_size(skb->len);
- if (n + 16 > space) {
- /* No room for this packet - put it back on queue */
- skb_queue_head(&lvcc->tx.backlog, skb);
- return;
- }
- lanai_send_one_aal5(lanai, lvcc, skb, n);
- space -= n + 16;
- }
- if (!vcc_is_backlogged(lvcc)) {
- no_backlog:
- __clear_bit(lvcc->vci, lanai->backlog_vccs);
- }
-}
-
-/* Given an skb that we want to transmit either send it now or queue */
-static void vcc_tx_aal5(struct lanai_dev *lanai, struct lanai_vcc *lvcc,
- struct sk_buff *skb)
-{
- int space, n;
- if (vcc_is_backlogged(lvcc)) /* Already backlogged */
- goto queue_it;
- space = vcc_tx_space(lvcc,
- TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr)));
- n = aal5_size(skb->len);
- APRINTK(n + 16 >= 64, "vcc_tx_aal5: n too small (%d)\n", n);
- if (space < n + 16) { /* No space for this PDU */
- __set_bit(lvcc->vci, lanai->backlog_vccs);
- queue_it:
- skb_queue_tail(&lvcc->tx.backlog, skb);
- return;
- }
- lanai_send_one_aal5(lanai, lvcc, skb, n);
-}
-
-static void vcc_tx_unqueue_aal0(struct lanai_dev *lanai,
- struct lanai_vcc *lvcc, int endptr)
-{
- printk(KERN_INFO DEV_LABEL
- ": vcc_tx_unqueue_aal0: not implemented\n");
-}
-
-static void vcc_tx_aal0(struct lanai_dev *lanai, struct lanai_vcc *lvcc,
- struct sk_buff *skb)
-{
- printk(KERN_INFO DEV_LABEL ": vcc_tx_aal0: not implemented\n");
- /* Remember to increment lvcc->tx.atmvcc->stats->tx */
- lanai_free_skb(lvcc->tx.atmvcc, skb);
-}
-
-/* -------------------- VCC RX BUFFER UTILITIES: */
-
-/* unlike the _tx_ cousins, this doesn't update ptr */
-static inline void vcc_rx_memcpy(unsigned char *dest,
- const struct lanai_vcc *lvcc, int n)
-{
- int m = ((const unsigned char *) lvcc->rx.buf.ptr) + n -
- ((const unsigned char *) (lvcc->rx.buf.end));
- if (m < 0)
- m = 0;
- memcpy(dest, lvcc->rx.buf.ptr, n - m);
- memcpy(dest + n - m, lvcc->rx.buf.start, m);
- /* Make sure that these copies don't get reordered */
- barrier();
-}
-
-/* Receive AAL5 data on a VCC with a particular endptr */
-static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr)
-{
- int size;
- struct sk_buff *skb;
- const u32 *x;
- u32 *end = &lvcc->rx.buf.start[endptr * 4];
- int n = ((unsigned long) end) - ((unsigned long) lvcc->rx.buf.ptr);
- if (n < 0)
- n += lanai_buf_size(&lvcc->rx.buf);
- APRINTK(n >= 0 && n < lanai_buf_size(&lvcc->rx.buf) && !(n & 15),
- "vcc_rx_aal5: n out of range (%d/%zu)\n",
- n, lanai_buf_size(&lvcc->rx.buf));
- /* Recover the second-to-last word to get true pdu length */
- if ((x = &end[-2]) < lvcc->rx.buf.start)
- x = &lvcc->rx.buf.end[-2];
- /*
- * Before we actually read from the buffer, make sure the memory
- * changes have arrived
- */
- rmb();
- size = be32_to_cpup(x) & 0xffff;
- if (unlikely(n != aal5_size(size))) {
- /* Make sure size matches padding */
- printk(KERN_INFO DEV_LABEL "(itf %d): Got bad AAL5 length "
- "on vci=%d - size=%d n=%d\n",
- lvcc->rx.atmvcc->dev->number, lvcc->vci, size, n);
- lvcc->stats.x.aal5.rx_badlen++;
- goto out;
- }
- skb = atm_alloc_charge(lvcc->rx.atmvcc, size, GFP_ATOMIC);
- if (unlikely(skb == NULL)) {
- lvcc->stats.rx_nomem++;
- goto out;
- }
- skb_put(skb, size);
- vcc_rx_memcpy(skb->data, lvcc, size);
- ATM_SKB(skb)->vcc = lvcc->rx.atmvcc;
- __net_timestamp(skb);
- lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb);
- atomic_inc(&lvcc->rx.atmvcc->stats->rx);
- out:
- lvcc->rx.buf.ptr = end;
- cardvcc_write(lvcc, endptr, vcc_rxreadptr);
-}
-
-static void vcc_rx_aal0(struct lanai_dev *lanai)
-{
- printk(KERN_INFO DEV_LABEL ": vcc_rx_aal0: not implemented\n");
- /* Remember to get read_lock(&vcc_sklist_lock) while looking up VC */
- /* Remember to increment lvcc->rx.atmvcc->stats->rx */
-}
-
-/* -------------------- MANAGING HOST-BASED VCC TABLE: */
-
-/* Decide whether to use vmalloc or get_zeroed_page for VCC table */
-#if (NUM_VCI * BITS_PER_LONG) <= PAGE_SIZE
-#define VCCTABLE_GETFREEPAGE
-#else
-#include <linux/vmalloc.h>
-#endif
-
-static int vcc_table_allocate(struct lanai_dev *lanai)
-{
-#ifdef VCCTABLE_GETFREEPAGE
- APRINTK((lanai->num_vci) * sizeof(struct lanai_vcc *) <= PAGE_SIZE,
- "vcc table > PAGE_SIZE!");
- lanai->vccs = (struct lanai_vcc **) get_zeroed_page(GFP_KERNEL);
- return (lanai->vccs == NULL) ? -ENOMEM : 0;
-#else
- int bytes = (lanai->num_vci) * sizeof(struct lanai_vcc *);
- lanai->vccs = vzalloc(bytes);
- if (unlikely(lanai->vccs == NULL))
- return -ENOMEM;
- return 0;
-#endif
-}
-
-static inline void vcc_table_deallocate(const struct lanai_dev *lanai)
-{
-#ifdef VCCTABLE_GETFREEPAGE
- free_page((unsigned long) lanai->vccs);
-#else
- vfree(lanai->vccs);
-#endif
-}
-
-/* Allocate a fresh lanai_vcc, with the appropriate things cleared */
-static inline struct lanai_vcc *new_lanai_vcc(void)
-{
- struct lanai_vcc *lvcc;
- lvcc = kzalloc_obj(*lvcc);
- if (likely(lvcc != NULL)) {
- skb_queue_head_init(&lvcc->tx.backlog);
-#ifdef DEBUG
- lvcc->vci = -1;
-#endif
- }
- return lvcc;
-}
-
-static int lanai_get_sized_buffer(struct lanai_dev *lanai,
- struct lanai_buffer *buf, int max_sdu, int multiplier,
- const char *name)
-{
- int size;
- if (unlikely(max_sdu < 1))
- max_sdu = 1;
- max_sdu = aal5_size(max_sdu);
- size = (max_sdu + 16) * multiplier + 16;
- lanai_buf_allocate(buf, size, max_sdu + 32, lanai->pci);
- if (unlikely(buf->start == NULL))
- return -ENOMEM;
- if (unlikely(lanai_buf_size(buf) < size))
- printk(KERN_WARNING DEV_LABEL "(itf %d): wanted %d bytes "
- "for %s buffer, got only %zu\n", lanai->number, size,
- name, lanai_buf_size(buf));
- DPRINTK("Allocated %zu byte %s buffer\n", lanai_buf_size(buf), name);
- return 0;
-}
-
-/* Setup a RX buffer for a currently unbound AAL5 vci */
-static inline int lanai_setup_rx_vci_aal5(struct lanai_dev *lanai,
- struct lanai_vcc *lvcc, const struct atm_qos *qos)
-{
- return lanai_get_sized_buffer(lanai, &lvcc->rx.buf,
- qos->rxtp.max_sdu, AAL5_RX_MULTIPLIER, "RX");
-}
-
-/* Setup a TX buffer for a currently unbound AAL5 vci */
-static int lanai_setup_tx_vci(struct lanai_dev *lanai, struct lanai_vcc *lvcc,
- const struct atm_qos *qos)
-{
- int max_sdu, multiplier;
- if (qos->aal == ATM_AAL0) {
- lvcc->tx.unqueue = vcc_tx_unqueue_aal0;
- max_sdu = ATM_CELL_SIZE - 1;
- multiplier = AAL0_TX_MULTIPLIER;
- } else {
- lvcc->tx.unqueue = vcc_tx_unqueue_aal5;
- max_sdu = qos->txtp.max_sdu;
- multiplier = AAL5_TX_MULTIPLIER;
- }
- return lanai_get_sized_buffer(lanai, &lvcc->tx.buf, max_sdu,
- multiplier, "TX");
-}
-
-static inline void host_vcc_bind(struct lanai_dev *lanai,
- struct lanai_vcc *lvcc, vci_t vci)
-{
- if (lvcc->vbase != NULL)
- return; /* We already were bound in the other direction */
- DPRINTK("Binding vci %d\n", vci);
-#ifdef USE_POWERDOWN
- if (lanai->nbound++ == 0) {
- DPRINTK("Coming out of powerdown\n");
- lanai->conf1 &= ~CONFIG1_POWERDOWN;
- conf1_write(lanai);
- conf2_write(lanai);
- }
-#endif
- lvcc->vbase = cardvcc_addr(lanai, vci);
- lanai->vccs[lvcc->vci = vci] = lvcc;
-}
-
-static inline void host_vcc_unbind(struct lanai_dev *lanai,
- struct lanai_vcc *lvcc)
-{
- if (lvcc->vbase == NULL)
- return; /* This vcc was never bound */
- DPRINTK("Unbinding vci %d\n", lvcc->vci);
- lvcc->vbase = NULL;
- lanai->vccs[lvcc->vci] = NULL;
-#ifdef USE_POWERDOWN
- if (--lanai->nbound == 0) {
- DPRINTK("Going into powerdown\n");
- lanai->conf1 |= CONFIG1_POWERDOWN;
- conf1_write(lanai);
- }
-#endif
-}
-
-/* -------------------- RESET CARD: */
-
-static void lanai_reset(struct lanai_dev *lanai)
-{
- printk(KERN_CRIT DEV_LABEL "(itf %d): *NOT* resetting - not "
- "implemented\n", lanai->number);
- /* TODO */
- /* The following is just a hack until we write the real
- * resetter - at least ack whatever interrupt sent us
- * here
- */
- reg_write(lanai, INT_ALL, IntAck_Reg);
- lanai->stats.card_reset++;
-}
-
-/* -------------------- SERVICE LIST UTILITIES: */
-
-/*
- * Allocate service buffer and tell card about it
- */
-static int service_buffer_allocate(struct lanai_dev *lanai)
-{
- lanai_buf_allocate(&lanai->service, SERVICE_ENTRIES * 4, 8,
- lanai->pci);
- if (unlikely(lanai->service.start == NULL))
- return -ENOMEM;
- DPRINTK("allocated service buffer at %p, size %zu(%d)\n",
- lanai->service.start,
- lanai_buf_size(&lanai->service),
- lanai_buf_size_cardorder(&lanai->service));
- /* Clear ServWrite register to be safe */
- reg_write(lanai, 0, ServWrite_Reg);
- /* ServiceStuff register contains size and address of buffer */
- reg_write(lanai,
- SSTUFF_SET_SIZE(lanai_buf_size_cardorder(&lanai->service)) |
- SSTUFF_SET_ADDR(lanai->service.dmaaddr),
- ServiceStuff_Reg);
- return 0;
-}
-
-static inline void service_buffer_deallocate(struct lanai_dev *lanai)
-{
- lanai_buf_deallocate(&lanai->service, lanai->pci);
-}
-
-/* Bitfields in service list */
-#define SERVICE_TX (0x80000000) /* Was from transmission */
-#define SERVICE_TRASH (0x40000000) /* RXed PDU was trashed */
-#define SERVICE_CRCERR (0x20000000) /* RXed PDU had CRC error */
-#define SERVICE_CI (0x10000000) /* RXed PDU had CI set */
-#define SERVICE_CLP (0x08000000) /* RXed PDU had CLP set */
-#define SERVICE_STREAM (0x04000000) /* RX Stream mode */
-#define SERVICE_GET_VCI(x) (((x)>>16)&0x3FF)
-#define SERVICE_GET_END(x) ((x)&0x1FFF)
-
-/* Handle one thing from the service list - returns true if it marked a
- * VCC ready for xmit
- */
-static int handle_service(struct lanai_dev *lanai, u32 s)
-{
- vci_t vci = SERVICE_GET_VCI(s);
- struct lanai_vcc *lvcc;
- read_lock(&vcc_sklist_lock);
- lvcc = lanai->vccs[vci];
- if (unlikely(lvcc == NULL)) {
- read_unlock(&vcc_sklist_lock);
- DPRINTK("(itf %d) got service entry 0x%X for nonexistent "
- "vcc %d\n", lanai->number, (unsigned int) s, vci);
- if (s & SERVICE_TX)
- lanai->stats.service_notx++;
- else
- lanai->stats.service_norx++;
- return 0;
- }
- if (s & SERVICE_TX) { /* segmentation interrupt */
- if (unlikely(lvcc->tx.atmvcc == NULL)) {
- read_unlock(&vcc_sklist_lock);
- DPRINTK("(itf %d) got service entry 0x%X for non-TX "
- "vcc %d\n", lanai->number, (unsigned int) s, vci);
- lanai->stats.service_notx++;
- return 0;
- }
- __set_bit(vci, lanai->transmit_ready);
- lvcc->tx.endptr = SERVICE_GET_END(s);
- read_unlock(&vcc_sklist_lock);
- return 1;
- }
- if (unlikely(lvcc->rx.atmvcc == NULL)) {
- read_unlock(&vcc_sklist_lock);
- DPRINTK("(itf %d) got service entry 0x%X for non-RX "
- "vcc %d\n", lanai->number, (unsigned int) s, vci);
- lanai->stats.service_norx++;
- return 0;
- }
- if (unlikely(lvcc->rx.atmvcc->qos.aal != ATM_AAL5)) {
- read_unlock(&vcc_sklist_lock);
- DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "
- "vcc %d\n", lanai->number, (unsigned int) s, vci);
- lanai->stats.service_rxnotaal5++;
- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
- return 0;
- }
- if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) {
- vcc_rx_aal5(lvcc, SERVICE_GET_END(s));
- read_unlock(&vcc_sklist_lock);
- return 0;
- }
- if (s & SERVICE_TRASH) {
- int bytes;
- read_unlock(&vcc_sklist_lock);
- DPRINTK("got trashed rx pdu on vci %d\n", vci);
- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
- lvcc->stats.x.aal5.service_trash++;
- bytes = (SERVICE_GET_END(s) * 16) -
- (((unsigned long) lvcc->rx.buf.ptr) -
- ((unsigned long) lvcc->rx.buf.start)) + 47;
- if (bytes < 0)
- bytes += lanai_buf_size(&lvcc->rx.buf);
- lanai->stats.ovfl_trash += (bytes / 48);
- return 0;
- }
- if (s & SERVICE_STREAM) {
- read_unlock(&vcc_sklist_lock);
- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
- lvcc->stats.x.aal5.service_stream++;
- printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "
- "PDU on VCI %d!\n", lanai->number, vci);
- lanai_reset(lanai);
- return 0;
- }
- DPRINTK("got rx crc error on vci %d\n", vci);
- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
- lvcc->stats.x.aal5.service_rxcrc++;
- lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];
- cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);
- read_unlock(&vcc_sklist_lock);
- return 0;
-}
-
-/* Try transmitting on all VCIs that we marked ready to serve */
-static void iter_transmit(struct lanai_dev *lanai, vci_t vci)
-{
- struct lanai_vcc *lvcc = lanai->vccs[vci];
- if (vcc_is_backlogged(lvcc))
- lvcc->tx.unqueue(lanai, lvcc, lvcc->tx.endptr);
-}
-
-/* Run service queue -- called from interrupt context or with
- * interrupts otherwise disabled and with the lanai->servicelock
- * lock held
- */
-static void run_service(struct lanai_dev *lanai)
-{
- int ntx = 0;
- u32 wreg = reg_read(lanai, ServWrite_Reg);
- const u32 *end = lanai->service.start + wreg;
- while (lanai->service.ptr != end) {
- ntx += handle_service(lanai,
- le32_to_cpup(lanai->service.ptr++));
- if (lanai->service.ptr >= lanai->service.end)
- lanai->service.ptr = lanai->service.start;
- }
- reg_write(lanai, wreg, ServRead_Reg);
- if (ntx != 0) {
- read_lock(&vcc_sklist_lock);
- vci_bitfield_iterate(lanai, lanai->transmit_ready,
- iter_transmit);
- bitmap_zero(lanai->transmit_ready, NUM_VCI);
- read_unlock(&vcc_sklist_lock);
- }
-}
-
-/* -------------------- GATHER STATISTICS: */
-
-static void get_statistics(struct lanai_dev *lanai)
-{
- u32 statreg = reg_read(lanai, Statistics_Reg);
- lanai->stats.atm_ovfl += STATS_GET_FIFO_OVFL(statreg);
- lanai->stats.hec_err += STATS_GET_HEC_ERR(statreg);
- lanai->stats.vci_trash += STATS_GET_BAD_VCI(statreg);
- lanai->stats.ovfl_trash += STATS_GET_BUF_OVFL(statreg);
-}
-
-/* -------------------- POLLING TIMER: */
-
-#ifndef DEBUG_RW
-/* Try to undequeue 1 backlogged vcc */
-static void iter_dequeue(struct lanai_dev *lanai, vci_t vci)
-{
- struct lanai_vcc *lvcc = lanai->vccs[vci];
- int endptr;
- if (lvcc == NULL || lvcc->tx.atmvcc == NULL ||
- !vcc_is_backlogged(lvcc)) {
- __clear_bit(vci, lanai->backlog_vccs);
- return;
- }
- endptr = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr));
- lvcc->tx.unqueue(lanai, lvcc, endptr);
-}
-#endif /* !DEBUG_RW */
-
-static void lanai_timed_poll(struct timer_list *t)
-{
- struct lanai_dev *lanai = timer_container_of(lanai, t, timer);
-#ifndef DEBUG_RW
- unsigned long flags;
-#ifdef USE_POWERDOWN
- if (lanai->conf1 & CONFIG1_POWERDOWN)
- return;
-#endif /* USE_POWERDOWN */
- local_irq_save(flags);
- /* If we can grab the spinlock, check if any services need to be run */
- if (spin_trylock(&lanai->servicelock)) {
- run_service(lanai);
- spin_unlock(&lanai->servicelock);
- }
- /* ...and see if any backlogged VCs can make progress */
- /* unfortunately linux has no read_trylock() currently */
- read_lock(&vcc_sklist_lock);
- vci_bitfield_iterate(lanai, lanai->backlog_vccs, iter_dequeue);
- read_unlock(&vcc_sklist_lock);
- local_irq_restore(flags);
-
- get_statistics(lanai);
-#endif /* !DEBUG_RW */
- mod_timer(&lanai->timer, jiffies + LANAI_POLL_PERIOD);
-}
-
-static inline void lanai_timed_poll_start(struct lanai_dev *lanai)
-{
- timer_setup(&lanai->timer, lanai_timed_poll, 0);
- lanai->timer.expires = jiffies + LANAI_POLL_PERIOD;
- add_timer(&lanai->timer);
-}
-
-static inline void lanai_timed_poll_stop(struct lanai_dev *lanai)
-{
- timer_delete_sync(&lanai->timer);
-}
-
-/* -------------------- INTERRUPT SERVICE: */
-
-static inline void lanai_int_1(struct lanai_dev *lanai, u32 reason)
-{
- u32 ack = 0;
- if (reason & INT_SERVICE) {
- ack = INT_SERVICE;
- spin_lock(&lanai->servicelock);
- run_service(lanai);
- spin_unlock(&lanai->servicelock);
- }
- if (reason & (INT_AAL0_STR | INT_AAL0)) {
- ack |= reason & (INT_AAL0_STR | INT_AAL0);
- vcc_rx_aal0(lanai);
- }
- /* The rest of the interrupts are pretty rare */
- if (ack == reason)
- goto done;
- if (reason & INT_STATS) {
- reason &= ~INT_STATS; /* No need to ack */
- get_statistics(lanai);
- }
- if (reason & INT_STATUS) {
- ack |= reason & INT_STATUS;
- lanai_check_status(lanai);
- }
- if (unlikely(reason & INT_DMASHUT)) {
- printk(KERN_ERR DEV_LABEL "(itf %d): driver error - DMA "
- "shutdown, reason=0x%08X, address=0x%08X\n",
- lanai->number, (unsigned int) (reason & INT_DMASHUT),
- (unsigned int) reg_read(lanai, DMA_Addr_Reg));
- if (reason & INT_TABORTBM) {
- lanai_reset(lanai);
- return;
- }
- ack |= (reason & INT_DMASHUT);
- printk(KERN_ERR DEV_LABEL "(itf %d): re-enabling DMA\n",
- lanai->number);
- conf1_write(lanai);
- lanai->stats.dma_reenable++;
- pcistatus_check(lanai, 0);
- }
- if (unlikely(reason & INT_TABORTSENT)) {
- ack |= (reason & INT_TABORTSENT);
- printk(KERN_ERR DEV_LABEL "(itf %d): sent PCI target abort\n",
- lanai->number);
- pcistatus_check(lanai, 0);
- }
- if (unlikely(reason & INT_SEGSHUT)) {
- printk(KERN_ERR DEV_LABEL "(itf %d): driver error - "
- "segmentation shutdown, reason=0x%08X\n", lanai->number,
- (unsigned int) (reason & INT_SEGSHUT));
- lanai_reset(lanai);
- return;
- }
- if (unlikely(reason & (INT_PING | INT_WAKE))) {
- printk(KERN_ERR DEV_LABEL "(itf %d): driver error - "
- "unexpected interrupt 0x%08X, resetting\n",
- lanai->number,
- (unsigned int) (reason & (INT_PING | INT_WAKE)));
- lanai_reset(lanai);
- return;
- }
-#ifdef DEBUG
- if (unlikely(ack != reason)) {
- DPRINTK("unacked ints: 0x%08X\n",
- (unsigned int) (reason & ~ack));
- ack = reason;
- }
-#endif
- done:
- if (ack != 0)
- reg_write(lanai, ack, IntAck_Reg);
-}
-
-static irqreturn_t lanai_int(int irq, void *devid)
-{
- struct lanai_dev *lanai = devid;
- u32 reason;
-
-#ifdef USE_POWERDOWN
- /*
- * If we're powered down we shouldn't be generating any interrupts -
- * so assume that this is a shared interrupt line and it's for someone
- * else
- */
- if (unlikely(lanai->conf1 & CONFIG1_POWERDOWN))
- return IRQ_NONE;
-#endif
-
- reason = intr_pending(lanai);
- if (reason == 0)
- return IRQ_NONE; /* Must be for someone else */
-
- do {
- if (unlikely(reason == 0xFFFFFFFF))
- break; /* Maybe we've been unplugged? */
- lanai_int_1(lanai, reason);
- reason = intr_pending(lanai);
- } while (reason != 0);
-
- return IRQ_HANDLED;
-}
-
-/* TODO - it would be nice if we could use the "delayed interrupt" system
- * to some advantage
- */
-
-/* -------------------- CHECK BOARD ID/REV: */
-
-/*
- * The board id and revision are stored both in the reset register and
- * in the PCI configuration space - the documentation says to check
- * each of them. If revp!=NULL we store the revision there
- */
-static int check_board_id_and_rev(const char *name, u32 val, int *revp)
-{
- DPRINTK("%s says board_id=%d, board_rev=%d\n", name,
- (int) RESET_GET_BOARD_ID(val),
- (int) RESET_GET_BOARD_REV(val));
- if (RESET_GET_BOARD_ID(val) != BOARD_ID_LANAI256) {
- printk(KERN_ERR DEV_LABEL ": Found %s board-id %d -- not a "
- "Lanai 25.6\n", name, (int) RESET_GET_BOARD_ID(val));
- return -ENODEV;
- }
- if (revp != NULL)
- *revp = RESET_GET_BOARD_REV(val);
- return 0;
-}
-
-/* -------------------- PCI INITIALIZATION/SHUTDOWN: */
-
-static int lanai_pci_start(struct lanai_dev *lanai)
-{
- struct pci_dev *pci = lanai->pci;
- int result;
-
- if (pci_enable_device(pci) != 0) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't enable "
- "PCI device", lanai->number);
- return -ENXIO;
- }
- pci_set_master(pci);
- if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32)) != 0) {
- printk(KERN_WARNING DEV_LABEL
- "(itf %d): No suitable DMA available.\n", lanai->number);
- return -EBUSY;
- }
- result = check_board_id_and_rev("PCI", pci->subsystem_device, NULL);
- if (result != 0)
- return result;
- /* Set latency timer to zero as per lanai docs */
- result = pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0);
- if (result != PCIBIOS_SUCCESSFUL) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't write "
- "PCI_LATENCY_TIMER: %d\n", lanai->number, result);
- return -EINVAL;
- }
- pcistatus_check(lanai, 1);
- pcistatus_check(lanai, 0);
- return 0;
-}
-
-/* -------------------- VPI/VCI ALLOCATION: */
-
-/*
- * We _can_ use VCI==0 for normal traffic, but only for UBR (or we'll
- * get a CBRZERO interrupt), and we can use it only if no one is receiving
- * AAL0 traffic (since they will use the same queue) - according to the
- * docs we shouldn't even use it for AAL0 traffic
- */
-static inline int vci0_is_ok(struct lanai_dev *lanai,
- const struct atm_qos *qos)
-{
- if (qos->txtp.traffic_class == ATM_CBR || qos->aal == ATM_AAL0)
- return 0;
- if (qos->rxtp.traffic_class != ATM_NONE) {
- if (lanai->naal0 != 0)
- return 0;
- lanai->conf2 |= CONFIG2_VCI0_NORMAL;
- conf2_write_if_powerup(lanai);
- }
- return 1;
-}
-
-/* return true if vci is currently unused, or if requested qos is
- * compatible
- */
-static int vci_is_ok(struct lanai_dev *lanai, vci_t vci,
- const struct atm_vcc *atmvcc)
-{
- const struct atm_qos *qos = &atmvcc->qos;
- const struct lanai_vcc *lvcc = lanai->vccs[vci];
- if (vci == 0 && !vci0_is_ok(lanai, qos))
- return 0;
- if (unlikely(lvcc != NULL)) {
- if (qos->rxtp.traffic_class != ATM_NONE &&
- lvcc->rx.atmvcc != NULL && lvcc->rx.atmvcc != atmvcc)
- return 0;
- if (qos->txtp.traffic_class != ATM_NONE &&
- lvcc->tx.atmvcc != NULL && lvcc->tx.atmvcc != atmvcc)
- return 0;
- if (qos->txtp.traffic_class == ATM_CBR &&
- lanai->cbrvcc != NULL && lanai->cbrvcc != atmvcc)
- return 0;
- }
- if (qos->aal == ATM_AAL0 && lanai->naal0 == 0 &&
- qos->rxtp.traffic_class != ATM_NONE) {
- const struct lanai_vcc *vci0 = lanai->vccs[0];
- if (vci0 != NULL && vci0->rx.atmvcc != NULL)
- return 0;
- lanai->conf2 &= ~CONFIG2_VCI0_NORMAL;
- conf2_write_if_powerup(lanai);
- }
- return 1;
-}
-
-static int lanai_normalize_ci(struct lanai_dev *lanai,
- const struct atm_vcc *atmvcc, short *vpip, vci_t *vcip)
-{
- switch (*vpip) {
- case ATM_VPI_ANY:
- *vpip = 0;
- fallthrough;
- case 0:
- break;
- default:
- return -EADDRINUSE;
- }
- switch (*vcip) {
- case ATM_VCI_ANY:
- for (*vcip = ATM_NOT_RSV_VCI; *vcip < lanai->num_vci;
- (*vcip)++)
- if (vci_is_ok(lanai, *vcip, atmvcc))
- return 0;
- return -EADDRINUSE;
- default:
- if (*vcip >= lanai->num_vci || *vcip < 0 ||
- !vci_is_ok(lanai, *vcip, atmvcc))
- return -EADDRINUSE;
- }
- return 0;
-}
-
-/* -------------------- MANAGE CBR: */
-
-/*
- * CBR ICG is stored as a fixed-point number with 4 fractional bits.
- * Note that storing a number greater than 2046.0 will result in
- * incorrect shaping
- */
-#define CBRICG_FRAC_BITS (4)
-#define CBRICG_MAX (2046 << CBRICG_FRAC_BITS)
-
-/*
- * ICG is related to PCR with the formula PCR = MAXPCR / (ICG + 1)
- * where MAXPCR is (according to the docs) 25600000/(54*8),
- * which is equal to (3125<<9)/27.
- *
- * Solving for ICG, we get:
- * ICG = MAXPCR/PCR - 1
- * ICG = (3125<<9)/(27*PCR) - 1
- * ICG = ((3125<<9) - (27*PCR)) / (27*PCR)
- *
- * The end result is supposed to be a fixed-point number with FRAC_BITS
- * bits of a fractional part, so we keep everything in the numerator
- * shifted by that much as we compute
- *
- */
-static int pcr_to_cbricg(const struct atm_qos *qos)
-{
- int rounddown = 0; /* 1 = Round PCR down, i.e. round ICG _up_ */
- int x, icg, pcr = atm_pcr_goal(&qos->txtp);
- if (pcr == 0) /* Use maximum bandwidth */
- return 0;
- if (pcr < 0) {
- rounddown = 1;
- pcr = -pcr;
- }
- x = pcr * 27;
- icg = (3125 << (9 + CBRICG_FRAC_BITS)) - (x << CBRICG_FRAC_BITS);
- if (rounddown)
- icg += x - 1;
- icg /= x;
- if (icg > CBRICG_MAX)
- icg = CBRICG_MAX;
- DPRINTK("pcr_to_cbricg: pcr=%d rounddown=%c icg=%d\n",
- pcr, rounddown ? 'Y' : 'N', icg);
- return icg;
-}
-
-static inline void lanai_cbr_setup(struct lanai_dev *lanai)
-{
- reg_write(lanai, pcr_to_cbricg(&lanai->cbrvcc->qos), CBR_ICG_Reg);
- reg_write(lanai, lanai->cbrvcc->vci, CBR_PTR_Reg);
- lanai->conf2 |= CONFIG2_CBR_ENABLE;
- conf2_write(lanai);
-}
-
-static inline void lanai_cbr_shutdown(struct lanai_dev *lanai)
-{
- lanai->conf2 &= ~CONFIG2_CBR_ENABLE;
- conf2_write(lanai);
-}
-
-/* -------------------- OPERATIONS: */
-
-/* setup a newly detected device */
-static int lanai_dev_open(struct atm_dev *atmdev)
-{
- struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
- unsigned long raw_base;
- int result;
-
- DPRINTK("In lanai_dev_open()\n");
- /* Basic device fields */
- lanai->number = atmdev->number;
- lanai->num_vci = NUM_VCI;
- bitmap_zero(lanai->backlog_vccs, NUM_VCI);
- bitmap_zero(lanai->transmit_ready, NUM_VCI);
- lanai->naal0 = 0;
-#ifdef USE_POWERDOWN
- lanai->nbound = 0;
-#endif
- lanai->cbrvcc = NULL;
- memset(&lanai->stats, 0, sizeof lanai->stats);
- spin_lock_init(&lanai->endtxlock);
- spin_lock_init(&lanai->servicelock);
- atmdev->ci_range.vpi_bits = 0;
- atmdev->ci_range.vci_bits = 0;
- while (1 << atmdev->ci_range.vci_bits < lanai->num_vci)
- atmdev->ci_range.vci_bits++;
- atmdev->link_rate = ATM_25_PCR;
-
- /* 3.2: PCI initialization */
- if ((result = lanai_pci_start(lanai)) != 0)
- goto error;
- raw_base = lanai->pci->resource[0].start;
- lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE);
- if (lanai->base == NULL) {
- printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n");
- result = -ENOMEM;
- goto error_pci;
- }
- /* 3.3: Reset lanai and PHY */
- reset_board(lanai);
- lanai->conf1 = reg_read(lanai, Config1_Reg);
- lanai->conf1 &= ~(CONFIG1_GPOUT1 | CONFIG1_POWERDOWN |
- CONFIG1_MASK_LEDMODE);
- lanai->conf1 |= CONFIG1_SET_LEDMODE(LEDMODE_NOT_SOOL);
- reg_write(lanai, lanai->conf1 | CONFIG1_GPOUT1, Config1_Reg);
- udelay(1000);
- conf1_write(lanai);
-
- /*
- * 3.4: Turn on endian mode for big-endian hardware
- * We don't actually want to do this - the actual bit fields
- * in the endian register are not documented anywhere.
- * Instead we do the bit-flipping ourselves on big-endian
- * hardware.
- *
- * 3.5: get the board ID/rev by reading the reset register
- */
- result = check_board_id_and_rev("register",
- reg_read(lanai, Reset_Reg), &lanai->board_rev);
- if (result != 0)
- goto error_unmap;
-
- /* 3.6: read EEPROM */
- if ((result = eeprom_read(lanai)) != 0)
- goto error_unmap;
- if ((result = eeprom_validate(lanai)) != 0)
- goto error_unmap;
-
- /* 3.7: re-reset PHY, do loopback tests, setup PHY */
- reg_write(lanai, lanai->conf1 | CONFIG1_GPOUT1, Config1_Reg);
- udelay(1000);
- conf1_write(lanai);
- /* TODO - loopback tests */
- lanai->conf1 |= (CONFIG1_GPOUT2 | CONFIG1_GPOUT3 | CONFIG1_DMA_ENABLE);
- conf1_write(lanai);
-
- /* 3.8/3.9: test and initialize card SRAM */
- if ((result = sram_test_and_clear(lanai)) != 0)
- goto error_unmap;
-
- /* 3.10: initialize lanai registers */
- lanai->conf1 |= CONFIG1_DMA_ENABLE;
- conf1_write(lanai);
- if ((result = service_buffer_allocate(lanai)) != 0)
- goto error_unmap;
- if ((result = vcc_table_allocate(lanai)) != 0)
- goto error_service;
- lanai->conf2 = (lanai->num_vci >= 512 ? CONFIG2_HOWMANY : 0) |
- CONFIG2_HEC_DROP | /* ??? */ CONFIG2_PTI7_MODE;
- conf2_write(lanai);
- reg_write(lanai, TX_FIFO_DEPTH, TxDepth_Reg);
- reg_write(lanai, 0, CBR_ICG_Reg); /* CBR defaults to no limit */
- if ((result = request_irq(lanai->pci->irq, lanai_int, IRQF_SHARED,
- DEV_LABEL, lanai)) != 0) {
- printk(KERN_ERR DEV_LABEL ": can't allocate interrupt\n");
- goto error_vcctable;
- }
- mb(); /* Make sure that all that made it */
- intr_enable(lanai, INT_ALL & ~(INT_PING | INT_WAKE));
- /* 3.11: initialize loop mode (i.e. turn looping off) */
- lanai->conf1 = (lanai->conf1 & ~CONFIG1_MASK_LOOPMODE) |
- CONFIG1_SET_LOOPMODE(LOOPMODE_NORMAL) |
- CONFIG1_GPOUT2 | CONFIG1_GPOUT3;
- conf1_write(lanai);
- lanai->status = reg_read(lanai, Status_Reg);
- /* We're now done initializing this card */
-#ifdef USE_POWERDOWN
- lanai->conf1 |= CONFIG1_POWERDOWN;
- conf1_write(lanai);
-#endif
- memcpy(atmdev->esi, eeprom_mac(lanai), ESI_LEN);
- lanai_timed_poll_start(lanai);
- printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=%p, irq=%u "
- "(%pMF)\n", lanai->number, (int) lanai->pci->revision,
- lanai->base, lanai->pci->irq, atmdev->esi);
- printk(KERN_NOTICE DEV_LABEL "(itf %d): LANAI%s, serialno=%u(0x%X), "
- "board_rev=%d\n", lanai->number,
- lanai->type==lanai2 ? "2" : "HB", (unsigned int) lanai->serialno,
- (unsigned int) lanai->serialno, lanai->board_rev);
- return 0;
-
- error_vcctable:
- vcc_table_deallocate(lanai);
- error_service:
- service_buffer_deallocate(lanai);
- error_unmap:
- reset_board(lanai);
-#ifdef USE_POWERDOWN
- lanai->conf1 = reg_read(lanai, Config1_Reg) | CONFIG1_POWERDOWN;
- conf1_write(lanai);
-#endif
- iounmap(lanai->base);
- lanai->base = NULL;
- error_pci:
- pci_disable_device(lanai->pci);
- error:
- return result;
-}
-
-/* called when device is being shutdown, and all vcc's are gone - higher
- * levels will deallocate the atm device for us
- */
-static void lanai_dev_close(struct atm_dev *atmdev)
-{
- struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
- if (lanai->base==NULL)
- return;
- printk(KERN_INFO DEV_LABEL "(itf %d): shutting down interface\n",
- lanai->number);
- lanai_timed_poll_stop(lanai);
-#ifdef USE_POWERDOWN
- lanai->conf1 = reg_read(lanai, Config1_Reg) & ~CONFIG1_POWERDOWN;
- conf1_write(lanai);
-#endif
- intr_disable(lanai, INT_ALL);
- free_irq(lanai->pci->irq, lanai);
- reset_board(lanai);
-#ifdef USE_POWERDOWN
- lanai->conf1 |= CONFIG1_POWERDOWN;
- conf1_write(lanai);
-#endif
- pci_disable_device(lanai->pci);
- vcc_table_deallocate(lanai);
- service_buffer_deallocate(lanai);
- iounmap(lanai->base);
- kfree(lanai);
-}
-
-/* close a vcc */
-static void lanai_close(struct atm_vcc *atmvcc)
-{
- struct lanai_vcc *lvcc = (struct lanai_vcc *) atmvcc->dev_data;
- struct lanai_dev *lanai = (struct lanai_dev *) atmvcc->dev->dev_data;
- if (lvcc == NULL)
- return;
- clear_bit(ATM_VF_READY, &atmvcc->flags);
- clear_bit(ATM_VF_PARTIAL, &atmvcc->flags);
- if (lvcc->rx.atmvcc == atmvcc) {
- lanai_shutdown_rx_vci(lvcc);
- if (atmvcc->qos.aal == ATM_AAL0) {
- if (--lanai->naal0 <= 0)
- aal0_buffer_free(lanai);
- } else
- lanai_buf_deallocate(&lvcc->rx.buf, lanai->pci);
- lvcc->rx.atmvcc = NULL;
- }
- if (lvcc->tx.atmvcc == atmvcc) {
- if (atmvcc == lanai->cbrvcc) {
- if (lvcc->vbase != NULL)
- lanai_cbr_shutdown(lanai);
- lanai->cbrvcc = NULL;
- }
- lanai_shutdown_tx_vci(lanai, lvcc);
- lanai_buf_deallocate(&lvcc->tx.buf, lanai->pci);
- lvcc->tx.atmvcc = NULL;
- }
- if (--lvcc->nref == 0) {
- host_vcc_unbind(lanai, lvcc);
- kfree(lvcc);
- }
- atmvcc->dev_data = NULL;
- clear_bit(ATM_VF_ADDR, &atmvcc->flags);
-}
-
-/* open a vcc on the card to vpi/vci */
-static int lanai_open(struct atm_vcc *atmvcc)
-{
- struct lanai_dev *lanai;
- struct lanai_vcc *lvcc;
- int result = 0;
- int vci = atmvcc->vci;
- short vpi = atmvcc->vpi;
- /* we don't support partial open - it's not really useful anyway */
- if ((test_bit(ATM_VF_PARTIAL, &atmvcc->flags)) ||
- (vpi == ATM_VPI_UNSPEC) || (vci == ATM_VCI_UNSPEC))
- return -EINVAL;
- lanai = (struct lanai_dev *) atmvcc->dev->dev_data;
- result = lanai_normalize_ci(lanai, atmvcc, &vpi, &vci);
- if (unlikely(result != 0))
- goto out;
- set_bit(ATM_VF_ADDR, &atmvcc->flags);
- if (atmvcc->qos.aal != ATM_AAL0 && atmvcc->qos.aal != ATM_AAL5)
- return -EINVAL;
- DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n", lanai->number,
- (int) vpi, vci);
- lvcc = lanai->vccs[vci];
- if (lvcc == NULL) {
- lvcc = new_lanai_vcc();
- if (unlikely(lvcc == NULL))
- return -ENOMEM;
- atmvcc->dev_data = lvcc;
- }
- lvcc->nref++;
- if (atmvcc->qos.rxtp.traffic_class != ATM_NONE) {
- APRINTK(lvcc->rx.atmvcc == NULL, "rx.atmvcc!=NULL, vci=%d\n",
- vci);
- if (atmvcc->qos.aal == ATM_AAL0) {
- if (lanai->naal0 == 0)
- result = aal0_buffer_allocate(lanai);
- } else
- result = lanai_setup_rx_vci_aal5(
- lanai, lvcc, &atmvcc->qos);
- if (unlikely(result != 0))
- goto out_free;
- lvcc->rx.atmvcc = atmvcc;
- lvcc->stats.rx_nomem = 0;
- lvcc->stats.x.aal5.rx_badlen = 0;
- lvcc->stats.x.aal5.service_trash = 0;
- lvcc->stats.x.aal5.service_stream = 0;
- lvcc->stats.x.aal5.service_rxcrc = 0;
- if (atmvcc->qos.aal == ATM_AAL0)
- lanai->naal0++;
- }
- if (atmvcc->qos.txtp.traffic_class != ATM_NONE) {
- APRINTK(lvcc->tx.atmvcc == NULL, "tx.atmvcc!=NULL, vci=%d\n",
- vci);
- result = lanai_setup_tx_vci(lanai, lvcc, &atmvcc->qos);
- if (unlikely(result != 0))
- goto out_free;
- lvcc->tx.atmvcc = atmvcc;
- if (atmvcc->qos.txtp.traffic_class == ATM_CBR) {
- APRINTK(lanai->cbrvcc == NULL,
- "cbrvcc!=NULL, vci=%d\n", vci);
- lanai->cbrvcc = atmvcc;
- }
- }
- host_vcc_bind(lanai, lvcc, vci);
- /*
- * Make sure everything made it to RAM before we tell the card about
- * the VCC
- */
- wmb();
- if (atmvcc == lvcc->rx.atmvcc)
- host_vcc_start_rx(lvcc);
- if (atmvcc == lvcc->tx.atmvcc) {
- host_vcc_start_tx(lvcc);
- if (lanai->cbrvcc == atmvcc)
- lanai_cbr_setup(lanai);
- }
- set_bit(ATM_VF_READY, &atmvcc->flags);
- return 0;
- out_free:
- lanai_close(atmvcc);
- out:
- return result;
-}
-
-static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb)
-{
- struct lanai_vcc *lvcc = (struct lanai_vcc *) atmvcc->dev_data;
- struct lanai_dev *lanai = (struct lanai_dev *) atmvcc->dev->dev_data;
- unsigned long flags;
- if (unlikely(lvcc == NULL || lvcc->vbase == NULL ||
- lvcc->tx.atmvcc != atmvcc))
- goto einval;
-#ifdef DEBUG
- if (unlikely(skb == NULL)) {
- DPRINTK("lanai_send: skb==NULL for vci=%d\n", atmvcc->vci);
- goto einval;
- }
- if (unlikely(lanai == NULL)) {
- DPRINTK("lanai_send: lanai==NULL for vci=%d\n", atmvcc->vci);
- goto einval;
- }
-#endif
- ATM_SKB(skb)->vcc = atmvcc;
- switch (atmvcc->qos.aal) {
- case ATM_AAL5:
- read_lock_irqsave(&vcc_sklist_lock, flags);
- vcc_tx_aal5(lanai, lvcc, skb);
- read_unlock_irqrestore(&vcc_sklist_lock, flags);
- return 0;
- case ATM_AAL0:
- if (unlikely(skb->len != ATM_CELL_SIZE-1))
- goto einval;
- /* NOTE - this next line is technically invalid - we haven't unshared skb */
- cpu_to_be32s((u32 *) skb->data);
- read_lock_irqsave(&vcc_sklist_lock, flags);
- vcc_tx_aal0(lanai, lvcc, skb);
- read_unlock_irqrestore(&vcc_sklist_lock, flags);
- return 0;
- }
- DPRINTK("lanai_send: bad aal=%d on vci=%d\n", (int) atmvcc->qos.aal,
- atmvcc->vci);
- einval:
- lanai_free_skb(atmvcc, skb);
- return -EINVAL;
-}
-
-static int lanai_change_qos(struct atm_vcc *atmvcc,
- /*const*/ struct atm_qos *qos, int flags)
-{
- return -EBUSY; /* TODO: need to write this */
-}
-
-#ifndef CONFIG_PROC_FS
-#define lanai_proc_read NULL
-#else
-static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page)
-{
- struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
- loff_t left = *pos;
- struct lanai_vcc *lvcc;
- if (left-- == 0)
- return sprintf(page, DEV_LABEL "(itf %d): chip=LANAI%s, "
- "serial=%u, magic=0x%08X, num_vci=%d\n",
- atmdev->number, lanai->type==lanai2 ? "2" : "HB",
- (unsigned int) lanai->serialno,
- (unsigned int) lanai->magicno, lanai->num_vci);
- if (left-- == 0)
- return sprintf(page, "revision: board=%d, pci_if=%d\n",
- lanai->board_rev, (int) lanai->pci->revision);
- if (left-- == 0)
- return sprintf(page, "EEPROM ESI: %pM\n",
- &lanai->eeprom[EEPROM_MAC]);
- if (left-- == 0)
- return sprintf(page, "status: SOOL=%d, LOCD=%d, LED=%d, "
- "GPIN=%d\n", (lanai->status & STATUS_SOOL) ? 1 : 0,
- (lanai->status & STATUS_LOCD) ? 1 : 0,
- (lanai->status & STATUS_LED) ? 1 : 0,
- (lanai->status & STATUS_GPIN) ? 1 : 0);
- if (left-- == 0)
- return sprintf(page, "global buffer sizes: service=%zu, "
- "aal0_rx=%zu\n", lanai_buf_size(&lanai->service),
- lanai->naal0 ? lanai_buf_size(&lanai->aal0buf) : 0);
- if (left-- == 0) {
- get_statistics(lanai);
- return sprintf(page, "cells in error: overflow=%u, "
- "closed_vci=%u, bad_HEC=%u, rx_fifo=%u\n",
- lanai->stats.ovfl_trash, lanai->stats.vci_trash,
- lanai->stats.hec_err, lanai->stats.atm_ovfl);
- }
- if (left-- == 0)
- return sprintf(page, "PCI errors: parity_detect=%u, "
- "master_abort=%u, master_target_abort=%u,\n",
- lanai->stats.pcierr_parity_detect,
- lanai->stats.pcierr_serr_set,
- lanai->stats.pcierr_m_target_abort);
- if (left-- == 0)
- return sprintf(page, " slave_target_abort=%u, "
- "master_parity=%u\n", lanai->stats.pcierr_s_target_abort,
- lanai->stats.pcierr_master_parity);
- if (left-- == 0)
- return sprintf(page, " no_tx=%u, "
- "no_rx=%u, bad_rx_aal=%u\n", lanai->stats.service_norx,
- lanai->stats.service_notx,
- lanai->stats.service_rxnotaal5);
- if (left-- == 0)
- return sprintf(page, "resets: dma=%u, card=%u\n",
- lanai->stats.dma_reenable, lanai->stats.card_reset);
- /* At this point, "left" should be the VCI we're looking for */
- read_lock(&vcc_sklist_lock);
- for (; ; left++) {
- if (left >= NUM_VCI) {
- left = 0;
- goto out;
- }
- if ((lvcc = lanai->vccs[left]) != NULL)
- break;
- (*pos)++;
- }
- /* Note that we re-use "left" here since we're done with it */
- left = sprintf(page, "VCI %4d: nref=%d, rx_nomem=%u", (vci_t) left,
- lvcc->nref, lvcc->stats.rx_nomem);
- if (lvcc->rx.atmvcc != NULL) {
- left += sprintf(&page[left], ",\n rx_AAL=%d",
- lvcc->rx.atmvcc->qos.aal == ATM_AAL5 ? 5 : 0);
- if (lvcc->rx.atmvcc->qos.aal == ATM_AAL5)
- left += sprintf(&page[left], ", rx_buf_size=%zu, "
- "rx_bad_len=%u,\n rx_service_trash=%u, "
- "rx_service_stream=%u, rx_bad_crc=%u",
- lanai_buf_size(&lvcc->rx.buf),
- lvcc->stats.x.aal5.rx_badlen,
- lvcc->stats.x.aal5.service_trash,
- lvcc->stats.x.aal5.service_stream,
- lvcc->stats.x.aal5.service_rxcrc);
- }
- if (lvcc->tx.atmvcc != NULL)
- left += sprintf(&page[left], ",\n tx_AAL=%d, "
- "tx_buf_size=%zu, tx_qos=%cBR, tx_backlogged=%c",
- lvcc->tx.atmvcc->qos.aal == ATM_AAL5 ? 5 : 0,
- lanai_buf_size(&lvcc->tx.buf),
- lvcc->tx.atmvcc == lanai->cbrvcc ? 'C' : 'U',
- vcc_is_backlogged(lvcc) ? 'Y' : 'N');
- page[left++] = '\n';
- page[left] = '\0';
- out:
- read_unlock(&vcc_sklist_lock);
- return left;
-}
-#endif /* CONFIG_PROC_FS */
-
-/* -------------------- HOOKS: */
-
-static const struct atmdev_ops ops = {
- .dev_close = lanai_dev_close,
- .open = lanai_open,
- .close = lanai_close,
- .send = lanai_send,
- .phy_put = NULL,
- .phy_get = NULL,
- .change_qos = lanai_change_qos,
- .proc_read = lanai_proc_read,
- .owner = THIS_MODULE
-};
-
-/* initialize one probed card */
-static int lanai_init_one(struct pci_dev *pci,
- const struct pci_device_id *ident)
-{
- struct lanai_dev *lanai;
- struct atm_dev *atmdev;
- int result;
-
- lanai = kzalloc_obj(*lanai);
- if (lanai == NULL) {
- printk(KERN_ERR DEV_LABEL
- ": couldn't allocate dev_data structure!\n");
- return -ENOMEM;
- }
-
- atmdev = atm_dev_register(DEV_LABEL, &pci->dev, &ops, -1, NULL);
- if (atmdev == NULL) {
- printk(KERN_ERR DEV_LABEL
- ": couldn't register atm device!\n");
- kfree(lanai);
- return -EBUSY;
- }
-
- atmdev->dev_data = lanai;
- lanai->pci = pci;
- lanai->type = (enum lanai_type) ident->device;
-
- result = lanai_dev_open(atmdev);
- if (result != 0) {
- DPRINTK("lanai_start() failed, err=%d\n", -result);
- atm_dev_deregister(atmdev);
- kfree(lanai);
- }
- return result;
-}
-
-static const struct pci_device_id lanai_pci_tbl[] = {
- { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAI2) },
- { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAIHB) },
- { 0, } /* terminal entry */
-};
-MODULE_DEVICE_TABLE(pci, lanai_pci_tbl);
-
-static struct pci_driver lanai_driver = {
- .name = DEV_LABEL,
- .id_table = lanai_pci_tbl,
- .probe = lanai_init_one,
-};
-
-module_pci_driver(lanai_driver);
-
-MODULE_AUTHOR("Mitchell Blank Jr <mitch@sfgoth.com>");
-MODULE_DESCRIPTION("Efficient Networks Speedstream 3010 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
deleted file mode 100644
index 24e51343df15..000000000000
--- a/drivers/atm/nicstar.c
+++ /dev/null
@@ -1,2759 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * nicstar.c
- *
- * Device driver supporting CBR for IDT 77201/77211 "NICStAR" based cards.
- *
- * IMPORTANT: The included file nicstarmac.c was NOT WRITTEN BY ME.
- * It was taken from the frle-0.22 device driver.
- * As the file doesn't have a copyright notice, in the file
- * nicstarmac.copyright I put the copyright notice from the
- * frle-0.22 device driver.
- * Some code is based on the nicstar driver by M. Welsh.
- *
- * Author: Rui Prior (rprior@inescn.pt)
- * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999
- *
- *
- * (C) INESC 1999
- */
-
-/*
- * IMPORTANT INFORMATION
- *
- * There are currently three types of spinlocks:
- *
- * 1 - Per card interrupt spinlock (to protect structures and such)
- * 2 - Per SCQ scq spinlock
- * 3 - Per card resource spinlock (to access registers, etc.)
- *
- * These must NEVER be grabbed in reverse order.
- *
- */
-
-/* Header files */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/atmdev.h>
-#include <linux/atm.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/hex.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/idr.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-#include <linux/etherdevice.h>
-#include "nicstar.h"
-#ifdef CONFIG_ATM_NICSTAR_USE_SUNI
-#include "suni.h"
-#endif /* CONFIG_ATM_NICSTAR_USE_SUNI */
-#ifdef CONFIG_ATM_NICSTAR_USE_IDT77105
-#include "idt77105.h"
-#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
-
-/* Additional code */
-
-#include "nicstarmac.c"
-
-/* Configurable parameters */
-
-#undef PHY_LOOPBACK
-#undef TX_DEBUG
-#undef RX_DEBUG
-#undef GENERAL_DEBUG
-#undef EXTRA_DEBUG
-
-/* Do not touch these */
-
-#ifdef TX_DEBUG
-#define TXPRINTK(args...) printk(args)
-#else
-#define TXPRINTK(args...)
-#endif /* TX_DEBUG */
-
-#ifdef RX_DEBUG
-#define RXPRINTK(args...) printk(args)
-#else
-#define RXPRINTK(args...)
-#endif /* RX_DEBUG */
-
-#ifdef GENERAL_DEBUG
-#define PRINTK(args...) printk(args)
-#else
-#define PRINTK(args...) do {} while (0)
-#endif /* GENERAL_DEBUG */
-
-#ifdef EXTRA_DEBUG
-#define XPRINTK(args...) printk(args)
-#else
-#define XPRINTK(args...)
-#endif /* EXTRA_DEBUG */
-
-/* Macros */
-
-#define CMD_BUSY(card) (readl((card)->membase + STAT) & NS_STAT_CMDBZ)
-
-#define NS_DELAY mdelay(1)
-
-#define PTR_DIFF(a, b) ((u32)((unsigned long)(a) - (unsigned long)(b)))
-
-#ifndef ATM_SKB
-#define ATM_SKB(s) (&(s)->atm)
-#endif
-
-#define scq_virt_to_bus(scq, p) \
- (scq->dma + ((unsigned long)(p) - (unsigned long)(scq)->org))
-
-/* Function declarations */
-
-static u32 ns_read_sram(ns_dev * card, u32 sram_address);
-static void ns_write_sram(ns_dev * card, u32 sram_address, u32 * value,
- int count);
-static int ns_init_card(int i, struct pci_dev *pcidev);
-static void ns_init_card_error(ns_dev * card, int error);
-static scq_info *get_scq(ns_dev *card, int size, u32 scd);
-static void free_scq(ns_dev *card, scq_info * scq, struct atm_vcc *vcc);
-static void push_rxbufs(ns_dev *, struct sk_buff *);
-static irqreturn_t ns_irq_handler(int irq, void *dev_id);
-static int ns_open(struct atm_vcc *vcc);
-static void ns_close(struct atm_vcc *vcc);
-static void fill_tst(ns_dev * card, int n, vc_map * vc);
-static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb);
-static int ns_send_bh(struct atm_vcc *vcc, struct sk_buff *skb);
-static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
- struct sk_buff *skb, bool may_sleep);
-static void process_tsq(ns_dev * card);
-static void drain_scq(ns_dev * card, scq_info * scq, int pos);
-static void process_rsq(ns_dev * card);
-static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe);
-static void recycle_rx_buf(ns_dev * card, struct sk_buff *skb);
-static void recycle_iovec_rx_bufs(ns_dev * card, struct iovec *iov, int count);
-static void recycle_iov_buf(ns_dev * card, struct sk_buff *iovb);
-static void dequeue_sm_buf(ns_dev * card, struct sk_buff *sb);
-static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb);
-static int ns_proc_read(struct atm_dev *dev, loff_t * pos, char *page);
-static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);
-#ifdef EXTRA_DEBUG
-static void which_list(ns_dev * card, struct sk_buff *skb);
-#endif
-static void ns_poll(struct timer_list *unused);
-static void ns_phy_put(struct atm_dev *dev, unsigned char value,
- unsigned long addr);
-static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr);
-
-/* Global variables */
-
-static struct ns_dev *cards[NS_MAX_CARDS];
-static unsigned num_cards;
-static const struct atmdev_ops atm_ops = {
- .open = ns_open,
- .close = ns_close,
- .ioctl = ns_ioctl,
- .send = ns_send,
- .send_bh = ns_send_bh,
- .phy_put = ns_phy_put,
- .phy_get = ns_phy_get,
- .proc_read = ns_proc_read,
- .owner = THIS_MODULE,
-};
-
-static struct timer_list ns_timer;
-static char *mac[NS_MAX_CARDS];
-module_param_array(mac, charp, NULL, 0);
-MODULE_DESCRIPTION("ATM NIC driver for IDT 77201/77211 \"NICStAR\" and Fore ForeRunnerLE.");
-MODULE_LICENSE("GPL");
-
-/* Functions */
-
-static int nicstar_init_one(struct pci_dev *pcidev,
- const struct pci_device_id *ent)
-{
- static int index = -1;
- unsigned int error;
-
- index++;
- cards[index] = NULL;
-
- error = ns_init_card(index, pcidev);
- if (error) {
- cards[index--] = NULL; /* don't increment index */
- goto err_out;
- }
-
- return 0;
-err_out:
- return -ENODEV;
-}
-
-static void nicstar_remove_one(struct pci_dev *pcidev)
-{
- int i, j;
- ns_dev *card = pci_get_drvdata(pcidev);
- struct sk_buff *hb;
- struct sk_buff *iovb;
- struct sk_buff *lb;
- struct sk_buff *sb;
-
- i = card->index;
-
- if (cards[i] == NULL)
- return;
-
- if (card->atmdev->phy && card->atmdev->phy->stop)
- card->atmdev->phy->stop(card->atmdev);
-
- /* Stop everything */
- writel(0x00000000, card->membase + CFG);
-
- /* De-register device */
- atm_dev_deregister(card->atmdev);
-
- /* Disable PCI device */
- pci_disable_device(pcidev);
-
- /* Free up resources */
- j = 0;
- PRINTK("nicstar%d: freeing %d huge buffers.\n", i, card->hbpool.count);
- while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) {
- dev_kfree_skb_any(hb);
- j++;
- }
- PRINTK("nicstar%d: %d huge buffers freed.\n", i, j);
- j = 0;
- PRINTK("nicstar%d: freeing %d iovec buffers.\n", i,
- card->iovpool.count);
- while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) {
- dev_kfree_skb_any(iovb);
- j++;
- }
- PRINTK("nicstar%d: %d iovec buffers freed.\n", i, j);
- while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL)
- dev_kfree_skb_any(lb);
- while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL)
- dev_kfree_skb_any(sb);
- free_scq(card, card->scq0, NULL);
- for (j = 0; j < NS_FRSCD_NUM; j++) {
- if (card->scd2vc[j] != NULL)
- free_scq(card, card->scd2vc[j]->scq, card->scd2vc[j]->tx_vcc);
- }
- idr_destroy(&card->idr);
- dma_free_coherent(&card->pcidev->dev, NS_RSQSIZE + NS_RSQ_ALIGNMENT,
- card->rsq.org, card->rsq.dma);
- dma_free_coherent(&card->pcidev->dev, NS_TSQSIZE + NS_TSQ_ALIGNMENT,
- card->tsq.org, card->tsq.dma);
- free_irq(card->pcidev->irq, card);
- iounmap(card->membase);
- kfree(card);
-}
-
-static const struct pci_device_id nicstar_pci_tbl[] = {
- { PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77201), 0 },
- {0,} /* terminate list */
-};
-
-MODULE_DEVICE_TABLE(pci, nicstar_pci_tbl);
-
-static struct pci_driver nicstar_driver = {
- .name = "nicstar",
- .id_table = nicstar_pci_tbl,
- .probe = nicstar_init_one,
- .remove = nicstar_remove_one,
-};
-
-static int __init nicstar_init(void)
-{
- unsigned error = 0; /* Initialized to remove compile warning */
-
- XPRINTK("nicstar: nicstar_init() called.\n");
-
- error = pci_register_driver(&nicstar_driver);
-
- TXPRINTK("nicstar: TX debug enabled.\n");
- RXPRINTK("nicstar: RX debug enabled.\n");
- PRINTK("nicstar: General debug enabled.\n");
-#ifdef PHY_LOOPBACK
- printk("nicstar: using PHY loopback.\n");
-#endif /* PHY_LOOPBACK */
- XPRINTK("nicstar: nicstar_init() returned.\n");
-
- if (!error) {
- timer_setup(&ns_timer, ns_poll, 0);
- ns_timer.expires = jiffies + NS_POLL_PERIOD;
- add_timer(&ns_timer);
- }
-
- return error;
-}
-
-static void __exit nicstar_cleanup(void)
-{
- XPRINTK("nicstar: nicstar_cleanup() called.\n");
-
- timer_delete_sync(&ns_timer);
-
- pci_unregister_driver(&nicstar_driver);
-
- XPRINTK("nicstar: nicstar_cleanup() returned.\n");
-}
-
-static u32 ns_read_sram(ns_dev * card, u32 sram_address)
-{
- unsigned long flags;
- u32 data;
- sram_address <<= 2;
- sram_address &= 0x0007FFFC; /* address must be dword aligned */
- sram_address |= 0x50000000; /* SRAM read command */
- spin_lock_irqsave(&card->res_lock, flags);
- while (CMD_BUSY(card)) ;
- writel(sram_address, card->membase + CMD);
- while (CMD_BUSY(card)) ;
- data = readl(card->membase + DR0);
- spin_unlock_irqrestore(&card->res_lock, flags);
- return data;
-}
-
-static void ns_write_sram(ns_dev * card, u32 sram_address, u32 * value,
- int count)
-{
- unsigned long flags;
- int i, c;
- count--; /* count range now is 0..3 instead of 1..4 */
- c = count;
- c <<= 2; /* to use increments of 4 */
- spin_lock_irqsave(&card->res_lock, flags);
- while (CMD_BUSY(card)) ;
- for (i = 0; i <= c; i += 4)
- writel(*(value++), card->membase + i);
- /* Note: DR# registers are the first 4 dwords in nicstar's memspace,
- so card->membase + DR0 == card->membase */
- sram_address <<= 2;
- sram_address &= 0x0007FFFC;
- sram_address |= (0x40000000 | count);
- writel(sram_address, card->membase + CMD);
- spin_unlock_irqrestore(&card->res_lock, flags);
-}
-
-static int ns_init_card(int i, struct pci_dev *pcidev)
-{
- int j;
- struct ns_dev *card = NULL;
- unsigned char pci_latency;
- unsigned error;
- u32 data;
- u32 u32d[4];
- u32 ns_cfg_rctsize;
- int bcount;
- unsigned long membase;
-
- error = 0;
-
- if (pci_enable_device(pcidev)) {
- printk("nicstar%d: can't enable PCI device\n", i);
- error = 2;
- ns_init_card_error(card, error);
- return error;
- }
- if (dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(32)) != 0) {
- printk(KERN_WARNING
- "nicstar%d: No suitable DMA available.\n", i);
- error = 2;
- ns_init_card_error(card, error);
- return error;
- }
-
- card = kmalloc_obj(*card);
- if (!card) {
- printk
- ("nicstar%d: can't allocate memory for device structure.\n",
- i);
- error = 2;
- ns_init_card_error(card, error);
- return error;
- }
- cards[i] = card;
- spin_lock_init(&card->int_lock);
- spin_lock_init(&card->res_lock);
-
- pci_set_drvdata(pcidev, card);
-
- card->index = i;
- card->atmdev = NULL;
- card->pcidev = pcidev;
- membase = pci_resource_start(pcidev, 1);
- card->membase = ioremap(membase, NS_IOREMAP_SIZE);
- if (!card->membase) {
- printk("nicstar%d: can't ioremap() membase.\n", i);
- error = 3;
- ns_init_card_error(card, error);
- return error;
- }
- PRINTK("nicstar%d: membase at 0x%p.\n", i, card->membase);
-
- pci_set_master(pcidev);
-
- if (pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency) != 0) {
- printk("nicstar%d: can't read PCI latency timer.\n", i);
- error = 6;
- ns_init_card_error(card, error);
- return error;
- }
-#ifdef NS_PCI_LATENCY
- if (pci_latency < NS_PCI_LATENCY) {
- PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i,
- NS_PCI_LATENCY);
- for (j = 1; j < 4; j++) {
- if (pci_write_config_byte
- (pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0)
- break;
- }
- if (j == 4) {
- printk
- ("nicstar%d: can't set PCI latency timer to %d.\n",
- i, NS_PCI_LATENCY);
- error = 7;
- ns_init_card_error(card, error);
- return error;
- }
- }
-#endif /* NS_PCI_LATENCY */
-
- /* Clear timer overflow */
- data = readl(card->membase + STAT);
- if (data & NS_STAT_TMROF)
- writel(NS_STAT_TMROF, card->membase + STAT);
-
- /* Software reset */
- writel(NS_CFG_SWRST, card->membase + CFG);
- NS_DELAY;
- writel(0x00000000, card->membase + CFG);
-
- /* PHY reset */
- writel(0x00000008, card->membase + GP);
- NS_DELAY;
- writel(0x00000001, card->membase + GP);
- NS_DELAY;
- while (CMD_BUSY(card)) ;
- writel(NS_CMD_WRITE_UTILITY | 0x00000100, card->membase + CMD); /* Sync UTOPIA with SAR clock */
- NS_DELAY;
-
- /* Detect PHY type */
- while (CMD_BUSY(card)) ;
- writel(NS_CMD_READ_UTILITY | 0x00000200, card->membase + CMD);
- while (CMD_BUSY(card)) ;
- data = readl(card->membase + DR0);
- switch (data) {
- case 0x00000009:
- printk("nicstar%d: PHY seems to be 25 Mbps.\n", i);
- card->max_pcr = ATM_25_PCR;
- while (CMD_BUSY(card)) ;
- writel(0x00000008, card->membase + DR0);
- writel(NS_CMD_WRITE_UTILITY | 0x00000200, card->membase + CMD);
- /* Clear an eventual pending interrupt */
- writel(NS_STAT_SFBQF, card->membase + STAT);
-#ifdef PHY_LOOPBACK
- while (CMD_BUSY(card)) ;
- writel(0x00000022, card->membase + DR0);
- writel(NS_CMD_WRITE_UTILITY | 0x00000202, card->membase + CMD);
-#endif /* PHY_LOOPBACK */
- break;
- case 0x00000030:
- case 0x00000031:
- printk("nicstar%d: PHY seems to be 155 Mbps.\n", i);
- card->max_pcr = ATM_OC3_PCR;
-#ifdef PHY_LOOPBACK
- while (CMD_BUSY(card)) ;
- writel(0x00000002, card->membase + DR0);
- writel(NS_CMD_WRITE_UTILITY | 0x00000205, card->membase + CMD);
-#endif /* PHY_LOOPBACK */
- break;
- default:
- printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data);
- error = 8;
- ns_init_card_error(card, error);
- return error;
- }
- writel(0x00000000, card->membase + GP);
-
- /* Determine SRAM size */
- data = 0x76543210;
- ns_write_sram(card, 0x1C003, &data, 1);
- data = 0x89ABCDEF;
- ns_write_sram(card, 0x14003, &data, 1);
- if (ns_read_sram(card, 0x14003) == 0x89ABCDEF &&
- ns_read_sram(card, 0x1C003) == 0x76543210)
- card->sram_size = 128;
- else
- card->sram_size = 32;
- PRINTK("nicstar%d: %dK x 32bit SRAM size.\n", i, card->sram_size);
-
- card->rct_size = NS_MAX_RCTSIZE;
-
-#if (NS_MAX_RCTSIZE == 4096)
- if (card->sram_size == 128)
- printk
- ("nicstar%d: limiting maximum VCI. See NS_MAX_RCTSIZE in nicstar.h\n",
- i);
-#elif (NS_MAX_RCTSIZE == 16384)
- if (card->sram_size == 32) {
- printk
- ("nicstar%d: wasting memory. See NS_MAX_RCTSIZE in nicstar.h\n",
- i);
- card->rct_size = 4096;
- }
-#else
-#error NS_MAX_RCTSIZE must be either 4096 or 16384 in nicstar.c
-#endif
-
- card->vpibits = NS_VPIBITS;
- if (card->rct_size == 4096)
- card->vcibits = 12 - NS_VPIBITS;
- else /* card->rct_size == 16384 */
- card->vcibits = 14 - NS_VPIBITS;
-
- /* Initialize the nicstar eeprom/eprom stuff, for the MAC addr */
- if (mac[i] == NULL)
- nicstar_init_eprom(card->membase);
-
- /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */
- writel(0x00000000, card->membase + VPM);
-
- card->intcnt = 0;
- if (request_irq
- (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) {
- pr_err("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq);
- error = 9;
- ns_init_card_error(card, error);
- return error;
- }
-
- /* Initialize TSQ */
- card->tsq.org = dma_alloc_coherent(&card->pcidev->dev,
- NS_TSQSIZE + NS_TSQ_ALIGNMENT,
- &card->tsq.dma, GFP_KERNEL);
- if (card->tsq.org == NULL) {
- printk("nicstar%d: can't allocate TSQ.\n", i);
- error = 10;
- ns_init_card_error(card, error);
- return error;
- }
- card->tsq.base = PTR_ALIGN(card->tsq.org, NS_TSQ_ALIGNMENT);
- card->tsq.next = card->tsq.base;
- card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1);
- for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++)
- ns_tsi_init(card->tsq.base + j);
- writel(0x00000000, card->membase + TSQH);
- writel(ALIGN(card->tsq.dma, NS_TSQ_ALIGNMENT), card->membase + TSQB);
- PRINTK("nicstar%d: TSQ base at 0x%p.\n", i, card->tsq.base);
-
- /* Initialize RSQ */
- card->rsq.org = dma_alloc_coherent(&card->pcidev->dev,
- NS_RSQSIZE + NS_RSQ_ALIGNMENT,
- &card->rsq.dma, GFP_KERNEL);
- if (card->rsq.org == NULL) {
- printk("nicstar%d: can't allocate RSQ.\n", i);
- error = 11;
- ns_init_card_error(card, error);
- return error;
- }
- card->rsq.base = PTR_ALIGN(card->rsq.org, NS_RSQ_ALIGNMENT);
- card->rsq.next = card->rsq.base;
- card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1);
- for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++)
- ns_rsqe_init(card->rsq.base + j);
- writel(0x00000000, card->membase + RSQH);
- writel(ALIGN(card->rsq.dma, NS_RSQ_ALIGNMENT), card->membase + RSQB);
- PRINTK("nicstar%d: RSQ base at 0x%p.\n", i, card->rsq.base);
-
- /* Initialize SCQ0, the only VBR SCQ used */
- card->scq1 = NULL;
- card->scq2 = NULL;
- card->scq0 = get_scq(card, VBR_SCQSIZE, NS_VRSCD0);
- if (card->scq0 == NULL) {
- printk("nicstar%d: can't get SCQ0.\n", i);
- error = 12;
- ns_init_card_error(card, error);
- return error;
- }
- u32d[0] = scq_virt_to_bus(card->scq0, card->scq0->base);
- u32d[1] = (u32) 0x00000000;
- u32d[2] = (u32) 0xffffffff;
- u32d[3] = (u32) 0x00000000;
- ns_write_sram(card, NS_VRSCD0, u32d, 4);
- ns_write_sram(card, NS_VRSCD1, u32d, 4); /* These last two won't be used */
- ns_write_sram(card, NS_VRSCD2, u32d, 4); /* but are initialized, just in case... */
- card->scq0->scd = NS_VRSCD0;
- PRINTK("nicstar%d: VBR-SCQ0 base at 0x%p.\n", i, card->scq0->base);
-
- /* Initialize TSTs */
- card->tst_addr = NS_TST0;
- card->tst_free_entries = NS_TST_NUM_ENTRIES;
- data = NS_TST_OPCODE_VARIABLE;
- for (j = 0; j < NS_TST_NUM_ENTRIES; j++)
- ns_write_sram(card, NS_TST0 + j, &data, 1);
- data = ns_tste_make(NS_TST_OPCODE_END, NS_TST0);
- ns_write_sram(card, NS_TST0 + NS_TST_NUM_ENTRIES, &data, 1);
- for (j = 0; j < NS_TST_NUM_ENTRIES; j++)
- ns_write_sram(card, NS_TST1 + j, &data, 1);
- data = ns_tste_make(NS_TST_OPCODE_END, NS_TST1);
- ns_write_sram(card, NS_TST1 + NS_TST_NUM_ENTRIES, &data, 1);
- for (j = 0; j < NS_TST_NUM_ENTRIES; j++)
- card->tste2vc[j] = NULL;
- writel(NS_TST0 << 2, card->membase + TSTB);
-
- /* Initialize RCT. AAL type is set on opening the VC. */
-#ifdef RCQ_SUPPORT
- u32d[0] = NS_RCTE_RAWCELLINTEN;
-#else
- u32d[0] = 0x00000000;
-#endif /* RCQ_SUPPORT */
- u32d[1] = 0x00000000;
- u32d[2] = 0x00000000;
- u32d[3] = 0xFFFFFFFF;
- for (j = 0; j < card->rct_size; j++)
- ns_write_sram(card, j * 4, u32d, 4);
-
- memset(card->vcmap, 0, sizeof(card->vcmap));
-
- for (j = 0; j < NS_FRSCD_NUM; j++)
- card->scd2vc[j] = NULL;
-
- /* Initialize buffer levels */
- card->sbnr.min = MIN_SB;
- card->sbnr.init = NUM_SB;
- card->sbnr.max = MAX_SB;
- card->lbnr.min = MIN_LB;
- card->lbnr.init = NUM_LB;
- card->lbnr.max = MAX_LB;
- card->iovnr.min = MIN_IOVB;
- card->iovnr.init = NUM_IOVB;
- card->iovnr.max = MAX_IOVB;
- card->hbnr.min = MIN_HB;
- card->hbnr.init = NUM_HB;
- card->hbnr.max = MAX_HB;
-
- card->sm_handle = NULL;
- card->sm_addr = 0x00000000;
- card->lg_handle = NULL;
- card->lg_addr = 0x00000000;
-
- card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */
-
- idr_init(&card->idr);
-
- /* Pre-allocate some huge buffers */
- skb_queue_head_init(&card->hbpool.queue);
- card->hbpool.count = 0;
- for (j = 0; j < NUM_HB; j++) {
- struct sk_buff *hb;
- hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
- if (hb == NULL) {
- printk
- ("nicstar%d: can't allocate %dth of %d huge buffers.\n",
- i, j, NUM_HB);
- error = 13;
- ns_init_card_error(card, error);
- return error;
- }
- NS_PRV_BUFTYPE(hb) = BUF_NONE;
- skb_queue_tail(&card->hbpool.queue, hb);
- card->hbpool.count++;
- }
-
- /* Allocate large buffers */
- skb_queue_head_init(&card->lbpool.queue);
- card->lbpool.count = 0; /* Not used */
- for (j = 0; j < NUM_LB; j++) {
- struct sk_buff *lb;
- lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
- if (lb == NULL) {
- printk
- ("nicstar%d: can't allocate %dth of %d large buffers.\n",
- i, j, NUM_LB);
- error = 14;
- ns_init_card_error(card, error);
- return error;
- }
- NS_PRV_BUFTYPE(lb) = BUF_LG;
- skb_queue_tail(&card->lbpool.queue, lb);
- skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, lb);
- /* Due to the implementation of push_rxbufs() this is 1, not 0 */
- if (j == 1) {
- card->rcbuf = lb;
- card->rawcell = (struct ns_rcqe *) lb->data;
- card->rawch = NS_PRV_DMA(lb);
- }
- }
- /* Test for strange behaviour which leads to crashes */
- if ((bcount =
- ns_stat_lfbqc_get(readl(card->membase + STAT))) < card->lbnr.min) {
- printk
- ("nicstar%d: Strange... Just allocated %d large buffers and lfbqc = %d.\n",
- i, j, bcount);
- error = 14;
- ns_init_card_error(card, error);
- return error;
- }
-
- /* Allocate small buffers */
- skb_queue_head_init(&card->sbpool.queue);
- card->sbpool.count = 0; /* Not used */
- for (j = 0; j < NUM_SB; j++) {
- struct sk_buff *sb;
- sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
- if (sb == NULL) {
- printk
- ("nicstar%d: can't allocate %dth of %d small buffers.\n",
- i, j, NUM_SB);
- error = 15;
- ns_init_card_error(card, error);
- return error;
- }
- NS_PRV_BUFTYPE(sb) = BUF_SM;
- skb_queue_tail(&card->sbpool.queue, sb);
- skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, sb);
- }
- /* Test for strange behaviour which leads to crashes */
- if ((bcount =
- ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min) {
- printk
- ("nicstar%d: Strange... Just allocated %d small buffers and sfbqc = %d.\n",
- i, j, bcount);
- error = 15;
- ns_init_card_error(card, error);
- return error;
- }
-
- /* Allocate iovec buffers */
- skb_queue_head_init(&card->iovpool.queue);
- card->iovpool.count = 0;
- for (j = 0; j < NUM_IOVB; j++) {
- struct sk_buff *iovb;
- iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);
- if (iovb == NULL) {
- printk
- ("nicstar%d: can't allocate %dth of %d iovec buffers.\n",
- i, j, NUM_IOVB);
- error = 16;
- ns_init_card_error(card, error);
- return error;
- }
- NS_PRV_BUFTYPE(iovb) = BUF_NONE;
- skb_queue_tail(&card->iovpool.queue, iovb);
- card->iovpool.count++;
- }
-
- /* Configure NICStAR */
- if (card->rct_size == 4096)
- ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES;
- else /* (card->rct_size == 16384) */
- ns_cfg_rctsize = NS_CFG_RCTSIZE_16384_ENTRIES;
-
- card->efbie = 1;
-
- /* Register device */
- card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops,
- -1, NULL);
- if (card->atmdev == NULL) {
- printk("nicstar%d: can't register device.\n", i);
- error = 17;
- ns_init_card_error(card, error);
- return error;
- }
-
- if (mac[i] == NULL || !mac_pton(mac[i], card->atmdev->esi)) {
- nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,
- card->atmdev->esi, 6);
- if (ether_addr_equal(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00")) {
- nicstar_read_eprom(card->membase,
- NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT,
- card->atmdev->esi, 6);
- }
- }
-
- printk("nicstar%d: MAC address %pM\n", i, card->atmdev->esi);
-
- card->atmdev->dev_data = card;
- card->atmdev->ci_range.vpi_bits = card->vpibits;
- card->atmdev->ci_range.vci_bits = card->vcibits;
- card->atmdev->link_rate = card->max_pcr;
- card->atmdev->phy = NULL;
-
-#ifdef CONFIG_ATM_NICSTAR_USE_SUNI
- if (card->max_pcr == ATM_OC3_PCR)
- suni_init(card->atmdev);
-#endif /* CONFIG_ATM_NICSTAR_USE_SUNI */
-
-#ifdef CONFIG_ATM_NICSTAR_USE_IDT77105
- if (card->max_pcr == ATM_25_PCR)
- idt77105_init(card->atmdev);
-#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
-
- if (card->atmdev->phy && card->atmdev->phy->start)
- card->atmdev->phy->start(card->atmdev);
-
- writel(NS_CFG_RXPATH | NS_CFG_SMBUFSIZE | NS_CFG_LGBUFSIZE | NS_CFG_EFBIE | NS_CFG_RSQSIZE | NS_CFG_VPIBITS | ns_cfg_rctsize | NS_CFG_RXINT_NODELAY | NS_CFG_RAWIE | /* Only enabled if RCQ_SUPPORT */
- NS_CFG_RSQAFIE | NS_CFG_TXEN | NS_CFG_TXIE | NS_CFG_TSQFIE_OPT | /* Only enabled if ENABLE_TSQFIE */
- NS_CFG_PHYIE, card->membase + CFG);
-
- num_cards++;
-
- return error;
-}
-
-static void ns_init_card_error(ns_dev *card, int error)
-{
- if (error >= 17) {
- writel(0x00000000, card->membase + CFG);
- }
- if (error >= 16) {
- struct sk_buff *iovb;
- while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL)
- dev_kfree_skb_any(iovb);
- }
- if (error >= 15) {
- struct sk_buff *sb;
- while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL)
- dev_kfree_skb_any(sb);
- free_scq(card, card->scq0, NULL);
- }
- if (error >= 14) {
- struct sk_buff *lb;
- while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL)
- dev_kfree_skb_any(lb);
- }
- if (error >= 13) {
- struct sk_buff *hb;
- while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL)
- dev_kfree_skb_any(hb);
- }
- if (error >= 12) {
- dma_free_coherent(&card->pcidev->dev, NS_RSQSIZE + NS_RSQ_ALIGNMENT,
- card->rsq.org, card->rsq.dma);
- }
- if (error >= 11) {
- dma_free_coherent(&card->pcidev->dev, NS_TSQSIZE + NS_TSQ_ALIGNMENT,
- card->tsq.org, card->tsq.dma);
- }
- if (error >= 10) {
- free_irq(card->pcidev->irq, card);
- }
- if (error >= 4) {
- iounmap(card->membase);
- }
- if (error >= 3) {
- pci_disable_device(card->pcidev);
- kfree(card);
- }
-}
-
-static scq_info *get_scq(ns_dev *card, int size, u32 scd)
-{
- scq_info *scq;
-
- if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
- return NULL;
-
- scq = kmalloc_obj(*scq);
- if (!scq)
- return NULL;
- scq->org = dma_alloc_coherent(&card->pcidev->dev,
- 2 * size, &scq->dma, GFP_KERNEL);
- if (!scq->org) {
- kfree(scq);
- return NULL;
- }
- scq->skb = kzalloc_objs(*scq->skb, size / NS_SCQE_SIZE);
- if (!scq->skb) {
- dma_free_coherent(&card->pcidev->dev,
- 2 * size, scq->org, scq->dma);
- kfree(scq);
- return NULL;
- }
- scq->num_entries = size / NS_SCQE_SIZE;
- scq->base = PTR_ALIGN(scq->org, size);
- scq->next = scq->base;
- scq->last = scq->base + (scq->num_entries - 1);
- scq->tail = scq->last;
- scq->scd = scd;
- scq->tbd_count = 0;
- init_waitqueue_head(&scq->scqfull_waitq);
- scq->full = 0;
- spin_lock_init(&scq->lock);
-
- return scq;
-}
-
-/* For variable rate SCQ vcc must be NULL */
-static void free_scq(ns_dev *card, scq_info *scq, struct atm_vcc *vcc)
-{
- int i;
-
- if (scq->num_entries == VBR_SCQ_NUM_ENTRIES)
- for (i = 0; i < scq->num_entries; i++) {
- if (scq->skb[i] != NULL) {
- vcc = ATM_SKB(scq->skb[i])->vcc;
- if (vcc->pop != NULL)
- vcc->pop(vcc, scq->skb[i]);
- else
- dev_kfree_skb_any(scq->skb[i]);
- }
- } else { /* vcc must be != NULL */
-
- if (vcc == NULL) {
- printk
- ("nicstar: free_scq() called with vcc == NULL for fixed rate scq.");
- for (i = 0; i < scq->num_entries; i++)
- dev_kfree_skb_any(scq->skb[i]);
- } else
- for (i = 0; i < scq->num_entries; i++) {
- if (scq->skb[i] != NULL) {
- if (vcc->pop != NULL)
- vcc->pop(vcc, scq->skb[i]);
- else
- dev_kfree_skb_any(scq->skb[i]);
- }
- }
- }
- kfree(scq->skb);
- dma_free_coherent(&card->pcidev->dev,
- 2 * (scq->num_entries == VBR_SCQ_NUM_ENTRIES ?
- VBR_SCQSIZE : CBR_SCQSIZE),
- scq->org, scq->dma);
- kfree(scq);
-}
-
-/* The handles passed must be pointers to the sk_buff containing the small
- or large buffer(s) cast to u32. */
-static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
-{
- struct sk_buff *handle1, *handle2;
- int id1, id2;
- u32 addr1, addr2;
- u32 stat;
- unsigned long flags;
-
- /* *BARF* */
- handle2 = NULL;
- addr2 = 0;
- handle1 = skb;
- addr1 = dma_map_single(&card->pcidev->dev,
- skb->data,
- (NS_PRV_BUFTYPE(skb) == BUF_SM
- ? NS_SMSKBSIZE : NS_LGSKBSIZE),
- DMA_TO_DEVICE);
- NS_PRV_DMA(skb) = addr1; /* save so we can unmap later */
-
-#ifdef GENERAL_DEBUG
- if (!addr1)
- printk("nicstar%d: push_rxbufs called with addr1 = 0.\n",
- card->index);
-#endif /* GENERAL_DEBUG */
-
- stat = readl(card->membase + STAT);
- card->sbfqc = ns_stat_sfbqc_get(stat);
- card->lbfqc = ns_stat_lfbqc_get(stat);
- if (NS_PRV_BUFTYPE(skb) == BUF_SM) {
- if (!addr2) {
- if (card->sm_addr) {
- addr2 = card->sm_addr;
- handle2 = card->sm_handle;
- card->sm_addr = 0x00000000;
- card->sm_handle = NULL;
- } else { /* (!sm_addr) */
-
- card->sm_addr = addr1;
- card->sm_handle = handle1;
- }
- }
- } else { /* buf_type == BUF_LG */
-
- if (!addr2) {
- if (card->lg_addr) {
- addr2 = card->lg_addr;
- handle2 = card->lg_handle;
- card->lg_addr = 0x00000000;
- card->lg_handle = NULL;
- } else { /* (!lg_addr) */
-
- card->lg_addr = addr1;
- card->lg_handle = handle1;
- }
- }
- }
-
- if (addr2) {
- if (NS_PRV_BUFTYPE(skb) == BUF_SM) {
- if (card->sbfqc >= card->sbnr.max) {
- skb_unlink(handle1, &card->sbpool.queue);
- dev_kfree_skb_any(handle1);
- skb_unlink(handle2, &card->sbpool.queue);
- dev_kfree_skb_any(handle2);
- return;
- } else
- card->sbfqc += 2;
- } else { /* (buf_type == BUF_LG) */
-
- if (card->lbfqc >= card->lbnr.max) {
- skb_unlink(handle1, &card->lbpool.queue);
- dev_kfree_skb_any(handle1);
- skb_unlink(handle2, &card->lbpool.queue);
- dev_kfree_skb_any(handle2);
- return;
- } else
- card->lbfqc += 2;
- }
-
- id1 = idr_alloc(&card->idr, handle1, 0, 0, GFP_ATOMIC);
- if (id1 < 0)
- goto out;
-
- id2 = idr_alloc(&card->idr, handle2, 0, 0, GFP_ATOMIC);
- if (id2 < 0)
- goto out;
-
- spin_lock_irqsave(&card->res_lock, flags);
- while (CMD_BUSY(card)) ;
- writel(addr2, card->membase + DR3);
- writel(id2, card->membase + DR2);
- writel(addr1, card->membase + DR1);
- writel(id1, card->membase + DR0);
- writel(NS_CMD_WRITE_FREEBUFQ | NS_PRV_BUFTYPE(skb),
- card->membase + CMD);
- spin_unlock_irqrestore(&card->res_lock, flags);
-
- XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n",
- card->index,
- (NS_PRV_BUFTYPE(skb) == BUF_SM ? "small" : "large"),
- addr1, addr2);
- }
-
- if (!card->efbie && card->sbfqc >= card->sbnr.min &&
- card->lbfqc >= card->lbnr.min) {
- card->efbie = 1;
- writel((readl(card->membase + CFG) | NS_CFG_EFBIE),
- card->membase + CFG);
- }
-
-out:
- return;
-}
-
-static irqreturn_t ns_irq_handler(int irq, void *dev_id)
-{
- u32 stat_r;
- ns_dev *card;
- struct atm_dev *dev;
- unsigned long flags;
-
- card = (ns_dev *) dev_id;
- dev = card->atmdev;
- card->intcnt++;
-
- PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);
-
- spin_lock_irqsave(&card->int_lock, flags);
-
- stat_r = readl(card->membase + STAT);
-
- /* Transmit Status Indicator has been written to T. S. Queue */
- if (stat_r & NS_STAT_TSIF) {
- TXPRINTK("nicstar%d: TSI interrupt\n", card->index);
- process_tsq(card);
- writel(NS_STAT_TSIF, card->membase + STAT);
- }
-
- /* Incomplete CS-PDU has been transmitted */
- if (stat_r & NS_STAT_TXICP) {
- writel(NS_STAT_TXICP, card->membase + STAT);
- TXPRINTK("nicstar%d: Incomplete CS-PDU transmitted.\n",
- card->index);
- }
-
- /* Transmit Status Queue 7/8 full */
- if (stat_r & NS_STAT_TSQF) {
- writel(NS_STAT_TSQF, card->membase + STAT);
- PRINTK("nicstar%d: TSQ full.\n", card->index);
- process_tsq(card);
- }
-
- /* Timer overflow */
- if (stat_r & NS_STAT_TMROF) {
- writel(NS_STAT_TMROF, card->membase + STAT);
- PRINTK("nicstar%d: Timer overflow.\n", card->index);
- }
-
- /* PHY device interrupt signal active */
- if (stat_r & NS_STAT_PHYI) {
- writel(NS_STAT_PHYI, card->membase + STAT);
- PRINTK("nicstar%d: PHY interrupt.\n", card->index);
- if (dev->phy && dev->phy->interrupt) {
- dev->phy->interrupt(dev);
- }
- }
-
- /* Small Buffer Queue is full */
- if (stat_r & NS_STAT_SFBQF) {
- writel(NS_STAT_SFBQF, card->membase + STAT);
- printk("nicstar%d: Small free buffer queue is full.\n",
- card->index);
- }
-
- /* Large Buffer Queue is full */
- if (stat_r & NS_STAT_LFBQF) {
- writel(NS_STAT_LFBQF, card->membase + STAT);
- printk("nicstar%d: Large free buffer queue is full.\n",
- card->index);
- }
-
- /* Receive Status Queue is full */
- if (stat_r & NS_STAT_RSQF) {
- writel(NS_STAT_RSQF, card->membase + STAT);
- printk("nicstar%d: RSQ full.\n", card->index);
- process_rsq(card);
- }
-
- /* Complete CS-PDU received */
- if (stat_r & NS_STAT_EOPDU) {
- RXPRINTK("nicstar%d: End of CS-PDU received.\n", card->index);
- process_rsq(card);
- writel(NS_STAT_EOPDU, card->membase + STAT);
- }
-
- /* Raw cell received */
- if (stat_r & NS_STAT_RAWCF) {
- writel(NS_STAT_RAWCF, card->membase + STAT);
-#ifndef RCQ_SUPPORT
- printk("nicstar%d: Raw cell received and no support yet...\n",
- card->index);
-#endif /* RCQ_SUPPORT */
- /* NOTE: the following procedure may keep a raw cell pending until the
- next interrupt. As this preliminary support is only meant to
- avoid buffer leakage, this is not an issue. */
- while (readl(card->membase + RAWCT) != card->rawch) {
-
- if (ns_rcqe_islast(card->rawcell)) {
- struct sk_buff *oldbuf;
-
- oldbuf = card->rcbuf;
- card->rcbuf = idr_find(&card->idr,
- ns_rcqe_nextbufhandle(card->rawcell));
- card->rawch = NS_PRV_DMA(card->rcbuf);
- card->rawcell = (struct ns_rcqe *)
- card->rcbuf->data;
- recycle_rx_buf(card, oldbuf);
- } else {
- card->rawch += NS_RCQE_SIZE;
- card->rawcell++;
- }
- }
- }
-
- /* Small buffer queue is empty */
- if (stat_r & NS_STAT_SFBQE) {
- int i;
- struct sk_buff *sb;
-
- writel(NS_STAT_SFBQE, card->membase + STAT);
- printk("nicstar%d: Small free buffer queue empty.\n",
- card->index);
- for (i = 0; i < card->sbnr.min; i++) {
- sb = dev_alloc_skb(NS_SMSKBSIZE);
- if (sb == NULL) {
- writel(readl(card->membase + CFG) &
- ~NS_CFG_EFBIE, card->membase + CFG);
- card->efbie = 0;
- break;
- }
- NS_PRV_BUFTYPE(sb) = BUF_SM;
- skb_queue_tail(&card->sbpool.queue, sb);
- skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, sb);
- }
- card->sbfqc = i;
- process_rsq(card);
- }
-
- /* Large buffer queue empty */
- if (stat_r & NS_STAT_LFBQE) {
- int i;
- struct sk_buff *lb;
-
- writel(NS_STAT_LFBQE, card->membase + STAT);
- printk("nicstar%d: Large free buffer queue empty.\n",
- card->index);
- for (i = 0; i < card->lbnr.min; i++) {
- lb = dev_alloc_skb(NS_LGSKBSIZE);
- if (lb == NULL) {
- writel(readl(card->membase + CFG) &
- ~NS_CFG_EFBIE, card->membase + CFG);
- card->efbie = 0;
- break;
- }
- NS_PRV_BUFTYPE(lb) = BUF_LG;
- skb_queue_tail(&card->lbpool.queue, lb);
- skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, lb);
- }
- card->lbfqc = i;
- process_rsq(card);
- }
-
- /* Receive Status Queue is 7/8 full */
- if (stat_r & NS_STAT_RSQAF) {
- writel(NS_STAT_RSQAF, card->membase + STAT);
- RXPRINTK("nicstar%d: RSQ almost full.\n", card->index);
- process_rsq(card);
- }
-
- spin_unlock_irqrestore(&card->int_lock, flags);
- PRINTK("nicstar%d: end of interrupt service\n", card->index);
- return IRQ_HANDLED;
-}
-
-static int ns_open(struct atm_vcc *vcc)
-{
- ns_dev *card;
- vc_map *vc;
- unsigned long tmpl, modl;
- int tcr, tcra; /* target cell rate, and absolute value */
- int n = 0; /* Number of entries in the TST. Initialized to remove
- the compiler warning. */
- u32 u32d[4];
- int frscdi = 0; /* Index of the SCD. Initialized to remove the compiler
- warning. How I wish compilers were clever enough to
- tell which variables can truly be used
- uninitialized... */
- int inuse; /* tx or rx vc already in use by another vcc */
- short vpi = vcc->vpi;
- int vci = vcc->vci;
-
- card = (ns_dev *) vcc->dev->dev_data;
- PRINTK("nicstar%d: opening vpi.vci %d.%d \n", card->index, (int)vpi,
- vci);
- if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) {
- PRINTK("nicstar%d: unsupported AAL.\n", card->index);
- return -EINVAL;
- }
-
- vc = &(card->vcmap[vpi << card->vcibits | vci]);
- vcc->dev_data = vc;
-
- inuse = 0;
- if (vcc->qos.txtp.traffic_class != ATM_NONE && vc->tx)
- inuse = 1;
- if (vcc->qos.rxtp.traffic_class != ATM_NONE && vc->rx)
- inuse += 2;
- if (inuse) {
- printk("nicstar%d: %s vci already in use.\n", card->index,
- inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx");
- return -EINVAL;
- }
-
- set_bit(ATM_VF_ADDR, &vcc->flags);
-
- /* NOTE: You are not allowed to modify an open connection's QOS. To change
- that, remove the ATM_VF_PARTIAL flag checking. There may be other changes
- needed to do that. */
- if (!test_bit(ATM_VF_PARTIAL, &vcc->flags)) {
- scq_info *scq;
-
- set_bit(ATM_VF_PARTIAL, &vcc->flags);
- if (vcc->qos.txtp.traffic_class == ATM_CBR) {
- /* Check requested cell rate and availability of SCD */
- if (vcc->qos.txtp.max_pcr == 0 && vcc->qos.txtp.pcr == 0
- && vcc->qos.txtp.min_pcr == 0) {
- PRINTK
- ("nicstar%d: trying to open a CBR vc with cell rate = 0 \n",
- card->index);
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- return -EINVAL;
- }
-
- tcr = atm_pcr_goal(&(vcc->qos.txtp));
- tcra = tcr >= 0 ? tcr : -tcr;
-
- PRINTK("nicstar%d: target cell rate = %d.\n",
- card->index, vcc->qos.txtp.max_pcr);
-
- tmpl =
- (unsigned long)tcra *(unsigned long)
- NS_TST_NUM_ENTRIES;
- modl = tmpl % card->max_pcr;
-
- n = (int)(tmpl / card->max_pcr);
- if (tcr > 0) {
- if (modl > 0)
- n++;
- } else if (tcr == 0) {
- if ((n =
- (card->tst_free_entries -
- NS_TST_RESERVED)) <= 0) {
- PRINTK
- ("nicstar%d: no CBR bandwidth free.\n",
- card->index);
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- return -EINVAL;
- }
- }
-
- if (n == 0) {
- printk
- ("nicstar%d: selected bandwidth < granularity.\n",
- card->index);
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- return -EINVAL;
- }
-
- if (n > (card->tst_free_entries - NS_TST_RESERVED)) {
- PRINTK
- ("nicstar%d: not enough free CBR bandwidth.\n",
- card->index);
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- return -EINVAL;
- } else
- card->tst_free_entries -= n;
-
- XPRINTK("nicstar%d: writing %d tst entries.\n",
- card->index, n);
- for (frscdi = 0; frscdi < NS_FRSCD_NUM; frscdi++) {
- if (card->scd2vc[frscdi] == NULL) {
- card->scd2vc[frscdi] = vc;
- break;
- }
- }
- if (frscdi == NS_FRSCD_NUM) {
- PRINTK
- ("nicstar%d: no SCD available for CBR channel.\n",
- card->index);
- card->tst_free_entries += n;
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- return -EBUSY;
- }
-
- vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;
-
- scq = get_scq(card, CBR_SCQSIZE, vc->cbr_scd);
- if (scq == NULL) {
- PRINTK("nicstar%d: can't get fixed rate SCQ.\n",
- card->index);
- card->scd2vc[frscdi] = NULL;
- card->tst_free_entries += n;
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
- return -ENOMEM;
- }
- vc->scq = scq;
- u32d[0] = scq_virt_to_bus(scq, scq->base);
- u32d[1] = (u32) 0x00000000;
- u32d[2] = (u32) 0xffffffff;
- u32d[3] = (u32) 0x00000000;
- ns_write_sram(card, vc->cbr_scd, u32d, 4);
-
- fill_tst(card, n, vc);
- } else if (vcc->qos.txtp.traffic_class == ATM_UBR) {
- vc->cbr_scd = 0x00000000;
- vc->scq = card->scq0;
- }
-
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
- vc->tx = 1;
- vc->tx_vcc = vcc;
- vc->tbd_count = 0;
- }
- if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
- u32 status;
-
- vc->rx = 1;
- vc->rx_vcc = vcc;
- vc->rx_iov = NULL;
-
- /* Open the connection in hardware */
- if (vcc->qos.aal == ATM_AAL5)
- status = NS_RCTE_AAL5 | NS_RCTE_CONNECTOPEN;
- else /* vcc->qos.aal == ATM_AAL0 */
- status = NS_RCTE_AAL0 | NS_RCTE_CONNECTOPEN;
-#ifdef RCQ_SUPPORT
- status |= NS_RCTE_RAWCELLINTEN;
-#endif /* RCQ_SUPPORT */
- ns_write_sram(card,
- NS_RCT +
- (vpi << card->vcibits | vci) *
- NS_RCT_ENTRY_SIZE, &status, 1);
- }
-
- }
-
- set_bit(ATM_VF_READY, &vcc->flags);
- return 0;
-}
-
-static void ns_close(struct atm_vcc *vcc)
-{
- vc_map *vc;
- ns_dev *card;
- u32 data;
- int i;
-
- vc = vcc->dev_data;
- card = vcc->dev->dev_data;
- PRINTK("nicstar%d: closing vpi.vci %d.%d \n", card->index,
- (int)vcc->vpi, vcc->vci);
-
- clear_bit(ATM_VF_READY, &vcc->flags);
-
- if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
- u32 addr;
- unsigned long flags;
-
- addr =
- NS_RCT +
- (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE;
- spin_lock_irqsave(&card->res_lock, flags);
- while (CMD_BUSY(card)) ;
- writel(NS_CMD_CLOSE_CONNECTION | addr << 2,
- card->membase + CMD);
- spin_unlock_irqrestore(&card->res_lock, flags);
-
- vc->rx = 0;
- if (vc->rx_iov != NULL) {
- struct sk_buff *iovb;
- u32 stat;
-
- stat = readl(card->membase + STAT);
- card->sbfqc = ns_stat_sfbqc_get(stat);
- card->lbfqc = ns_stat_lfbqc_get(stat);
-
- PRINTK
- ("nicstar%d: closing a VC with pending rx buffers.\n",
- card->index);
- iovb = vc->rx_iov;
- recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
- NS_PRV_IOVCNT(iovb));
- NS_PRV_IOVCNT(iovb) = 0;
- spin_lock_irqsave(&card->int_lock, flags);
- recycle_iov_buf(card, iovb);
- spin_unlock_irqrestore(&card->int_lock, flags);
- vc->rx_iov = NULL;
- }
- }
-
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
- vc->tx = 0;
- }
-
- if (vcc->qos.txtp.traffic_class == ATM_CBR) {
- unsigned long flags;
- ns_scqe *scqep;
- scq_info *scq;
-
- scq = vc->scq;
-
- for (;;) {
- spin_lock_irqsave(&scq->lock, flags);
- scqep = scq->next;
- if (scqep == scq->base)
- scqep = scq->last;
- else
- scqep--;
- if (scqep == scq->tail) {
- spin_unlock_irqrestore(&scq->lock, flags);
- break;
- }
- /* If the last entry is not a TSR, place one in the SCQ in order to
- be able to completely drain it and then close. */
- if (!ns_scqe_is_tsr(scqep) && scq->tail != scq->next) {
- ns_scqe tsr;
- u32 scdi, scqi;
- u32 data;
- int index;
-
- tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE);
- scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE;
- scqi = scq->next - scq->base;
- tsr.word_2 = ns_tsr_mkword_2(scdi, scqi);
- tsr.word_3 = 0x00000000;
- tsr.word_4 = 0x00000000;
- *scq->next = tsr;
- index = (int)scqi;
- scq->skb[index] = NULL;
- if (scq->next == scq->last)
- scq->next = scq->base;
- else
- scq->next++;
- data = scq_virt_to_bus(scq, scq->next);
- ns_write_sram(card, scq->scd, &data, 1);
- }
- spin_unlock_irqrestore(&scq->lock, flags);
- schedule();
- }
-
- /* Free all TST entries */
- data = NS_TST_OPCODE_VARIABLE;
- for (i = 0; i < NS_TST_NUM_ENTRIES; i++) {
- if (card->tste2vc[i] == vc) {
- ns_write_sram(card, card->tst_addr + i, &data,
- 1);
- card->tste2vc[i] = NULL;
- card->tst_free_entries++;
- }
- }
-
- card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL;
- free_scq(card, vc->scq, vcc);
- }
-
- /* remove all references to vcc before deleting it */
- if (vcc->qos.txtp.traffic_class != ATM_NONE) {
- unsigned long flags;
- scq_info *scq = card->scq0;
-
- spin_lock_irqsave(&scq->lock, flags);
-
- for (i = 0; i < scq->num_entries; i++) {
- if (scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) {
- ATM_SKB(scq->skb[i])->vcc = NULL;
- atm_return(vcc, scq->skb[i]->truesize);
- PRINTK
- ("nicstar: deleted pending vcc mapping\n");
- }
- }
-
- spin_unlock_irqrestore(&scq->lock, flags);
- }
-
- vcc->dev_data = NULL;
- clear_bit(ATM_VF_PARTIAL, &vcc->flags);
- clear_bit(ATM_VF_ADDR, &vcc->flags);
-
-#ifdef RX_DEBUG
- {
- u32 stat, cfg;
- stat = readl(card->membase + STAT);
- cfg = readl(card->membase + CFG);
- printk("STAT = 0x%08X CFG = 0x%08X \n", stat, cfg);
- printk
- ("TSQ: base = 0x%p next = 0x%p last = 0x%p TSQT = 0x%08X \n",
- card->tsq.base, card->tsq.next,
- card->tsq.last, readl(card->membase + TSQT));
- printk
- ("RSQ: base = 0x%p next = 0x%p last = 0x%p RSQT = 0x%08X \n",
- card->rsq.base, card->rsq.next,
- card->rsq.last, readl(card->membase + RSQT));
- printk("Empty free buffer queue interrupt %s \n",
- card->efbie ? "enabled" : "disabled");
- printk("SBCNT = %d count = %d LBCNT = %d count = %d \n",
- ns_stat_sfbqc_get(stat), card->sbpool.count,
- ns_stat_lfbqc_get(stat), card->lbpool.count);
- printk("hbpool.count = %d iovpool.count = %d \n",
- card->hbpool.count, card->iovpool.count);
- }
-#endif /* RX_DEBUG */
-}
-
-static void fill_tst(ns_dev * card, int n, vc_map * vc)
-{
- u32 new_tst;
- unsigned long cl;
- int e, r;
- u32 data;
-
- /* It would be very complicated to keep the two TSTs synchronized while
- assuring that writes are only made to the inactive TST. So, for now I
- will use only one TST. If problems occur, I will change this again */
-
- new_tst = card->tst_addr;
-
- /* Fill procedure */
-
- for (e = 0; e < NS_TST_NUM_ENTRIES; e++) {
- if (card->tste2vc[e] == NULL)
- break;
- }
- if (e == NS_TST_NUM_ENTRIES) {
- printk("nicstar%d: No free TST entries found. \n", card->index);
- return;
- }
-
- r = n;
- cl = NS_TST_NUM_ENTRIES;
- data = ns_tste_make(NS_TST_OPCODE_FIXED, vc->cbr_scd);
-
- while (r > 0) {
- if (cl >= NS_TST_NUM_ENTRIES && card->tste2vc[e] == NULL) {
- card->tste2vc[e] = vc;
- ns_write_sram(card, new_tst + e, &data, 1);
- cl -= NS_TST_NUM_ENTRIES;
- r--;
- }
-
- if (++e == NS_TST_NUM_ENTRIES) {
- e = 0;
- }
- cl += n;
- }
-
- /* End of fill procedure */
-
- data = ns_tste_make(NS_TST_OPCODE_END, new_tst);
- ns_write_sram(card, new_tst + NS_TST_NUM_ENTRIES, &data, 1);
- ns_write_sram(card, card->tst_addr + NS_TST_NUM_ENTRIES, &data, 1);
- card->tst_addr = new_tst;
-}
-
-static int _ns_send(struct atm_vcc *vcc, struct sk_buff *skb, bool may_sleep)
-{
- ns_dev *card;
- vc_map *vc;
- scq_info *scq;
- unsigned long buflen;
- ns_scqe scqe;
- u32 flags; /* TBD flags, not CPU flags */
-
- card = vcc->dev->dev_data;
- TXPRINTK("nicstar%d: ns_send() called.\n", card->index);
- if ((vc = (vc_map *) vcc->dev_data) == NULL) {
- printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n",
- card->index);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb_any(skb);
- return -EINVAL;
- }
-
- if (!vc->tx) {
- printk("nicstar%d: Trying to transmit on a non-tx VC.\n",
- card->index);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb_any(skb);
- return -EINVAL;
- }
-
- if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) {
- printk("nicstar%d: Only AAL0 and AAL5 are supported.\n",
- card->index);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb_any(skb);
- return -EINVAL;
- }
-
- if (skb_shinfo(skb)->nr_frags != 0) {
- printk("nicstar%d: No scatter-gather yet.\n", card->index);
- atomic_inc(&vcc->stats->tx_err);
- dev_kfree_skb_any(skb);
- return -EINVAL;
- }
-
- ATM_SKB(skb)->vcc = vcc;
-
- NS_PRV_DMA(skb) = dma_map_single(&card->pcidev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
-
- if (vcc->qos.aal == ATM_AAL5) {
- buflen = (skb->len + 47 + 8) / 48 * 48; /* Multiple of 48 */
- flags = NS_TBD_AAL5;
- scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb));
- scqe.word_3 = cpu_to_le32(skb->len);
- scqe.word_4 =
- ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0,
- ATM_SKB(skb)->
- atm_options & ATM_ATMOPT_CLP ? 1 : 0);
- flags |= NS_TBD_EOPDU;
- } else { /* (vcc->qos.aal == ATM_AAL0) */
-
- buflen = ATM_CELL_PAYLOAD; /* i.e., 48 bytes */
- flags = NS_TBD_AAL0;
- scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb) + NS_AAL0_HEADER);
- scqe.word_3 = cpu_to_le32(0x00000000);
- if (*skb->data & 0x02) /* Payload type 1 - end of pdu */
- flags |= NS_TBD_EOPDU;
- scqe.word_4 =
- cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK);
- /* Force the VPI/VCI to be the same as in VCC struct */
- scqe.word_4 |=
- cpu_to_le32((((u32) vcc->
- vpi) << NS_TBD_VPI_SHIFT | ((u32) vcc->
- vci) <<
- NS_TBD_VCI_SHIFT) & NS_TBD_VC_MASK);
- }
-
- if (vcc->qos.txtp.traffic_class == ATM_CBR) {
- scqe.word_1 = ns_tbd_mkword_1_novbr(flags, (u32) buflen);
- scq = ((vc_map *) vcc->dev_data)->scq;
- } else {
- scqe.word_1 =
- ns_tbd_mkword_1(flags, (u32) 1, (u32) 1, (u32) buflen);
- scq = card->scq0;
- }
-
- if (push_scqe(card, vc, scq, &scqe, skb, may_sleep) != 0) {
- atomic_inc(&vcc->stats->tx_err);
- dma_unmap_single(&card->pcidev->dev, NS_PRV_DMA(skb), skb->len,
- DMA_TO_DEVICE);
- dev_kfree_skb_any(skb);
- return -EIO;
- }
- atomic_inc(&vcc->stats->tx);
-
- return 0;
-}
-
-static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- return _ns_send(vcc, skb, true);
-}
-
-static int ns_send_bh(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- return _ns_send(vcc, skb, false);
-}
-
-static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
- struct sk_buff *skb, bool may_sleep)
-{
- unsigned long flags;
- ns_scqe tsr;
- u32 scdi, scqi;
- int scq_is_vbr;
- u32 data;
- int index;
-
- spin_lock_irqsave(&scq->lock, flags);
- while (scq->tail == scq->next) {
- if (!may_sleep) {
- spin_unlock_irqrestore(&scq->lock, flags);
- printk("nicstar%d: Error pushing TBD.\n", card->index);
- return 1;
- }
-
- scq->full = 1;
- wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
- scq->tail != scq->next,
- scq->lock,
- SCQFULL_TIMEOUT);
-
- if (scq->full) {
- spin_unlock_irqrestore(&scq->lock, flags);
- printk("nicstar%d: Timeout pushing TBD.\n",
- card->index);
- return 1;
- }
- }
- *scq->next = *tbd;
- index = (int)(scq->next - scq->base);
- scq->skb[index] = skb;
- XPRINTK("nicstar%d: sending skb at 0x%p (pos %d).\n",
- card->index, skb, index);
- XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n",
- card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2),
- le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4),
- scq->next);
- if (scq->next == scq->last)
- scq->next = scq->base;
- else
- scq->next++;
-
- vc->tbd_count++;
- if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) {
- scq->tbd_count++;
- scq_is_vbr = 1;
- } else
- scq_is_vbr = 0;
-
- if (vc->tbd_count >= MAX_TBD_PER_VC
- || scq->tbd_count >= MAX_TBD_PER_SCQ) {
- int has_run = 0;
-
- while (scq->tail == scq->next) {
- if (!may_sleep) {
- data = scq_virt_to_bus(scq, scq->next);
- ns_write_sram(card, scq->scd, &data, 1);
- spin_unlock_irqrestore(&scq->lock, flags);
- printk("nicstar%d: Error pushing TSR.\n",
- card->index);
- return 0;
- }
-
- scq->full = 1;
- if (has_run++)
- break;
- wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
- scq->tail != scq->next,
- scq->lock,
- SCQFULL_TIMEOUT);
- }
-
- if (!scq->full) {
- tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE);
- if (scq_is_vbr)
- scdi = NS_TSR_SCDISVBR;
- else
- scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE;
- scqi = scq->next - scq->base;
- tsr.word_2 = ns_tsr_mkword_2(scdi, scqi);
- tsr.word_3 = 0x00000000;
- tsr.word_4 = 0x00000000;
-
- *scq->next = tsr;
- index = (int)scqi;
- scq->skb[index] = NULL;
- XPRINTK
- ("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n",
- card->index, le32_to_cpu(tsr.word_1),
- le32_to_cpu(tsr.word_2), le32_to_cpu(tsr.word_3),
- le32_to_cpu(tsr.word_4), scq->next);
- if (scq->next == scq->last)
- scq->next = scq->base;
- else
- scq->next++;
- vc->tbd_count = 0;
- scq->tbd_count = 0;
- } else
- PRINTK("nicstar%d: Timeout pushing TSR.\n",
- card->index);
- }
- data = scq_virt_to_bus(scq, scq->next);
- ns_write_sram(card, scq->scd, &data, 1);
-
- spin_unlock_irqrestore(&scq->lock, flags);
-
- return 0;
-}
-
-static void process_tsq(ns_dev * card)
-{
- u32 scdi;
- scq_info *scq;
- ns_tsi *previous = NULL, *one_ahead, *two_ahead;
- int serviced_entries; /* flag indicating at least on entry was serviced */
-
- serviced_entries = 0;
-
- if (card->tsq.next == card->tsq.last)
- one_ahead = card->tsq.base;
- else
- one_ahead = card->tsq.next + 1;
-
- if (one_ahead == card->tsq.last)
- two_ahead = card->tsq.base;
- else
- two_ahead = one_ahead + 1;
-
- while (!ns_tsi_isempty(card->tsq.next) || !ns_tsi_isempty(one_ahead) ||
- !ns_tsi_isempty(two_ahead))
- /* At most two empty, as stated in the 77201 errata */
- {
- serviced_entries = 1;
-
- /* Skip the one or two possible empty entries */
- while (ns_tsi_isempty(card->tsq.next)) {
- if (card->tsq.next == card->tsq.last)
- card->tsq.next = card->tsq.base;
- else
- card->tsq.next++;
- }
-
- if (!ns_tsi_tmrof(card->tsq.next)) {
- scdi = ns_tsi_getscdindex(card->tsq.next);
- if (scdi == NS_TSI_SCDISVBR)
- scq = card->scq0;
- else {
- if (card->scd2vc[scdi] == NULL) {
- printk
- ("nicstar%d: could not find VC from SCD index.\n",
- card->index);
- ns_tsi_init(card->tsq.next);
- return;
- }
- scq = card->scd2vc[scdi]->scq;
- }
- drain_scq(card, scq, ns_tsi_getscqpos(card->tsq.next));
- scq->full = 0;
- wake_up_interruptible(&(scq->scqfull_waitq));
- }
-
- ns_tsi_init(card->tsq.next);
- previous = card->tsq.next;
- if (card->tsq.next == card->tsq.last)
- card->tsq.next = card->tsq.base;
- else
- card->tsq.next++;
-
- if (card->tsq.next == card->tsq.last)
- one_ahead = card->tsq.base;
- else
- one_ahead = card->tsq.next + 1;
-
- if (one_ahead == card->tsq.last)
- two_ahead = card->tsq.base;
- else
- two_ahead = one_ahead + 1;
- }
-
- if (serviced_entries)
- writel(PTR_DIFF(previous, card->tsq.base),
- card->membase + TSQH);
-}
-
-static void drain_scq(ns_dev * card, scq_info * scq, int pos)
-{
- struct atm_vcc *vcc;
- struct sk_buff *skb;
- int i;
- unsigned long flags;
-
- XPRINTK("nicstar%d: drain_scq() called, scq at 0x%p, pos %d.\n",
- card->index, scq, pos);
- if (pos >= scq->num_entries) {
- printk("nicstar%d: Bad index on drain_scq().\n", card->index);
- return;
- }
-
- spin_lock_irqsave(&scq->lock, flags);
- i = (int)(scq->tail - scq->base);
- if (++i == scq->num_entries)
- i = 0;
- while (i != pos) {
- skb = scq->skb[i];
- XPRINTK("nicstar%d: freeing skb at 0x%p (index %d).\n",
- card->index, skb, i);
- if (skb != NULL) {
- dma_unmap_single(&card->pcidev->dev,
- NS_PRV_DMA(skb),
- skb->len,
- DMA_TO_DEVICE);
- vcc = ATM_SKB(skb)->vcc;
- if (vcc && vcc->pop != NULL) {
- vcc->pop(vcc, skb);
- } else {
- dev_kfree_skb_irq(skb);
- }
- scq->skb[i] = NULL;
- }
- if (++i == scq->num_entries)
- i = 0;
- }
- scq->tail = scq->base + pos;
- spin_unlock_irqrestore(&scq->lock, flags);
-}
-
-static void process_rsq(ns_dev * card)
-{
- ns_rsqe *previous;
-
- if (!ns_rsqe_valid(card->rsq.next))
- return;
- do {
- dequeue_rx(card, card->rsq.next);
- ns_rsqe_init(card->rsq.next);
- previous = card->rsq.next;
- if (card->rsq.next == card->rsq.last)
- card->rsq.next = card->rsq.base;
- else
- card->rsq.next++;
- } while (ns_rsqe_valid(card->rsq.next));
- writel(PTR_DIFF(previous, card->rsq.base), card->membase + RSQH);
-}
-
-static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
-{
- u32 vpi, vci;
- vc_map *vc;
- struct sk_buff *iovb;
- struct iovec *iov;
- struct atm_vcc *vcc;
- struct sk_buff *skb;
- unsigned short aal5_len;
- int len;
- u32 stat;
- u32 id;
-
- stat = readl(card->membase + STAT);
- card->sbfqc = ns_stat_sfbqc_get(stat);
- card->lbfqc = ns_stat_lfbqc_get(stat);
-
- id = le32_to_cpu(rsqe->buffer_handle);
- skb = idr_remove(&card->idr, id);
- if (!skb) {
- RXPRINTK(KERN_ERR
- "nicstar%d: skb not found!\n", card->index);
- return;
- }
- dma_sync_single_for_cpu(&card->pcidev->dev,
- NS_PRV_DMA(skb),
- (NS_PRV_BUFTYPE(skb) == BUF_SM
- ? NS_SMSKBSIZE : NS_LGSKBSIZE),
- DMA_FROM_DEVICE);
- dma_unmap_single(&card->pcidev->dev,
- NS_PRV_DMA(skb),
- (NS_PRV_BUFTYPE(skb) == BUF_SM
- ? NS_SMSKBSIZE : NS_LGSKBSIZE),
- DMA_FROM_DEVICE);
- vpi = ns_rsqe_vpi(rsqe);
- vci = ns_rsqe_vci(rsqe);
- if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) {
- printk("nicstar%d: SDU received for out-of-range vc %d.%d.\n",
- card->index, vpi, vci);
- recycle_rx_buf(card, skb);
- return;
- }
-
- vc = &(card->vcmap[vpi << card->vcibits | vci]);
- if (!vc->rx) {
- RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n",
- card->index, vpi, vci);
- recycle_rx_buf(card, skb);
- return;
- }
-
- vcc = vc->rx_vcc;
-
- if (vcc->qos.aal == ATM_AAL0) {
- struct sk_buff *sb;
- unsigned char *cell;
- int i;
-
- cell = skb->data;
- for (i = ns_rsqe_cellcount(rsqe); i; i--) {
- sb = dev_alloc_skb(NS_SMSKBSIZE);
- if (!sb) {
- printk
- ("nicstar%d: Can't allocate buffers for aal0.\n",
- card->index);
- atomic_add(i, &vcc->stats->rx_drop);
- break;
- }
- if (!atm_charge(vcc, sb->truesize)) {
- RXPRINTK
- ("nicstar%d: atm_charge() dropped aal0 packets.\n",
- card->index);
- atomic_add(i - 1, &vcc->stats->rx_drop); /* already increased by 1 */
- dev_kfree_skb_any(sb);
- break;
- }
- /* Rebuild the header */
- *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 |
- (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000);
- if (i == 1 && ns_rsqe_eopdu(rsqe))
- *((u32 *) sb->data) |= 0x00000002;
- skb_put(sb, NS_AAL0_HEADER);
- memcpy(skb_tail_pointer(sb), cell, ATM_CELL_PAYLOAD);
- skb_put(sb, ATM_CELL_PAYLOAD);
- ATM_SKB(sb)->vcc = vcc;
- __net_timestamp(sb);
- vcc->push(vcc, sb);
- atomic_inc(&vcc->stats->rx);
- cell += ATM_CELL_PAYLOAD;
- }
-
- recycle_rx_buf(card, skb);
- return;
- }
-
- /* To reach this point, the AAL layer can only be AAL5 */
-
- if ((iovb = vc->rx_iov) == NULL) {
- iovb = skb_dequeue(&(card->iovpool.queue));
- if (iovb == NULL) { /* No buffers in the queue */
- iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC);
- if (iovb == NULL) {
- printk("nicstar%d: Out of iovec buffers.\n",
- card->index);
- atomic_inc(&vcc->stats->rx_drop);
- recycle_rx_buf(card, skb);
- return;
- }
- NS_PRV_BUFTYPE(iovb) = BUF_NONE;
- } else if (--card->iovpool.count < card->iovnr.min) {
- struct sk_buff *new_iovb;
- if ((new_iovb =
- alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL) {
- NS_PRV_BUFTYPE(iovb) = BUF_NONE;
- skb_queue_tail(&card->iovpool.queue, new_iovb);
- card->iovpool.count++;
- }
- }
- vc->rx_iov = iovb;
- NS_PRV_IOVCNT(iovb) = 0;
- iovb->len = 0;
- iovb->data = iovb->head;
- skb_reset_tail_pointer(iovb);
- /* IMPORTANT: a pointer to the sk_buff containing the small or large
- buffer is stored as iovec base, NOT a pointer to the
- small or large buffer itself. */
- } else if (NS_PRV_IOVCNT(iovb) >= NS_MAX_IOVECS) {
- printk("nicstar%d: received too big AAL5 SDU.\n", card->index);
- atomic_inc(&vcc->stats->rx_err);
- recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
- NS_MAX_IOVECS);
- NS_PRV_IOVCNT(iovb) = 0;
- iovb->len = 0;
- iovb->data = iovb->head;
- skb_reset_tail_pointer(iovb);
- }
- iov = &((struct iovec *)iovb->data)[NS_PRV_IOVCNT(iovb)++];
- iov->iov_base = (void *)skb;
- iov->iov_len = ns_rsqe_cellcount(rsqe) * 48;
- iovb->len += iov->iov_len;
-
-#ifdef EXTRA_DEBUG
- if (NS_PRV_IOVCNT(iovb) == 1) {
- if (NS_PRV_BUFTYPE(skb) != BUF_SM) {
- printk
- ("nicstar%d: Expected a small buffer, and this is not one.\n",
- card->index);
- which_list(card, skb);
- atomic_inc(&vcc->stats->rx_err);
- recycle_rx_buf(card, skb);
- vc->rx_iov = NULL;
- recycle_iov_buf(card, iovb);
- return;
- }
- } else { /* NS_PRV_IOVCNT(iovb) >= 2 */
-
- if (NS_PRV_BUFTYPE(skb) != BUF_LG) {
- printk
- ("nicstar%d: Expected a large buffer, and this is not one.\n",
- card->index);
- which_list(card, skb);
- atomic_inc(&vcc->stats->rx_err);
- recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
- NS_PRV_IOVCNT(iovb));
- vc->rx_iov = NULL;
- recycle_iov_buf(card, iovb);
- return;
- }
- }
-#endif /* EXTRA_DEBUG */
-
- if (ns_rsqe_eopdu(rsqe)) {
- /* This works correctly regardless of the endianness of the host */
- unsigned char *L1L2 = (unsigned char *)
- (skb->data + iov->iov_len - 6);
- aal5_len = L1L2[0] << 8 | L1L2[1];
- len = (aal5_len == 0x0000) ? 0x10000 : aal5_len;
- if (ns_rsqe_crcerr(rsqe) ||
- len + 8 > iovb->len || len + (47 + 8) < iovb->len) {
- printk("nicstar%d: AAL5 CRC error", card->index);
- if (len + 8 > iovb->len || len + (47 + 8) < iovb->len)
- printk(" - PDU size mismatch.\n");
- else
- printk(".\n");
- atomic_inc(&vcc->stats->rx_err);
- recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
- NS_PRV_IOVCNT(iovb));
- vc->rx_iov = NULL;
- recycle_iov_buf(card, iovb);
- return;
- }
-
- /* By this point we (hopefully) have a complete SDU without errors. */
-
- if (NS_PRV_IOVCNT(iovb) == 1) { /* Just a small buffer */
- /* skb points to a small buffer */
- if (!atm_charge(vcc, skb->truesize)) {
- push_rxbufs(card, skb);
- atomic_inc(&vcc->stats->rx_drop);
- } else {
- skb_put(skb, len);
- dequeue_sm_buf(card, skb);
- ATM_SKB(skb)->vcc = vcc;
- __net_timestamp(skb);
- vcc->push(vcc, skb);
- atomic_inc(&vcc->stats->rx);
- }
- } else if (NS_PRV_IOVCNT(iovb) == 2) { /* One small plus one large buffer */
- struct sk_buff *sb;
-
- sb = (struct sk_buff *)(iov - 1)->iov_base;
- /* skb points to a large buffer */
-
- if (len <= NS_SMBUFSIZE) {
- if (!atm_charge(vcc, sb->truesize)) {
- push_rxbufs(card, sb);
- atomic_inc(&vcc->stats->rx_drop);
- } else {
- skb_put(sb, len);
- dequeue_sm_buf(card, sb);
- ATM_SKB(sb)->vcc = vcc;
- __net_timestamp(sb);
- vcc->push(vcc, sb);
- atomic_inc(&vcc->stats->rx);
- }
-
- push_rxbufs(card, skb);
-
- } else { /* len > NS_SMBUFSIZE, the usual case */
-
- if (!atm_charge(vcc, skb->truesize)) {
- push_rxbufs(card, skb);
- atomic_inc(&vcc->stats->rx_drop);
- } else {
- dequeue_lg_buf(card, skb);
- skb_push(skb, NS_SMBUFSIZE);
- skb_copy_from_linear_data(sb, skb->data,
- NS_SMBUFSIZE);
- skb_put(skb, len - NS_SMBUFSIZE);
- ATM_SKB(skb)->vcc = vcc;
- __net_timestamp(skb);
- vcc->push(vcc, skb);
- atomic_inc(&vcc->stats->rx);
- }
-
- push_rxbufs(card, sb);
-
- }
-
- } else { /* Must push a huge buffer */
-
- struct sk_buff *hb, *sb, *lb;
- int remaining, tocopy;
- int j;
-
- hb = skb_dequeue(&(card->hbpool.queue));
- if (hb == NULL) { /* No buffers in the queue */
-
- hb = dev_alloc_skb(NS_HBUFSIZE);
- if (hb == NULL) {
- printk
- ("nicstar%d: Out of huge buffers.\n",
- card->index);
- atomic_inc(&vcc->stats->rx_drop);
- recycle_iovec_rx_bufs(card,
- (struct iovec *)
- iovb->data,
- NS_PRV_IOVCNT(iovb));
- vc->rx_iov = NULL;
- recycle_iov_buf(card, iovb);
- return;
- } else if (card->hbpool.count < card->hbnr.min) {
- struct sk_buff *new_hb;
- if ((new_hb =
- dev_alloc_skb(NS_HBUFSIZE)) !=
- NULL) {
- skb_queue_tail(&card->hbpool.
- queue, new_hb);
- card->hbpool.count++;
- }
- }
- NS_PRV_BUFTYPE(hb) = BUF_NONE;
- } else if (--card->hbpool.count < card->hbnr.min) {
- struct sk_buff *new_hb;
- if ((new_hb =
- dev_alloc_skb(NS_HBUFSIZE)) != NULL) {
- NS_PRV_BUFTYPE(new_hb) = BUF_NONE;
- skb_queue_tail(&card->hbpool.queue,
- new_hb);
- card->hbpool.count++;
- }
- if (card->hbpool.count < card->hbnr.min) {
- if ((new_hb =
- dev_alloc_skb(NS_HBUFSIZE)) !=
- NULL) {
- NS_PRV_BUFTYPE(new_hb) =
- BUF_NONE;
- skb_queue_tail(&card->hbpool.
- queue, new_hb);
- card->hbpool.count++;
- }
- }
- }
-
- iov = (struct iovec *)iovb->data;
-
- if (!atm_charge(vcc, hb->truesize)) {
- recycle_iovec_rx_bufs(card, iov,
- NS_PRV_IOVCNT(iovb));
- if (card->hbpool.count < card->hbnr.max) {
- skb_queue_tail(&card->hbpool.queue, hb);
- card->hbpool.count++;
- } else
- dev_kfree_skb_any(hb);
- atomic_inc(&vcc->stats->rx_drop);
- } else {
- /* Copy the small buffer to the huge buffer */
- sb = (struct sk_buff *)iov->iov_base;
- skb_copy_from_linear_data(sb, hb->data,
- iov->iov_len);
- skb_put(hb, iov->iov_len);
- remaining = len - iov->iov_len;
- iov++;
- /* Free the small buffer */
- push_rxbufs(card, sb);
-
- /* Copy all large buffers to the huge buffer and free them */
- for (j = 1; j < NS_PRV_IOVCNT(iovb); j++) {
- lb = (struct sk_buff *)iov->iov_base;
- tocopy =
- min_t(int, remaining, iov->iov_len);
- skb_copy_from_linear_data(lb,
- skb_tail_pointer
- (hb), tocopy);
- skb_put(hb, tocopy);
- iov++;
- remaining -= tocopy;
- push_rxbufs(card, lb);
- }
-#ifdef EXTRA_DEBUG
- if (remaining != 0 || hb->len != len)
- printk
- ("nicstar%d: Huge buffer len mismatch.\n",
- card->index);
-#endif /* EXTRA_DEBUG */
- ATM_SKB(hb)->vcc = vcc;
- __net_timestamp(hb);
- vcc->push(vcc, hb);
- atomic_inc(&vcc->stats->rx);
- }
- }
-
- vc->rx_iov = NULL;
- recycle_iov_buf(card, iovb);
- }
-
-}
-
-static void recycle_rx_buf(ns_dev * card, struct sk_buff *skb)
-{
- if (unlikely(NS_PRV_BUFTYPE(skb) == BUF_NONE)) {
- printk("nicstar%d: What kind of rx buffer is this?\n",
- card->index);
- dev_kfree_skb_any(skb);
- } else
- push_rxbufs(card, skb);
-}
-
-static void recycle_iovec_rx_bufs(ns_dev * card, struct iovec *iov, int count)
-{
- while (count-- > 0)
- recycle_rx_buf(card, (struct sk_buff *)(iov++)->iov_base);
-}
-
-static void recycle_iov_buf(ns_dev * card, struct sk_buff *iovb)
-{
- if (card->iovpool.count < card->iovnr.max) {
- skb_queue_tail(&card->iovpool.queue, iovb);
- card->iovpool.count++;
- } else
- dev_kfree_skb_any(iovb);
-}
-
-static void dequeue_sm_buf(ns_dev * card, struct sk_buff *sb)
-{
- skb_unlink(sb, &card->sbpool.queue);
- if (card->sbfqc < card->sbnr.init) {
- struct sk_buff *new_sb;
- if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) {
- NS_PRV_BUFTYPE(new_sb) = BUF_SM;
- skb_queue_tail(&card->sbpool.queue, new_sb);
- skb_reserve(new_sb, NS_AAL0_HEADER);
- push_rxbufs(card, new_sb);
- }
- }
- if (card->sbfqc < card->sbnr.init)
- {
- struct sk_buff *new_sb;
- if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) {
- NS_PRV_BUFTYPE(new_sb) = BUF_SM;
- skb_queue_tail(&card->sbpool.queue, new_sb);
- skb_reserve(new_sb, NS_AAL0_HEADER);
- push_rxbufs(card, new_sb);
- }
- }
-}
-
-static void dequeue_lg_buf(ns_dev * card, struct sk_buff *lb)
-{
- skb_unlink(lb, &card->lbpool.queue);
- if (card->lbfqc < card->lbnr.init) {
- struct sk_buff *new_lb;
- if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) {
- NS_PRV_BUFTYPE(new_lb) = BUF_LG;
- skb_queue_tail(&card->lbpool.queue, new_lb);
- skb_reserve(new_lb, NS_SMBUFSIZE);
- push_rxbufs(card, new_lb);
- }
- }
- if (card->lbfqc < card->lbnr.init)
- {
- struct sk_buff *new_lb;
- if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) {
- NS_PRV_BUFTYPE(new_lb) = BUF_LG;
- skb_queue_tail(&card->lbpool.queue, new_lb);
- skb_reserve(new_lb, NS_SMBUFSIZE);
- push_rxbufs(card, new_lb);
- }
- }
-}
-
-static int ns_proc_read(struct atm_dev *dev, loff_t * pos, char *page)
-{
- u32 stat;
- ns_dev *card;
- int left;
-
- left = (int)*pos;
- card = (ns_dev *) dev->dev_data;
- stat = readl(card->membase + STAT);
- if (!left--)
- return sprintf(page, "Pool count min init max \n");
- if (!left--)
- return sprintf(page, "Small %5d %5d %5d %5d \n",
- ns_stat_sfbqc_get(stat), card->sbnr.min,
- card->sbnr.init, card->sbnr.max);
- if (!left--)
- return sprintf(page, "Large %5d %5d %5d %5d \n",
- ns_stat_lfbqc_get(stat), card->lbnr.min,
- card->lbnr.init, card->lbnr.max);
- if (!left--)
- return sprintf(page, "Huge %5d %5d %5d %5d \n",
- card->hbpool.count, card->hbnr.min,
- card->hbnr.init, card->hbnr.max);
- if (!left--)
- return sprintf(page, "Iovec %5d %5d %5d %5d \n",
- card->iovpool.count, card->iovnr.min,
- card->iovnr.init, card->iovnr.max);
- if (!left--) {
- int retval;
- retval =
- sprintf(page, "Interrupt counter: %u \n", card->intcnt);
- card->intcnt = 0;
- return retval;
- }
-#if 0
- /* Dump 25.6 Mbps PHY registers */
- /* Now there's a 25.6 Mbps PHY driver this code isn't needed. I left it
- here just in case it's needed for debugging. */
- if (card->max_pcr == ATM_25_PCR && !left--) {
- u32 phy_regs[4];
- u32 i;
-
- for (i = 0; i < 4; i++) {
- while (CMD_BUSY(card)) ;
- writel(NS_CMD_READ_UTILITY | 0x00000200 | i,
- card->membase + CMD);
- while (CMD_BUSY(card)) ;
- phy_regs[i] = readl(card->membase + DR0) & 0x000000FF;
- }
-
- return sprintf(page, "PHY regs: 0x%02X 0x%02X 0x%02X 0x%02X \n",
- phy_regs[0], phy_regs[1], phy_regs[2],
- phy_regs[3]);
- }
-#endif /* 0 - Dump 25.6 Mbps PHY registers */
-#if 0
- /* Dump TST */
- if (left-- < NS_TST_NUM_ENTRIES) {
- if (card->tste2vc[left + 1] == NULL)
- return sprintf(page, "%5d - VBR/UBR \n", left + 1);
- else
- return sprintf(page, "%5d - %d %d \n", left + 1,
- card->tste2vc[left + 1]->tx_vcc->vpi,
- card->tste2vc[left + 1]->tx_vcc->vci);
- }
-#endif /* 0 */
- return 0;
-}
-
-static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg)
-{
- ns_dev *card;
- pool_levels pl;
- long btype;
- unsigned long flags;
-
- card = dev->dev_data;
- switch (cmd) {
- case NS_GETPSTAT:
- if (get_user
- (pl.buftype, &((pool_levels __user *) arg)->buftype))
- return -EFAULT;
- switch (pl.buftype) {
- case NS_BUFTYPE_SMALL:
- pl.count =
- ns_stat_sfbqc_get(readl(card->membase + STAT));
- pl.level.min = card->sbnr.min;
- pl.level.init = card->sbnr.init;
- pl.level.max = card->sbnr.max;
- break;
-
- case NS_BUFTYPE_LARGE:
- pl.count =
- ns_stat_lfbqc_get(readl(card->membase + STAT));
- pl.level.min = card->lbnr.min;
- pl.level.init = card->lbnr.init;
- pl.level.max = card->lbnr.max;
- break;
-
- case NS_BUFTYPE_HUGE:
- pl.count = card->hbpool.count;
- pl.level.min = card->hbnr.min;
- pl.level.init = card->hbnr.init;
- pl.level.max = card->hbnr.max;
- break;
-
- case NS_BUFTYPE_IOVEC:
- pl.count = card->iovpool.count;
- pl.level.min = card->iovnr.min;
- pl.level.init = card->iovnr.init;
- pl.level.max = card->iovnr.max;
- break;
-
- default:
- return -ENOIOCTLCMD;
-
- }
- if (!copy_to_user((pool_levels __user *) arg, &pl, sizeof(pl)))
- return (sizeof(pl));
- else
- return -EFAULT;
-
- case NS_SETBUFLEV:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (copy_from_user(&pl, (pool_levels __user *) arg, sizeof(pl)))
- return -EFAULT;
- if (pl.level.min >= pl.level.init
- || pl.level.init >= pl.level.max)
- return -EINVAL;
- if (pl.level.min == 0)
- return -EINVAL;
- switch (pl.buftype) {
- case NS_BUFTYPE_SMALL:
- if (pl.level.max > TOP_SB)
- return -EINVAL;
- card->sbnr.min = pl.level.min;
- card->sbnr.init = pl.level.init;
- card->sbnr.max = pl.level.max;
- break;
-
- case NS_BUFTYPE_LARGE:
- if (pl.level.max > TOP_LB)
- return -EINVAL;
- card->lbnr.min = pl.level.min;
- card->lbnr.init = pl.level.init;
- card->lbnr.max = pl.level.max;
- break;
-
- case NS_BUFTYPE_HUGE:
- if (pl.level.max > TOP_HB)
- return -EINVAL;
- card->hbnr.min = pl.level.min;
- card->hbnr.init = pl.level.init;
- card->hbnr.max = pl.level.max;
- break;
-
- case NS_BUFTYPE_IOVEC:
- if (pl.level.max > TOP_IOVB)
- return -EINVAL;
- card->iovnr.min = pl.level.min;
- card->iovnr.init = pl.level.init;
- card->iovnr.max = pl.level.max;
- break;
-
- default:
- return -EINVAL;
-
- }
- return 0;
-
- case NS_ADJBUFLEV:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- btype = (long)arg; /* a long is the same size as a pointer or bigger */
- switch (btype) {
- case NS_BUFTYPE_SMALL:
- while (card->sbfqc < card->sbnr.init) {
- struct sk_buff *sb;
-
- sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
- if (sb == NULL)
- return -ENOMEM;
- NS_PRV_BUFTYPE(sb) = BUF_SM;
- skb_queue_tail(&card->sbpool.queue, sb);
- skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, sb);
- }
- break;
-
- case NS_BUFTYPE_LARGE:
- while (card->lbfqc < card->lbnr.init) {
- struct sk_buff *lb;
-
- lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
- if (lb == NULL)
- return -ENOMEM;
- NS_PRV_BUFTYPE(lb) = BUF_LG;
- skb_queue_tail(&card->lbpool.queue, lb);
- skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, lb);
- }
- break;
-
- case NS_BUFTYPE_HUGE:
- while (card->hbpool.count > card->hbnr.init) {
- struct sk_buff *hb;
-
- spin_lock_irqsave(&card->int_lock, flags);
- hb = skb_dequeue(&card->hbpool.queue);
- card->hbpool.count--;
- spin_unlock_irqrestore(&card->int_lock, flags);
- if (hb == NULL)
- printk
- ("nicstar%d: huge buffer count inconsistent.\n",
- card->index);
- else
- dev_kfree_skb_any(hb);
-
- }
- while (card->hbpool.count < card->hbnr.init) {
- struct sk_buff *hb;
-
- hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
- if (hb == NULL)
- return -ENOMEM;
- NS_PRV_BUFTYPE(hb) = BUF_NONE;
- spin_lock_irqsave(&card->int_lock, flags);
- skb_queue_tail(&card->hbpool.queue, hb);
- card->hbpool.count++;
- spin_unlock_irqrestore(&card->int_lock, flags);
- }
- break;
-
- case NS_BUFTYPE_IOVEC:
- while (card->iovpool.count > card->iovnr.init) {
- struct sk_buff *iovb;
-
- spin_lock_irqsave(&card->int_lock, flags);
- iovb = skb_dequeue(&card->iovpool.queue);
- card->iovpool.count--;
- spin_unlock_irqrestore(&card->int_lock, flags);
- if (iovb == NULL)
- printk
- ("nicstar%d: iovec buffer count inconsistent.\n",
- card->index);
- else
- dev_kfree_skb_any(iovb);
-
- }
- while (card->iovpool.count < card->iovnr.init) {
- struct sk_buff *iovb;
-
- iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);
- if (iovb == NULL)
- return -ENOMEM;
- NS_PRV_BUFTYPE(iovb) = BUF_NONE;
- spin_lock_irqsave(&card->int_lock, flags);
- skb_queue_tail(&card->iovpool.queue, iovb);
- card->iovpool.count++;
- spin_unlock_irqrestore(&card->int_lock, flags);
- }
- break;
-
- default:
- return -EINVAL;
-
- }
- return 0;
-
- default:
- if (dev->phy && dev->phy->ioctl) {
- return dev->phy->ioctl(dev, cmd, arg);
- } else {
- printk("nicstar%d: %s == NULL \n", card->index,
- dev->phy ? "dev->phy->ioctl" : "dev->phy");
- return -ENOIOCTLCMD;
- }
- }
-}
-
-#ifdef EXTRA_DEBUG
-static void which_list(ns_dev * card, struct sk_buff *skb)
-{
- printk("skb buf_type: 0x%08x\n", NS_PRV_BUFTYPE(skb));
-}
-#endif /* EXTRA_DEBUG */
-
-static void ns_poll(struct timer_list *unused)
-{
- int i;
- ns_dev *card;
- unsigned long flags;
- u32 stat_r, stat_w;
-
- PRINTK("nicstar: Entering ns_poll().\n");
- for (i = 0; i < num_cards; i++) {
- card = cards[i];
- if (!spin_trylock_irqsave(&card->int_lock, flags)) {
- /* Probably it isn't worth spinning */
- continue;
- }
-
- stat_w = 0;
- stat_r = readl(card->membase + STAT);
- if (stat_r & NS_STAT_TSIF)
- stat_w |= NS_STAT_TSIF;
- if (stat_r & NS_STAT_EOPDU)
- stat_w |= NS_STAT_EOPDU;
-
- process_tsq(card);
- process_rsq(card);
-
- writel(stat_w, card->membase + STAT);
- spin_unlock_irqrestore(&card->int_lock, flags);
- }
- mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD);
- PRINTK("nicstar: Leaving ns_poll().\n");
-}
-
-static void ns_phy_put(struct atm_dev *dev, unsigned char value,
- unsigned long addr)
-{
- ns_dev *card;
- unsigned long flags;
-
- card = dev->dev_data;
- spin_lock_irqsave(&card->res_lock, flags);
- while (CMD_BUSY(card)) ;
- writel((u32) value, card->membase + DR0);
- writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF),
- card->membase + CMD);
- spin_unlock_irqrestore(&card->res_lock, flags);
-}
-
-static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr)
-{
- ns_dev *card;
- unsigned long flags;
- u32 data;
-
- card = dev->dev_data;
- spin_lock_irqsave(&card->res_lock, flags);
- while (CMD_BUSY(card)) ;
- writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF),
- card->membase + CMD);
- while (CMD_BUSY(card)) ;
- data = readl(card->membase + DR0) & 0x000000FF;
- spin_unlock_irqrestore(&card->res_lock, flags);
- return (unsigned char)data;
-}
-
-module_init(nicstar_init);
-module_exit(nicstar_cleanup);
diff --git a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c
deleted file mode 100644
index 791f69a07ddf..000000000000
--- a/drivers/atm/nicstarmac.c
+++ /dev/null
@@ -1,244 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * this file included by nicstar.c
- */
-
-/*
- * nicstarmac.c
- * Read this ForeRunner's MAC address from eprom/eeprom
- */
-
-#include <linux/kernel.h>
-
-typedef void __iomem *virt_addr_t;
-
-#define CYCLE_DELAY 5
-
-#define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \
- udelay((useconds));}
-/*
- * The following tables represent the timing diagrams found in
- * the Data Sheet for the Xicor X25020 EEProm. The #defines below
- * represent the bits in the NICStAR's General Purpose register
- * that must be toggled for the corresponding actions on the EEProm
- * to occur.
- */
-
-/* Write Data To EEProm from SI line on rising edge of CLK */
-/* Read Data From EEProm on falling edge of CLK */
-
-#define CS_HIGH 0x0002 /* Chip select high */
-#define CS_LOW 0x0000 /* Chip select low (active low) */
-#define CLK_HIGH 0x0004 /* Clock high */
-#define CLK_LOW 0x0000 /* Clock low */
-#define SI_HIGH 0x0001 /* Serial input data high */
-#define SI_LOW 0x0000 /* Serial input data low */
-
-/* Read Status Register = 0000 0101b */
-#if 0
-static u_int32_t rdsrtab[] = {
- CS_HIGH | CLK_HIGH,
- CS_LOW | CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW | SI_HIGH,
- CLK_HIGH | SI_HIGH, /* 1 */
- CLK_LOW | SI_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW | SI_HIGH,
- CLK_HIGH | SI_HIGH /* 1 */
-};
-#endif /* 0 */
-
-/* Read from EEPROM = 0000 0011b */
-static u_int32_t readtab[] = {
- /*
- CS_HIGH | CLK_HIGH,
- */
- CS_LOW | CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW,
- CLK_HIGH, /* 0 */
- CLK_LOW | SI_HIGH,
- CLK_HIGH | SI_HIGH, /* 1 */
- CLK_LOW | SI_HIGH,
- CLK_HIGH | SI_HIGH /* 1 */
-};
-
-/* Clock to read from/write to the eeprom */
-static u_int32_t clocktab[] = {
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW,
- CLK_HIGH,
- CLK_LOW
-};
-
-#define NICSTAR_REG_WRITE(bs, reg, val) \
- while ( readl(bs + STAT) & 0x0200 ) ; \
- writel((val),(base)+(reg))
-#define NICSTAR_REG_READ(bs, reg) \
- readl((base)+(reg))
-#define NICSTAR_REG_GENERAL_PURPOSE GP
-
-/*
- * This routine will clock the Read_Status_reg function into the X2520
- * eeprom, then pull the result from bit 16 of the NicSTaR's General Purpose
- * register.
- */
-#if 0
-u_int32_t nicstar_read_eprom_status(virt_addr_t base)
-{
- u_int32_t val;
- u_int32_t rbyte;
- int32_t i, j;
-
- /* Send read instruction */
- val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
-
- for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | rdsrtab[i]));
- osp_MicroDelay(CYCLE_DELAY);
- }
-
- /* Done sending instruction - now pull data off of bit 16, MSB first */
- /* Data clocked out of eeprom on falling edge of clock */
-
- rbyte = 0;
- for (i = 7, j = 0; i >= 0; i--) {
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | clocktab[j++]));
- rbyte |= (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
- & 0x00010000) >> 16) << i);
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | clocktab[j++]));
- osp_MicroDelay(CYCLE_DELAY);
- }
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
- osp_MicroDelay(CYCLE_DELAY);
- return rbyte;
-}
-#endif /* 0 */
-
-/*
- * This routine will clock the Read_data function into the X2520
- * eeprom, followed by the address to read from, through the NicSTaR's General
- * Purpose register.
- */
-
-static u_int8_t read_eprom_byte(virt_addr_t base, u_int8_t offset)
-{
- u_int32_t val = 0;
- int i, j = 0;
- u_int8_t tempread = 0;
-
- val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
-
- /* Send READ instruction */
- for (i = 0; i < ARRAY_SIZE(readtab); i++) {
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | readtab[i]));
- osp_MicroDelay(CYCLE_DELAY);
- }
-
- /* Next, we need to send the byte address to read from */
- for (i = 7; i >= 0; i--) {
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | clocktab[j++] | ((offset >> i) & 1)));
- osp_MicroDelay(CYCLE_DELAY);
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | clocktab[j++] | ((offset >> i) & 1)));
- osp_MicroDelay(CYCLE_DELAY);
- }
-
- j = 0;
-
- /* Now, we can read data from the eeprom by clocking it in */
- for (i = 7; i >= 0; i--) {
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | clocktab[j++]));
- osp_MicroDelay(CYCLE_DELAY);
- tempread |=
- (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
- & 0x00010000) >> 16) << i);
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | clocktab[j++]));
- osp_MicroDelay(CYCLE_DELAY);
- }
-
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
- osp_MicroDelay(CYCLE_DELAY);
- return tempread;
-}
-
-static void nicstar_init_eprom(virt_addr_t base)
-{
- u_int32_t val;
-
- /*
- * turn chip select off
- */
- val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
-
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | CS_HIGH | CLK_HIGH));
- osp_MicroDelay(CYCLE_DELAY);
-
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | CS_HIGH | CLK_LOW));
- osp_MicroDelay(CYCLE_DELAY);
-
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | CS_HIGH | CLK_HIGH));
- osp_MicroDelay(CYCLE_DELAY);
-
- NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
- (val | CS_HIGH | CLK_LOW));
- osp_MicroDelay(CYCLE_DELAY);
-}
-
-/*
- * This routine will be the interface to the ReadPromByte function
- * above.
- */
-
-static void
-nicstar_read_eprom(virt_addr_t base,
- u_int8_t prom_offset, u_int8_t * buffer, u_int32_t nbytes)
-{
- u_int i;
-
- for (i = 0; i < nbytes; i++) {
- buffer[i] = read_eprom_byte(base, prom_offset);
- ++prom_offset;
- osp_MicroDelay(CYCLE_DELAY);
- }
-}
diff --git a/drivers/atm/solos-attrlist.c b/drivers/atm/solos-attrlist.c
deleted file mode 100644
index 1830d1b8619f..000000000000
--- a/drivers/atm/solos-attrlist.c
+++ /dev/null
@@ -1,83 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-SOLOS_ATTR_RO(DriverVersion)
-SOLOS_ATTR_RO(APIVersion)
-SOLOS_ATTR_RO(FirmwareVersion)
-SOLOS_ATTR_RO(Version)
-// SOLOS_ATTR_RO(DspVersion)
-// SOLOS_ATTR_RO(CommonHandshake)
-SOLOS_ATTR_RO(Connected)
-SOLOS_ATTR_RO(OperationalMode)
-SOLOS_ATTR_RO(State)
-SOLOS_ATTR_RO(Watchdog)
-SOLOS_ATTR_RO(OperationProgress)
-SOLOS_ATTR_RO(LastFailed)
-SOLOS_ATTR_RO(TxBitRate)
-SOLOS_ATTR_RO(RxBitRate)
-// SOLOS_ATTR_RO(DeltACTATPds)
-// SOLOS_ATTR_RO(DeltACTATPus)
-SOLOS_ATTR_RO(TxATTNDR)
-SOLOS_ATTR_RO(RxATTNDR)
-SOLOS_ATTR_RO(AnnexType)
-SOLOS_ATTR_RO(GeneralFailure)
-SOLOS_ATTR_RO(InterleaveDpDn)
-SOLOS_ATTR_RO(InterleaveDpUp)
-SOLOS_ATTR_RO(RSCorrectedErrorsDn)
-SOLOS_ATTR_RO(RSUnCorrectedErrorsDn)
-SOLOS_ATTR_RO(RSCorrectedErrorsUp)
-SOLOS_ATTR_RO(RSUnCorrectedErrorsUp)
-SOLOS_ATTR_RO(InterleaveRDn)
-SOLOS_ATTR_RO(InterleaveRUp)
-SOLOS_ATTR_RO(BisRDn)
-SOLOS_ATTR_RO(BisRUp)
-SOLOS_ATTR_RO(INPdown)
-SOLOS_ATTR_RO(INPup)
-SOLOS_ATTR_RO(ShowtimeStart)
-SOLOS_ATTR_RO(ATURVendor)
-SOLOS_ATTR_RO(ATUCCountry)
-SOLOS_ATTR_RO(ATURANSIRev)
-SOLOS_ATTR_RO(ATURANSISTD)
-SOLOS_ATTR_RO(ATUCANSIRev)
-SOLOS_ATTR_RO(ATUCANSIId)
-SOLOS_ATTR_RO(ATUCANSISTD)
-SOLOS_ATTR_RO(DataBoost)
-SOLOS_ATTR_RO(LocalITUCountryCode)
-SOLOS_ATTR_RO(LocalSEF)
-SOLOS_ATTR_RO(LocalEndLOS)
-SOLOS_ATTR_RO(LocalSNRMargin)
-SOLOS_ATTR_RO(LocalLineAttn)
-SOLOS_ATTR_RO(RawAttn)
-SOLOS_ATTR_RO(LocalTxPower)
-SOLOS_ATTR_RO(RemoteTxPower)
-SOLOS_ATTR_RO(RemoteSEF)
-SOLOS_ATTR_RO(RemoteLOS)
-SOLOS_ATTR_RO(RemoteLineAttn)
-SOLOS_ATTR_RO(RemoteSNRMargin)
-SOLOS_ATTR_RO(LineUpCount)
-SOLOS_ATTR_RO(SRACnt)
-SOLOS_ATTR_RO(SRACntUp)
-SOLOS_ATTR_RO(ProfileStatus)
-SOLOS_ATTR_RW(Action)
-SOLOS_ATTR_RW(ActivateLine)
-SOLOS_ATTR_RO(LineStatus)
-SOLOS_ATTR_RW(HostControl)
-SOLOS_ATTR_RW(AutoStart)
-SOLOS_ATTR_RW(Failsafe)
-SOLOS_ATTR_RW(ShowtimeLed)
-SOLOS_ATTR_RW(Retrain)
-SOLOS_ATTR_RW(Defaults)
-SOLOS_ATTR_RW(LineMode)
-SOLOS_ATTR_RW(Profile)
-SOLOS_ATTR_RW(DetectNoise)
-SOLOS_ATTR_RW(BisAForceSNRMarginDn)
-SOLOS_ATTR_RW(BisMForceSNRMarginDn)
-SOLOS_ATTR_RW(BisAMaxMargin)
-SOLOS_ATTR_RW(BisMMaxMargin)
-SOLOS_ATTR_RW(AnnexAForceSNRMarginDn)
-SOLOS_ATTR_RW(AnnexAMaxMargin)
-SOLOS_ATTR_RW(AnnexMMaxMargin)
-SOLOS_ATTR_RO(SupportedAnnexes)
-SOLOS_ATTR_RO(Status)
-SOLOS_ATTR_RO(TotalStart)
-SOLOS_ATTR_RO(RecentShowtimeStart)
-SOLOS_ATTR_RO(TotalRxBlocks)
-SOLOS_ATTR_RO(TotalTxBlocks)
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
deleted file mode 100644
index 24c764664c24..000000000000
--- a/drivers/atm/solos-pci.c
+++ /dev/null
@@ -1,1496 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for the Solos PCI ADSL2+ card, designed to support Linux by
- * Traverse Technologies -- https://www.traverse.com.au/
- * Xrio Limited -- http://www.xrio.com/
- *
- * Copyright © 2008 Traverse Technologies
- * Copyright © 2008 Intel Corporation
- *
- * Authors: Nathan Williams <nathan@traverse.com.au>
- * David Woodhouse <dwmw2@infradead.org>
- * Treker Chen <treker@xrio.com>
- */
-
-#define DEBUG
-#define VERBOSE_DEBUG
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/skbuff.h>
-#include <linux/sysfs.h>
-#include <linux/device.h>
-#include <linux/kobject.h>
-#include <linux/firmware.h>
-#include <linux/ctype.h>
-#include <linux/swab.h>
-#include <linux/slab.h>
-
-#define VERSION "1.04"
-#define DRIVER_VERSION 0x01
-#define PTAG "solos-pci"
-
-#define CONFIG_RAM_SIZE 128
-#define FLAGS_ADDR 0x7C
-#define IRQ_EN_ADDR 0x78
-#define FPGA_VER 0x74
-#define IRQ_CLEAR 0x70
-#define WRITE_FLASH 0x6C
-#define PORTS 0x68
-#define FLASH_BLOCK 0x64
-#define FLASH_BUSY 0x60
-#define FPGA_MODE 0x5C
-#define FLASH_MODE 0x58
-#define GPIO_STATUS 0x54
-#define DRIVER_VER 0x50
-#define TX_DMA_ADDR(port) (0x40 + (4 * (port)))
-#define RX_DMA_ADDR(port) (0x30 + (4 * (port)))
-
-#define DATA_RAM_SIZE 32768
-#define BUF_SIZE 2048
-#define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/
-/* Old boards use ATMEL AD45DB161D flash */
-#define ATMEL_FPGA_PAGE 528 /* FPGA flash page size*/
-#define ATMEL_SOLOS_PAGE 512 /* Solos flash page size*/
-#define ATMEL_FPGA_BLOCK (ATMEL_FPGA_PAGE * 8) /* FPGA block size*/
-#define ATMEL_SOLOS_BLOCK (ATMEL_SOLOS_PAGE * 8) /* Solos block size*/
-/* Current boards use M25P/M25PE SPI flash */
-#define SPI_FLASH_BLOCK (256 * 64)
-
-#define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
-#define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
-#define FLASH_BUF ((card->buffers) + 4*(card->buffer_size)*2)
-
-#define RX_DMA_SIZE 2048
-
-#define FPGA_VERSION(a,b) (((a) << 8) + (b))
-#define LEGACY_BUFFERS 2
-#define DMA_SUPPORTED 4
-
-static int reset = 0;
-static int atmdebug = 0;
-static int firmware_upgrade = 0;
-static int fpga_upgrade = 0;
-static int db_firmware_upgrade = 0;
-static int db_fpga_upgrade = 0;
-
-struct pkt_hdr {
- __le16 size;
- __le16 vpi;
- __le16 vci;
- __le16 type;
-};
-
-struct solos_skb_cb {
- struct atm_vcc *vcc;
- uint32_t dma_addr;
-};
-
-
-#define SKB_CB(skb) ((struct solos_skb_cb *)skb->cb)
-
-#define PKT_DATA 0
-#define PKT_COMMAND 1
-#define PKT_POPEN 3
-#define PKT_PCLOSE 4
-#define PKT_STATUS 5
-
-struct solos_card {
- void __iomem *config_regs;
- void __iomem *buffers;
- int nr_ports;
- int tx_mask;
- struct pci_dev *dev;
- struct atm_dev *atmdev[4];
- struct tasklet_struct tlet;
- spinlock_t tx_lock;
- spinlock_t tx_queue_lock;
- spinlock_t cli_queue_lock;
- spinlock_t param_queue_lock;
- struct list_head param_queue;
- struct sk_buff_head tx_queue[4];
- struct sk_buff_head cli_queue[4];
- struct sk_buff *tx_skb[4];
- struct sk_buff *rx_skb[4];
- unsigned char *dma_bounce;
- wait_queue_head_t param_wq;
- wait_queue_head_t fw_wq;
- int using_dma;
- int dma_alignment;
- int fpga_version;
- int buffer_size;
- int atmel_flash;
-};
-
-
-struct solos_param {
- struct list_head list;
- pid_t pid;
- int port;
- struct sk_buff *response;
-};
-
-#define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data)
-
-MODULE_AUTHOR("Traverse Technologies <support@traverse.com.au>");
-MODULE_DESCRIPTION("Solos PCI driver");
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("solos-FPGA.bin");
-MODULE_FIRMWARE("solos-Firmware.bin");
-MODULE_FIRMWARE("solos-db-FPGA.bin");
-MODULE_PARM_DESC(reset, "Reset Solos chips on startup");
-MODULE_PARM_DESC(atmdebug, "Print ATM data");
-MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
-MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade");
-MODULE_PARM_DESC(db_firmware_upgrade, "Initiate daughter board Solos firmware upgrade");
-MODULE_PARM_DESC(db_fpga_upgrade, "Initiate daughter board FPGA upgrade");
-module_param(reset, int, 0444);
-module_param(atmdebug, int, 0644);
-module_param(firmware_upgrade, int, 0444);
-module_param(fpga_upgrade, int, 0444);
-module_param(db_firmware_upgrade, int, 0444);
-module_param(db_fpga_upgrade, int, 0444);
-
-static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
- struct atm_vcc *vcc);
-static uint32_t fpga_tx(struct solos_card *);
-static irqreturn_t solos_irq(int irq, void *dev_id);
-static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
-static int atm_init(struct solos_card *, struct device *);
-static void atm_remove(struct solos_card *);
-static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
-static void solos_bh(unsigned long);
-static int print_buffer(struct sk_buff *buf);
-
-static inline void solos_pop(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- if (vcc->pop)
- vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
-}
-
-static ssize_t solos_param_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
- struct solos_card *card = atmdev->dev_data;
- struct solos_param prm;
- struct sk_buff *skb;
- struct pkt_hdr *header;
- int buflen;
-
- buflen = strlen(attr->attr.name) + 10;
-
- skb = alloc_skb(sizeof(*header) + buflen, GFP_KERNEL);
- if (!skb) {
- dev_warn(&card->dev->dev, "Failed to allocate sk_buff in solos_param_show()\n");
- return -ENOMEM;
- }
-
- header = skb_put(skb, sizeof(*header));
-
- buflen = snprintf((void *)&header[1], buflen - 1,
- "L%05d\n%s\n", current->pid, attr->attr.name);
- skb_put(skb, buflen);
-
- header->size = cpu_to_le16(buflen);
- header->vpi = cpu_to_le16(0);
- header->vci = cpu_to_le16(0);
- header->type = cpu_to_le16(PKT_COMMAND);
-
- prm.pid = current->pid;
- prm.response = NULL;
- prm.port = SOLOS_CHAN(atmdev);
-
- spin_lock_irq(&card->param_queue_lock);
- list_add(&prm.list, &card->param_queue);
- spin_unlock_irq(&card->param_queue_lock);
-
- fpga_queue(card, prm.port, skb, NULL);
-
- wait_event_timeout(card->param_wq, prm.response, 5 * HZ);
-
- spin_lock_irq(&card->param_queue_lock);
- list_del(&prm.list);
- spin_unlock_irq(&card->param_queue_lock);
-
- if (!prm.response)
- return -EIO;
-
- buflen = prm.response->len;
- memcpy(buf, prm.response->data, buflen);
- kfree_skb(prm.response);
-
- return buflen;
-}
-
-static ssize_t solos_param_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
- struct solos_card *card = atmdev->dev_data;
- struct solos_param prm;
- struct sk_buff *skb;
- struct pkt_hdr *header;
- int buflen;
- ssize_t ret;
-
- buflen = strlen(attr->attr.name) + 11 + count;
-
- skb = alloc_skb(sizeof(*header) + buflen, GFP_KERNEL);
- if (!skb) {
- dev_warn(&card->dev->dev, "Failed to allocate sk_buff in solos_param_store()\n");
- return -ENOMEM;
- }
-
- header = skb_put(skb, sizeof(*header));
-
- buflen = snprintf((void *)&header[1], buflen - 1,
- "L%05d\n%s\n%s\n", current->pid, attr->attr.name, buf);
-
- skb_put(skb, buflen);
- header->size = cpu_to_le16(buflen);
- header->vpi = cpu_to_le16(0);
- header->vci = cpu_to_le16(0);
- header->type = cpu_to_le16(PKT_COMMAND);
-
- prm.pid = current->pid;
- prm.response = NULL;
- prm.port = SOLOS_CHAN(atmdev);
-
- spin_lock_irq(&card->param_queue_lock);
- list_add(&prm.list, &card->param_queue);
- spin_unlock_irq(&card->param_queue_lock);
-
- fpga_queue(card, prm.port, skb, NULL);
-
- wait_event_timeout(card->param_wq, prm.response, 5 * HZ);
-
- spin_lock_irq(&card->param_queue_lock);
- list_del(&prm.list);
- spin_unlock_irq(&card->param_queue_lock);
-
- skb = prm.response;
-
- if (!skb)
- return -EIO;
-
- buflen = skb->len;
-
- /* Sometimes it has a newline, sometimes it doesn't. */
- if (skb->data[buflen - 1] == '\n')
- buflen--;
-
- if (buflen == 2 && !strncmp(skb->data, "OK", 2))
- ret = count;
- else if (buflen == 5 && !strncmp(skb->data, "ERROR", 5))
- ret = -EIO;
- else {
- /* We know we have enough space allocated for this; we allocated
- it ourselves */
- skb->data[buflen] = 0;
-
- dev_warn(&card->dev->dev, "Unexpected parameter response: '%s'\n",
- skb->data);
- ret = -EIO;
- }
- kfree_skb(skb);
-
- return ret;
-}
-
-static char *next_string(struct sk_buff *skb)
-{
- int i = 0;
- char *this = skb->data;
-
- for (i = 0; i < skb->len; i++) {
- if (this[i] == '\n') {
- this[i] = 0;
- skb_pull(skb, i + 1);
- return this;
- }
- if (!isprint(this[i]))
- return NULL;
- }
- return NULL;
-}
-
-/*
- * Status packet has fields separated by \n, starting with a version number
- * for the information therein. Fields are....
- *
- * packet version
- * RxBitRate (version >= 1)
- * TxBitRate (version >= 1)
- * State (version >= 1)
- * LocalSNRMargin (version >= 1)
- * LocalLineAttn (version >= 1)
- */
-static int process_status(struct solos_card *card, int port, struct sk_buff *skb)
-{
- char *str, *state_str, *snr, *attn;
- int ver, rate_up, rate_down, err;
-
- if (!card->atmdev[port])
- return -ENODEV;
-
- str = next_string(skb);
- if (!str)
- return -EIO;
-
- err = kstrtoint(str, 10, &ver);
- if (err) {
- dev_warn(&card->dev->dev, "Unexpected status interrupt version\n");
- return err;
- }
- if (ver < 1) {
- dev_warn(&card->dev->dev, "Unexpected status interrupt version %d\n",
- ver);
- return -EIO;
- }
-
- str = next_string(skb);
- if (!str)
- return -EIO;
- if (!strcmp(str, "ERROR")) {
- dev_dbg(&card->dev->dev, "Status packet indicated Solos error on port %d (starting up?)\n",
- port);
- return 0;
- }
-
- err = kstrtoint(str, 10, &rate_down);
- if (err)
- return err;
-
- str = next_string(skb);
- if (!str)
- return -EIO;
- err = kstrtoint(str, 10, &rate_up);
- if (err)
- return err;
-
- state_str = next_string(skb);
- if (!state_str)
- return -EIO;
-
- /* Anything but 'Showtime' is down */
- if (strcmp(state_str, "Showtime")) {
- atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
- dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
- return 0;
- }
-
- snr = next_string(skb);
- if (!snr)
- return -EIO;
- attn = next_string(skb);
- if (!attn)
- return -EIO;
-
- dev_info(&card->dev->dev, "Port %d: %s @%d/%d kb/s%s%s%s%s\n",
- port, state_str, rate_down/1000, rate_up/1000,
- snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn);
-
- card->atmdev[port]->link_rate = rate_down / 424;
- atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_FOUND);
-
- return 0;
-}
-
-static int process_command(struct solos_card *card, int port, struct sk_buff *skb)
-{
- struct solos_param *prm;
- unsigned long flags;
- int cmdpid;
- int found = 0, err;
-
- if (skb->len < 7)
- return 0;
-
- if (skb->data[0] != 'L' || !isdigit(skb->data[1]) ||
- !isdigit(skb->data[2]) || !isdigit(skb->data[3]) ||
- !isdigit(skb->data[4]) || !isdigit(skb->data[5]) ||
- skb->data[6] != '\n')
- return 0;
-
- err = kstrtoint(&skb->data[1], 10, &cmdpid);
- if (err)
- return err;
-
- spin_lock_irqsave(&card->param_queue_lock, flags);
- list_for_each_entry(prm, &card->param_queue, list) {
- if (prm->port == port && prm->pid == cmdpid) {
- prm->response = skb;
- skb_pull(skb, 7);
- wake_up(&card->param_wq);
- found = 1;
- break;
- }
- }
- spin_unlock_irqrestore(&card->param_queue_lock, flags);
- return found;
-}
-
-static ssize_t console_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
- struct solos_card *card = atmdev->dev_data;
- struct sk_buff *skb;
- unsigned int len;
-
- spin_lock_bh(&card->cli_queue_lock);
- skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]);
- spin_unlock_bh(&card->cli_queue_lock);
- if(skb == NULL)
- return sprintf(buf, "No data.\n");
-
- len = skb->len;
- memcpy(buf, skb->data, len);
-
- kfree_skb(skb);
- return len;
-}
-
-static int send_command(struct solos_card *card, int dev, const char *buf, size_t size)
-{
- struct sk_buff *skb;
- struct pkt_hdr *header;
-
- if (size > (BUF_SIZE - sizeof(*header))) {
- dev_dbg(&card->dev->dev, "Command is too big. Dropping request\n");
- return 0;
- }
- skb = alloc_skb(size + sizeof(*header), GFP_ATOMIC);
- if (!skb) {
- dev_warn(&card->dev->dev, "Failed to allocate sk_buff in send_command()\n");
- return 0;
- }
-
- header = skb_put(skb, sizeof(*header));
-
- header->size = cpu_to_le16(size);
- header->vpi = cpu_to_le16(0);
- header->vci = cpu_to_le16(0);
- header->type = cpu_to_le16(PKT_COMMAND);
-
- skb_put_data(skb, buf, size);
-
- fpga_queue(card, dev, skb, NULL);
-
- return 0;
-}
-
-static ssize_t console_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
- struct solos_card *card = atmdev->dev_data;
- int err;
-
- err = send_command(card, SOLOS_CHAN(atmdev), buf, count);
-
- return err?:count;
-}
-
-struct geos_gpio_attr {
- struct device_attribute attr;
- int offset;
-};
-
-#define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset) \
- struct geos_gpio_attr gpio_attr_##_name = { \
- .attr = __ATTR(_name, _mode, _show, _store), \
- .offset = _offset }
-
-static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
- struct solos_card *card = dev_get_drvdata(dev);
- uint32_t data32;
-
- if (count != 1 && (count != 2 || buf[1] != '\n'))
- return -EINVAL;
-
- spin_lock_irq(&card->param_queue_lock);
- data32 = ioread32(card->config_regs + GPIO_STATUS);
- if (buf[0] == '1') {
- data32 |= 1 << gattr->offset;
- iowrite32(data32, card->config_regs + GPIO_STATUS);
- } else if (buf[0] == '0') {
- data32 &= ~(1 << gattr->offset);
- iowrite32(data32, card->config_regs + GPIO_STATUS);
- } else {
- count = -EINVAL;
- }
- spin_unlock_irq(&card->param_queue_lock);
- return count;
-}
-
-static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
- struct solos_card *card = dev_get_drvdata(dev);
- uint32_t data32;
-
- data32 = ioread32(card->config_regs + GPIO_STATUS);
- data32 = (data32 >> gattr->offset) & 1;
-
- return sprintf(buf, "%d\n", data32);
-}
-
-static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
- struct solos_card *card = dev_get_drvdata(dev);
- uint32_t data32;
-
- data32 = ioread32(card->config_regs + GPIO_STATUS);
- switch (gattr->offset) {
- case 0:
- /* HardwareVersion */
- data32 = data32 & 0x1F;
- break;
- case 1:
- /* HardwareVariant */
- data32 = (data32 >> 5) & 0x0F;
- break;
- }
- return sprintf(buf, "%d\n", data32);
-}
-
-static DEVICE_ATTR_RW(console);
-
-
-#define SOLOS_ATTR_RO(x) static DEVICE_ATTR(x, 0444, solos_param_show, NULL);
-#define SOLOS_ATTR_RW(x) static DEVICE_ATTR(x, 0644, solos_param_show, solos_param_store);
-
-#include "solos-attrlist.c"
-
-static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9);
-static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10);
-static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11);
-static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12);
-static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13);
-static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14);
-static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0);
-static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1);
-#undef SOLOS_ATTR_RO
-#undef SOLOS_ATTR_RW
-
-#define SOLOS_ATTR_RO(x) &dev_attr_##x.attr,
-#define SOLOS_ATTR_RW(x) &dev_attr_##x.attr,
-
-static struct attribute *solos_attrs[] = {
-#include "solos-attrlist.c"
- NULL
-};
-
-static const struct attribute_group solos_attr_group = {
- .attrs = solos_attrs,
- .name = "parameters",
-};
-
-static struct attribute *gpio_attrs[] = {
- &gpio_attr_GPIO1.attr.attr,
- &gpio_attr_GPIO2.attr.attr,
- &gpio_attr_GPIO3.attr.attr,
- &gpio_attr_GPIO4.attr.attr,
- &gpio_attr_GPIO5.attr.attr,
- &gpio_attr_PushButton.attr.attr,
- &gpio_attr_HardwareVersion.attr.attr,
- &gpio_attr_HardwareVariant.attr.attr,
- NULL
-};
-
-static const struct attribute_group gpio_attr_group = {
- .attrs = gpio_attrs,
- .name = "gpio",
-};
-
-static int flash_upgrade(struct solos_card *card, int chip)
-{
- const struct firmware *fw;
- const char *fw_name;
- int blocksize = 0;
- int numblocks = 0;
- int offset;
-
- switch (chip) {
- case 0:
- fw_name = "solos-FPGA.bin";
- if (card->atmel_flash)
- blocksize = ATMEL_FPGA_BLOCK;
- else
- blocksize = SPI_FLASH_BLOCK;
- break;
- case 1:
- fw_name = "solos-Firmware.bin";
- if (card->atmel_flash)
- blocksize = ATMEL_SOLOS_BLOCK;
- else
- blocksize = SPI_FLASH_BLOCK;
- break;
- case 2:
- if (card->fpga_version > LEGACY_BUFFERS){
- fw_name = "solos-db-FPGA.bin";
- if (card->atmel_flash)
- blocksize = ATMEL_FPGA_BLOCK;
- else
- blocksize = SPI_FLASH_BLOCK;
- } else {
- dev_info(&card->dev->dev, "FPGA version doesn't support"
- " daughter board upgrades\n");
- return -EPERM;
- }
- break;
- case 3:
- if (card->fpga_version > LEGACY_BUFFERS){
- fw_name = "solos-Firmware.bin";
- if (card->atmel_flash)
- blocksize = ATMEL_SOLOS_BLOCK;
- else
- blocksize = SPI_FLASH_BLOCK;
- } else {
- dev_info(&card->dev->dev, "FPGA version doesn't support"
- " daughter board upgrades\n");
- return -EPERM;
- }
- break;
- default:
- return -ENODEV;
- }
-
- if (request_firmware(&fw, fw_name, &card->dev->dev))
- return -ENOENT;
-
- dev_info(&card->dev->dev, "Flash upgrade starting\n");
-
- /* New FPGAs require driver version before permitting flash upgrades */
- iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER);
-
- numblocks = fw->size / blocksize;
- dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size);
- dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
-
- dev_info(&card->dev->dev, "Changing FPGA to Update mode\n");
- iowrite32(1, card->config_regs + FPGA_MODE);
- (void) ioread32(card->config_regs + FPGA_MODE);
-
- /* Set mode to Chip Erase */
- if(chip == 0 || chip == 2)
- dev_info(&card->dev->dev, "Set FPGA Flash mode to FPGA Chip Erase\n");
- if(chip == 1 || chip == 3)
- dev_info(&card->dev->dev, "Set FPGA Flash mode to Solos Chip Erase\n");
- iowrite32((chip * 2), card->config_regs + FLASH_MODE);
-
-
- iowrite32(1, card->config_regs + WRITE_FLASH);
- wait_event(card->fw_wq, !ioread32(card->config_regs + FLASH_BUSY));
-
- for (offset = 0; offset < fw->size; offset += blocksize) {
- int i;
-
- /* Clear write flag */
- iowrite32(0, card->config_regs + WRITE_FLASH);
-
- /* Set mode to Block Write */
- /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */
- iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE);
-
- /* Copy block to buffer, swapping each 16 bits for Atmel flash */
- for(i = 0; i < blocksize; i += 4) {
- uint32_t word;
- if (card->atmel_flash)
- word = swahb32p((uint32_t *)(fw->data + offset + i));
- else
- word = *(uint32_t *)(fw->data + offset + i);
- if(card->fpga_version > LEGACY_BUFFERS)
- iowrite32(word, FLASH_BUF + i);
- else
- iowrite32(word, RX_BUF(card, 3) + i);
- }
-
- /* Specify block number and then trigger flash write */
- iowrite32(offset / blocksize, card->config_regs + FLASH_BLOCK);
- iowrite32(1, card->config_regs + WRITE_FLASH);
- wait_event(card->fw_wq, !ioread32(card->config_regs + FLASH_BUSY));
- }
-
- release_firmware(fw);
- iowrite32(0, card->config_regs + WRITE_FLASH);
- iowrite32(0, card->config_regs + FPGA_MODE);
- iowrite32(0, card->config_regs + FLASH_MODE);
- dev_info(&card->dev->dev, "Returning FPGA to Data mode\n");
- return 0;
-}
-
-static irqreturn_t solos_irq(int irq, void *dev_id)
-{
- struct solos_card *card = dev_id;
- int handled = 1;
-
- iowrite32(0, card->config_regs + IRQ_CLEAR);
-
- /* If we're up and running, just kick the tasklet to process TX/RX */
- if (card->atmdev[0])
- tasklet_schedule(&card->tlet);
- else
- wake_up(&card->fw_wq);
-
- return IRQ_RETVAL(handled);
-}
-
-static void solos_bh(unsigned long card_arg)
-{
- struct solos_card *card = (void *)card_arg;
- uint32_t card_flags;
- uint32_t rx_done = 0;
- int port;
-
- /*
- * Since fpga_tx() is going to need to read the flags under its lock,
- * it can return them to us so that we don't have to hit PCI MMIO
- * again for the same information
- */
- card_flags = fpga_tx(card);
-
- for (port = 0; port < card->nr_ports; port++) {
- if (card_flags & (0x10 << port)) {
- struct pkt_hdr _hdr, *header;
- struct sk_buff *skb;
- struct atm_vcc *vcc;
- int size;
-
- if (card->using_dma) {
- skb = card->rx_skb[port];
- card->rx_skb[port] = NULL;
-
- dma_unmap_single(&card->dev->dev, SKB_CB(skb)->dma_addr,
- RX_DMA_SIZE, DMA_FROM_DEVICE);
-
- header = (void *)skb->data;
- size = le16_to_cpu(header->size);
- skb_put(skb, size + sizeof(*header));
- skb_pull(skb, sizeof(*header));
- } else {
- header = &_hdr;
-
- rx_done |= 0x10 << port;
-
- memcpy_fromio(header, RX_BUF(card, port), sizeof(*header));
-
- size = le16_to_cpu(header->size);
- if (size > (card->buffer_size - sizeof(*header))){
- dev_warn(&card->dev->dev, "Invalid buffer size\n");
- continue;
- }
-
- /* Use netdev_alloc_skb() because it adds NET_SKB_PAD of
- * headroom, and ensures we can route packets back out an
- * Ethernet interface (for example) without having to
- * reallocate. Adding NET_IP_ALIGN also ensures that both
- * PPPoATM and PPPoEoBR2684 packets end up aligned. */
- skb = netdev_alloc_skb_ip_align(NULL, size + 1);
- if (!skb) {
- if (net_ratelimit())
- dev_warn(&card->dev->dev, "Failed to allocate sk_buff for RX\n");
- continue;
- }
-
- memcpy_fromio(skb_put(skb, size),
- RX_BUF(card, port) + sizeof(*header),
- size);
- }
- if (atmdebug) {
- dev_info(&card->dev->dev, "Received: port %d\n", port);
- dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
- size, le16_to_cpu(header->vpi),
- le16_to_cpu(header->vci));
- print_buffer(skb);
- }
-
- switch (le16_to_cpu(header->type)) {
- case PKT_DATA:
- vcc = find_vcc(card->atmdev[port], le16_to_cpu(header->vpi),
- le16_to_cpu(header->vci));
- if (!vcc) {
- if (net_ratelimit())
- dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
- le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
- port);
- dev_kfree_skb_any(skb);
- break;
- }
- atm_charge(vcc, skb->truesize);
- vcc->push(vcc, skb);
- atomic_inc(&vcc->stats->rx);
- break;
-
- case PKT_STATUS:
- if (process_status(card, port, skb) &&
- net_ratelimit()) {
- dev_warn(&card->dev->dev, "Bad status packet of %d bytes on port %d:\n", skb->len, port);
- print_buffer(skb);
- }
- dev_kfree_skb_any(skb);
- break;
-
- case PKT_COMMAND:
- default: /* FIXME: Not really, surely? */
- if (process_command(card, port, skb))
- break;
- spin_lock(&card->cli_queue_lock);
- if (skb_queue_len(&card->cli_queue[port]) > 10) {
- if (net_ratelimit())
- dev_warn(&card->dev->dev, "Dropping console response on port %d\n",
- port);
- dev_kfree_skb_any(skb);
- } else
- skb_queue_tail(&card->cli_queue[port], skb);
- spin_unlock(&card->cli_queue_lock);
- break;
- }
- }
- /* Allocate RX skbs for any ports which need them */
- if (card->using_dma && card->atmdev[port] &&
- !card->rx_skb[port]) {
- /* Unlike the MMIO case (qv) we can't add NET_IP_ALIGN
- * here; the FPGA can only DMA to addresses which are
- * aligned to 4 bytes. */
- struct sk_buff *skb = dev_alloc_skb(RX_DMA_SIZE);
- if (skb) {
- SKB_CB(skb)->dma_addr =
- dma_map_single(&card->dev->dev, skb->data,
- RX_DMA_SIZE, DMA_FROM_DEVICE);
- iowrite32(SKB_CB(skb)->dma_addr,
- card->config_regs + RX_DMA_ADDR(port));
- card->rx_skb[port] = skb;
- } else {
- if (net_ratelimit())
- dev_warn(&card->dev->dev, "Failed to allocate RX skb");
-
- /* We'll have to try again later */
- tasklet_schedule(&card->tlet);
- }
- }
- }
- if (rx_done)
- iowrite32(rx_done, card->config_regs + FLAGS_ADDR);
-
- return;
-}
-
-static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci)
-{
- struct hlist_head *head;
- struct atm_vcc *vcc = NULL;
- struct sock *s;
-
- read_lock(&vcc_sklist_lock);
- head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
- sk_for_each(s, head) {
- vcc = atm_sk(s);
- if (vcc->dev == dev && vcc->vci == vci &&
- vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE &&
- test_bit(ATM_VF_READY, &vcc->flags))
- goto out;
- }
- vcc = NULL;
- out:
- read_unlock(&vcc_sklist_lock);
- return vcc;
-}
-
-static int popen(struct atm_vcc *vcc)
-{
- struct solos_card *card = vcc->dev->dev_data;
- struct sk_buff *skb;
- struct pkt_hdr *header;
-
- if (vcc->qos.aal != ATM_AAL5) {
- dev_warn(&card->dev->dev, "Unsupported ATM type %d\n",
- vcc->qos.aal);
- return -EINVAL;
- }
-
- skb = alloc_skb(sizeof(*header), GFP_KERNEL);
- if (!skb) {
- if (net_ratelimit())
- dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n");
- return -ENOMEM;
- }
- header = skb_put(skb, sizeof(*header));
-
- header->size = cpu_to_le16(0);
- header->vpi = cpu_to_le16(vcc->vpi);
- header->vci = cpu_to_le16(vcc->vci);
- header->type = cpu_to_le16(PKT_POPEN);
-
- fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL);
-
- set_bit(ATM_VF_ADDR, &vcc->flags);
- set_bit(ATM_VF_READY, &vcc->flags);
-
- return 0;
-}
-
-static void pclose(struct atm_vcc *vcc)
-{
- struct solos_card *card = vcc->dev->dev_data;
- unsigned char port = SOLOS_CHAN(vcc->dev);
- struct sk_buff *skb, *tmpskb;
- struct pkt_hdr *header;
-
- /* Remove any yet-to-be-transmitted packets from the pending queue */
- spin_lock_bh(&card->tx_queue_lock);
- skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
- if (SKB_CB(skb)->vcc == vcc) {
- skb_unlink(skb, &card->tx_queue[port]);
- solos_pop(vcc, skb);
- }
- }
- spin_unlock_bh(&card->tx_queue_lock);
-
- skb = alloc_skb(sizeof(*header), GFP_KERNEL);
- if (!skb) {
- dev_warn(&card->dev->dev, "Failed to allocate sk_buff in pclose()\n");
- return;
- }
- header = skb_put(skb, sizeof(*header));
-
- header->size = cpu_to_le16(0);
- header->vpi = cpu_to_le16(vcc->vpi);
- header->vci = cpu_to_le16(vcc->vci);
- header->type = cpu_to_le16(PKT_PCLOSE);
-
- skb_get(skb);
- fpga_queue(card, port, skb, NULL);
-
- if (!wait_event_timeout(card->param_wq, !skb_shared(skb), 5 * HZ))
- dev_warn(&card->dev->dev,
- "Timeout waiting for VCC close on port %d\n", port);
-
- dev_kfree_skb(skb);
-
- /* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
- tasklet has finished processing any incoming packets (and, more to
- the point, using the vcc pointer). */
- tasklet_unlock_wait(&card->tlet);
-
- clear_bit(ATM_VF_ADDR, &vcc->flags);
-
- return;
-}
-
-static int print_buffer(struct sk_buff *buf)
-{
- int len,i;
- char msg[500];
- char item[10];
-
- len = buf->len;
- for (i = 0; i < len; i++){
- if(i % 8 == 0)
- sprintf(msg, "%02X: ", i);
-
- sprintf(item,"%02X ",*(buf->data + i));
- strcat(msg, item);
- if(i % 8 == 7) {
- sprintf(item, "\n");
- strcat(msg, item);
- printk(KERN_DEBUG "%s", msg);
- }
- }
- if (i % 8 != 0) {
- sprintf(item, "\n");
- strcat(msg, item);
- printk(KERN_DEBUG "%s", msg);
- }
- printk(KERN_DEBUG "\n");
-
- return 0;
-}
-
-static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
- struct atm_vcc *vcc)
-{
- int old_len;
- unsigned long flags;
-
- SKB_CB(skb)->vcc = vcc;
-
- spin_lock_irqsave(&card->tx_queue_lock, flags);
- old_len = skb_queue_len(&card->tx_queue[port]);
- skb_queue_tail(&card->tx_queue[port], skb);
- if (!old_len)
- card->tx_mask |= (1 << port);
- spin_unlock_irqrestore(&card->tx_queue_lock, flags);
-
- /* Theoretically we could just schedule the tasklet here, but
- that introduces latency we don't want -- it's noticeable */
- if (!old_len)
- fpga_tx(card);
-}
-
-static uint32_t fpga_tx(struct solos_card *card)
-{
- uint32_t tx_pending, card_flags;
- uint32_t tx_started = 0;
- struct sk_buff *skb;
- struct atm_vcc *vcc;
- unsigned char port;
- unsigned long flags;
-
- spin_lock_irqsave(&card->tx_lock, flags);
-
- card_flags = ioread32(card->config_regs + FLAGS_ADDR);
- /*
- * The queue lock is required for _writing_ to tx_mask, but we're
- * OK to read it here without locking. The only potential update
- * that we could race with is in fpga_queue() where it sets a bit
- * for a new port... but it's going to call this function again if
- * it's doing that, anyway.
- */
- tx_pending = card->tx_mask & ~card_flags;
-
- for (port = 0; tx_pending; tx_pending >>= 1, port++) {
- if (tx_pending & 1) {
- struct sk_buff *oldskb = card->tx_skb[port];
- if (oldskb) {
- dma_unmap_single(&card->dev->dev, SKB_CB(oldskb)->dma_addr,
- oldskb->len, DMA_TO_DEVICE);
- card->tx_skb[port] = NULL;
- }
- spin_lock(&card->tx_queue_lock);
- skb = skb_dequeue(&card->tx_queue[port]);
- if (!skb)
- card->tx_mask &= ~(1 << port);
- spin_unlock(&card->tx_queue_lock);
-
- if (skb && !card->using_dma) {
- memcpy_toio(TX_BUF(card, port), skb->data, skb->len);
- tx_started |= 1 << port;
- oldskb = skb; /* We're done with this skb already */
- } else if (skb && card->using_dma) {
- unsigned char *data = skb->data;
- if ((unsigned long)data & card->dma_alignment) {
- data = card->dma_bounce + (BUF_SIZE * port);
- memcpy(data, skb->data, skb->len);
- }
- SKB_CB(skb)->dma_addr = dma_map_single(&card->dev->dev, data,
- skb->len, DMA_TO_DEVICE);
- card->tx_skb[port] = skb;
- iowrite32(SKB_CB(skb)->dma_addr,
- card->config_regs + TX_DMA_ADDR(port));
- }
-
- if (!oldskb)
- continue;
-
- /* Clean up and free oldskb now it's gone */
- if (atmdebug) {
- struct pkt_hdr *header = (void *)oldskb->data;
- int size = le16_to_cpu(header->size);
-
- skb_pull(oldskb, sizeof(*header));
- dev_info(&card->dev->dev, "Transmitted: port %d\n",
- port);
- dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
- size, le16_to_cpu(header->vpi),
- le16_to_cpu(header->vci));
- print_buffer(oldskb);
- }
-
- vcc = SKB_CB(oldskb)->vcc;
-
- if (vcc) {
- atomic_inc(&vcc->stats->tx);
- solos_pop(vcc, oldskb);
- } else {
- dev_kfree_skb_irq(oldskb);
- wake_up(&card->param_wq);
- }
- }
- }
- /* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */
- if (tx_started)
- iowrite32(tx_started, card->config_regs + FLAGS_ADDR);
-
- spin_unlock_irqrestore(&card->tx_lock, flags);
- return card_flags;
-}
-
-static int psend(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct solos_card *card = vcc->dev->dev_data;
- struct pkt_hdr *header;
- int pktlen;
-
- pktlen = skb->len;
- if (pktlen > (BUF_SIZE - sizeof(*header))) {
- dev_warn(&card->dev->dev, "Length of PDU is too large. Dropping PDU.\n");
- solos_pop(vcc, skb);
- return 0;
- }
-
- if (!skb_clone_writable(skb, sizeof(*header))) {
- int expand_by = 0;
- int ret;
-
- if (skb_headroom(skb) < sizeof(*header))
- expand_by = sizeof(*header) - skb_headroom(skb);
-
- ret = pskb_expand_head(skb, expand_by, 0, GFP_ATOMIC);
- if (ret) {
- dev_warn(&card->dev->dev, "pskb_expand_head failed.\n");
- solos_pop(vcc, skb);
- return ret;
- }
- }
-
- header = skb_push(skb, sizeof(*header));
-
- /* This does _not_ include the size of the header */
- header->size = cpu_to_le16(pktlen);
- header->vpi = cpu_to_le16(vcc->vpi);
- header->vci = cpu_to_le16(vcc->vci);
- header->type = cpu_to_le16(PKT_DATA);
-
- fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, vcc);
-
- return 0;
-}
-
-static const struct atmdev_ops fpga_ops = {
- .open = popen,
- .close = pclose,
- .ioctl = NULL,
- .send = psend,
- .send_oam = NULL,
- .phy_put = NULL,
- .phy_get = NULL,
- .change_qos = NULL,
- .proc_read = NULL,
- .owner = THIS_MODULE
-};
-
-static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
- int err;
- uint16_t fpga_ver;
- uint8_t major_ver, minor_ver;
- uint32_t data32;
- struct solos_card *card;
-
- card = kzalloc_obj(*card);
- if (!card)
- return -ENOMEM;
-
- card->dev = dev;
- init_waitqueue_head(&card->fw_wq);
- init_waitqueue_head(&card->param_wq);
-
- err = pci_enable_device(dev);
- if (err) {
- dev_warn(&dev->dev, "Failed to enable PCI device\n");
- goto out;
- }
-
- err = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
- if (err) {
- dev_warn(&dev->dev, "Failed to set 32-bit DMA mask\n");
- goto out;
- }
-
- err = pci_request_regions(dev, "solos");
- if (err) {
- dev_warn(&dev->dev, "Failed to request regions\n");
- goto out;
- }
-
- card->config_regs = pci_iomap(dev, 0, CONFIG_RAM_SIZE);
- if (!card->config_regs) {
- dev_warn(&dev->dev, "Failed to ioremap config registers\n");
- err = -ENOMEM;
- goto out_release_regions;
- }
- card->buffers = pci_iomap(dev, 1, DATA_RAM_SIZE);
- if (!card->buffers) {
- dev_warn(&dev->dev, "Failed to ioremap data buffers\n");
- err = -ENOMEM;
- goto out_unmap_config;
- }
-
- if (reset) {
- iowrite32(1, card->config_regs + FPGA_MODE);
- ioread32(card->config_regs + FPGA_MODE);
-
- iowrite32(0, card->config_regs + FPGA_MODE);
- ioread32(card->config_regs + FPGA_MODE);
- }
-
- data32 = ioread32(card->config_regs + FPGA_VER);
- fpga_ver = (data32 & 0x0000FFFF);
- major_ver = ((data32 & 0xFF000000) >> 24);
- minor_ver = ((data32 & 0x00FF0000) >> 16);
- card->fpga_version = FPGA_VERSION(major_ver,minor_ver);
- if (card->fpga_version > LEGACY_BUFFERS)
- card->buffer_size = BUF_SIZE;
- else
- card->buffer_size = OLD_BUF_SIZE;
- dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n",
- major_ver, minor_ver, fpga_ver);
-
- if (fpga_ver < 37 && (fpga_upgrade || firmware_upgrade ||
- db_fpga_upgrade || db_firmware_upgrade)) {
- dev_warn(&dev->dev,
- "FPGA too old; cannot upgrade flash. Use JTAG.\n");
- fpga_upgrade = firmware_upgrade = 0;
- db_fpga_upgrade = db_firmware_upgrade = 0;
- }
-
- /* Stopped using Atmel flash after 0.03-38 */
- if (fpga_ver < 39)
- card->atmel_flash = 1;
- else
- card->atmel_flash = 0;
-
- data32 = ioread32(card->config_regs + PORTS);
- card->nr_ports = (data32 & 0x000000FF);
-
- if (card->fpga_version >= DMA_SUPPORTED) {
- pci_set_master(dev);
- card->using_dma = 1;
- if (1) { /* All known FPGA versions so far */
- card->dma_alignment = 3;
- card->dma_bounce = kmalloc_array(card->nr_ports,
- BUF_SIZE, GFP_KERNEL);
- if (!card->dma_bounce) {
- dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
- err = -ENOMEM;
- /* Fallback to MMIO doesn't work */
- goto out_unmap_both;
- }
- }
- } else {
- card->using_dma = 0;
- /* Set RX empty flag for all ports */
- iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
- }
-
- pci_set_drvdata(dev, card);
-
- tasklet_init(&card->tlet, solos_bh, (unsigned long)card);
- spin_lock_init(&card->tx_lock);
- spin_lock_init(&card->tx_queue_lock);
- spin_lock_init(&card->cli_queue_lock);
- spin_lock_init(&card->param_queue_lock);
- INIT_LIST_HEAD(&card->param_queue);
-
- err = request_irq(dev->irq, solos_irq, IRQF_SHARED,
- "solos-pci", card);
- if (err) {
- dev_dbg(&card->dev->dev, "Failed to request interrupt IRQ: %d\n", dev->irq);
- goto out_unmap_both;
- }
-
- iowrite32(1, card->config_regs + IRQ_EN_ADDR);
-
- if (fpga_upgrade)
- flash_upgrade(card, 0);
-
- if (firmware_upgrade)
- flash_upgrade(card, 1);
-
- if (db_fpga_upgrade)
- flash_upgrade(card, 2);
-
- if (db_firmware_upgrade)
- flash_upgrade(card, 3);
-
- err = atm_init(card, &dev->dev);
- if (err)
- goto out_free_irq;
-
- if (card->fpga_version >= DMA_SUPPORTED &&
- sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group))
- dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n");
-
- return 0;
-
- out_free_irq:
- iowrite32(0, card->config_regs + IRQ_EN_ADDR);
- free_irq(dev->irq, card);
- tasklet_kill(&card->tlet);
-
- out_unmap_both:
- kfree(card->dma_bounce);
- pci_iounmap(dev, card->buffers);
- out_unmap_config:
- pci_iounmap(dev, card->config_regs);
- out_release_regions:
- pci_release_regions(dev);
- out:
- kfree(card);
- return err;
-}
-
-static int atm_init(struct solos_card *card, struct device *parent)
-{
- int i;
-
- for (i = 0; i < card->nr_ports; i++) {
- struct sk_buff *skb;
- struct pkt_hdr *header;
-
- skb_queue_head_init(&card->tx_queue[i]);
- skb_queue_head_init(&card->cli_queue[i]);
-
- card->atmdev[i] = atm_dev_register("solos-pci", parent, &fpga_ops, -1, NULL);
- if (!card->atmdev[i]) {
- dev_err(&card->dev->dev, "Could not register ATM device %d\n", i);
- atm_remove(card);
- return -ENODEV;
- }
- if (device_create_file(&card->atmdev[i]->class_dev, &dev_attr_console))
- dev_err(&card->dev->dev, "Could not register console for ATM device %d\n", i);
- if (sysfs_create_group(&card->atmdev[i]->class_dev.kobj, &solos_attr_group))
- dev_err(&card->dev->dev, "Could not register parameter group for ATM device %d\n", i);
-
- dev_info(&card->dev->dev, "Registered ATM device %d\n", card->atmdev[i]->number);
-
- card->atmdev[i]->ci_range.vpi_bits = 8;
- card->atmdev[i]->ci_range.vci_bits = 16;
- card->atmdev[i]->dev_data = card;
- card->atmdev[i]->phy_data = (void *)(unsigned long)i;
- atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
-
- skb = alloc_skb(sizeof(*header), GFP_KERNEL);
- if (!skb) {
- dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n");
- continue;
- }
-
- header = skb_put(skb, sizeof(*header));
-
- header->size = cpu_to_le16(0);
- header->vpi = cpu_to_le16(0);
- header->vci = cpu_to_le16(0);
- header->type = cpu_to_le16(PKT_STATUS);
-
- fpga_queue(card, i, skb, NULL);
- }
- return 0;
-}
-
-static void atm_remove(struct solos_card *card)
-{
- int i;
-
- for (i = 0; i < card->nr_ports; i++) {
- if (card->atmdev[i]) {
- struct sk_buff *skb;
-
- dev_info(&card->dev->dev, "Unregistering ATM device %d\n", card->atmdev[i]->number);
-
- sysfs_remove_group(&card->atmdev[i]->class_dev.kobj, &solos_attr_group);
- atm_dev_deregister(card->atmdev[i]);
-
- skb = card->rx_skb[i];
- if (skb) {
- dma_unmap_single(&card->dev->dev, SKB_CB(skb)->dma_addr,
- RX_DMA_SIZE, DMA_FROM_DEVICE);
- dev_kfree_skb(skb);
- }
- skb = card->tx_skb[i];
- if (skb) {
- dma_unmap_single(&card->dev->dev, SKB_CB(skb)->dma_addr,
- skb->len, DMA_TO_DEVICE);
- dev_kfree_skb(skb);
- }
- while ((skb = skb_dequeue(&card->tx_queue[i])))
- dev_kfree_skb(skb);
-
- }
- }
-}
-
-static void fpga_remove(struct pci_dev *dev)
-{
- struct solos_card *card = pci_get_drvdata(dev);
-
- /* Disable IRQs */
- iowrite32(0, card->config_regs + IRQ_EN_ADDR);
-
- /* Reset FPGA */
- iowrite32(1, card->config_regs + FPGA_MODE);
- (void)ioread32(card->config_regs + FPGA_MODE);
-
- if (card->fpga_version >= DMA_SUPPORTED)
- sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group);
-
- atm_remove(card);
-
- free_irq(dev->irq, card);
- tasklet_kill(&card->tlet);
-
- kfree(card->dma_bounce);
-
- /* Release device from reset */
- iowrite32(0, card->config_regs + FPGA_MODE);
- (void)ioread32(card->config_regs + FPGA_MODE);
-
- pci_iounmap(dev, card->buffers);
- pci_iounmap(dev, card->config_regs);
-
- pci_release_regions(dev);
- pci_disable_device(dev);
-
- kfree(card);
-}
-
-static const struct pci_device_id fpga_pci_tbl[] = {
- { 0x10ee, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci,fpga_pci_tbl);
-
-static struct pci_driver fpga_driver = {
- .name = "solos",
- .id_table = fpga_pci_tbl,
- .probe = fpga_probe,
- .remove = fpga_remove,
-};
-
-
-static int __init solos_pci_init(void)
-{
- BUILD_BUG_ON(sizeof(struct solos_skb_cb) > sizeof(((struct sk_buff *)0)->cb));
-
- printk(KERN_INFO "Solos PCI Driver Version %s\n", VERSION);
- return pci_register_driver(&fpga_driver);
-}
-
-static void __exit solos_pci_exit(void)
-{
- pci_unregister_driver(&fpga_driver);
- printk(KERN_INFO "Solos PCI Driver %s Unloaded\n", VERSION);
-}
-
-module_init(solos_pci_init);
-module_exit(solos_pci_exit);
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c
deleted file mode 100644
index bb588c98216d..000000000000
--- a/drivers/atm/suni.c
+++ /dev/null
@@ -1,391 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * drivers/atm/suni.c - S/UNI PHY driver
- *
- * Supports the following:
- * PMC PM5346 S/UNI LITE
- * PMC PM5350 S/UNI 155 ULTRA
- * PMC PM5355 S/UNI 622
- */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/atmdev.h>
-#include <linux/sonet.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/capability.h>
-#include <linux/slab.h>
-#include <asm/param.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-
-#include "suni.h"
-
-
-#if 0
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-#define PRIV(dev) ((struct suni_priv *) dev->phy_data)
-
-#define PUT(val,reg) dev->ops->phy_put(dev,val,SUNI_##reg)
-#define GET(reg) dev->ops->phy_get(dev,SUNI_##reg)
-#define REG_CHANGE(mask,shift,value,reg) \
- PUT((GET(reg) & ~(mask)) | ((value) << (shift)),reg)
-
-
-static struct timer_list poll_timer;
-static struct suni_priv *sunis = NULL;
-static DEFINE_SPINLOCK(sunis_lock);
-
-
-#define ADD_LIMITED(s,v) \
- atomic_add((v),&stats->s); \
- if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX);
-
-
-static void suni_hz(struct timer_list *timer)
-{
- struct suni_priv *walk;
- struct atm_dev *dev;
- struct k_sonet_stats *stats;
-
- for (walk = sunis; walk; walk = walk->next) {
- dev = walk->dev;
- stats = &walk->sonet_stats;
- PUT(0,MRI); /* latch counters */
- udelay(1);
- ADD_LIMITED(section_bip,(GET(RSOP_SBL) & 0xff) |
- ((GET(RSOP_SBM) & 0xff) << 8));
- ADD_LIMITED(line_bip,(GET(RLOP_LBL) & 0xff) |
- ((GET(RLOP_LB) & 0xff) << 8) |
- ((GET(RLOP_LBM) & 0xf) << 16));
- ADD_LIMITED(path_bip,(GET(RPOP_PBL) & 0xff) |
- ((GET(RPOP_PBM) & 0xff) << 8));
- ADD_LIMITED(line_febe,(GET(RLOP_LFL) & 0xff) |
- ((GET(RLOP_LF) & 0xff) << 8) |
- ((GET(RLOP_LFM) & 0xf) << 16));
- ADD_LIMITED(path_febe,(GET(RPOP_PFL) & 0xff) |
- ((GET(RPOP_PFM) & 0xff) << 8));
- ADD_LIMITED(corr_hcs,GET(RACP_CHEC) & 0xff);
- ADD_LIMITED(uncorr_hcs,GET(RACP_UHEC) & 0xff);
- ADD_LIMITED(rx_cells,(GET(RACP_RCCL) & 0xff) |
- ((GET(RACP_RCC) & 0xff) << 8) |
- ((GET(RACP_RCCM) & 7) << 16));
- ADD_LIMITED(tx_cells,(GET(TACP_TCCL) & 0xff) |
- ((GET(TACP_TCC) & 0xff) << 8) |
- ((GET(TACP_TCCM) & 7) << 16));
- }
- if (timer) mod_timer(&poll_timer,jiffies+HZ);
-}
-
-
-#undef ADD_LIMITED
-
-
-static int fetch_stats(struct atm_dev *dev,struct sonet_stats __user *arg,int zero)
-{
- struct sonet_stats tmp;
- int error = 0;
-
- sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp);
- if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp));
- if (zero && !error) sonet_subtract_stats(&PRIV(dev)->sonet_stats,&tmp);
- return error ? -EFAULT : 0;
-}
-
-
-#define HANDLE_FLAG(flag,reg,bit) \
- if (todo & flag) { \
- if (set) PUT(GET(reg) | bit,reg); \
- else PUT(GET(reg) & ~bit,reg); \
- todo &= ~flag; \
- }
-
-
-static int change_diag(struct atm_dev *dev,void __user *arg,int set)
-{
- int todo;
-
- if (get_user(todo,(int __user *)arg)) return -EFAULT;
- HANDLE_FLAG(SONET_INS_SBIP,TSOP_DIAG,SUNI_TSOP_DIAG_DBIP8);
- HANDLE_FLAG(SONET_INS_LBIP,TLOP_DIAG,SUNI_TLOP_DIAG_DBIP);
- HANDLE_FLAG(SONET_INS_PBIP,TPOP_CD,SUNI_TPOP_DIAG_DB3);
- HANDLE_FLAG(SONET_INS_FRAME,RSOP_CIE,SUNI_RSOP_CIE_FOOF);
- HANDLE_FLAG(SONET_INS_LAIS,TSOP_CTRL,SUNI_TSOP_CTRL_LAIS);
- HANDLE_FLAG(SONET_INS_PAIS,TPOP_CD,SUNI_TPOP_DIAG_PAIS);
- HANDLE_FLAG(SONET_INS_LOS,TSOP_DIAG,SUNI_TSOP_DIAG_DLOS);
- HANDLE_FLAG(SONET_INS_HCS,TACP_CS,SUNI_TACP_CS_DHCS);
- return put_user(todo,(int __user *)arg) ? -EFAULT : 0;
-}
-
-
-#undef HANDLE_FLAG
-
-
-static int get_diag(struct atm_dev *dev,void __user *arg)
-{
- int set;
-
- set = 0;
- if (GET(TSOP_DIAG) & SUNI_TSOP_DIAG_DBIP8) set |= SONET_INS_SBIP;
- if (GET(TLOP_DIAG) & SUNI_TLOP_DIAG_DBIP) set |= SONET_INS_LBIP;
- if (GET(TPOP_CD) & SUNI_TPOP_DIAG_DB3) set |= SONET_INS_PBIP;
- /* SONET_INS_FRAME is one-shot only */
- if (GET(TSOP_CTRL) & SUNI_TSOP_CTRL_LAIS) set |= SONET_INS_LAIS;
- if (GET(TPOP_CD) & SUNI_TPOP_DIAG_PAIS) set |= SONET_INS_PAIS;
- if (GET(TSOP_DIAG) & SUNI_TSOP_DIAG_DLOS) set |= SONET_INS_LOS;
- if (GET(TACP_CS) & SUNI_TACP_CS_DHCS) set |= SONET_INS_HCS;
- return put_user(set,(int __user *)arg) ? -EFAULT : 0;
-}
-
-
-static int set_loopback(struct atm_dev *dev,int mode)
-{
- unsigned char control;
- int reg, dle, lle;
-
- if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
- reg = SUNI_MCM;
- dle = SUNI_MCM_DLE;
- lle = SUNI_MCM_LLE;
- } else {
- reg = SUNI_MCT;
- dle = SUNI_MCT_DLE;
- lle = SUNI_MCT_LLE;
- }
-
- control = dev->ops->phy_get(dev, reg) & ~(dle | lle);
- switch (mode) {
- case ATM_LM_NONE:
- break;
- case ATM_LM_LOC_PHY:
- control |= dle;
- break;
- case ATM_LM_RMT_PHY:
- control |= lle;
- break;
- default:
- return -EINVAL;
- }
- dev->ops->phy_put(dev, control, reg);
- PRIV(dev)->loop_mode = mode;
- return 0;
-}
-
-/*
- * SONET vs. SDH Configuration
- *
- * Z0INS (register 0x06): 0 for SONET, 1 for SDH
- * ENSS (register 0x3D): 0 for SONET, 1 for SDH
- * LEN16 (register 0x28): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD)
- * LEN16 (register 0x50): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD)
- * S[1:0] (register 0x46): 00 for SONET, 10 for SDH
- */
-
-static int set_sonet(struct atm_dev *dev)
-{
- if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
- PUT(GET(RPOP_RC) & ~SUNI_RPOP_RC_ENSS, RPOP_RC);
- PUT(GET(SSTB_CTRL) & ~SUNI_SSTB_CTRL_LEN16, SSTB_CTRL);
- PUT(GET(SPTB_CTRL) & ~SUNI_SPTB_CTRL_LEN16, SPTB_CTRL);
- }
-
- REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT,
- SUNI_TPOP_S_SONET, TPOP_APM);
-
- return 0;
-}
-
-static int set_sdh(struct atm_dev *dev)
-{
- if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
- PUT(GET(RPOP_RC) | SUNI_RPOP_RC_ENSS, RPOP_RC);
- PUT(GET(SSTB_CTRL) | SUNI_SSTB_CTRL_LEN16, SSTB_CTRL);
- PUT(GET(SPTB_CTRL) | SUNI_SPTB_CTRL_LEN16, SPTB_CTRL);
- }
-
- REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT,
- SUNI_TPOP_S_SDH, TPOP_APM);
-
- return 0;
-}
-
-
-static int get_framing(struct atm_dev *dev, void __user *arg)
-{
- int framing;
- unsigned char s;
-
-
- s = (GET(TPOP_APM) & SUNI_TPOP_APM_S) >> SUNI_TPOP_APM_S_SHIFT;
- if (s == SUNI_TPOP_S_SONET)
- framing = SONET_FRAME_SONET;
- else
- framing = SONET_FRAME_SDH;
-
- return put_user(framing, (int __user *) arg) ? -EFAULT : 0;
-}
-
-static int set_framing(struct atm_dev *dev, void __user *arg)
-{
- int mode;
-
- if (get_user(mode, (int __user *) arg))
- return -EFAULT;
-
- if (mode == SONET_FRAME_SONET)
- return set_sonet(dev);
- else if (mode == SONET_FRAME_SDH)
- return set_sdh(dev);
-
- return -EINVAL;
-}
-
-
-static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
-{
- switch (cmd) {
- case SONET_GETSTATZ:
- case SONET_GETSTAT:
- return fetch_stats(dev, arg, cmd == SONET_GETSTATZ);
- case SONET_SETDIAG:
- return change_diag(dev,arg,1);
- case SONET_CLRDIAG:
- return change_diag(dev,arg,0);
- case SONET_GETDIAG:
- return get_diag(dev,arg);
- case SONET_SETFRAMING:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- return set_framing(dev, arg);
- case SONET_GETFRAMING:
- return get_framing(dev, arg);
- case SONET_GETFRSENSE:
- return -EINVAL;
- case ATM_SETLOOP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- return set_loopback(dev,(int)(unsigned long)arg);
- case ATM_GETLOOP:
- return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ?
- -EFAULT : 0;
- case ATM_QUERYLOOP:
- return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY,
- (int __user *) arg) ? -EFAULT : 0;
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-
-static void poll_los(struct atm_dev *dev)
-{
- atm_dev_signal_change(dev,
- GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ?
- ATM_PHY_SIG_LOST : ATM_PHY_SIG_FOUND);
-}
-
-
-static void suni_int(struct atm_dev *dev)
-{
- poll_los(dev);
- printk(KERN_NOTICE "%s(itf %d): signal %s\n",dev->type,dev->number,
- dev->signal == ATM_PHY_SIG_LOST ? "lost" : "detected again");
-}
-
-
-static int suni_start(struct atm_dev *dev)
-{
- unsigned long flags;
- int first;
-
- spin_lock_irqsave(&sunis_lock,flags);
- first = !sunis;
- PRIV(dev)->next = sunis;
- sunis = PRIV(dev);
- spin_unlock_irqrestore(&sunis_lock,flags);
- memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats));
- PUT(GET(RSOP_CIE) | SUNI_RSOP_CIE_LOSE,RSOP_CIE);
- /* interrupt on loss of signal */
- poll_los(dev); /* ... and clear SUNI interrupts */
- if (dev->signal == ATM_PHY_SIG_LOST)
- printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type,
- dev->number);
- PRIV(dev)->loop_mode = ATM_LM_NONE;
- suni_hz(NULL); /* clear SUNI counters */
- (void) fetch_stats(dev,NULL,1); /* clear kernel counters */
- if (first) {
- timer_setup(&poll_timer, suni_hz, 0);
- poll_timer.expires = jiffies+HZ;
-#if 0
-printk(KERN_DEBUG "[u] p=0x%lx,n=0x%lx\n",(unsigned long) poll_timer.list.prev,
- (unsigned long) poll_timer.list.next);
-#endif
- add_timer(&poll_timer);
- }
- return 0;
-}
-
-
-static int suni_stop(struct atm_dev *dev)
-{
- struct suni_priv **walk;
- unsigned long flags;
-
- /* let SAR driver worry about stopping interrupts */
- spin_lock_irqsave(&sunis_lock,flags);
- for (walk = &sunis; *walk != PRIV(dev);
- walk = &PRIV((*walk)->dev)->next);
- *walk = PRIV((*walk)->dev)->next;
- if (!sunis) timer_delete_sync(&poll_timer);
- spin_unlock_irqrestore(&sunis_lock,flags);
- kfree(PRIV(dev));
-
- return 0;
-}
-
-
-static const struct atmphy_ops suni_ops = {
- .start = suni_start,
- .ioctl = suni_ioctl,
- .interrupt = suni_int,
- .stop = suni_stop,
-};
-
-
-int suni_init(struct atm_dev *dev)
-{
- unsigned char mri;
-
- if (!(dev->phy_data = kmalloc_obj(struct suni_priv)))
- return -ENOMEM;
- PRIV(dev)->dev = dev;
-
- mri = GET(MRI); /* reset SUNI */
- PRIV(dev)->type = (mri & SUNI_MRI_TYPE) >> SUNI_MRI_TYPE_SHIFT;
- PUT(mri | SUNI_MRI_RESET,MRI);
- PUT(mri,MRI);
- PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */
- set_sonet(dev);
- REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP,
- TACP_IUCHP); /* idle cells */
- PUT(SUNI_IDLE_PATTERN,TACP_IUCPOP);
- dev->phy = &suni_ops;
-
- return 0;
-}
-
-EXPORT_SYMBOL(suni_init);
-
-MODULE_DESCRIPTION("S/UNI PHY driver");
-MODULE_LICENSE("GPL");
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
deleted file mode 100644
index 6580d67c3456..000000000000
--- a/net/atm/br2684.c
+++ /dev/null
@@ -1,872 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Ethernet netdevice using ATM AAL5 as underlying carrier
- * (RFC1483 obsoleted by RFC2684) for Linux
- *
- * Authors: Marcell GAL, 2000, XDSL Ltd, Hungary
- * Eric Kinzie, 2006-2007, US Naval Research Laboratory
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <linux/ip.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <net/arp.h>
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/capability.h>
-#include <linux/seq_file.h>
-
-#include <linux/atmbr2684.h>
-
-#include "common.h"
-
-static void skb_debug(const struct sk_buff *skb)
-{
-#ifdef SKB_DEBUG
-#define NUM2PRINT 50
- print_hex_dump(KERN_DEBUG, "br2684: skb: ", DUMP_OFFSET,
- 16, 1, skb->data, min(NUM2PRINT, skb->len), true);
-#endif
-}
-
-#define BR2684_ETHERTYPE_LEN 2
-#define BR2684_PAD_LEN 2
-
-#define LLC 0xaa, 0xaa, 0x03
-#define SNAP_BRIDGED 0x00, 0x80, 0xc2
-#define SNAP_ROUTED 0x00, 0x00, 0x00
-#define PID_ETHERNET 0x00, 0x07
-#define ETHERTYPE_IPV4 0x08, 0x00
-#define ETHERTYPE_IPV6 0x86, 0xdd
-#define PAD_BRIDGED 0x00, 0x00
-
-static const unsigned char ethertype_ipv4[] = { ETHERTYPE_IPV4 };
-static const unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 };
-static const unsigned char llc_oui_pid_pad[] =
- { LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED };
-static const unsigned char pad[] = { PAD_BRIDGED };
-static const unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 };
-static const unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 };
-
-enum br2684_encaps {
- e_vc = BR2684_ENCAPS_VC,
- e_llc = BR2684_ENCAPS_LLC,
-};
-
-struct br2684_vcc {
- struct atm_vcc *atmvcc;
- struct net_device *device;
- /* keep old push, pop functions for chaining */
- void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
- void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
- void (*old_release_cb)(struct atm_vcc *vcc);
- struct module *old_owner;
- enum br2684_encaps encaps;
- struct list_head brvccs;
-#ifdef CONFIG_ATM_BR2684_IPFILTER
- struct br2684_filter filter;
-#endif /* CONFIG_ATM_BR2684_IPFILTER */
- unsigned int copies_needed, copies_failed;
- atomic_t qspace;
-};
-
-struct br2684_dev {
- struct net_device *net_dev;
- struct list_head br2684_devs;
- int number;
- struct list_head brvccs; /* one device <=> one vcc (before xmas) */
- int mac_was_set;
- enum br2684_payload payload;
-};
-
-/*
- * This lock should be held for writing any time the list of devices or
- * their attached vcc's could be altered. It should be held for reading
- * any time these are being queried. Note that we sometimes need to
- * do read-locking under interrupting context, so write locking must block
- * the current CPU's interrupts.
- */
-static DEFINE_RWLOCK(devs_lock);
-
-static LIST_HEAD(br2684_devs);
-
-static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
-{
- return netdev_priv(net_dev);
-}
-
-static inline struct net_device *list_entry_brdev(const struct list_head *le)
-{
- return list_entry(le, struct br2684_dev, br2684_devs)->net_dev;
-}
-
-static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
-{
- return (struct br2684_vcc *)(atmvcc->user_back);
-}
-
-static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
-{
- return list_entry(le, struct br2684_vcc, brvccs);
-}
-
-/* Caller should hold read_lock(&devs_lock) */
-static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
-{
- struct list_head *lh;
- struct net_device *net_dev;
- switch (s->method) {
- case BR2684_FIND_BYNUM:
- list_for_each(lh, &br2684_devs) {
- net_dev = list_entry_brdev(lh);
- if (BRPRIV(net_dev)->number == s->spec.devnum)
- return net_dev;
- }
- break;
- case BR2684_FIND_BYIFNAME:
- list_for_each(lh, &br2684_devs) {
- net_dev = list_entry_brdev(lh);
- if (!strncmp(net_dev->name, s->spec.ifname, IFNAMSIZ))
- return net_dev;
- }
- break;
- }
- return NULL;
-}
-
-static int atm_dev_event(struct notifier_block *this, unsigned long event,
- void *arg)
-{
- struct atm_dev *atm_dev = arg;
- struct list_head *lh;
- struct net_device *net_dev;
- struct br2684_vcc *brvcc;
- struct atm_vcc *atm_vcc;
- unsigned long flags;
-
- pr_debug("event=%ld dev=%p\n", event, atm_dev);
-
- read_lock_irqsave(&devs_lock, flags);
- list_for_each(lh, &br2684_devs) {
- net_dev = list_entry_brdev(lh);
-
- list_for_each_entry(brvcc, &BRPRIV(net_dev)->brvccs, brvccs) {
- atm_vcc = brvcc->atmvcc;
- if (atm_vcc && brvcc->atmvcc->dev == atm_dev) {
-
- if (atm_vcc->dev->signal == ATM_PHY_SIG_LOST)
- netif_carrier_off(net_dev);
- else
- netif_carrier_on(net_dev);
-
- }
- }
- }
- read_unlock_irqrestore(&devs_lock, flags);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block atm_dev_notifier = {
- .notifier_call = atm_dev_event,
-};
-
-/* chained vcc->pop function. Check if we should wake the netif_queue */
-static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct br2684_vcc *brvcc = BR2684_VCC(vcc);
-
- pr_debug("(vcc %p ; net_dev %p )\n", vcc, brvcc->device);
- brvcc->old_pop(vcc, skb);
-
- /* If the queue space just went up from zero, wake */
- if (atomic_inc_return(&brvcc->qspace) == 1)
- netif_wake_queue(brvcc->device);
-}
-
-/*
- * Send a packet out a particular vcc. Not to useful right now, but paves
- * the way for multiple vcc's per itf. Returns true if we can send,
- * otherwise false
- */
-static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
- struct br2684_vcc *brvcc)
-{
- struct br2684_dev *brdev = BRPRIV(dev);
- struct atm_vcc *atmvcc;
- int minheadroom = (brvcc->encaps == e_llc) ?
- ((brdev->payload == p_bridged) ?
- sizeof(llc_oui_pid_pad) : sizeof(llc_oui_ipv4)) :
- ((brdev->payload == p_bridged) ? BR2684_PAD_LEN : 0);
-
- if (skb_headroom(skb) < minheadroom) {
- struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
- brvcc->copies_needed++;
- dev_kfree_skb(skb);
- if (skb2 == NULL) {
- brvcc->copies_failed++;
- return 0;
- }
- skb = skb2;
- }
-
- if (brvcc->encaps == e_llc) {
- if (brdev->payload == p_bridged) {
- skb_push(skb, sizeof(llc_oui_pid_pad));
- skb_copy_to_linear_data(skb, llc_oui_pid_pad,
- sizeof(llc_oui_pid_pad));
- } else if (brdev->payload == p_routed) {
- unsigned short prot = ntohs(skb->protocol);
-
- skb_push(skb, sizeof(llc_oui_ipv4));
- switch (prot) {
- case ETH_P_IP:
- skb_copy_to_linear_data(skb, llc_oui_ipv4,
- sizeof(llc_oui_ipv4));
- break;
- case ETH_P_IPV6:
- skb_copy_to_linear_data(skb, llc_oui_ipv6,
- sizeof(llc_oui_ipv6));
- break;
- default:
- dev_kfree_skb(skb);
- return 0;
- }
- }
- } else { /* e_vc */
- if (brdev->payload == p_bridged) {
- skb_push(skb, 2);
- memset(skb->data, 0, 2);
- }
- }
- skb_debug(skb);
-
- ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
- pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
- atm_account_tx(atmvcc, skb);
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
-
- if (atomic_dec_return(&brvcc->qspace) < 1) {
- /* No more please! */
- netif_stop_queue(brvcc->device);
- /* We might have raced with br2684_pop() */
- if (unlikely(atomic_read(&brvcc->qspace) > 0))
- netif_wake_queue(brvcc->device);
- }
-
- /* If this fails immediately, the skb will be freed and br2684_pop()
- will wake the queue if appropriate. Just return an error so that
- the stats are updated correctly */
- return !atmvcc->send(atmvcc, skb);
-}
-
-static void br2684_release_cb(struct atm_vcc *atmvcc)
-{
- struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
-
- if (atomic_read(&brvcc->qspace) > 0)
- netif_wake_queue(brvcc->device);
-
- if (brvcc->old_release_cb)
- brvcc->old_release_cb(atmvcc);
-}
-
-static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
- const struct br2684_dev *brdev)
-{
- return list_empty(&brdev->brvccs) ? NULL : list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
-}
-
-static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct br2684_dev *brdev = BRPRIV(dev);
- struct br2684_vcc *brvcc;
- struct atm_vcc *atmvcc;
- netdev_tx_t ret = NETDEV_TX_OK;
-
- pr_debug("skb_dst(skb)=%p\n", skb_dst(skb));
- read_lock(&devs_lock);
- brvcc = pick_outgoing_vcc(skb, brdev);
- if (brvcc == NULL) {
- pr_debug("no vcc attached to dev %s\n", dev->name);
- dev->stats.tx_errors++;
- dev->stats.tx_carrier_errors++;
- /* netif_stop_queue(dev); */
- dev_kfree_skb(skb);
- goto out_devs;
- }
- atmvcc = brvcc->atmvcc;
-
- bh_lock_sock(sk_atm(atmvcc));
-
- if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
- test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
- !test_bit(ATM_VF_READY, &atmvcc->flags)) {
- dev->stats.tx_dropped++;
- dev_kfree_skb(skb);
- goto out;
- }
-
- if (sock_owned_by_user(sk_atm(atmvcc))) {
- netif_stop_queue(brvcc->device);
- ret = NETDEV_TX_BUSY;
- goto out;
- }
-
- if (!br2684_xmit_vcc(skb, dev, brvcc)) {
- /*
- * We should probably use netif_*_queue() here, but that
- * involves added complication. We need to walk before
- * we can run.
- *
- * Don't free here! this pointer might be no longer valid!
- */
- dev->stats.tx_errors++;
- dev->stats.tx_fifo_errors++;
- }
- out:
- bh_unlock_sock(sk_atm(atmvcc));
- out_devs:
- read_unlock(&devs_lock);
- return ret;
-}
-
-/*
- * We remember when the MAC gets set, so we don't override it later with
- * the ESI of the ATM card of the first VC
- */
-static int br2684_mac_addr(struct net_device *dev, void *p)
-{
- int err = eth_mac_addr(dev, p);
- if (!err)
- BRPRIV(dev)->mac_was_set = 1;
- return err;
-}
-
-#ifdef CONFIG_ATM_BR2684_IPFILTER
-/* this IOCTL is experimental. */
-static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg)
-{
- struct br2684_vcc *brvcc;
- struct br2684_filter_set fs;
-
- if (copy_from_user(&fs, arg, sizeof fs))
- return -EFAULT;
- if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
- /*
- * This is really a per-vcc thing, but we can also search
- * by device.
- */
- struct br2684_dev *brdev;
- read_lock(&devs_lock);
- brdev = BRPRIV(br2684_find_dev(&fs.ifspec));
- if (brdev == NULL || list_empty(&brdev->brvccs) ||
- brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */
- brvcc = NULL;
- else
- brvcc = list_entry_brvcc(brdev->brvccs.next);
- read_unlock(&devs_lock);
- if (brvcc == NULL)
- return -ESRCH;
- } else
- brvcc = BR2684_VCC(atmvcc);
- memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
- return 0;
-}
-
-/* Returns 1 if packet should be dropped */
-static inline int
-packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
-{
- if (brvcc->filter.netmask == 0)
- return 0; /* no filter in place */
- if (type == htons(ETH_P_IP) &&
- (((struct iphdr *)(skb->data))->daddr & brvcc->filter.
- netmask) == brvcc->filter.prefix)
- return 0;
- if (type == htons(ETH_P_ARP))
- return 0;
- /*
- * TODO: we should probably filter ARPs too.. don't want to have
- * them returning values that don't make sense, or is that ok?
- */
- return 1; /* drop */
-}
-#endif /* CONFIG_ATM_BR2684_IPFILTER */
-
-static void br2684_close_vcc(struct br2684_vcc *brvcc)
-{
- pr_debug("removing VCC %p from dev %p\n", brvcc, brvcc->device);
- write_lock_irq(&devs_lock);
- list_del(&brvcc->brvccs);
- write_unlock_irq(&devs_lock);
- brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
- brvcc->atmvcc->release_cb = brvcc->old_release_cb;
- brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
- module_put(brvcc->old_owner);
- kfree(brvcc);
-}
-
-/* when AAL5 PDU comes in: */
-static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
-{
- struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
- struct net_device *net_dev = brvcc->device;
- struct br2684_dev *brdev = BRPRIV(net_dev);
-
- pr_debug("\n");
-
- if (unlikely(skb == NULL)) {
- /* skb==NULL means VCC is being destroyed */
- br2684_close_vcc(brvcc);
- if (list_empty(&brdev->brvccs)) {
- write_lock_irq(&devs_lock);
- list_del(&brdev->br2684_devs);
- write_unlock_irq(&devs_lock);
- unregister_netdev(net_dev);
- free_netdev(net_dev);
- }
- return;
- }
-
- skb_debug(skb);
- atm_return(atmvcc, skb->truesize);
- pr_debug("skb from brdev %p\n", brdev);
- if (brvcc->encaps == e_llc) {
-
- if (skb->len > 7 && skb->data[7] == 0x01)
- __skb_trim(skb, skb->len - 4);
-
- /* accept packets that have "ipv[46]" in the snap header */
- if ((skb->len >= (sizeof(llc_oui_ipv4))) &&
- (memcmp(skb->data, llc_oui_ipv4,
- sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) {
- if (memcmp(skb->data + 6, ethertype_ipv6,
- sizeof(ethertype_ipv6)) == 0)
- skb->protocol = htons(ETH_P_IPV6);
- else if (memcmp(skb->data + 6, ethertype_ipv4,
- sizeof(ethertype_ipv4)) == 0)
- skb->protocol = htons(ETH_P_IP);
- else
- goto error;
- skb_pull(skb, sizeof(llc_oui_ipv4));
- skb_reset_network_header(skb);
- skb->pkt_type = PACKET_HOST;
- /*
- * Let us waste some time for checking the encapsulation.
- * Note, that only 7 char is checked so frames with a valid FCS
- * are also accepted (but FCS is not checked of course).
- */
- } else if ((skb->len >= sizeof(llc_oui_pid_pad)) &&
- (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) {
- skb_pull(skb, sizeof(llc_oui_pid_pad));
- skb->protocol = eth_type_trans(skb, net_dev);
- } else
- goto error;
-
- } else { /* e_vc */
- if (brdev->payload == p_routed) {
- struct iphdr *iph;
-
- skb_reset_network_header(skb);
- iph = ip_hdr(skb);
- if (iph->version == 4)
- skb->protocol = htons(ETH_P_IP);
- else if (iph->version == 6)
- skb->protocol = htons(ETH_P_IPV6);
- else
- goto error;
- skb->pkt_type = PACKET_HOST;
- } else { /* p_bridged */
- /* first 2 chars should be 0 */
- if (memcmp(skb->data, pad, BR2684_PAD_LEN) != 0)
- goto error;
- skb_pull(skb, BR2684_PAD_LEN);
- skb->protocol = eth_type_trans(skb, net_dev);
- }
- }
-
-#ifdef CONFIG_ATM_BR2684_IPFILTER
- if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb)))
- goto dropped;
-#endif /* CONFIG_ATM_BR2684_IPFILTER */
- skb->dev = net_dev;
- ATM_SKB(skb)->vcc = atmvcc; /* needed ? */
- pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol));
- skb_debug(skb);
- /* sigh, interface is down? */
- if (unlikely(!(net_dev->flags & IFF_UP)))
- goto dropped;
- net_dev->stats.rx_packets++;
- net_dev->stats.rx_bytes += skb->len;
- memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
- netif_rx(skb);
- return;
-
-dropped:
- net_dev->stats.rx_dropped++;
- goto free_skb;
-error:
- net_dev->stats.rx_errors++;
-free_skb:
- dev_kfree_skb(skb);
-}
-
-/*
- * Assign a vcc to a dev
- * Note: we do not have explicit unassign, but look at _push()
- */
-static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
-{
- struct br2684_vcc *brvcc;
- struct br2684_dev *brdev;
- struct net_device *net_dev;
- struct atm_backend_br2684 be;
- int err;
-
- if (copy_from_user(&be, arg, sizeof be))
- return -EFAULT;
- brvcc = kzalloc_obj(struct br2684_vcc);
- if (!brvcc)
- return -ENOMEM;
- /*
- * Allow two packets in the ATM queue. One actually being sent, and one
- * for the ATM 'TX done' handler to send. It shouldn't take long to get
- * the next one from the netdev queue, when we need it. More than that
- * would be bufferbloat.
- */
- atomic_set(&brvcc->qspace, 2);
- write_lock_irq(&devs_lock);
- net_dev = br2684_find_dev(&be.ifspec);
- if (net_dev == NULL) {
- pr_err("tried to attach to non-existent device\n");
- err = -ENXIO;
- goto error;
- }
- brdev = BRPRIV(net_dev);
- if (atmvcc->push == NULL) {
- err = -EBADFD;
- goto error;
- }
- if (!list_empty(&brdev->brvccs)) {
- /* Only 1 VCC/dev right now */
- err = -EEXIST;
- goto error;
- }
- if (be.fcs_in != BR2684_FCSIN_NO ||
- be.fcs_out != BR2684_FCSOUT_NO ||
- be.fcs_auto || be.has_vpiid || be.send_padding ||
- (be.encaps != BR2684_ENCAPS_VC &&
- be.encaps != BR2684_ENCAPS_LLC) ||
- be.min_size != 0) {
- err = -EINVAL;
- goto error;
- }
- pr_debug("vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, brvcc);
- if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
- unsigned char *esi = atmvcc->dev->esi;
- const u8 one = 1;
-
- if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
- dev_addr_set(net_dev, esi);
- else
- dev_addr_mod(net_dev, 2, &one, 1);
- }
- list_add(&brvcc->brvccs, &brdev->brvccs);
- write_unlock_irq(&devs_lock);
- brvcc->device = net_dev;
- brvcc->atmvcc = atmvcc;
- atmvcc->user_back = brvcc;
- brvcc->encaps = (enum br2684_encaps)be.encaps;
- brvcc->old_push = atmvcc->push;
- brvcc->old_pop = atmvcc->pop;
- brvcc->old_release_cb = atmvcc->release_cb;
- brvcc->old_owner = atmvcc->owner;
- barrier();
- atmvcc->push = br2684_push;
- atmvcc->pop = br2684_pop;
- atmvcc->release_cb = br2684_release_cb;
- atmvcc->owner = THIS_MODULE;
-
- /* initialize netdev carrier state */
- if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
- netif_carrier_off(net_dev);
- else
- netif_carrier_on(net_dev);
-
- __module_get(THIS_MODULE);
-
- /* re-process everything received between connection setup and
- backend setup */
- vcc_process_recv_queue(atmvcc);
- return 0;
-
-error:
- write_unlock_irq(&devs_lock);
- kfree(brvcc);
- return err;
-}
-
-static const struct net_device_ops br2684_netdev_ops = {
- .ndo_start_xmit = br2684_start_xmit,
- .ndo_set_mac_address = br2684_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-static const struct net_device_ops br2684_netdev_ops_routed = {
- .ndo_start_xmit = br2684_start_xmit,
- .ndo_set_mac_address = br2684_mac_addr,
-};
-
-static void br2684_setup(struct net_device *netdev)
-{
- struct br2684_dev *brdev = BRPRIV(netdev);
-
- ether_setup(netdev);
- netdev->hard_header_len += sizeof(llc_oui_pid_pad); /* worst case */
- brdev->net_dev = netdev;
-
- netdev->netdev_ops = &br2684_netdev_ops;
-
- INIT_LIST_HEAD(&brdev->brvccs);
-}
-
-static void br2684_setup_routed(struct net_device *netdev)
-{
- struct br2684_dev *brdev = BRPRIV(netdev);
-
- brdev->net_dev = netdev;
- netdev->hard_header_len = sizeof(llc_oui_ipv4); /* worst case */
- netdev->netdev_ops = &br2684_netdev_ops_routed;
- netdev->addr_len = 0;
- netdev->mtu = ETH_DATA_LEN;
- netdev->min_mtu = 0;
- netdev->max_mtu = ETH_MAX_MTU;
- netdev->type = ARPHRD_PPP;
- netdev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
- netdev->tx_queue_len = 100;
- INIT_LIST_HEAD(&brdev->brvccs);
-}
-
-static int br2684_create(void __user *arg)
-{
- int err;
- struct net_device *netdev;
- struct br2684_dev *brdev;
- struct atm_newif_br2684 ni;
- enum br2684_payload payload;
-
- pr_debug("\n");
-
- if (copy_from_user(&ni, arg, sizeof ni))
- return -EFAULT;
-
- if (ni.media & BR2684_FLAG_ROUTED)
- payload = p_routed;
- else
- payload = p_bridged;
- ni.media &= 0xffff; /* strip flags */
-
- if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500)
- return -EINVAL;
-
- netdev = alloc_netdev(sizeof(struct br2684_dev),
- ni.ifname[0] ? ni.ifname : "nas%d",
- NET_NAME_UNKNOWN,
- (payload == p_routed) ? br2684_setup_routed : br2684_setup);
- if (!netdev)
- return -ENOMEM;
-
- brdev = BRPRIV(netdev);
-
- pr_debug("registered netdev %s\n", netdev->name);
- /* open, stop, do_ioctl ? */
- err = register_netdev(netdev);
- if (err < 0) {
- pr_err("register_netdev failed\n");
- free_netdev(netdev);
- return err;
- }
-
- write_lock_irq(&devs_lock);
-
- brdev->payload = payload;
-
- if (list_empty(&br2684_devs)) {
- /* 1st br2684 device */
- brdev->number = 1;
- } else
- brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
-
- list_add_tail(&brdev->br2684_devs, &br2684_devs);
- write_unlock_irq(&devs_lock);
- return 0;
-}
-
-/*
- * This handles ioctls actually performed on our vcc - we must return
- * -ENOIOCTLCMD for any unrecognized ioctl
- */
-static int br2684_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg)
-{
- struct atm_vcc *atmvcc = ATM_SD(sock);
- void __user *argp = (void __user *)arg;
- atm_backend_t b;
-
- int err;
- switch (cmd) {
- case ATM_SETBACKEND:
- case ATM_NEWBACKENDIF:
- err = get_user(b, (atm_backend_t __user *) argp);
- if (err)
- return -EFAULT;
- if (b != ATM_BACKEND_BR2684)
- return -ENOIOCTLCMD;
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (cmd == ATM_SETBACKEND) {
- if (sock->state != SS_CONNECTED)
- return -EINVAL;
- return br2684_regvcc(atmvcc, argp);
- } else {
- return br2684_create(argp);
- }
-#ifdef CONFIG_ATM_BR2684_IPFILTER
- case BR2684_SETFILT:
- if (atmvcc->push != br2684_push)
- return -ENOIOCTLCMD;
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- err = br2684_setfilt(atmvcc, argp);
-
- return err;
-#endif /* CONFIG_ATM_BR2684_IPFILTER */
- }
- return -ENOIOCTLCMD;
-}
-
-static struct atm_ioctl br2684_ioctl_ops = {
- .owner = THIS_MODULE,
- .ioctl = br2684_ioctl,
-};
-
-#ifdef CONFIG_PROC_FS
-static void *br2684_seq_start(struct seq_file *seq, loff_t * pos)
- __acquires(devs_lock)
-{
- read_lock(&devs_lock);
- return seq_list_start(&br2684_devs, *pos);
-}
-
-static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t * pos)
-{
- return seq_list_next(v, &br2684_devs, pos);
-}
-
-static void br2684_seq_stop(struct seq_file *seq, void *v)
- __releases(devs_lock)
-{
- read_unlock(&devs_lock);
-}
-
-static int br2684_seq_show(struct seq_file *seq, void *v)
-{
- const struct br2684_dev *brdev = list_entry(v, struct br2684_dev,
- br2684_devs);
- const struct net_device *net_dev = brdev->net_dev;
- const struct br2684_vcc *brvcc;
-
- seq_printf(seq, "dev %.16s: num=%d, mac=%pM (%s)\n",
- net_dev->name,
- brdev->number,
- net_dev->dev_addr,
- brdev->mac_was_set ? "set" : "auto");
-
- list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
- seq_printf(seq, " vcc %d.%d.%d: encaps=%s payload=%s"
- ", failed copies %u/%u"
- "\n", brvcc->atmvcc->dev->number,
- brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
- (brvcc->encaps == e_llc) ? "LLC" : "VC",
- (brdev->payload == p_bridged) ? "bridged" : "routed",
- brvcc->copies_failed, brvcc->copies_needed);
-#ifdef CONFIG_ATM_BR2684_IPFILTER
- if (brvcc->filter.netmask != 0)
- seq_printf(seq, " filter=%pI4/%pI4\n",
- &brvcc->filter.prefix,
- &brvcc->filter.netmask);
-#endif /* CONFIG_ATM_BR2684_IPFILTER */
- }
- return 0;
-}
-
-static const struct seq_operations br2684_seq_ops = {
- .start = br2684_seq_start,
- .next = br2684_seq_next,
- .stop = br2684_seq_stop,
- .show = br2684_seq_show,
-};
-
-extern struct proc_dir_entry *atm_proc_root; /* from proc.c */
-#endif /* CONFIG_PROC_FS */
-
-static int __init br2684_init(void)
-{
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *p;
- p = proc_create_seq("br2684", 0, atm_proc_root, &br2684_seq_ops);
- if (p == NULL)
- return -ENOMEM;
-#endif
- register_atm_ioctl(&br2684_ioctl_ops);
- register_atmdevice_notifier(&atm_dev_notifier);
- return 0;
-}
-
-static void __exit br2684_exit(void)
-{
- struct net_device *net_dev;
- struct br2684_dev *brdev;
- struct br2684_vcc *brvcc;
- deregister_atm_ioctl(&br2684_ioctl_ops);
-
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("br2684", atm_proc_root);
-#endif
-
-
- unregister_atmdevice_notifier(&atm_dev_notifier);
-
- while (!list_empty(&br2684_devs)) {
- net_dev = list_entry_brdev(br2684_devs.next);
- brdev = BRPRIV(net_dev);
- while (!list_empty(&brdev->brvccs)) {
- brvcc = list_entry_brvcc(brdev->brvccs.next);
- br2684_close_vcc(brvcc);
- }
-
- list_del(&brdev->br2684_devs);
- unregister_netdev(net_dev);
- free_netdev(net_dev);
- }
-}
-
-module_init(br2684_init);
-module_exit(br2684_exit);
-
-MODULE_AUTHOR("Marcell GAL");
-MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
-MODULE_LICENSE("GPL");
diff --git a/net/atm/clip.c b/net/atm/clip.c
deleted file mode 100644
index 516b2214680b..000000000000
--- a/net/atm/clip.c
+++ /dev/null
@@ -1,960 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* net/atm/clip.c - RFC1577 Classical IP over ATM */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/kernel.h> /* for UINT_MAX */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/wait.h>
-#include <linux/timer.h>
-#include <linux/if_arp.h> /* for some manifest constants */
-#include <linux/notifier.h>
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/atmclip.h>
-#include <linux/atmarp.h>
-#include <linux/capability.h>
-#include <linux/ip.h> /* for net/route.h */
-#include <linux/in.h> /* for struct sockaddr_in */
-#include <linux/if.h> /* for IFF_UP */
-#include <linux/inetdevice.h>
-#include <linux/bitops.h>
-#include <linux/poison.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/rcupdate.h>
-#include <linux/jhash.h>
-#include <linux/slab.h>
-#include <net/route.h> /* for struct rtable and routing */
-#include <net/icmp.h> /* icmp_send */
-#include <net/arp.h>
-#include <linux/param.h> /* for HZ */
-#include <linux/uaccess.h>
-#include <asm/byteorder.h> /* for htons etc. */
-#include <linux/atomic.h>
-
-#include "common.h"
-#include "resources.h"
-#include <net/atmclip.h>
-
-static struct net_device *clip_devs;
-static struct atm_vcc __rcu *atmarpd;
-static DEFINE_MUTEX(atmarpd_lock);
-static struct timer_list idle_timer;
-static const struct neigh_ops clip_neigh_ops;
-
-static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip)
-{
- struct sock *sk;
- struct atmarp_ctrl *ctrl;
- struct atm_vcc *vcc;
- struct sk_buff *skb;
- int err = 0;
-
- pr_debug("(%d)\n", type);
-
- rcu_read_lock();
- vcc = rcu_dereference(atmarpd);
- if (!vcc) {
- err = -EUNATCH;
- goto unlock;
- }
- skb = alloc_skb(sizeof(struct atmarp_ctrl), GFP_ATOMIC);
- if (!skb) {
- err = -ENOMEM;
- goto unlock;
- }
- ctrl = skb_put(skb, sizeof(struct atmarp_ctrl));
- ctrl->type = type;
- ctrl->itf_num = itf;
- ctrl->ip = ip;
- atm_force_charge(vcc, skb->truesize);
-
- sk = sk_atm(vcc);
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk);
-unlock:
- rcu_read_unlock();
- return err;
-}
-
-static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
-{
- pr_debug("%p to entry %p (neigh %p)\n", clip_vcc, entry, entry->neigh);
- clip_vcc->entry = entry;
- clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
- clip_vcc->next = entry->vccs;
- entry->vccs = clip_vcc;
- entry->neigh->used = jiffies;
-}
-
-static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
-{
- struct atmarp_entry *entry = clip_vcc->entry;
- struct clip_vcc **walk;
-
- if (!entry) {
- pr_err("!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
- return;
- }
- netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */
- entry->neigh->used = jiffies;
- for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
- if (*walk == clip_vcc) {
- int error;
-
- *walk = clip_vcc->next; /* atomic */
- clip_vcc->entry = NULL;
- if (clip_vcc->xoff)
- netif_wake_queue(entry->neigh->dev);
- if (entry->vccs)
- goto out;
- entry->expires = jiffies - 1;
- /* force resolution or expiration */
- error = neigh_update(entry->neigh, NULL, NUD_NONE,
- NEIGH_UPDATE_F_ADMIN, 0);
- if (error)
- pr_err("neigh_update failed with %d\n", error);
- goto out;
- }
- pr_err("ATMARP: failed (entry %p, vcc 0x%p)\n", entry, clip_vcc);
-out:
- netif_tx_unlock_bh(entry->neigh->dev);
-}
-
-/* The neighbour entry n->lock is held. */
-static int neigh_check_cb(struct neighbour *n)
-{
- struct atmarp_entry *entry = neighbour_priv(n);
- struct clip_vcc *cv;
-
- if (n->ops != &clip_neigh_ops)
- return 0;
- for (cv = entry->vccs; cv; cv = cv->next) {
- unsigned long exp = cv->last_use + cv->idle_timeout;
-
- if (cv->idle_timeout && time_after(jiffies, exp)) {
- pr_debug("releasing vcc %p->%p of entry %p\n",
- cv, cv->vcc, entry);
- vcc_release_async(cv->vcc, -ETIMEDOUT);
- }
- }
-
- if (entry->vccs || time_before(jiffies, entry->expires))
- return 0;
-
- if (refcount_read(&n->refcnt) > 1) {
- struct sk_buff *skb;
-
- pr_debug("destruction postponed with ref %d\n",
- refcount_read(&n->refcnt));
-
- while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
- dev_kfree_skb(skb);
-
- return 0;
- }
-
- pr_debug("expired neigh %p\n", n);
- return 1;
-}
-
-static void idle_timer_check(struct timer_list *unused)
-{
- spin_lock(&arp_tbl.lock);
- __neigh_for_each_release(&arp_tbl, neigh_check_cb);
- mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
- spin_unlock(&arp_tbl.lock);
-}
-
-static int clip_arp_rcv(struct sk_buff *skb)
-{
- struct atm_vcc *vcc;
-
- pr_debug("\n");
- vcc = ATM_SKB(skb)->vcc;
- if (!vcc || !atm_charge(vcc, skb->truesize)) {
- dev_kfree_skb_any(skb);
- return 0;
- }
- pr_debug("pushing to %p\n", vcc);
- pr_debug("using %p\n", CLIP_VCC(vcc)->old_push);
- CLIP_VCC(vcc)->old_push(vcc, skb);
- return 0;
-}
-
-static const unsigned char llc_oui[] = {
- 0xaa, /* DSAP: non-ISO */
- 0xaa, /* SSAP: non-ISO */
- 0x03, /* Ctrl: Unnumbered Information Command PDU */
- 0x00, /* OUI: EtherType */
- 0x00,
- 0x00
-};
-
-static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
-
- pr_debug("\n");
-
- if (!skb) {
- pr_debug("removing VCC %p\n", clip_vcc);
- if (clip_vcc->entry)
- unlink_clip_vcc(clip_vcc);
- clip_vcc->old_push(vcc, NULL); /* pass on the bad news */
- kfree(clip_vcc);
- return;
- }
- atm_return(vcc, skb->truesize);
- if (!clip_devs) {
- kfree_skb(skb);
- return;
- }
-
- skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
- /* clip_vcc->entry == NULL if we don't have an IP address yet */
- if (!skb->dev) {
- dev_kfree_skb_any(skb);
- return;
- }
- ATM_SKB(skb)->vcc = vcc;
- skb_reset_mac_header(skb);
- if (!clip_vcc->encap ||
- skb->len < RFC1483LLC_LEN ||
- memcmp(skb->data, llc_oui, sizeof(llc_oui)))
- skb->protocol = htons(ETH_P_IP);
- else {
- skb->protocol = ((__be16 *)skb->data)[3];
- skb_pull(skb, RFC1483LLC_LEN);
- if (skb->protocol == htons(ETH_P_ARP)) {
- skb->dev->stats.rx_packets++;
- skb->dev->stats.rx_bytes += skb->len;
- clip_arp_rcv(skb);
- return;
- }
- }
- clip_vcc->last_use = jiffies;
- skb->dev->stats.rx_packets++;
- skb->dev->stats.rx_bytes += skb->len;
- memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
- netif_rx(skb);
-}
-
-/*
- * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
- * clip_pop is atomic with respect to the critical section in clip_start_xmit.
- */
-
-static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
- struct net_device *dev = skb->dev;
- int old;
- unsigned long flags;
-
- pr_debug("(vcc %p)\n", vcc);
- clip_vcc->old_pop(vcc, skb);
- /* skb->dev == NULL in outbound ARP packets */
- if (!dev)
- return;
- spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
- if (atm_may_send(vcc, 0)) {
- old = xchg(&clip_vcc->xoff, 0);
- if (old)
- netif_wake_queue(dev);
- }
- spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
-}
-
-static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
-{
- __be32 *ip = (__be32 *) neigh->primary_key;
-
- pr_debug("(neigh %p, skb %p)\n", neigh, skb);
- to_atmarpd(act_need, PRIV(neigh->dev)->number, *ip);
-}
-
-static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
-{
-#ifndef CONFIG_ATM_CLIP_NO_ICMP
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
-#endif
- kfree_skb(skb);
-}
-
-static const struct neigh_ops clip_neigh_ops = {
- .family = AF_INET,
- .solicit = clip_neigh_solicit,
- .error_report = clip_neigh_error,
- .output = neigh_direct_output,
- .connected_output = neigh_direct_output,
-};
-
-static int clip_constructor(struct net_device *dev, struct neighbour *neigh)
-{
- struct atmarp_entry *entry = neighbour_priv(neigh);
-
- if (neigh->tbl->family != AF_INET)
- return -EINVAL;
-
- if (neigh->type != RTN_UNICAST)
- return -EINVAL;
-
- neigh->nud_state = NUD_NONE;
- neigh->ops = &clip_neigh_ops;
- neigh->output = neigh->ops->output;
- entry->neigh = neigh;
- entry->vccs = NULL;
- entry->expires = jiffies - 1;
-
- return 0;
-}
-
-/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
-
-/*
- * We play with the resolve flag: 0 and 1 have the usual meaning, but -1 means
- * to allocate the neighbour entry but not to ask atmarpd for resolution. Also,
- * don't increment the usage count. This is used to create entries in
- * clip_setentry.
- */
-
-static int clip_encap(struct atm_vcc *vcc, int mode)
-{
- if (!CLIP_VCC(vcc))
- return -EBADFD;
-
- CLIP_VCC(vcc)->encap = mode;
- return 0;
-}
-
-static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct clip_priv *clip_priv = PRIV(dev);
- struct dst_entry *dst = skb_dst(skb);
- struct atmarp_entry *entry;
- struct neighbour *n;
- struct atm_vcc *vcc;
- struct rtable *rt;
- __be32 *daddr;
- int old;
- unsigned long flags;
-
- pr_debug("(skb %p)\n", skb);
- if (!dst) {
- pr_err("skb_dst(skb) == NULL\n");
- dev_kfree_skb(skb);
- dev->stats.tx_dropped++;
- return NETDEV_TX_OK;
- }
- rt = dst_rtable(dst);
- if (rt->rt_gw_family == AF_INET)
- daddr = &rt->rt_gw4;
- else
- daddr = &ip_hdr(skb)->daddr;
- n = dst_neigh_lookup(dst, daddr);
- if (!n) {
- pr_err("NO NEIGHBOUR !\n");
- dev_kfree_skb(skb);
- dev->stats.tx_dropped++;
- return NETDEV_TX_OK;
- }
- entry = neighbour_priv(n);
- if (!entry->vccs) {
- if (time_after(jiffies, entry->expires)) {
- /* should be resolved */
- entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
- to_atmarpd(act_need, PRIV(dev)->number, *((__be32 *)n->primary_key));
- }
- if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
- skb_queue_tail(&entry->neigh->arp_queue, skb);
- else {
- dev_kfree_skb(skb);
- dev->stats.tx_dropped++;
- }
- goto out_release_neigh;
- }
- pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
- ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
- pr_debug("using neighbour %p, vcc %p\n", n, vcc);
- if (entry->vccs->encap) {
- void *here;
-
- here = skb_push(skb, RFC1483LLC_LEN);
- memcpy(here, llc_oui, sizeof(llc_oui));
- ((__be16 *) here)[3] = skb->protocol;
- }
- atm_account_tx(vcc, skb);
- entry->vccs->last_use = jiffies;
- pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
- old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */
- if (old) {
- pr_warn("XOFF->XOFF transition\n");
- goto out_release_neigh;
- }
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
- vcc->send(vcc, skb);
- if (atm_may_send(vcc, 0)) {
- entry->vccs->xoff = 0;
- goto out_release_neigh;
- }
- spin_lock_irqsave(&clip_priv->xoff_lock, flags);
- netif_stop_queue(dev); /* XOFF -> throttle immediately */
- barrier();
- if (!entry->vccs->xoff)
- netif_start_queue(dev);
- /* Oh, we just raced with clip_pop. netif_start_queue should be
- good enough, because nothing should really be asleep because
- of the brief netif_stop_queue. If this isn't true or if it
- changes, use netif_wake_queue instead. */
- spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
-out_release_neigh:
- neigh_release(n);
- return NETDEV_TX_OK;
-}
-
-static int clip_mkip(struct atm_vcc *vcc, int timeout)
-{
- struct clip_vcc *clip_vcc;
-
- if (!vcc->push)
- return -EBADFD;
- if (vcc->user_back)
- return -EINVAL;
- clip_vcc = kmalloc_obj(struct clip_vcc);
- if (!clip_vcc)
- return -ENOMEM;
- pr_debug("%p vcc %p\n", clip_vcc, vcc);
- clip_vcc->vcc = vcc;
- vcc->user_back = clip_vcc;
- set_bit(ATM_VF_IS_CLIP, &vcc->flags);
- clip_vcc->entry = NULL;
- clip_vcc->xoff = 0;
- clip_vcc->encap = 1;
- clip_vcc->last_use = jiffies;
- clip_vcc->idle_timeout = timeout * HZ;
- clip_vcc->old_push = vcc->push;
- clip_vcc->old_pop = vcc->pop;
- vcc->push = clip_push;
- vcc->pop = clip_pop;
-
- /* re-process everything received between connection setup and MKIP */
- vcc_process_recv_queue(vcc);
-
- return 0;
-}
-
-static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
-{
- struct neighbour *neigh;
- struct atmarp_entry *entry;
- int error;
- struct clip_vcc *clip_vcc;
- struct rtable *rt;
-
- if (vcc->push != clip_push) {
- pr_warn("non-CLIP VCC\n");
- return -EBADF;
- }
- clip_vcc = CLIP_VCC(vcc);
- if (!ip) {
- if (!clip_vcc->entry) {
- pr_err("hiding hidden ATMARP entry\n");
- return 0;
- }
- pr_debug("remove\n");
- unlink_clip_vcc(clip_vcc);
- return 0;
- }
- rt = ip_route_output(&init_net, ip, 0, 0, 0, RT_SCOPE_LINK);
- if (IS_ERR(rt))
- return PTR_ERR(rt);
- neigh = __neigh_lookup(&arp_tbl, &ip, rt->dst.dev, 1);
- ip_rt_put(rt);
- if (!neigh)
- return -ENOMEM;
- entry = neighbour_priv(neigh);
- if (entry != clip_vcc->entry) {
- if (!clip_vcc->entry)
- pr_debug("add\n");
- else {
- pr_debug("update\n");
- unlink_clip_vcc(clip_vcc);
- }
- link_vcc(clip_vcc, entry);
- }
- error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
- NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN, 0);
- neigh_release(neigh);
- return error;
-}
-
-static const struct net_device_ops clip_netdev_ops = {
- .ndo_start_xmit = clip_start_xmit,
- .ndo_neigh_construct = clip_constructor,
-};
-
-static void clip_setup(struct net_device *dev)
-{
- dev->netdev_ops = &clip_netdev_ops;
- dev->type = ARPHRD_ATM;
- dev->neigh_priv_len = sizeof(struct atmarp_entry);
- dev->hard_header_len = RFC1483LLC_LEN;
- dev->mtu = RFC1626_MTU;
- dev->tx_queue_len = 100; /* "normal" queue (packets) */
- /* When using a "real" qdisc, the qdisc determines the queue */
- /* length. tx_queue_len is only used for the default case, */
- /* without any more elaborate queuing. 100 is a reasonable */
- /* compromise between decent burst-tolerance and protection */
- /* against memory hogs. */
- netif_keep_dst(dev);
-}
-
-static int clip_create(int number)
-{
- struct net_device *dev;
- struct clip_priv *clip_priv;
- int error;
-
- if (number != -1) {
- for (dev = clip_devs; dev; dev = PRIV(dev)->next)
- if (PRIV(dev)->number == number)
- return -EEXIST;
- } else {
- number = 0;
- for (dev = clip_devs; dev; dev = PRIV(dev)->next)
- if (PRIV(dev)->number >= number)
- number = PRIV(dev)->number + 1;
- }
- dev = alloc_netdev(sizeof(struct clip_priv), "", NET_NAME_UNKNOWN,
- clip_setup);
- if (!dev)
- return -ENOMEM;
- clip_priv = PRIV(dev);
- sprintf(dev->name, "atm%d", number);
- spin_lock_init(&clip_priv->xoff_lock);
- clip_priv->number = number;
- error = register_netdev(dev);
- if (error) {
- free_netdev(dev);
- return error;
- }
- clip_priv->next = clip_devs;
- clip_devs = dev;
- pr_debug("registered (net:%s)\n", dev->name);
- return number;
-}
-
-static int clip_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_UNREGISTER)
- return NOTIFY_DONE;
-
- /* ignore non-CLIP devices */
- if (dev->type != ARPHRD_ATM || dev->netdev_ops != &clip_netdev_ops)
- return NOTIFY_DONE;
-
- switch (event) {
- case NETDEV_UP:
- pr_debug("NETDEV_UP\n");
- to_atmarpd(act_up, PRIV(dev)->number, 0);
- break;
- case NETDEV_GOING_DOWN:
- pr_debug("NETDEV_DOWN\n");
- to_atmarpd(act_down, PRIV(dev)->number, 0);
- break;
- case NETDEV_CHANGE:
- case NETDEV_CHANGEMTU:
- pr_debug("NETDEV_CHANGE*\n");
- to_atmarpd(act_change, PRIV(dev)->number, 0);
- break;
- }
- return NOTIFY_DONE;
-}
-
-static int clip_inet_event(struct notifier_block *this, unsigned long event,
- void *ifa)
-{
- struct in_device *in_dev;
- struct netdev_notifier_info info;
-
- in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
- /*
- * Transitions are of the down-change-up type, so it's sufficient to
- * handle the change on up.
- */
- if (event != NETDEV_UP)
- return NOTIFY_DONE;
- netdev_notifier_info_init(&info, in_dev->dev);
- return clip_device_event(this, NETDEV_CHANGE, &info);
-}
-
-static struct notifier_block clip_dev_notifier = {
- .notifier_call = clip_device_event,
-};
-
-
-
-static struct notifier_block clip_inet_notifier = {
- .notifier_call = clip_inet_event,
-};
-
-
-
-static void atmarpd_close(struct atm_vcc *vcc)
-{
- pr_debug("\n");
-
- mutex_lock(&atmarpd_lock);
- RCU_INIT_POINTER(atmarpd, NULL);
- mutex_unlock(&atmarpd_lock);
-
- synchronize_rcu();
- skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
-
- pr_debug("(done)\n");
- module_put(THIS_MODULE);
-}
-
-static int atmarpd_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- atm_return_tx(vcc, skb);
- dev_kfree_skb_any(skb);
- return 0;
-}
-
-static const struct atmdev_ops atmarpd_dev_ops = {
- .close = atmarpd_close,
- .send = atmarpd_send
-};
-
-
-static struct atm_dev atmarpd_dev = {
- .ops = &atmarpd_dev_ops,
- .type = "arpd",
- .number = 999,
- .lock = __SPIN_LOCK_UNLOCKED(atmarpd_dev.lock)
-};
-
-
-static int atm_init_atmarp(struct atm_vcc *vcc)
-{
- if (vcc->push == clip_push)
- return -EINVAL;
-
- mutex_lock(&atmarpd_lock);
- if (atmarpd) {
- mutex_unlock(&atmarpd_lock);
- return -EADDRINUSE;
- }
-
- mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
-
- rcu_assign_pointer(atmarpd, vcc);
- set_bit(ATM_VF_META, &vcc->flags);
- set_bit(ATM_VF_READY, &vcc->flags);
- /* allow replies and avoid getting closed if signaling dies */
- vcc->dev = &atmarpd_dev;
- vcc_insert_socket(sk_atm(vcc));
- vcc->push = NULL;
- vcc->pop = NULL; /* crash */
- vcc->push_oam = NULL; /* crash */
- mutex_unlock(&atmarpd_lock);
- return 0;
-}
-
-static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- struct atm_vcc *vcc = ATM_SD(sock);
- struct sock *sk = sock->sk;
- int err = 0;
-
- switch (cmd) {
- case SIOCMKCLIP:
- case ATMARPD_CTRL:
- case ATMARP_MKIP:
- case ATMARP_SETENTRY:
- case ATMARP_ENCAP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- break;
- default:
- return -ENOIOCTLCMD;
- }
-
- switch (cmd) {
- case SIOCMKCLIP:
- err = clip_create(arg);
- break;
- case ATMARPD_CTRL:
- lock_sock(sk);
- err = atm_init_atmarp(vcc);
- if (!err) {
- sock->state = SS_CONNECTED;
- __module_get(THIS_MODULE);
- }
- release_sock(sk);
- break;
- case ATMARP_MKIP:
- lock_sock(sk);
- err = clip_mkip(vcc, arg);
- release_sock(sk);
- break;
- case ATMARP_SETENTRY:
- err = clip_setentry(vcc, (__force __be32)arg);
- break;
- case ATMARP_ENCAP:
- err = clip_encap(vcc, arg);
- break;
- }
- return err;
-}
-
-static struct atm_ioctl clip_ioctl_ops = {
- .owner = THIS_MODULE,
- .ioctl = clip_ioctl,
-};
-
-#ifdef CONFIG_PROC_FS
-
-static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
-{
- static int code[] = { 1, 2, 10, 6, 1, 0 };
- static int e164[] = { 1, 8, 4, 6, 1, 0 };
-
- if (*addr->sas_addr.pub) {
- seq_printf(seq, "%s", addr->sas_addr.pub);
- if (*addr->sas_addr.prv)
- seq_putc(seq, '+');
- } else if (!*addr->sas_addr.prv) {
- seq_printf(seq, "%s", "(none)");
- return;
- }
- if (*addr->sas_addr.prv) {
- unsigned char *prv = addr->sas_addr.prv;
- int *fields;
- int i, j;
-
- fields = *prv == ATM_AFI_E164 ? e164 : code;
- for (i = 0; fields[i]; i++) {
- for (j = fields[i]; j; j--)
- seq_printf(seq, "%02X", *prv++);
- if (fields[i + 1])
- seq_putc(seq, '.');
- }
- }
-}
-
-/* This means the neighbour entry has no attached VCC objects. */
-#define SEQ_NO_VCC_TOKEN ((void *) 2)
-
-static void atmarp_info(struct seq_file *seq, struct neighbour *n,
- struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
-{
- struct net_device *dev = n->dev;
- unsigned long exp;
- char buf[17];
- int svc, llc, off;
-
- svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
- (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
-
- llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
-
- if (clip_vcc == SEQ_NO_VCC_TOKEN)
- exp = entry->neigh->used;
- else
- exp = clip_vcc->last_use;
-
- exp = (jiffies - exp) / HZ;
-
- seq_printf(seq, "%-6s%-4s%-4s%5ld ",
- dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
-
- off = scnprintf(buf, sizeof(buf) - 1, "%pI4", n->primary_key);
- while (off < 16)
- buf[off++] = ' ';
- buf[off] = '\0';
- seq_printf(seq, "%s", buf);
-
- if (clip_vcc == SEQ_NO_VCC_TOKEN) {
- if (time_before(jiffies, entry->expires))
- seq_printf(seq, "(resolving)\n");
- else
- seq_printf(seq, "(expired, ref %d)\n",
- refcount_read(&entry->neigh->refcnt));
- } else if (!svc) {
- seq_printf(seq, "%d.%d.%d\n",
- clip_vcc->vcc->dev->number,
- clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
- } else {
- svc_addr(seq, &clip_vcc->vcc->remote);
- seq_putc(seq, '\n');
- }
-}
-
-struct clip_seq_state {
- /* This member must be first. */
- struct neigh_seq_state ns;
-
- /* Local to clip specific iteration. */
- struct clip_vcc *vcc;
-};
-
-static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
- struct clip_vcc *curr)
-{
- if (!curr) {
- curr = e->vccs;
- if (!curr)
- return SEQ_NO_VCC_TOKEN;
- return curr;
- }
- if (curr == SEQ_NO_VCC_TOKEN)
- return NULL;
-
- curr = curr->next;
-
- return curr;
-}
-
-static void *clip_seq_vcc_walk(struct clip_seq_state *state,
- struct atmarp_entry *e, loff_t * pos)
-{
- struct clip_vcc *vcc = state->vcc;
-
- vcc = clip_seq_next_vcc(e, vcc);
- if (vcc && pos != NULL) {
- while (*pos) {
- vcc = clip_seq_next_vcc(e, vcc);
- if (!vcc)
- break;
- --(*pos);
- }
- }
- state->vcc = vcc;
-
- return vcc;
-}
-
-static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
- struct neighbour *n, loff_t * pos)
-{
- struct clip_seq_state *state = (struct clip_seq_state *)_state;
-
- if (n->dev->type != ARPHRD_ATM)
- return NULL;
-
- return clip_seq_vcc_walk(state, neighbour_priv(n), pos);
-}
-
-static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
-{
- struct clip_seq_state *state = seq->private;
- state->ns.neigh_sub_iter = clip_seq_sub_iter;
- return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_NEIGH_ONLY);
-}
-
-static int clip_seq_show(struct seq_file *seq, void *v)
-{
- static char atm_arp_banner[] =
- "IPitf TypeEncp Idle IP address ATM address\n";
-
- if (v == SEQ_START_TOKEN) {
- seq_puts(seq, atm_arp_banner);
- } else {
- struct clip_seq_state *state = seq->private;
- struct clip_vcc *vcc = state->vcc;
- struct neighbour *n = v;
-
- atmarp_info(seq, n, neighbour_priv(n), vcc);
- }
- return 0;
-}
-
-static const struct seq_operations arp_seq_ops = {
- .start = clip_seq_start,
- .next = neigh_seq_next,
- .stop = neigh_seq_stop,
- .show = clip_seq_show,
-};
-#endif
-
-static void atm_clip_exit_noproc(void);
-
-static int __init atm_clip_init(void)
-{
- register_atm_ioctl(&clip_ioctl_ops);
- register_netdevice_notifier(&clip_dev_notifier);
- register_inetaddr_notifier(&clip_inet_notifier);
-
- timer_setup(&idle_timer, idle_timer_check, 0);
-
-#ifdef CONFIG_PROC_FS
- {
- struct proc_dir_entry *p;
-
- p = proc_create_net("arp", 0444, atm_proc_root, &arp_seq_ops,
- sizeof(struct clip_seq_state));
- if (!p) {
- pr_err("Unable to initialize /proc/net/atm/arp\n");
- atm_clip_exit_noproc();
- return -ENOMEM;
- }
- }
-#endif
-
- return 0;
-}
-
-static void atm_clip_exit_noproc(void)
-{
- struct net_device *dev, *next;
-
- unregister_inetaddr_notifier(&clip_inet_notifier);
- unregister_netdevice_notifier(&clip_dev_notifier);
-
- deregister_atm_ioctl(&clip_ioctl_ops);
-
- /* First, stop the idle timer, so it stops banging
- * on the table.
- */
- timer_delete_sync(&idle_timer);
-
- dev = clip_devs;
- while (dev) {
- next = PRIV(dev)->next;
- unregister_netdev(dev);
- free_netdev(dev);
- dev = next;
- }
-}
-
-static void __exit atm_clip_exit(void)
-{
- remove_proc_entry("arp", atm_proc_root);
-
- atm_clip_exit_noproc();
-}
-
-module_init(atm_clip_init);
-module_exit(atm_clip_exit);
-MODULE_AUTHOR("Werner Almesberger");
-MODULE_DESCRIPTION("Classical/IP over ATM interface");
-MODULE_LICENSE("GPL");
diff --git a/net/atm/lec.c b/net/atm/lec.c
deleted file mode 100644
index 10e260acf602..000000000000
--- a/net/atm/lec.c
+++ /dev/null
@@ -1,2274 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * lec.c: Lan Emulation driver
- *
- * Marko Kiiskila <mkiiskila@yahoo.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-#include <linux/capability.h>
-
-/* We are ethernet device */
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <net/sock.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <asm/byteorder.h>
-#include <linux/uaccess.h>
-#include <net/arp.h>
-#include <net/dst.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/seq_file.h>
-
-/* And atm device */
-#include <linux/atmdev.h>
-#include <linux/atmlec.h>
-
-/* Proxy LEC knows about bridging */
-#if IS_ENABLED(CONFIG_BRIDGE)
-#include "../bridge/br_private.h"
-
-static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
-#endif
-
-/* Modular too */
-#include <linux/module.h>
-#include <linux/init.h>
-
-/* Hardening for Spectre-v1 */
-#include <linux/nospec.h>
-
-#include "lec.h"
-#include "lec_arpc.h"
-#include "resources.h"
-
-#define DUMP_PACKETS 0 /*
- * 0 = None,
- * 1 = 30 first bytes
- * 2 = Whole packet
- */
-
-#define LEC_UNRES_QUE_LEN 8 /*
- * number of tx packets to queue for a
- * single destination while waiting for SVC
- */
-
-static int lec_open(struct net_device *dev);
-static netdev_tx_t lec_start_xmit(struct sk_buff *skb,
- struct net_device *dev);
-static int lec_close(struct net_device *dev);
-static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
- const unsigned char *mac_addr);
-static int lec_arp_remove(struct lec_priv *priv,
- struct lec_arp_table *to_remove);
-/* LANE2 functions */
-static void lane2_associate_ind(struct net_device *dev, const u8 *mac_address,
- const u8 *tlvs, u32 sizeoftlvs);
-static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
- u8 **tlvs, u32 *sizeoftlvs);
-static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
- const u8 *tlvs, u32 sizeoftlvs);
-
-static int lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr,
- unsigned long permanent);
-static void lec_arp_check_empties(struct lec_priv *priv,
- struct atm_vcc *vcc, struct sk_buff *skb);
-static void lec_arp_destroy(struct lec_priv *priv);
-static void lec_arp_init(struct lec_priv *priv);
-static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
- const unsigned char *mac_to_find,
- int is_rdesc,
- struct lec_arp_table **ret_entry);
-static void lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr,
- const unsigned char *atm_addr,
- unsigned long remoteflag,
- unsigned int targetless_le_arp);
-static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id);
-static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc);
-static void lec_set_flush_tran_id(struct lec_priv *priv,
- const unsigned char *atm_addr,
- unsigned long tran_id);
-static void lec_vcc_added(struct lec_priv *priv,
- const struct atmlec_ioc *ioc_data,
- struct atm_vcc *vcc,
- void (*old_push)(struct atm_vcc *vcc,
- struct sk_buff *skb));
-static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
-
-/* must be done under lec_arp_lock */
-static inline void lec_arp_hold(struct lec_arp_table *entry)
-{
- refcount_inc(&entry->usage);
-}
-
-static inline void lec_arp_put(struct lec_arp_table *entry)
-{
- if (refcount_dec_and_test(&entry->usage))
- kfree(entry);
-}
-
-static struct lane2_ops lane2_ops = {
- .resolve = lane2_resolve, /* spec 3.1.3 */
- .associate_req = lane2_associate_req, /* spec 3.1.4 */
- .associate_indicator = NULL /* spec 3.1.5 */
-};
-
-static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-/* Device structures */
-static struct net_device *dev_lec[MAX_LEC_ITF];
-static DEFINE_MUTEX(lec_mutex);
-
-#if IS_ENABLED(CONFIG_BRIDGE)
-static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
-{
- char *buff;
- struct lec_priv *priv;
-
- /*
- * Check if this is a BPDU. If so, ask zeppelin to send
- * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
- * as the Config BPDU has
- */
- buff = skb->data + skb->dev->hard_header_len;
- if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
- struct sock *sk;
- struct sk_buff *skb2;
- struct atmlec_msg *mesg;
-
- skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
- if (skb2 == NULL)
- return;
- skb2->len = sizeof(struct atmlec_msg);
- mesg = (struct atmlec_msg *)skb2->data;
- mesg->type = l_topology_change;
- buff += 4;
- mesg->content.normal.flag = *buff & 0x01;
- /* 0x01 is topology change */
-
- priv = netdev_priv(dev);
- struct atm_vcc *vcc;
-
- rcu_read_lock();
- vcc = rcu_dereference(priv->lecd);
- if (vcc) {
- atm_force_charge(vcc, skb2->truesize);
- sk = sk_atm(vcc);
- skb_queue_tail(&sk->sk_receive_queue, skb2);
- sk->sk_data_ready(sk);
- } else {
- dev_kfree_skb(skb2);
- }
- rcu_read_unlock();
- }
-}
-#endif /* IS_ENABLED(CONFIG_BRIDGE) */
-
-/*
- * Open/initialize the netdevice. 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 lec_open(struct net_device *dev)
-{
- netif_start_queue(dev);
-
- return 0;
-}
-
-static void
-lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct net_device *dev = skb->dev;
- unsigned int len = skb->len;
-
- ATM_SKB(skb)->vcc = vcc;
- atm_account_tx(vcc, skb);
-
- if (vcc->send(vcc, skb) < 0) {
- dev->stats.tx_dropped++;
- return;
- }
-
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += len;
-}
-
-static void lec_tx_timeout(struct net_device *dev, unsigned int txqueue)
-{
- pr_info("%s\n", dev->name);
- netif_trans_update(dev);
- netif_wake_queue(dev);
-}
-
-static netdev_tx_t lec_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct sk_buff *skb2;
- struct lec_priv *priv = netdev_priv(dev);
- struct lecdatahdr_8023 *lec_h;
- struct atm_vcc *vcc;
- struct lec_arp_table *entry;
- unsigned char *dst;
- int min_frame_size;
- int is_rdesc;
-
- pr_debug("called\n");
- if (!rcu_access_pointer(priv->lecd)) {
- pr_info("%s:No lecd attached\n", dev->name);
- dev->stats.tx_errors++;
- netif_stop_queue(dev);
- kfree_skb(skb);
- return NETDEV_TX_OK;
- }
-
- pr_debug("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
- (long)skb->head, (long)skb->data, (long)skb_tail_pointer(skb),
- (long)skb_end_pointer(skb));
-#if IS_ENABLED(CONFIG_BRIDGE)
- if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
- lec_handle_bridge(skb, dev);
-#endif
-
- /* Make sure we have room for lec_id */
- if (skb_headroom(skb) < 2) {
- pr_debug("reallocating skb\n");
- skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
- if (unlikely(!skb2)) {
- kfree_skb(skb);
- return NETDEV_TX_OK;
- }
- consume_skb(skb);
- skb = skb2;
- }
- skb_push(skb, 2);
-
- /* Put le header to place */
- lec_h = (struct lecdatahdr_8023 *)skb->data;
- lec_h->le_header = htons(priv->lecid);
-
-#if DUMP_PACKETS >= 2
-#define MAX_DUMP_SKB 99
-#elif DUMP_PACKETS >= 1
-#define MAX_DUMP_SKB 30
-#endif
-#if DUMP_PACKETS >= 1
- printk(KERN_DEBUG "%s: send datalen:%ld lecid:%4.4x\n",
- dev->name, skb->len, priv->lecid);
- print_hex_dump(KERN_DEBUG, "", DUMP_OFFSET, 16, 1,
- skb->data, min(skb->len, MAX_DUMP_SKB), true);
-#endif /* DUMP_PACKETS >= 1 */
-
- /* Minimum ethernet-frame size */
- min_frame_size = LEC_MINIMUM_8023_SIZE;
- if (skb->len < min_frame_size) {
- if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
- skb2 = skb_copy_expand(skb, 0,
- min_frame_size - skb->truesize,
- GFP_ATOMIC);
- dev_kfree_skb(skb);
- if (skb2 == NULL) {
- dev->stats.tx_dropped++;
- return NETDEV_TX_OK;
- }
- skb = skb2;
- }
- skb_put(skb, min_frame_size - skb->len);
- }
-
- /* Send to right vcc */
- is_rdesc = 0;
- dst = lec_h->h_dest;
- entry = NULL;
- vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
- pr_debug("%s:vcc:%p vcc_flags:%lx, entry:%p\n",
- dev->name, vcc, vcc ? vcc->flags : 0, entry);
- if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) {
- if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
- pr_debug("%s:queuing packet, MAC address %pM\n",
- dev->name, lec_h->h_dest);
- skb_queue_tail(&entry->tx_wait, skb);
- } else {
- pr_debug("%s:tx queue full or no arp entry, dropping, MAC address: %pM\n",
- dev->name, lec_h->h_dest);
- dev->stats.tx_dropped++;
- dev_kfree_skb(skb);
- }
- goto out;
- }
-#if DUMP_PACKETS > 0
- printk(KERN_DEBUG "%s:sending to vpi:%d vci:%d\n",
- dev->name, vcc->vpi, vcc->vci);
-#endif /* DUMP_PACKETS > 0 */
-
- while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
- pr_debug("emptying tx queue, MAC address %pM\n", lec_h->h_dest);
- lec_send(vcc, skb2);
- }
-
- lec_send(vcc, skb);
-
- if (!atm_may_send(vcc, 0)) {
- struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
-
- vpriv->xoff = 1;
- netif_stop_queue(dev);
-
- /*
- * vcc->pop() might have occurred in between, making
- * the vcc usuable again. Since xmit is serialized,
- * this is the only situation we have to re-test.
- */
-
- if (atm_may_send(vcc, 0))
- netif_wake_queue(dev);
- }
-
-out:
- if (entry)
- lec_arp_put(entry);
- netif_trans_update(dev);
- return NETDEV_TX_OK;
-}
-
-/* The inverse routine to net_open(). */
-static int lec_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
- return 0;
-}
-
-static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- static const u8 zero_addr[ETH_ALEN] = {};
- unsigned long flags;
- struct net_device *dev = (struct net_device *)vcc->proto_data;
- struct lec_priv *priv = netdev_priv(dev);
- struct atmlec_msg *mesg;
- struct lec_arp_table *entry;
- char *tmp; /* FIXME */
-
- WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
- mesg = (struct atmlec_msg *)skb->data;
- tmp = skb->data;
- tmp += sizeof(struct atmlec_msg);
- pr_debug("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
- switch (mesg->type) {
- case l_set_mac_addr:
- eth_hw_addr_set(dev, mesg->content.normal.mac_addr);
- break;
- case l_del_mac_addr:
- eth_hw_addr_set(dev, zero_addr);
- break;
- case l_addr_delete:
- lec_addr_delete(priv, mesg->content.normal.atm_addr,
- mesg->content.normal.flag);
- break;
- case l_topology_change:
- priv->topology_change = mesg->content.normal.flag;
- break;
- case l_flush_complete:
- lec_flush_complete(priv, mesg->content.normal.flag);
- break;
- case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
- lec_arp_remove(priv, entry);
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-
- if (mesg->content.normal.no_source_le_narp)
- break;
- fallthrough;
- case l_arp_update:
- lec_arp_update(priv, mesg->content.normal.mac_addr,
- mesg->content.normal.atm_addr,
- mesg->content.normal.flag,
- mesg->content.normal.targetless_le_arp);
- pr_debug("in l_arp_update\n");
- if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */
- pr_debug("LANE2 3.1.5, got tlvs, size %d\n",
- mesg->sizeoftlvs);
- lane2_associate_ind(dev, mesg->content.normal.mac_addr,
- tmp, mesg->sizeoftlvs);
- }
- break;
- case l_config:
- priv->maximum_unknown_frame_count =
- mesg->content.config.maximum_unknown_frame_count;
- priv->max_unknown_frame_time =
- (mesg->content.config.max_unknown_frame_time * HZ);
- priv->max_retry_count = mesg->content.config.max_retry_count;
- priv->aging_time = (mesg->content.config.aging_time * HZ);
- priv->forward_delay_time =
- (mesg->content.config.forward_delay_time * HZ);
- priv->arp_response_time =
- (mesg->content.config.arp_response_time * HZ);
- priv->flush_timeout = (mesg->content.config.flush_timeout * HZ);
- priv->path_switching_delay =
- (mesg->content.config.path_switching_delay * HZ);
- priv->lane_version = mesg->content.config.lane_version;
- /* LANE2 */
- priv->lane2_ops = NULL;
- if (priv->lane_version > 1)
- priv->lane2_ops = &lane2_ops;
- rtnl_lock();
- if (dev_set_mtu(dev, mesg->content.config.mtu))
- pr_info("%s: change_mtu to %d failed\n",
- dev->name, mesg->content.config.mtu);
- rtnl_unlock();
- priv->is_proxy = mesg->content.config.is_proxy;
- break;
- case l_flush_tran_id:
- lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
- mesg->content.normal.flag);
- break;
- case l_set_lecid:
- priv->lecid =
- (unsigned short)(0xffff & mesg->content.normal.flag);
- break;
- case l_should_bridge:
-#if IS_ENABLED(CONFIG_BRIDGE)
- {
- pr_debug("%s: bridge zeppelin asks about %pM\n",
- dev->name, mesg->content.proxy.mac_addr);
-
- if (br_fdb_test_addr_hook == NULL)
- break;
-
- if (br_fdb_test_addr_hook(dev, mesg->content.proxy.mac_addr)) {
- /* hit from bridge table, send LE_ARP_RESPONSE */
- struct sk_buff *skb2;
- struct sock *sk;
-
- pr_debug("%s: entry found, responding to zeppelin\n",
- dev->name);
- skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
- if (skb2 == NULL)
- break;
- skb2->len = sizeof(struct atmlec_msg);
- skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg));
- struct atm_vcc *vcc;
-
- rcu_read_lock();
- vcc = rcu_dereference(priv->lecd);
- if (vcc) {
- atm_force_charge(vcc, skb2->truesize);
- sk = sk_atm(vcc);
- skb_queue_tail(&sk->sk_receive_queue, skb2);
- sk->sk_data_ready(sk);
- } else {
- dev_kfree_skb(skb2);
- }
- rcu_read_unlock();
- }
- }
-#endif /* IS_ENABLED(CONFIG_BRIDGE) */
- break;
- default:
- pr_info("%s: Unknown message type %d\n", dev->name, mesg->type);
- dev_kfree_skb(skb);
- return -EINVAL;
- }
- dev_kfree_skb(skb);
- return 0;
-}
-
-static void lec_atm_close(struct atm_vcc *vcc)
-{
- struct net_device *dev = (struct net_device *)vcc->proto_data;
- struct lec_priv *priv = netdev_priv(dev);
-
- rcu_assign_pointer(priv->lecd, NULL);
- synchronize_rcu();
- /* Do something needful? */
-
- netif_stop_queue(dev);
- lec_arp_destroy(priv);
-
- pr_info("%s: Shut down!\n", dev->name);
- module_put(THIS_MODULE);
-}
-
-static const struct atmdev_ops lecdev_ops = {
- .close = lec_atm_close,
- .send = lec_atm_send
-};
-
-static struct atm_dev lecatm_dev = {
- .ops = &lecdev_ops,
- .type = "lec",
- .number = 999, /* dummy device number */
- .lock = __SPIN_LOCK_UNLOCKED(lecatm_dev.lock)
-};
-
-/*
- * LANE2: new argument struct sk_buff *data contains
- * the LE_ARP based TLVs introduced in the LANE2 spec
- */
-static int
-send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
- const unsigned char *mac_addr, const unsigned char *atm_addr,
- struct sk_buff *data)
-{
- struct atm_vcc *vcc;
- struct sock *sk;
- struct sk_buff *skb;
- struct atmlec_msg *mesg;
-
- if (!priv || !rcu_access_pointer(priv->lecd))
- return -1;
-
- skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
- if (!skb)
- return -1;
- skb->len = sizeof(struct atmlec_msg);
- mesg = (struct atmlec_msg *)skb->data;
- memset(mesg, 0, sizeof(struct atmlec_msg));
- mesg->type = type;
- if (data != NULL)
- mesg->sizeoftlvs = data->len;
- if (mac_addr)
- ether_addr_copy(mesg->content.normal.mac_addr, mac_addr);
- else
- mesg->content.normal.targetless_le_arp = 1;
- if (atm_addr)
- memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
-
- rcu_read_lock();
- vcc = rcu_dereference(priv->lecd);
- if (!vcc) {
- rcu_read_unlock();
- kfree_skb(skb);
- return -1;
- }
-
- atm_force_charge(vcc, skb->truesize);
- sk = sk_atm(vcc);
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk);
-
- if (data != NULL) {
- pr_debug("about to send %d bytes of data\n", data->len);
- atm_force_charge(vcc, data->truesize);
- skb_queue_tail(&sk->sk_receive_queue, data);
- sk->sk_data_ready(sk);
- }
-
- rcu_read_unlock();
- return 0;
-}
-
-static void lec_set_multicast_list(struct net_device *dev)
-{
- /*
- * by default, all multicast frames arrive over the bus.
- * eventually support selective multicast service
- */
-}
-
-static const struct net_device_ops lec_netdev_ops = {
- .ndo_open = lec_open,
- .ndo_stop = lec_close,
- .ndo_start_xmit = lec_start_xmit,
- .ndo_tx_timeout = lec_tx_timeout,
- .ndo_set_rx_mode = lec_set_multicast_list,
-};
-
-static const unsigned char lec_ctrl_magic[] = {
- 0xff,
- 0x00,
- 0x01,
- 0x01
-};
-
-#define LEC_DATA_DIRECT_8023 2
-#define LEC_DATA_DIRECT_8025 3
-
-static int lec_is_data_direct(struct atm_vcc *vcc)
-{
- return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
- (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
-}
-
-static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- unsigned long flags;
- struct net_device *dev = (struct net_device *)vcc->proto_data;
- struct lec_priv *priv = netdev_priv(dev);
-
-#if DUMP_PACKETS > 0
- printk(KERN_DEBUG "%s: vcc vpi:%d vci:%d\n",
- dev->name, vcc->vpi, vcc->vci);
-#endif
- if (!skb) {
- pr_debug("%s: null skb\n", dev->name);
- lec_vcc_close(priv, vcc);
- return;
- }
-#if DUMP_PACKETS >= 2
-#define MAX_SKB_DUMP 99
-#elif DUMP_PACKETS >= 1
-#define MAX_SKB_DUMP 30
-#endif
-#if DUMP_PACKETS > 0
- printk(KERN_DEBUG "%s: rcv datalen:%ld lecid:%4.4x\n",
- dev->name, skb->len, priv->lecid);
- print_hex_dump(KERN_DEBUG, "", DUMP_OFFSET, 16, 1,
- skb->data, min(MAX_SKB_DUMP, skb->len), true);
-#endif /* DUMP_PACKETS > 0 */
- if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) {
- /* Control frame, to daemon */
- struct sock *sk = sk_atm(vcc);
-
- pr_debug("%s: To daemon\n", dev->name);
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk);
- } else { /* Data frame, queue to protocol handlers */
- struct lec_arp_table *entry;
- unsigned char *src, *dst;
-
- atm_return(vcc, skb->truesize);
- if (*(__be16 *) skb->data == htons(priv->lecid) ||
- !rcu_access_pointer(priv->lecd) || !(dev->flags & IFF_UP)) {
- /*
- * Probably looping back, or if lecd is missing,
- * lecd has gone down
- */
- pr_debug("Ignoring frame...\n");
- dev_kfree_skb(skb);
- return;
- }
- dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
-
- /*
- * If this is a Data Direct VCC, and the VCC does not match
- * the LE_ARP cache entry, delete the LE_ARP cache entry.
- */
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- if (lec_is_data_direct(vcc)) {
- src = ((struct lecdatahdr_8023 *)skb->data)->h_source;
- entry = lec_arp_find(priv, src);
- if (entry && entry->vcc != vcc) {
- lec_arp_remove(priv, entry);
- lec_arp_put(entry);
- }
- }
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-
- if (!(dst[0] & 0x01) && /* Never filter Multi/Broadcast */
- !priv->is_proxy && /* Proxy wants all the packets */
- memcmp(dst, dev->dev_addr, dev->addr_len)) {
- dev_kfree_skb(skb);
- return;
- }
- if (!hlist_empty(&priv->lec_arp_empty_ones))
- lec_arp_check_empties(priv, vcc, skb);
- skb_pull(skb, 2); /* skip lec_id */
- skb->protocol = eth_type_trans(skb, dev);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
- memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
- netif_rx(skb);
- }
-}
-
-static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
- struct net_device *dev = skb->dev;
-
- if (vpriv == NULL) {
- pr_info("vpriv = NULL!?!?!?\n");
- return;
- }
-
- vpriv->old_pop(vcc, skb);
-
- if (vpriv->xoff && atm_may_send(vcc, 0)) {
- vpriv->xoff = 0;
- if (netif_running(dev) && netif_queue_stopped(dev))
- netif_wake_queue(dev);
- }
-}
-
-static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
-{
- struct lec_vcc_priv *vpriv;
- int bytes_left;
- struct atmlec_ioc ioc_data;
-
- lockdep_assert_held(&lec_mutex);
- /* Lecd must be up in this case */
- bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
- if (bytes_left != 0)
- pr_info("copy from user failed for %d bytes\n", bytes_left);
- if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
- return -EINVAL;
- ioc_data.dev_num = array_index_nospec(ioc_data.dev_num, MAX_LEC_ITF);
- if (!dev_lec[ioc_data.dev_num])
- return -EINVAL;
- vpriv = kmalloc_obj(struct lec_vcc_priv);
- if (!vpriv)
- return -ENOMEM;
- vpriv->xoff = 0;
- vpriv->old_pop = vcc->pop;
- vcc->user_back = vpriv;
- vcc->pop = lec_pop;
- lec_vcc_added(netdev_priv(dev_lec[ioc_data.dev_num]),
- &ioc_data, vcc, vcc->push);
- vcc->proto_data = dev_lec[ioc_data.dev_num];
- vcc->push = lec_push;
- return 0;
-}
-
-static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
-{
- lockdep_assert_held(&lec_mutex);
- if (arg < 0 || arg >= MAX_LEC_ITF)
- return -EINVAL;
- arg = array_index_nospec(arg, MAX_LEC_ITF);
- if (!dev_lec[arg])
- return -EINVAL;
- vcc->proto_data = dev_lec[arg];
- return lec_mcast_make(netdev_priv(dev_lec[arg]), vcc);
-}
-
-/* Initialize device. */
-static int lecd_attach(struct atm_vcc *vcc, int arg)
-{
- int i;
- struct lec_priv *priv;
-
- lockdep_assert_held(&lec_mutex);
- if (arg < 0)
- arg = 0;
- if (arg >= MAX_LEC_ITF)
- return -EINVAL;
- i = array_index_nospec(arg, MAX_LEC_ITF);
- if (!dev_lec[i]) {
- int size;
-
- size = sizeof(struct lec_priv);
- dev_lec[i] = alloc_etherdev(size);
- if (!dev_lec[i])
- return -ENOMEM;
- dev_lec[i]->netdev_ops = &lec_netdev_ops;
- dev_lec[i]->max_mtu = 18190;
- snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
- if (register_netdev(dev_lec[i])) {
- free_netdev(dev_lec[i]);
- dev_lec[i] = NULL;
- return -EINVAL;
- }
-
- priv = netdev_priv(dev_lec[i]);
- } else {
- priv = netdev_priv(dev_lec[i]);
- if (rcu_access_pointer(priv->lecd))
- return -EADDRINUSE;
- }
- lec_arp_init(priv);
- priv->itfnum = i; /* LANE2 addition */
- rcu_assign_pointer(priv->lecd, vcc);
- vcc->dev = &lecatm_dev;
- vcc_insert_socket(sk_atm(vcc));
-
- vcc->proto_data = dev_lec[i];
- set_bit(ATM_VF_META, &vcc->flags);
- set_bit(ATM_VF_READY, &vcc->flags);
-
- /* Set default values to these variables */
- priv->maximum_unknown_frame_count = 1;
- priv->max_unknown_frame_time = (1 * HZ);
- priv->vcc_timeout_period = (1200 * HZ);
- priv->max_retry_count = 1;
- priv->aging_time = (300 * HZ);
- priv->forward_delay_time = (15 * HZ);
- priv->topology_change = 0;
- priv->arp_response_time = (1 * HZ);
- priv->flush_timeout = (4 * HZ);
- priv->path_switching_delay = (6 * HZ);
-
- if (dev_lec[i]->flags & IFF_UP)
- netif_start_queue(dev_lec[i]);
- __module_get(THIS_MODULE);
- return i;
-}
-
-#ifdef CONFIG_PROC_FS
-static const char *lec_arp_get_status_string(unsigned char status)
-{
- static const char *const lec_arp_status_string[] = {
- "ESI_UNKNOWN ",
- "ESI_ARP_PENDING ",
- "ESI_VC_PENDING ",
- "<Undefined> ",
- "ESI_FLUSH_PENDING ",
- "ESI_FORWARD_DIRECT"
- };
-
- if (status > ESI_FORWARD_DIRECT)
- status = 3; /* ESI_UNDEFINED */
- return lec_arp_status_string[status];
-}
-
-static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
-{
- seq_printf(seq, "%pM ", entry->mac_addr);
- seq_printf(seq, "%*phN ", ATM_ESA_LEN, entry->atm_addr);
- seq_printf(seq, "%s %4.4x", lec_arp_get_status_string(entry->status),
- entry->flags & 0xffff);
- if (entry->vcc)
- seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci);
- else
- seq_printf(seq, " ");
- if (entry->recv_vcc) {
- seq_printf(seq, " %3d %3d", entry->recv_vcc->vpi,
- entry->recv_vcc->vci);
- }
- seq_putc(seq, '\n');
-}
-
-struct lec_state {
- unsigned long flags;
- struct lec_priv *locked;
- struct hlist_node *node;
- struct net_device *dev;
- int itf;
- int arp_table;
- int misc_table;
-};
-
-static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
- loff_t *l)
-{
- struct hlist_node *e = state->node;
-
- if (!e)
- e = tbl->first;
- if (e == SEQ_START_TOKEN) {
- e = tbl->first;
- --*l;
- }
-
- for (; e; e = e->next) {
- if (--*l < 0)
- break;
- }
- state->node = e;
-
- return (*l < 0) ? state : NULL;
-}
-
-static void *lec_arp_walk(struct lec_state *state, loff_t *l,
- struct lec_priv *priv)
-{
- void *v = NULL;
- int p;
-
- for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
- v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
- if (v)
- break;
- }
- state->arp_table = p;
- return v;
-}
-
-static void *lec_misc_walk(struct lec_state *state, loff_t *l,
- struct lec_priv *priv)
-{
- struct hlist_head *lec_misc_tables[] = {
- &priv->lec_arp_empty_ones,
- &priv->lec_no_forward,
- &priv->mcast_fwds
- };
- void *v = NULL;
- int q;
-
- for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) {
- v = lec_tbl_walk(state, lec_misc_tables[q], l);
- if (v)
- break;
- }
- state->misc_table = q;
- return v;
-}
-
-static void *lec_priv_walk(struct lec_state *state, loff_t *l,
- struct lec_priv *priv)
-{
- if (!state->locked) {
- state->locked = priv;
- spin_lock_irqsave(&priv->lec_arp_lock, state->flags);
- }
- if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {
- spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags);
- state->locked = NULL;
- /* Partial state reset for the next time we get called */
- state->arp_table = state->misc_table = 0;
- }
- return state->locked;
-}
-
-static void *lec_itf_walk(struct lec_state *state, loff_t *l)
-{
- struct net_device *dev;
- void *v;
-
- dev = state->dev ? state->dev : dev_lec[state->itf];
- v = (dev && netdev_priv(dev)) ?
- lec_priv_walk(state, l, netdev_priv(dev)) : NULL;
- if (!v && dev) {
- /* Partial state reset for the next time we get called */
- dev = NULL;
- }
- state->dev = dev;
- return v;
-}
-
-static void *lec_get_idx(struct lec_state *state, loff_t l)
-{
- void *v = NULL;
-
- for (; state->itf < MAX_LEC_ITF; state->itf++) {
- v = lec_itf_walk(state, &l);
- if (v)
- break;
- }
- return v;
-}
-
-static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
-{
- struct lec_state *state = seq->private;
-
- mutex_lock(&lec_mutex);
- state->itf = 0;
- state->dev = NULL;
- state->locked = NULL;
- state->arp_table = 0;
- state->misc_table = 0;
- state->node = SEQ_START_TOKEN;
-
- return *pos ? lec_get_idx(state, *pos) : SEQ_START_TOKEN;
-}
-
-static void lec_seq_stop(struct seq_file *seq, void *v)
-{
- struct lec_state *state = seq->private;
-
- if (state->dev) {
- spin_unlock_irqrestore(&state->locked->lec_arp_lock,
- state->flags);
- state->dev = NULL;
- }
- mutex_unlock(&lec_mutex);
-}
-
-static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
- struct lec_state *state = seq->private;
-
- ++*pos;
- return lec_get_idx(state, 1);
-}
-
-static int lec_seq_show(struct seq_file *seq, void *v)
-{
- static const char lec_banner[] =
- "Itf MAC ATM destination"
- " Status Flags "
- "VPI/VCI Recv VPI/VCI\n";
-
- if (v == SEQ_START_TOKEN)
- seq_puts(seq, lec_banner);
- else {
- struct lec_state *state = seq->private;
- struct net_device *dev = state->dev;
- struct lec_arp_table *entry = hlist_entry(state->node,
- struct lec_arp_table,
- next);
-
- seq_printf(seq, "%s ", dev->name);
- lec_info(seq, entry);
- }
- return 0;
-}
-
-static const struct seq_operations lec_seq_ops = {
- .start = lec_seq_start,
- .next = lec_seq_next,
- .stop = lec_seq_stop,
- .show = lec_seq_show,
-};
-#endif
-
-static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- struct atm_vcc *vcc = ATM_SD(sock);
- int err = 0;
-
- switch (cmd) {
- case ATMLEC_CTRL:
- case ATMLEC_MCAST:
- case ATMLEC_DATA:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- break;
- default:
- return -ENOIOCTLCMD;
- }
-
- mutex_lock(&lec_mutex);
- switch (cmd) {
- case ATMLEC_CTRL:
- err = lecd_attach(vcc, (int)arg);
- if (err >= 0)
- sock->state = SS_CONNECTED;
- break;
- case ATMLEC_MCAST:
- err = lec_mcast_attach(vcc, (int)arg);
- break;
- case ATMLEC_DATA:
- err = lec_vcc_attach(vcc, (void __user *)arg);
- break;
- }
-
- mutex_unlock(&lec_mutex);
- return err;
-}
-
-static struct atm_ioctl lane_ioctl_ops = {
- .owner = THIS_MODULE,
- .ioctl = lane_ioctl,
-};
-
-static int __init lane_module_init(void)
-{
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *p;
-
- p = proc_create_seq_private("lec", 0444, atm_proc_root, &lec_seq_ops,
- sizeof(struct lec_state), NULL);
- if (!p) {
- pr_err("Unable to initialize /proc/net/atm/lec\n");
- return -ENOMEM;
- }
-#endif
-
- register_atm_ioctl(&lane_ioctl_ops);
- pr_info("lec.c: initialized\n");
- return 0;
-}
-
-static void __exit lane_module_cleanup(void)
-{
- int i;
-
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("lec", atm_proc_root);
-#endif
-
- deregister_atm_ioctl(&lane_ioctl_ops);
-
- for (i = 0; i < MAX_LEC_ITF; i++) {
- if (dev_lec[i] != NULL) {
- unregister_netdev(dev_lec[i]);
- free_netdev(dev_lec[i]);
- dev_lec[i] = NULL;
- }
- }
-}
-
-module_init(lane_module_init);
-module_exit(lane_module_cleanup);
-
-/*
- * LANE2: 3.1.3, LE_RESOLVE.request
- * Non force allocates memory and fills in *tlvs, fills in *sizeoftlvs.
- * If sizeoftlvs == NULL the default TLVs associated with this
- * lec will be used.
- * If dst_mac == NULL, targetless LE_ARP will be sent
- */
-static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
- u8 **tlvs, u32 *sizeoftlvs)
-{
- unsigned long flags;
- struct lec_priv *priv = netdev_priv(dev);
- struct lec_arp_table *table;
- struct sk_buff *skb;
- int retval;
-
- if (force == 0) {
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- table = lec_arp_find(priv, dst_mac);
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
- if (table == NULL)
- return -1;
-
- *tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);
- if (*tlvs == NULL)
- return -1;
-
- *sizeoftlvs = table->sizeoftlvs;
-
- return 0;
- }
-
- if (sizeoftlvs == NULL)
- retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
-
- else {
- skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
- if (skb == NULL)
- return -1;
- skb->len = *sizeoftlvs;
- skb_copy_to_linear_data(skb, *tlvs, *sizeoftlvs);
- retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
- }
- return retval;
-}
-
-/*
- * LANE2: 3.1.4, LE_ASSOCIATE.request
- * Associate the *tlvs with the *lan_dst address.
- * Will overwrite any previous association
- * Returns 1 for success, 0 for failure (out of memory)
- *
- */
-static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
- const u8 *tlvs, u32 sizeoftlvs)
-{
- int retval;
- struct sk_buff *skb;
- struct lec_priv *priv = netdev_priv(dev);
-
- if (!ether_addr_equal(lan_dst, dev->dev_addr))
- return 0; /* not our mac address */
-
- kfree(priv->tlvs); /* NULL if there was no previous association */
-
- priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
- if (priv->tlvs == NULL)
- return 0;
- priv->sizeoftlvs = sizeoftlvs;
-
- skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
- if (skb == NULL)
- return 0;
- skb->len = sizeoftlvs;
- skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);
- retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
- if (retval != 0)
- pr_info("lec.c: lane2_associate_req() failed\n");
- /*
- * If the previous association has changed we must
- * somehow notify other LANE entities about the change
- */
- return 1;
-}
-
-/*
- * LANE2: 3.1.5, LE_ASSOCIATE.indication
- *
- */
-static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
- const u8 *tlvs, u32 sizeoftlvs)
-{
-#if 0
- int i = 0;
-#endif
- struct lec_priv *priv = netdev_priv(dev);
-#if 0 /*
- * Why have the TLVs in LE_ARP entries
- * since we do not use them? When you
- * uncomment this code, make sure the
- * TLVs get freed when entry is killed
- */
- struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
-
- if (entry == NULL)
- return; /* should not happen */
-
- kfree(entry->tlvs);
-
- entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
- if (entry->tlvs == NULL)
- return;
- entry->sizeoftlvs = sizeoftlvs;
-#endif
-#if 0
- pr_info("\n");
- pr_info("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
- while (i < sizeoftlvs)
- pr_cont("%02x ", tlvs[i++]);
-
- pr_cont("\n");
-#endif
-
- /* tell MPOA about the TLVs we saw */
- if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
- priv->lane2_ops->associate_indicator(dev, mac_addr,
- tlvs, sizeoftlvs);
- }
-}
-
-/*
- * Here starts what used to lec_arpc.c
- *
- * lec_arpc.c was added here when making
- * lane client modular. October 1997
- */
-
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/param.h>
-#include <linux/atomic.h>
-#include <linux/inetdevice.h>
-#include <net/route.h>
-
-#if 0
-#define pr_debug(format, args...)
-/*
- #define pr_debug printk
-*/
-#endif
-#define DEBUG_ARP_TABLE 0
-
-#define LEC_ARP_REFRESH_INTERVAL (3*HZ)
-
-static void lec_arp_check_expire(struct work_struct *work);
-static void lec_arp_expire_arp(struct timer_list *t);
-
-/*
- * Arp table funcs
- */
-
-#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE - 1))
-
-/*
- * Initialization of arp-cache
- */
-static void lec_arp_init(struct lec_priv *priv)
-{
- unsigned short i;
-
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
- INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
- INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
- INIT_HLIST_HEAD(&priv->lec_no_forward);
- INIT_HLIST_HEAD(&priv->mcast_fwds);
- spin_lock_init(&priv->lec_arp_lock);
- INIT_DELAYED_WORK(&priv->lec_arp_work, lec_arp_check_expire);
- schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
-}
-
-static void lec_arp_clear_vccs(struct lec_arp_table *entry)
-{
- if (entry->vcc) {
- struct atm_vcc *vcc = entry->vcc;
- struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
- struct net_device *dev = (struct net_device *)vcc->proto_data;
-
- if (vpriv) {
- vcc->pop = vpriv->old_pop;
- if (vpriv->xoff)
- netif_wake_queue(dev);
- kfree(vpriv);
- vcc->user_back = NULL;
- vcc->push = entry->old_push;
- vcc_release_async(vcc, -EPIPE);
- }
- entry->vcc = NULL;
- }
- if (entry->recv_vcc) {
- struct atm_vcc *vcc = entry->recv_vcc;
- struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
-
- if (vpriv) {
- kfree(vpriv);
- vcc->user_back = NULL;
-
- entry->recv_vcc->push = entry->old_recv_push;
- vcc_release_async(entry->recv_vcc, -EPIPE);
- }
- entry->recv_vcc = NULL;
- }
-}
-
-/*
- * Insert entry to lec_arp_table
- * LANE2: Add to the end of the list to satisfy 8.1.13
- */
-static inline void
-lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry)
-{
- struct hlist_head *tmp;
-
- tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])];
- hlist_add_head(&entry->next, tmp);
-
- pr_debug("Added entry:%pM\n", entry->mac_addr);
-}
-
-/*
- * Remove entry from lec_arp_table
- */
-static int
-lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
-{
- struct lec_arp_table *entry;
- int i, remove_vcc = 1;
-
- if (!to_remove)
- return -1;
-
- hlist_del(&to_remove->next);
- timer_delete(&to_remove->timer);
-
- /*
- * If this is the only MAC connected to this VCC,
- * also tear down the VCC
- */
- if (to_remove->status >= ESI_FLUSH_PENDING) {
- /*
- * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
- */
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry(entry,
- &priv->lec_arp_tables[i], next) {
- if (memcmp(to_remove->atm_addr,
- entry->atm_addr, ATM_ESA_LEN) == 0) {
- remove_vcc = 0;
- break;
- }
- }
- }
- if (remove_vcc)
- lec_arp_clear_vccs(to_remove);
- }
- skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
-
- pr_debug("Removed entry:%pM\n", to_remove->mac_addr);
- return 0;
-}
-
-#if DEBUG_ARP_TABLE
-static const char *get_status_string(unsigned char st)
-{
- switch (st) {
- case ESI_UNKNOWN:
- return "ESI_UNKNOWN";
- case ESI_ARP_PENDING:
- return "ESI_ARP_PENDING";
- case ESI_VC_PENDING:
- return "ESI_VC_PENDING";
- case ESI_FLUSH_PENDING:
- return "ESI_FLUSH_PENDING";
- case ESI_FORWARD_DIRECT:
- return "ESI_FORWARD_DIRECT";
- }
- return "<UNKNOWN>";
-}
-
-static void dump_arp_table(struct lec_priv *priv)
-{
- struct lec_arp_table *rulla;
- char buf[256];
- int i, offset;
-
- pr_info("Dump %p:\n", priv);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry(rulla,
- &priv->lec_arp_tables[i], next) {
- offset = 0;
- offset += sprintf(buf, "%d: %p\n", i, rulla);
- offset += sprintf(buf + offset, "Mac: %pM ",
- rulla->mac_addr);
- offset += sprintf(buf + offset, "Atm: %*ph ", ATM_ESA_LEN,
- rulla->atm_addr);
- offset += sprintf(buf + offset,
- "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
- rulla->vcc ? rulla->vcc->vpi : 0,
- rulla->vcc ? rulla->vcc->vci : 0,
- rulla->recv_vcc ? rulla->recv_vcc->
- vpi : 0,
- rulla->recv_vcc ? rulla->recv_vcc->
- vci : 0, rulla->last_used,
- rulla->timestamp, rulla->no_tries);
- offset +=
- sprintf(buf + offset,
- "Flags:%x, Packets_flooded:%x, Status: %s ",
- rulla->flags, rulla->packets_flooded,
- get_status_string(rulla->status));
- pr_info("%s\n", buf);
- }
- }
-
- if (!hlist_empty(&priv->lec_no_forward))
- pr_info("No forward\n");
- hlist_for_each_entry(rulla, &priv->lec_no_forward, next) {
- offset = 0;
- offset += sprintf(buf + offset, "Mac: %pM ", rulla->mac_addr);
- offset += sprintf(buf + offset, "Atm: %*ph ", ATM_ESA_LEN,
- rulla->atm_addr);
- offset += sprintf(buf + offset,
- "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
- rulla->vcc ? rulla->vcc->vpi : 0,
- rulla->vcc ? rulla->vcc->vci : 0,
- rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
- rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
- rulla->last_used,
- rulla->timestamp, rulla->no_tries);
- offset += sprintf(buf + offset,
- "Flags:%x, Packets_flooded:%x, Status: %s ",
- rulla->flags, rulla->packets_flooded,
- get_status_string(rulla->status));
- pr_info("%s\n", buf);
- }
-
- if (!hlist_empty(&priv->lec_arp_empty_ones))
- pr_info("Empty ones\n");
- hlist_for_each_entry(rulla, &priv->lec_arp_empty_ones, next) {
- offset = 0;
- offset += sprintf(buf + offset, "Mac: %pM ", rulla->mac_addr);
- offset += sprintf(buf + offset, "Atm: %*ph ", ATM_ESA_LEN,
- rulla->atm_addr);
- offset += sprintf(buf + offset,
- "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
- rulla->vcc ? rulla->vcc->vpi : 0,
- rulla->vcc ? rulla->vcc->vci : 0,
- rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
- rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
- rulla->last_used,
- rulla->timestamp, rulla->no_tries);
- offset += sprintf(buf + offset,
- "Flags:%x, Packets_flooded:%x, Status: %s ",
- rulla->flags, rulla->packets_flooded,
- get_status_string(rulla->status));
- pr_info("%s", buf);
- }
-
- if (!hlist_empty(&priv->mcast_fwds))
- pr_info("Multicast Forward VCCs\n");
- hlist_for_each_entry(rulla, &priv->mcast_fwds, next) {
- offset = 0;
- offset += sprintf(buf + offset, "Mac: %pM ", rulla->mac_addr);
- offset += sprintf(buf + offset, "Atm: %*ph ", ATM_ESA_LEN,
- rulla->atm_addr);
- offset += sprintf(buf + offset,
- "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
- rulla->vcc ? rulla->vcc->vpi : 0,
- rulla->vcc ? rulla->vcc->vci : 0,
- rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
- rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
- rulla->last_used,
- rulla->timestamp, rulla->no_tries);
- offset += sprintf(buf + offset,
- "Flags:%x, Packets_flooded:%x, Status: %s ",
- rulla->flags, rulla->packets_flooded,
- get_status_string(rulla->status));
- pr_info("%s\n", buf);
- }
-
-}
-#else
-#define dump_arp_table(priv) do { } while (0)
-#endif
-
-/*
- * Destruction of arp-cache
- */
-static void lec_arp_destroy(struct lec_priv *priv)
-{
- unsigned long flags;
- struct hlist_node *next;
- struct lec_arp_table *entry;
- int i;
-
- cancel_delayed_work_sync(&priv->lec_arp_work);
-
- /*
- * Remove all entries
- */
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_tables[i], next) {
- lec_arp_remove(priv, entry);
- lec_arp_put(entry);
- }
- INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
- }
-
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_empty_ones, next) {
- timer_delete_sync(&entry->timer);
- lec_arp_clear_vccs(entry);
- hlist_del(&entry->next);
- lec_arp_put(entry);
- }
- INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
-
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_no_forward, next) {
- timer_delete_sync(&entry->timer);
- lec_arp_clear_vccs(entry);
- hlist_del(&entry->next);
- lec_arp_put(entry);
- }
- INIT_HLIST_HEAD(&priv->lec_no_forward);
-
- hlist_for_each_entry_safe(entry, next, &priv->mcast_fwds, next) {
- /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
- lec_arp_clear_vccs(entry);
- hlist_del(&entry->next);
- lec_arp_put(entry);
- }
- INIT_HLIST_HEAD(&priv->mcast_fwds);
- priv->mcast_vcc = NULL;
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-}
-
-/*
- * Find entry by mac_address
- */
-static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
- const unsigned char *mac_addr)
-{
- struct hlist_head *head;
- struct lec_arp_table *entry;
-
- pr_debug("%pM\n", mac_addr);
-
- head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])];
- hlist_for_each_entry(entry, head, next) {
- if (ether_addr_equal(mac_addr, entry->mac_addr))
- return entry;
- }
- return NULL;
-}
-
-static struct lec_arp_table *make_entry(struct lec_priv *priv,
- const unsigned char *mac_addr)
-{
- struct lec_arp_table *to_return;
-
- to_return = kzalloc_obj(struct lec_arp_table, GFP_ATOMIC);
- if (!to_return)
- return NULL;
- ether_addr_copy(to_return->mac_addr, mac_addr);
- INIT_HLIST_NODE(&to_return->next);
- timer_setup(&to_return->timer, lec_arp_expire_arp, 0);
- to_return->last_used = jiffies;
- to_return->priv = priv;
- skb_queue_head_init(&to_return->tx_wait);
- refcount_set(&to_return->usage, 1);
- return to_return;
-}
-
-/* Arp sent timer expired */
-static void lec_arp_expire_arp(struct timer_list *t)
-{
- struct lec_arp_table *entry;
-
- entry = timer_container_of(entry, t, timer);
-
- pr_debug("\n");
- if (entry->status == ESI_ARP_PENDING) {
- if (entry->no_tries <= entry->priv->max_retry_count) {
- if (entry->is_rdesc)
- send_to_lecd(entry->priv, l_rdesc_arp_xmt,
- entry->mac_addr, NULL, NULL);
- else
- send_to_lecd(entry->priv, l_arp_xmt,
- entry->mac_addr, NULL, NULL);
- entry->no_tries++;
- }
- mod_timer(&entry->timer, jiffies + (1 * HZ));
- }
-}
-
-/* Unknown/unused vcc expire, remove associated entry */
-static void lec_arp_expire_vcc(struct timer_list *t)
-{
- unsigned long flags;
- struct lec_arp_table *to_remove = timer_container_of(to_remove, t,
- timer);
- struct lec_priv *priv = to_remove->priv;
-
- timer_delete(&to_remove->timer);
-
- pr_debug("%p %p: vpi:%d vci:%d\n",
- to_remove, priv,
- to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
- to_remove->vcc ? to_remove->recv_vcc->vci : 0);
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- hlist_del(&to_remove->next);
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-
- lec_arp_clear_vccs(to_remove);
- lec_arp_put(to_remove);
-}
-
-static bool __lec_arp_check_expire(struct lec_arp_table *entry,
- unsigned long now,
- struct lec_priv *priv)
-{
- unsigned long time_to_check;
-
- if ((entry->flags) & LEC_REMOTE_FLAG && priv->topology_change)
- time_to_check = priv->forward_delay_time;
- else
- time_to_check = priv->aging_time;
-
- pr_debug("About to expire: %lx - %lx > %lx\n",
- now, entry->last_used, time_to_check);
- if (time_after(now, entry->last_used + time_to_check) &&
- !(entry->flags & LEC_PERMANENT_FLAG) &&
- !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */
- /* Remove entry */
- pr_debug("Entry timed out\n");
- lec_arp_remove(priv, entry);
- lec_arp_put(entry);
- } else {
- /* Something else */
- if ((entry->status == ESI_VC_PENDING ||
- entry->status == ESI_ARP_PENDING) &&
- time_after_eq(now, entry->timestamp +
- priv->max_unknown_frame_time)) {
- entry->timestamp = jiffies;
- entry->packets_flooded = 0;
- if (entry->status == ESI_VC_PENDING)
- send_to_lecd(priv, l_svc_setup,
- entry->mac_addr,
- entry->atm_addr,
- NULL);
- }
- if (entry->status == ESI_FLUSH_PENDING &&
- time_after_eq(now, entry->timestamp +
- priv->path_switching_delay)) {
- lec_arp_hold(entry);
- return true;
- }
- }
-
- return false;
-}
-/*
- * Expire entries.
- * 1. Re-set timer
- * 2. For each entry, delete entries that have aged past the age limit.
- * 3. For each entry, depending on the status of the entry, perform
- * the following maintenance.
- * a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the
- * tick_count is above the max_unknown_frame_time, clear
- * the tick_count to zero and clear the packets_flooded counter
- * to zero. This supports the packet rate limit per address
- * while flooding unknowns.
- * b. If the status is ESI_FLUSH_PENDING and the tick_count is greater
- * than or equal to the path_switching_delay, change the status
- * to ESI_FORWARD_DIRECT. This causes the flush period to end
- * regardless of the progress of the flush protocol.
- */
-static void lec_arp_check_expire(struct work_struct *work)
-{
- unsigned long flags;
- struct lec_priv *priv =
- container_of(work, struct lec_priv, lec_arp_work.work);
- struct hlist_node *next;
- struct lec_arp_table *entry;
- unsigned long now;
- int i;
-
- pr_debug("%p\n", priv);
- now = jiffies;
-restart:
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_tables[i], next) {
- if (__lec_arp_check_expire(entry, now, priv)) {
- struct sk_buff *skb;
- struct atm_vcc *vcc = entry->vcc;
-
- spin_unlock_irqrestore(&priv->lec_arp_lock,
- flags);
- while ((skb = skb_dequeue(&entry->tx_wait)))
- lec_send(vcc, skb);
- entry->last_used = jiffies;
- entry->status = ESI_FORWARD_DIRECT;
- lec_arp_put(entry);
-
- goto restart;
- }
- }
- }
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-
- schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
-}
-
-/*
- * Try to find vcc where mac_address is attached.
- *
- */
-static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
- const unsigned char *mac_to_find,
- int is_rdesc,
- struct lec_arp_table **ret_entry)
-{
- unsigned long flags;
- struct lec_arp_table *entry;
- struct atm_vcc *found;
-
- if (mac_to_find[0] & 0x01) {
- switch (priv->lane_version) {
- case 1:
- return priv->mcast_vcc;
- case 2: /* LANE2 wants arp for multicast addresses */
- if (ether_addr_equal(mac_to_find, bus_mac))
- return priv->mcast_vcc;
- break;
- default:
- break;
- }
- }
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- entry = lec_arp_find(priv, mac_to_find);
-
- if (entry) {
- if (entry->status == ESI_FORWARD_DIRECT) {
- /* Connection Ok */
- entry->last_used = jiffies;
- lec_arp_hold(entry);
- *ret_entry = entry;
- found = entry->vcc;
- goto out;
- }
- /*
- * If the LE_ARP cache entry is still pending, reset count to 0
- * so another LE_ARP request can be made for this frame.
- */
- if (entry->status == ESI_ARP_PENDING)
- entry->no_tries = 0;
- /*
- * Data direct VC not yet set up, check to see if the unknown
- * frame count is greater than the limit. If the limit has
- * not been reached, allow the caller to send packet to
- * BUS.
- */
- if (entry->status != ESI_FLUSH_PENDING &&
- entry->packets_flooded <
- priv->maximum_unknown_frame_count) {
- entry->packets_flooded++;
- pr_debug("Flooding..\n");
- found = priv->mcast_vcc;
- goto out;
- }
- /*
- * We got here because entry->status == ESI_FLUSH_PENDING
- * or BUS flood limit was reached for an entry which is
- * in ESI_ARP_PENDING or ESI_VC_PENDING state.
- */
- lec_arp_hold(entry);
- *ret_entry = entry;
- pr_debug("entry->status %d entry->vcc %p\n", entry->status,
- entry->vcc);
- found = NULL;
- } else {
- /* No matching entry was found */
- entry = make_entry(priv, mac_to_find);
- pr_debug("Making entry\n");
- if (!entry) {
- found = priv->mcast_vcc;
- goto out;
- }
- lec_arp_add(priv, entry);
- /* We want arp-request(s) to be sent */
- entry->packets_flooded = 1;
- entry->status = ESI_ARP_PENDING;
- entry->no_tries = 1;
- entry->last_used = entry->timestamp = jiffies;
- entry->is_rdesc = is_rdesc;
- if (entry->is_rdesc)
- send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL,
- NULL);
- else
- send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
- entry->timer.expires = jiffies + (1 * HZ);
- entry->timer.function = lec_arp_expire_arp;
- add_timer(&entry->timer);
- found = priv->mcast_vcc;
- }
-
-out:
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
- return found;
-}
-
-static int
-lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr,
- unsigned long permanent)
-{
- unsigned long flags;
- struct hlist_node *next;
- struct lec_arp_table *entry;
- int i;
-
- pr_debug("\n");
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_tables[i], next) {
- if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) &&
- (permanent ||
- !(entry->flags & LEC_PERMANENT_FLAG))) {
- lec_arp_remove(priv, entry);
- lec_arp_put(entry);
- }
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
- return 0;
- }
- }
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
- return -1;
-}
-
-/*
- * Notifies: Response to arp_request (atm_addr != NULL)
- */
-static void
-lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr,
- const unsigned char *atm_addr, unsigned long remoteflag,
- unsigned int targetless_le_arp)
-{
- unsigned long flags;
- struct hlist_node *next;
- struct lec_arp_table *entry, *tmp;
- int i;
-
- pr_debug("%smac:%pM\n",
- (targetless_le_arp) ? "targetless " : "", mac_addr);
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- entry = lec_arp_find(priv, mac_addr);
- if (entry == NULL && targetless_le_arp)
- goto out; /*
- * LANE2: ignore targetless LE_ARPs for which
- * we have no entry in the cache. 7.1.30
- */
- if (!hlist_empty(&priv->lec_arp_empty_ones)) {
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_empty_ones, next) {
- if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
- hlist_del(&entry->next);
- timer_delete(&entry->timer);
- tmp = lec_arp_find(priv, mac_addr);
- if (tmp) {
- timer_delete(&tmp->timer);
- tmp->status = ESI_FORWARD_DIRECT;
- memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
- tmp->vcc = entry->vcc;
- tmp->old_push = entry->old_push;
- tmp->last_used = jiffies;
- timer_delete(&entry->timer);
- lec_arp_put(entry);
- entry = tmp;
- } else {
- entry->status = ESI_FORWARD_DIRECT;
- ether_addr_copy(entry->mac_addr,
- mac_addr);
- entry->last_used = jiffies;
- lec_arp_add(priv, entry);
- }
- if (remoteflag)
- entry->flags |= LEC_REMOTE_FLAG;
- else
- entry->flags &= ~LEC_REMOTE_FLAG;
- pr_debug("After update\n");
- dump_arp_table(priv);
- goto out;
- }
- }
- }
-
- entry = lec_arp_find(priv, mac_addr);
- if (!entry) {
- entry = make_entry(priv, mac_addr);
- if (!entry)
- goto out;
- entry->status = ESI_UNKNOWN;
- lec_arp_add(priv, entry);
- /* Temporary, changes before end of function */
- }
- memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
- timer_delete(&entry->timer);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry(tmp,
- &priv->lec_arp_tables[i], next) {
- if (entry != tmp &&
- !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {
- /* Vcc to this host exists */
- if (tmp->status > ESI_VC_PENDING) {
- /*
- * ESI_FLUSH_PENDING,
- * ESI_FORWARD_DIRECT
- */
- entry->vcc = tmp->vcc;
- entry->old_push = tmp->old_push;
- }
- entry->status = tmp->status;
- break;
- }
- }
- }
- if (remoteflag)
- entry->flags |= LEC_REMOTE_FLAG;
- else
- entry->flags &= ~LEC_REMOTE_FLAG;
- if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {
- entry->status = ESI_VC_PENDING;
- send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
- }
- pr_debug("After update2\n");
- dump_arp_table(priv);
-out:
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-}
-
-/*
- * Notifies: Vcc setup ready
- */
-static void
-lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data,
- struct atm_vcc *vcc,
- void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
-{
- unsigned long flags;
- struct lec_arp_table *entry;
- int i, found_entry = 0;
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
- if (ioc_data->receive == 2) {
- pr_debug("LEC_ARP: Attaching mcast forward\n");
-#if 0
- entry = lec_arp_find(priv, bus_mac);
- if (!entry) {
- pr_info("LEC_ARP: Multicast entry not found!\n");
- goto out;
- }
- memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
- entry->recv_vcc = vcc;
- entry->old_recv_push = old_push;
-#endif
- entry = make_entry(priv, bus_mac);
- if (entry == NULL)
- goto out;
- timer_delete(&entry->timer);
- memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
- entry->recv_vcc = vcc;
- entry->old_recv_push = old_push;
- hlist_add_head(&entry->next, &priv->mcast_fwds);
- goto out;
- } else if (ioc_data->receive == 1) {
- /*
- * Vcc which we don't want to make default vcc,
- * attach it anyway.
- */
- pr_debug("LEC_ARP:Attaching data direct, not default: %*phN\n",
- ATM_ESA_LEN, ioc_data->atm_addr);
- entry = make_entry(priv, bus_mac);
- if (entry == NULL)
- goto out;
- memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
- eth_zero_addr(entry->mac_addr);
- entry->recv_vcc = vcc;
- entry->old_recv_push = old_push;
- entry->status = ESI_UNKNOWN;
- entry->timer.expires = jiffies + priv->vcc_timeout_period;
- entry->timer.function = lec_arp_expire_vcc;
- hlist_add_head(&entry->next, &priv->lec_no_forward);
- add_timer(&entry->timer);
- dump_arp_table(priv);
- goto out;
- }
- pr_debug("LEC_ARP:Attaching data direct, default: %*phN\n",
- ATM_ESA_LEN, ioc_data->atm_addr);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry(entry,
- &priv->lec_arp_tables[i], next) {
- if (memcmp
- (ioc_data->atm_addr, entry->atm_addr,
- ATM_ESA_LEN) == 0) {
- pr_debug("LEC_ARP: Attaching data direct\n");
- pr_debug("Currently -> Vcc: %d, Rvcc:%d\n",
- entry->vcc ? entry->vcc->vci : 0,
- entry->recv_vcc ? entry->recv_vcc->
- vci : 0);
- found_entry = 1;
- timer_delete(&entry->timer);
- entry->vcc = vcc;
- entry->old_push = old_push;
- if (entry->status == ESI_VC_PENDING) {
- if (priv->maximum_unknown_frame_count
- == 0)
- entry->status =
- ESI_FORWARD_DIRECT;
- else {
- entry->timestamp = jiffies;
- entry->status =
- ESI_FLUSH_PENDING;
-#if 0
- send_to_lecd(priv, l_flush_xmt,
- NULL,
- entry->atm_addr,
- NULL);
-#endif
- }
- } else {
- /*
- * They were forming a connection
- * to us, and we to them. Our
- * ATM address is numerically lower
- * than theirs, so we make connection
- * we formed into default VCC (8.1.11).
- * Connection they made gets torn
- * down. This might confuse some
- * clients. Can be changed if
- * someone reports trouble...
- */
- ;
- }
- }
- }
- }
- if (found_entry) {
- pr_debug("After vcc was added\n");
- dump_arp_table(priv);
- goto out;
- }
- /*
- * Not found, snatch address from first data packet that arrives
- * from this vcc
- */
- entry = make_entry(priv, bus_mac);
- if (!entry)
- goto out;
- entry->vcc = vcc;
- entry->old_push = old_push;
- memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
- eth_zero_addr(entry->mac_addr);
- entry->status = ESI_UNKNOWN;
- hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
- entry->timer.expires = jiffies + priv->vcc_timeout_period;
- entry->timer.function = lec_arp_expire_vcc;
- add_timer(&entry->timer);
- pr_debug("After vcc was added\n");
- dump_arp_table(priv);
-out:
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-}
-
-static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
-{
- unsigned long flags;
- struct lec_arp_table *entry;
- int i;
-
- pr_debug("%lx\n", tran_id);
-restart:
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry(entry,
- &priv->lec_arp_tables[i], next) {
- if (entry->flush_tran_id == tran_id &&
- entry->status == ESI_FLUSH_PENDING) {
- struct sk_buff *skb;
- struct atm_vcc *vcc = entry->vcc;
-
- lec_arp_hold(entry);
- spin_unlock_irqrestore(&priv->lec_arp_lock,
- flags);
- while ((skb = skb_dequeue(&entry->tx_wait)))
- lec_send(vcc, skb);
- entry->last_used = jiffies;
- entry->status = ESI_FORWARD_DIRECT;
- lec_arp_put(entry);
- pr_debug("LEC_ARP: Flushed\n");
- goto restart;
- }
- }
- }
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
- dump_arp_table(priv);
-}
-
-static void
-lec_set_flush_tran_id(struct lec_priv *priv,
- const unsigned char *atm_addr, unsigned long tran_id)
-{
- unsigned long flags;
- struct lec_arp_table *entry;
- int i;
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
- hlist_for_each_entry(entry,
- &priv->lec_arp_tables[i], next) {
- if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
- entry->flush_tran_id = tran_id;
- pr_debug("Set flush transaction id to %lx for %p\n",
- tran_id, entry);
- }
- }
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-}
-
-static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
-{
- unsigned long flags;
- unsigned char mac_addr[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
- struct lec_arp_table *to_add;
- struct lec_vcc_priv *vpriv;
- int err = 0;
-
- vpriv = kmalloc_obj(struct lec_vcc_priv);
- if (!vpriv)
- return -ENOMEM;
- vpriv->xoff = 0;
- vpriv->old_pop = vcc->pop;
- vcc->user_back = vpriv;
- vcc->pop = lec_pop;
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- to_add = make_entry(priv, mac_addr);
- if (!to_add) {
- vcc->pop = vpriv->old_pop;
- kfree(vpriv);
- err = -ENOMEM;
- goto out;
- }
- memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
- to_add->status = ESI_FORWARD_DIRECT;
- to_add->flags |= LEC_PERMANENT_FLAG;
- to_add->vcc = vcc;
- to_add->old_push = vcc->push;
- vcc->push = lec_push;
- priv->mcast_vcc = vcc;
- lec_arp_add(priv, to_add);
-out:
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
- return err;
-}
-
-static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
-{
- unsigned long flags;
- struct hlist_node *next;
- struct lec_arp_table *entry;
- int i;
-
- pr_debug("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
- dump_arp_table(priv);
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
-
- for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_tables[i], next) {
- if (vcc == entry->vcc) {
- lec_arp_remove(priv, entry);
- lec_arp_put(entry);
- if (priv->mcast_vcc == vcc)
- priv->mcast_vcc = NULL;
- }
- }
- }
-
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_empty_ones, next) {
- if (entry->vcc == vcc) {
- lec_arp_clear_vccs(entry);
- timer_delete(&entry->timer);
- hlist_del(&entry->next);
- lec_arp_put(entry);
- }
- }
-
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_no_forward, next) {
- if (entry->recv_vcc == vcc) {
- lec_arp_clear_vccs(entry);
- timer_delete(&entry->timer);
- hlist_del(&entry->next);
- lec_arp_put(entry);
- }
- }
-
- hlist_for_each_entry_safe(entry, next, &priv->mcast_fwds, next) {
- if (entry->recv_vcc == vcc) {
- lec_arp_clear_vccs(entry);
- /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
- hlist_del(&entry->next);
- lec_arp_put(entry);
- }
- }
-
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
- dump_arp_table(priv);
-}
-
-static void
-lec_arp_check_empties(struct lec_priv *priv,
- struct atm_vcc *vcc, struct sk_buff *skb)
-{
- unsigned long flags;
- struct hlist_node *next;
- struct lec_arp_table *entry, *tmp;
- struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
- unsigned char *src = hdr->h_source;
-
- spin_lock_irqsave(&priv->lec_arp_lock, flags);
- hlist_for_each_entry_safe(entry, next,
- &priv->lec_arp_empty_ones, next) {
- if (vcc == entry->vcc) {
- timer_delete(&entry->timer);
- ether_addr_copy(entry->mac_addr, src);
- entry->status = ESI_FORWARD_DIRECT;
- entry->last_used = jiffies;
- /* We might have got an entry */
- tmp = lec_arp_find(priv, src);
- if (tmp) {
- lec_arp_remove(priv, tmp);
- lec_arp_put(tmp);
- }
- hlist_del(&entry->next);
- lec_arp_add(priv, entry);
- goto out;
- }
- }
- pr_debug("LEC_ARP: Arp_check_empties: entry not found!\n");
-out:
- spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-}
-
-MODULE_DESCRIPTION("ATM LAN Emulation (LANE) support");
-MODULE_LICENSE("GPL");
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
deleted file mode 100644
index ce8e9780373b..000000000000
--- a/net/atm/mpc.c
+++ /dev/null
@@ -1,1538 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/capability.h>
-#include <linux/seq_file.h>
-
-/* We are an ethernet device */
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <net/sock.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <net/checksum.h> /* for ip_fast_csum() */
-#include <net/arp.h>
-#include <net/dst.h>
-#include <linux/proc_fs.h>
-
-/* And atm device */
-#include <linux/atmdev.h>
-#include <linux/atmlec.h>
-#include <linux/atmmpc.h>
-/* Modular too */
-#include <linux/module.h>
-
-#include "lec.h"
-#include "mpc.h"
-#include "resources.h"
-
-/*
- * mpc.c: Implementation of MPOA client kernel part
- */
-
-#if 0
-#define dprintk(format, args...) \
- printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args)
-#define dprintk_cont(format, args...) printk(KERN_CONT format, ##args)
-#else
-#define dprintk(format, args...) \
- do { if (0) \
- printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args);\
- } while (0)
-#define dprintk_cont(format, args...) \
- do { if (0) printk(KERN_CONT format, ##args); } while (0)
-#endif
-
-#if 0
-#define ddprintk(format, args...) \
- printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args)
-#define ddprintk_cont(format, args...) printk(KERN_CONT format, ##args)
-#else
-#define ddprintk(format, args...) \
- do { if (0) \
- printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args);\
- } while (0)
-#define ddprintk_cont(format, args...) \
- do { if (0) printk(KERN_CONT format, ##args); } while (0)
-#endif
-
-/* mpc_daemon -> kernel */
-static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc);
-static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc);
-static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc);
-static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc);
-static void mps_death(struct k_message *msg, struct mpoa_client *mpc);
-static void clean_up(struct k_message *msg, struct mpoa_client *mpc,
- int action);
-static void MPOA_cache_impos_rcvd(struct k_message *msg,
- struct mpoa_client *mpc);
-static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg,
- struct mpoa_client *mpc);
-static void set_mps_mac_addr_rcvd(struct k_message *mesg,
- struct mpoa_client *mpc);
-
-static const uint8_t *copy_macs(struct mpoa_client *mpc,
- const uint8_t *router_mac,
- const uint8_t *tlvs, uint8_t mps_macs,
- uint8_t device_type);
-static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry);
-
-static void send_set_mps_ctrl_addr(const char *addr, struct mpoa_client *mpc);
-static void mpoad_close(struct atm_vcc *vcc);
-static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb);
-
-static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb);
-static netdev_tx_t mpc_send_packet(struct sk_buff *skb,
- struct net_device *dev);
-static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
- unsigned long event, void *dev);
-static void mpc_timer_refresh(void);
-static void mpc_cache_check(struct timer_list *unused);
-
-static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x5e},
- {0x00, 0x03} /* For MPOA control PDUs */
-};
-static struct llc_snap_hdr llc_snap_mpoa_data = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x00},
- {0x08, 0x00} /* This is for IP PDUs only */
-};
-static struct llc_snap_hdr llc_snap_mpoa_data_tagged = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x00},
- {0x88, 0x4c} /* This is for tagged data PDUs */
-};
-
-static struct notifier_block mpoa_notifier = {
- mpoa_event_listener,
- NULL,
- 0
-};
-
-struct mpoa_client *mpcs = NULL; /* FIXME */
-static struct atm_mpoa_qos *qos_head = NULL;
-static DEFINE_TIMER(mpc_timer, mpc_cache_check);
-
-
-static struct mpoa_client *find_mpc_by_itfnum(int itf)
-{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->dev_num == itf)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
-}
-
-static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
-{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->mpoad_vcc == vcc)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
-}
-
-static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
-{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->dev == dev)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
-}
-
-/*
- * Functions for managing QoS list
- */
-
-/*
- * Overwrites the old entry or makes a new one.
- */
-struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos)
-{
- struct atm_mpoa_qos *entry;
-
- entry = atm_mpoa_search_qos(dst_ip);
- if (entry != NULL) {
- entry->qos = *qos;
- return entry;
- }
-
- entry = kmalloc_obj(struct atm_mpoa_qos);
- if (entry == NULL) {
- pr_info("mpoa: out of memory\n");
- return entry;
- }
-
- entry->ipaddr = dst_ip;
- entry->qos = *qos;
-
- entry->next = qos_head;
- qos_head = entry;
-
- return entry;
-}
-
-struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip)
-{
- struct atm_mpoa_qos *qos;
-
- qos = qos_head;
- while (qos) {
- if (qos->ipaddr == dst_ip)
- break;
- qos = qos->next;
- }
-
- return qos;
-}
-
-/*
- * Returns 0 for failure
- */
-int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
-{
- struct atm_mpoa_qos *curr;
-
- if (entry == NULL)
- return 0;
- if (entry == qos_head) {
- qos_head = qos_head->next;
- kfree(entry);
- return 1;
- }
-
- curr = qos_head;
- while (curr != NULL) {
- if (curr->next == entry) {
- curr->next = entry->next;
- kfree(entry);
- return 1;
- }
- curr = curr->next;
- }
-
- return 0;
-}
-
-/* this is buggered - we need locking for qos_head */
-void atm_mpoa_disp_qos(struct seq_file *m)
-{
- struct atm_mpoa_qos *qos;
-
- qos = qos_head;
- seq_printf(m, "QoS entries for shortcuts:\n");
- seq_printf(m, "IP address\n TX:max_pcr pcr min_pcr max_cdv max_sdu\n RX:max_pcr pcr min_pcr max_cdv max_sdu\n");
-
- while (qos != NULL) {
- seq_printf(m, "%pI4\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
- &qos->ipaddr,
- qos->qos.txtp.max_pcr,
- qos->qos.txtp.pcr,
- qos->qos.txtp.min_pcr,
- qos->qos.txtp.max_cdv,
- qos->qos.txtp.max_sdu,
- qos->qos.rxtp.max_pcr,
- qos->qos.rxtp.pcr,
- qos->qos.rxtp.min_pcr,
- qos->qos.rxtp.max_cdv,
- qos->qos.rxtp.max_sdu);
- qos = qos->next;
- }
-}
-
-static struct net_device *find_lec_by_itfnum(int itf)
-{
- struct net_device *dev;
- char name[IFNAMSIZ];
-
- sprintf(name, "lec%d", itf);
- dev = dev_get_by_name(&init_net, name);
-
- return dev;
-}
-
-static struct mpoa_client *alloc_mpc(void)
-{
- struct mpoa_client *mpc;
-
- mpc = kzalloc_obj(struct mpoa_client);
- if (mpc == NULL)
- return NULL;
- rwlock_init(&mpc->ingress_lock);
- rwlock_init(&mpc->egress_lock);
- mpc->next = mpcs;
- atm_mpoa_init_cache(mpc);
-
- mpc->parameters.mpc_p1 = MPC_P1;
- mpc->parameters.mpc_p2 = MPC_P2;
- memset(mpc->parameters.mpc_p3, 0, sizeof(mpc->parameters.mpc_p3));
- mpc->parameters.mpc_p4 = MPC_P4;
- mpc->parameters.mpc_p5 = MPC_P5;
- mpc->parameters.mpc_p6 = MPC_P6;
-
- mpcs = mpc;
-
- return mpc;
-}
-
-/*
- *
- * start_mpc() puts the MPC on line. All the packets destined
- * to the lec underneath us are now being monitored and
- * shortcuts will be established.
- *
- */
-static void start_mpc(struct mpoa_client *mpc, struct net_device *dev)
-{
-
- dprintk("(%s)\n", mpc->dev->name);
- if (!dev->netdev_ops)
- pr_info("(%s) not starting\n", dev->name);
- else {
- mpc->old_ops = dev->netdev_ops;
- mpc->new_ops = *mpc->old_ops;
- mpc->new_ops.ndo_start_xmit = mpc_send_packet;
- dev->netdev_ops = &mpc->new_ops;
- }
-}
-
-static void stop_mpc(struct mpoa_client *mpc)
-{
- struct net_device *dev = mpc->dev;
- dprintk("(%s)", mpc->dev->name);
-
- /* Lets not nullify lec device's dev->hard_start_xmit */
- if (dev->netdev_ops != &mpc->new_ops) {
- dprintk_cont(" mpc already stopped, not fatal\n");
- return;
- }
- dprintk_cont("\n");
-
- dev->netdev_ops = mpc->old_ops;
- mpc->old_ops = NULL;
-
- /* close_shortcuts(mpc); ??? FIXME */
-}
-
-static const char *mpoa_device_type_string(char type) __attribute__ ((unused));
-
-static const char *mpoa_device_type_string(char type)
-{
- switch (type) {
- case NON_MPOA:
- return "non-MPOA device";
- case MPS:
- return "MPS";
- case MPC:
- return "MPC";
- case MPS_AND_MPC:
- return "both MPS and MPC";
- }
-
- return "unspecified (non-MPOA) device";
-}
-
-/*
- * lec device calls this via its netdev_priv(dev)->lane2_ops
- * ->associate_indicator() when it sees a TLV in LE_ARP packet.
- * We fill in the pointer above when we see a LANE2 lec initializing
- * See LANE2 spec 3.1.5
- *
- * Quite a big and ugly function but when you look at it
- * all it does is to try to locate and parse MPOA Device
- * Type TLV.
- * We give our lec a pointer to this function and when the
- * lec sees a TLV it uses the pointer to call this function.
- *
- */
-static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr,
- const u8 *tlvs, u32 sizeoftlvs)
-{
- uint32_t type;
- uint8_t length, mpoa_device_type, number_of_mps_macs;
- const uint8_t *end_of_tlvs;
- struct mpoa_client *mpc;
-
- mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
- dprintk("(%s) received TLV(s), ", dev->name);
- dprintk("total length of all TLVs %d\n", sizeoftlvs);
- mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
- if (mpc == NULL) {
- pr_info("(%s) no mpc\n", dev->name);
- return;
- }
- end_of_tlvs = tlvs + sizeoftlvs;
- while (end_of_tlvs - tlvs >= 5) {
- type = ((tlvs[0] << 24) | (tlvs[1] << 16) |
- (tlvs[2] << 8) | tlvs[3]);
- length = tlvs[4];
- tlvs += 5;
- dprintk(" type 0x%x length %02x\n", type, length);
- if (tlvs + length > end_of_tlvs) {
- pr_info("TLV value extends past its buffer, aborting parse\n");
- return;
- }
-
- if (type == 0) {
- pr_info("mpoa: (%s) TLV type was 0, returning\n",
- dev->name);
- return;
- }
-
- if (type != TLV_MPOA_DEVICE_TYPE) {
- tlvs += length;
- continue; /* skip other TLVs */
- }
- mpoa_device_type = *tlvs++;
- number_of_mps_macs = *tlvs++;
- dprintk("(%s) MPOA device type '%s', ",
- dev->name, mpoa_device_type_string(mpoa_device_type));
- if (mpoa_device_type == MPS_AND_MPC &&
- length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
- pr_info("(%s) short MPOA Device Type TLV\n",
- dev->name);
- continue;
- }
- if ((mpoa_device_type == MPS || mpoa_device_type == MPC) &&
- length < 22 + number_of_mps_macs*ETH_ALEN) {
- pr_info("(%s) short MPOA Device Type TLV\n", dev->name);
- continue;
- }
- if (mpoa_device_type != MPS &&
- mpoa_device_type != MPS_AND_MPC) {
- dprintk("ignoring non-MPS device ");
- if (mpoa_device_type == MPC)
- tlvs += 20;
- continue; /* we are only interested in MPSs */
- }
- if (number_of_mps_macs == 0 &&
- mpoa_device_type == MPS_AND_MPC) {
- pr_info("(%s) MPS_AND_MPC has zero MACs\n", dev->name);
- continue; /* someone should read the spec */
- }
- dprintk_cont("this MPS has %d MAC addresses\n",
- number_of_mps_macs);
-
- /*
- * ok, now we can go and tell our daemon
- * the control address of MPS
- */
- send_set_mps_ctrl_addr(tlvs, mpc);
-
- tlvs = copy_macs(mpc, mac_addr, tlvs,
- number_of_mps_macs, mpoa_device_type);
- if (tlvs == NULL)
- return;
- }
- if (end_of_tlvs - tlvs != 0)
- pr_info("(%s) ignoring %zd bytes of trailing TLV garbage\n",
- dev->name, end_of_tlvs - tlvs);
-}
-
-/*
- * Store at least advertizing router's MAC address
- * plus the possible MAC address(es) to mpc->mps_macs.
- * For a freshly allocated MPOA client mpc->mps_macs == 0.
- */
-static const uint8_t *copy_macs(struct mpoa_client *mpc,
- const uint8_t *router_mac,
- const uint8_t *tlvs, uint8_t mps_macs,
- uint8_t device_type)
-{
- int num_macs;
- num_macs = (mps_macs > 1) ? mps_macs : 1;
-
- if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
- if (mpc->number_of_mps_macs != 0)
- kfree(mpc->mps_macs);
- mpc->number_of_mps_macs = 0;
- mpc->mps_macs = kmalloc_array(ETH_ALEN, num_macs, GFP_KERNEL);
- if (mpc->mps_macs == NULL) {
- pr_info("(%s) out of mem\n", mpc->dev->name);
- return NULL;
- }
- }
- ether_addr_copy(mpc->mps_macs, router_mac);
- tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
- if (mps_macs > 0)
- memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
- tlvs += mps_macs*ETH_ALEN;
- mpc->number_of_mps_macs = num_macs;
-
- return tlvs;
-}
-
-static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
-{
- in_cache_entry *entry;
- struct iphdr *iph;
- char *buff;
- __be32 ipaddr = 0;
-
- static struct {
- struct llc_snap_hdr hdr;
- __be32 tag;
- } tagged_llc_snap_hdr = {
- {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
- 0
- };
-
- buff = skb->data + mpc->dev->hard_header_len;
- iph = (struct iphdr *)buff;
- ipaddr = iph->daddr;
-
- ddprintk("(%s) ipaddr 0x%x\n",
- mpc->dev->name, ipaddr);
-
- entry = mpc->in_ops->get(ipaddr, mpc);
- if (entry == NULL) {
- entry = mpc->in_ops->add_entry(ipaddr, mpc);
- if (entry != NULL)
- mpc->in_ops->put(entry);
- return 1;
- }
- /* threshold not exceeded or VCC not ready */
- if (mpc->in_ops->cache_hit(entry, mpc) != OPEN) {
- ddprintk("(%s) cache_hit: returns != OPEN\n",
- mpc->dev->name);
- mpc->in_ops->put(entry);
- return 1;
- }
-
- ddprintk("(%s) using shortcut\n",
- mpc->dev->name);
- /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
- if (iph->ttl <= 1) {
- ddprintk("(%s) IP ttl = %u, using LANE\n",
- mpc->dev->name, iph->ttl);
- mpc->in_ops->put(entry);
- return 1;
- }
- iph->ttl--;
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
- if (entry->ctrl_info.tag != 0) {
- ddprintk("(%s) adding tag 0x%x\n",
- mpc->dev->name, entry->ctrl_info.tag);
- tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
- skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
- skb_push(skb, sizeof(tagged_llc_snap_hdr));
- /* add LLC/SNAP header */
- skb_copy_to_linear_data(skb, &tagged_llc_snap_hdr,
- sizeof(tagged_llc_snap_hdr));
- } else {
- skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
- skb_push(skb, sizeof(struct llc_snap_hdr));
- /* add LLC/SNAP header + tag */
- skb_copy_to_linear_data(skb, &llc_snap_mpoa_data,
- sizeof(struct llc_snap_hdr));
- }
-
- atm_account_tx(entry->shortcut, skb);
- entry->shortcut->send(entry->shortcut, skb);
- entry->packets_fwded++;
- mpc->in_ops->put(entry);
-
- return 0;
-}
-
-/*
- * Probably needs some error checks and locking, not sure...
- */
-static netdev_tx_t mpc_send_packet(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct mpoa_client *mpc;
- struct ethhdr *eth;
- int i = 0;
-
- mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
- if (mpc == NULL) {
- pr_info("(%s) no MPC found\n", dev->name);
- goto non_ip;
- }
-
- eth = (struct ethhdr *)skb->data;
- if (eth->h_proto != htons(ETH_P_IP))
- goto non_ip; /* Multi-Protocol Over ATM :-) */
-
- /* Weed out funny packets (e.g., AF_PACKET or raw). */
- if (skb->len < ETH_HLEN + sizeof(struct iphdr))
- goto non_ip;
- skb_set_network_header(skb, ETH_HLEN);
- if (skb->len < ETH_HLEN + ip_hdr(skb)->ihl * 4 || ip_hdr(skb)->ihl < 5)
- goto non_ip;
-
- while (i < mpc->number_of_mps_macs) {
- if (ether_addr_equal(eth->h_dest, mpc->mps_macs + i * ETH_ALEN))
- if (send_via_shortcut(skb, mpc) == 0) /* try shortcut */
- return NETDEV_TX_OK;
- i++;
- }
-
-non_ip:
- return __netdev_start_xmit(mpc->old_ops, skb, dev, false);
-}
-
-static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
-{
- int bytes_left;
- struct mpoa_client *mpc;
- struct atmmpc_ioc ioc_data;
- in_cache_entry *in_entry;
- __be32 ipaddr;
-
- bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc));
- if (bytes_left != 0) {
- pr_info("mpoa:Short read (missed %d bytes) from userland\n",
- bytes_left);
- return -EFAULT;
- }
- ipaddr = ioc_data.ipaddr;
- if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
- return -EINVAL;
-
- mpc = find_mpc_by_itfnum(ioc_data.dev_num);
- if (mpc == NULL)
- return -EINVAL;
-
- if (ioc_data.type == MPC_SOCKET_INGRESS) {
- in_entry = mpc->in_ops->get(ipaddr, mpc);
- if (in_entry == NULL ||
- in_entry->entry_state < INGRESS_RESOLVED) {
- pr_info("(%s) did not find RESOLVED entry from ingress cache\n",
- mpc->dev->name);
- if (in_entry != NULL)
- mpc->in_ops->put(in_entry);
- return -EINVAL;
- }
- pr_info("(%s) attaching ingress SVC, entry = %pI4\n",
- mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
- in_entry->shortcut = vcc;
- mpc->in_ops->put(in_entry);
- } else {
- pr_info("(%s) attaching egress SVC\n", mpc->dev->name);
- }
-
- vcc->proto_data = mpc->dev;
- vcc->push = mpc_push;
-
- return 0;
-}
-
-/*
- *
- */
-static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
-{
- struct mpoa_client *mpc;
- in_cache_entry *in_entry;
- eg_cache_entry *eg_entry;
-
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL) {
- pr_info("(%s) close for unknown MPC\n", dev->name);
- return;
- }
-
- dprintk("(%s)\n", dev->name);
- in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
- if (in_entry) {
- dprintk("(%s) ingress SVC closed ip = %pI4\n",
- mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
- in_entry->shortcut = NULL;
- mpc->in_ops->put(in_entry);
- }
- eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc);
- if (eg_entry) {
- dprintk("(%s) egress SVC closed\n", mpc->dev->name);
- eg_entry->shortcut = NULL;
- mpc->eg_ops->put(eg_entry);
- }
-
- if (in_entry == NULL && eg_entry == NULL)
- dprintk("(%s) unused vcc closed\n", dev->name);
-}
-
-static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
-{
- struct net_device *dev = (struct net_device *)vcc->proto_data;
- struct sk_buff *new_skb;
- eg_cache_entry *eg;
- struct mpoa_client *mpc;
- __be32 tag;
- char *tmp;
-
- ddprintk("(%s)\n", dev->name);
- if (skb == NULL) {
- dprintk("(%s) null skb, closing VCC\n", dev->name);
- mpc_vcc_close(vcc, dev);
- return;
- }
-
- skb->dev = dev;
- if (memcmp(skb->data, &llc_snap_mpoa_ctrl,
- sizeof(struct llc_snap_hdr)) == 0) {
- struct sock *sk = sk_atm(vcc);
-
- dprintk("(%s) control packet arrived\n", dev->name);
- /* Pass control packets to daemon */
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk);
- return;
- }
-
- /* data coming over the shortcut */
- atm_return(vcc, skb->truesize);
-
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL) {
- pr_info("(%s) unknown MPC\n", dev->name);
- return;
- }
-
- if (memcmp(skb->data, &llc_snap_mpoa_data_tagged,
- sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
- ddprintk("(%s) tagged data packet arrived\n", dev->name);
-
- } else if (memcmp(skb->data, &llc_snap_mpoa_data,
- sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
- pr_info("(%s) Unsupported non-tagged data packet arrived. Purging\n",
- dev->name);
- dev_kfree_skb_any(skb);
- return;
- } else {
- pr_info("(%s) garbage arrived, purging\n", dev->name);
- dev_kfree_skb_any(skb);
- return;
- }
-
- tmp = skb->data + sizeof(struct llc_snap_hdr);
- tag = *(__be32 *)tmp;
-
- eg = mpc->eg_ops->get_by_tag(tag, mpc);
- if (eg == NULL) {
- pr_info("mpoa: (%s) Didn't find egress cache entry, tag = %u\n",
- dev->name, tag);
- purge_egress_shortcut(vcc, NULL);
- dev_kfree_skb_any(skb);
- return;
- }
-
- /*
- * See if ingress MPC is using shortcut we opened as a return channel.
- * This means we have a bi-directional vcc opened by us.
- */
- if (eg->shortcut == NULL) {
- eg->shortcut = vcc;
- pr_info("(%s) egress SVC in use\n", dev->name);
- }
-
- skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag));
- /* get rid of LLC/SNAP header */
- new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length);
- /* LLC/SNAP is shorter than MAC header :( */
- dev_kfree_skb_any(skb);
- if (new_skb == NULL) {
- mpc->eg_ops->put(eg);
- return;
- }
- skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */
- skb_copy_to_linear_data(new_skb, eg->ctrl_info.DLL_header,
- eg->ctrl_info.DH_length);
- new_skb->protocol = eth_type_trans(new_skb, dev);
- skb_reset_network_header(new_skb);
-
- eg->latest_ip_addr = ip_hdr(new_skb)->saddr;
- eg->packets_rcvd++;
- mpc->eg_ops->put(eg);
-
- memset(ATM_SKB(new_skb), 0, sizeof(struct atm_skb_data));
- netif_rx(new_skb);
-}
-
-static const struct atmdev_ops mpc_ops = { /* only send is required */
- .close = mpoad_close,
- .send = msg_from_mpoad
-};
-
-static struct atm_dev mpc_dev = {
- .ops = &mpc_ops,
- .type = "mpc",
- .number = 42,
- .lock = __SPIN_LOCK_UNLOCKED(mpc_dev.lock)
- /* members not explicitly initialised will be 0 */
-};
-
-static int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg)
-{
- struct mpoa_client *mpc;
- struct lec_priv *priv;
- int err;
-
- if (mpcs == NULL) {
- mpc_timer_refresh();
-
- /* This lets us now how our LECs are doing */
- err = register_netdevice_notifier(&mpoa_notifier);
- if (err < 0) {
- timer_delete(&mpc_timer);
- return err;
- }
- }
-
- mpc = find_mpc_by_itfnum(arg);
- if (mpc == NULL) {
- dprintk("allocating new mpc for itf %d\n", arg);
- mpc = alloc_mpc();
- if (mpc == NULL)
- return -ENOMEM;
- mpc->dev_num = arg;
- mpc->dev = find_lec_by_itfnum(arg);
- /* NULL if there was no lec */
- }
- if (mpc->mpoad_vcc) {
- pr_info("mpoad is already present for itf %d\n", arg);
- return -EADDRINUSE;
- }
-
- if (mpc->dev) { /* check if the lec is LANE2 capable */
- priv = netdev_priv(mpc->dev);
- if (priv->lane_version < 2) {
- dev_put(mpc->dev);
- mpc->dev = NULL;
- } else
- priv->lane2_ops->associate_indicator = lane2_assoc_ind;
- }
-
- mpc->mpoad_vcc = vcc;
- vcc->dev = &mpc_dev;
- vcc_insert_socket(sk_atm(vcc));
- set_bit(ATM_VF_META, &vcc->flags);
- set_bit(ATM_VF_READY, &vcc->flags);
-
- if (mpc->dev) {
- char empty[ATM_ESA_LEN];
- memset(empty, 0, ATM_ESA_LEN);
-
- start_mpc(mpc, mpc->dev);
- /* set address if mpcd e.g. gets killed and restarted.
- * If we do not do it now we have to wait for the next LE_ARP
- */
- if (memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0)
- send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
- }
-
- __module_get(THIS_MODULE);
- return arg;
-}
-
-static void send_set_mps_ctrl_addr(const char *addr, struct mpoa_client *mpc)
-{
- struct k_message mesg;
-
- memcpy(mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
-
- mesg.type = SET_MPS_CTRL_ADDR;
- memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
- msg_to_mpoad(&mesg, mpc);
-}
-
-static void mpoad_close(struct atm_vcc *vcc)
-{
- struct mpoa_client *mpc;
- struct sk_buff *skb;
-
- mpc = find_mpc_by_vcc(vcc);
- if (mpc == NULL) {
- pr_info("did not find MPC\n");
- return;
- }
- if (!mpc->mpoad_vcc) {
- pr_info("close for non-present mpoad\n");
- return;
- }
-
- mpc->mpoad_vcc = NULL;
- if (mpc->dev) {
- struct lec_priv *priv = netdev_priv(mpc->dev);
- priv->lane2_ops->associate_indicator = NULL;
- stop_mpc(mpc);
- dev_put(mpc->dev);
- }
-
- mpc->in_ops->destroy_cache(mpc);
- mpc->eg_ops->destroy_cache(mpc);
-
- while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
- atm_return(vcc, skb->truesize);
- kfree_skb(skb);
- }
-
- pr_info("(%s) going down\n",
- (mpc->dev) ? mpc->dev->name : "<unknown>");
- module_put(THIS_MODULE);
-}
-
-/*
- *
- */
-static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
-{
-
- struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
- struct k_message *mesg = (struct k_message *)skb->data;
- WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
-
- if (mpc == NULL) {
- pr_info("no mpc found\n");
- return 0;
- }
- dprintk("(%s)", mpc->dev ? mpc->dev->name : "<unknown>");
- switch (mesg->type) {
- case MPOA_RES_REPLY_RCVD:
- dprintk_cont("mpoa_res_reply_rcvd\n");
- MPOA_res_reply_rcvd(mesg, mpc);
- break;
- case MPOA_TRIGGER_RCVD:
- dprintk_cont("mpoa_trigger_rcvd\n");
- MPOA_trigger_rcvd(mesg, mpc);
- break;
- case INGRESS_PURGE_RCVD:
- dprintk_cont("nhrp_purge_rcvd\n");
- ingress_purge_rcvd(mesg, mpc);
- break;
- case EGRESS_PURGE_RCVD:
- dprintk_cont("egress_purge_reply_rcvd\n");
- egress_purge_rcvd(mesg, mpc);
- break;
- case MPS_DEATH:
- dprintk_cont("mps_death\n");
- mps_death(mesg, mpc);
- break;
- case CACHE_IMPOS_RCVD:
- dprintk_cont("cache_impos_rcvd\n");
- MPOA_cache_impos_rcvd(mesg, mpc);
- break;
- case SET_MPC_CTRL_ADDR:
- dprintk_cont("set_mpc_ctrl_addr\n");
- set_mpc_ctrl_addr_rcvd(mesg, mpc);
- break;
- case SET_MPS_MAC_ADDR:
- dprintk_cont("set_mps_mac_addr\n");
- set_mps_mac_addr_rcvd(mesg, mpc);
- break;
- case CLEAN_UP_AND_EXIT:
- dprintk_cont("clean_up_and_exit\n");
- clean_up(mesg, mpc, DIE);
- break;
- case RELOAD:
- dprintk_cont("reload\n");
- clean_up(mesg, mpc, RELOAD);
- break;
- case SET_MPC_PARAMS:
- dprintk_cont("set_mpc_params\n");
- mpc->parameters = mesg->content.params;
- break;
- default:
- dprintk_cont("unknown message %d\n", mesg->type);
- break;
- }
- kfree_skb(skb);
-
- return 0;
-}
-
-/* Remember that this function may not do things that sleep */
-int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
-{
- struct sk_buff *skb;
- struct sock *sk;
-
- if (mpc == NULL || !mpc->mpoad_vcc) {
- pr_info("mesg %d to a non-existent mpoad\n", mesg->type);
- return -ENXIO;
- }
-
- skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
- if (skb == NULL)
- return -ENOMEM;
- skb_put(skb, sizeof(struct k_message));
- skb_copy_to_linear_data(skb, mesg, sizeof(*mesg));
- atm_force_charge(mpc->mpoad_vcc, skb->truesize);
-
- sk = sk_atm(mpc->mpoad_vcc);
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk);
-
- return 0;
-}
-
-static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
- unsigned long event, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
- struct mpoa_client *mpc;
- struct lec_priv *priv;
-
- if (!net_eq(dev_net(dev), &init_net))
- return NOTIFY_DONE;
-
- if (strncmp(dev->name, "lec", 3))
- return NOTIFY_DONE; /* we are only interested in lec:s */
-
- switch (event) {
- case NETDEV_REGISTER: /* a new lec device was allocated */
- priv = netdev_priv(dev);
- if (priv->lane_version < 2)
- break;
- priv->lane2_ops->associate_indicator = lane2_assoc_ind;
- mpc = find_mpc_by_itfnum(priv->itfnum);
- if (mpc == NULL) {
- dprintk("allocating new mpc for %s\n", dev->name);
- mpc = alloc_mpc();
- if (mpc == NULL) {
- pr_info("no new mpc");
- break;
- }
- }
- mpc->dev_num = priv->itfnum;
- mpc->dev = dev;
- dev_hold(dev);
- dprintk("(%s) was initialized\n", dev->name);
- break;
- case NETDEV_UNREGISTER:
- /* the lec device was deallocated */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- dprintk("device (%s) was deallocated\n", dev->name);
- stop_mpc(mpc);
- dev_put(mpc->dev);
- mpc->dev = NULL;
- break;
- case NETDEV_UP:
- /* the dev was ifconfig'ed up */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- if (mpc->mpoad_vcc != NULL)
- start_mpc(mpc, dev);
- break;
- case NETDEV_DOWN:
- /* the dev was ifconfig'ed down */
- /* this means that the flow of packets from the
- * upper layer stops
- */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- if (mpc->mpoad_vcc != NULL)
- stop_mpc(mpc);
- break;
- case NETDEV_REBOOT:
- case NETDEV_CHANGE:
- case NETDEV_CHANGEMTU:
- case NETDEV_CHANGEADDR:
- case NETDEV_GOING_DOWN:
- break;
- default:
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-/*
- * Functions which are called after a message is received from mpcd.
- * Msg is reused on purpose.
- */
-
-
-static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
-{
- __be32 dst_ip = msg->content.in_info.in_dst_ip;
- in_cache_entry *entry;
-
- entry = mpc->in_ops->get(dst_ip, mpc);
- if (entry == NULL) {
- entry = mpc->in_ops->add_entry(dst_ip, mpc);
- entry->entry_state = INGRESS_RESOLVING;
- msg->type = SND_MPOA_RES_RQST;
- msg->content.in_info = entry->ctrl_info;
- msg_to_mpoad(msg, mpc);
- entry->reply_wait = ktime_get_seconds();
- mpc->in_ops->put(entry);
- return;
- }
-
- if (entry->entry_state == INGRESS_INVALID) {
- entry->entry_state = INGRESS_RESOLVING;
- msg->type = SND_MPOA_RES_RQST;
- msg->content.in_info = entry->ctrl_info;
- msg_to_mpoad(msg, mpc);
- entry->reply_wait = ktime_get_seconds();
- mpc->in_ops->put(entry);
- return;
- }
-
- pr_info("(%s) entry already in resolving state\n",
- (mpc->dev) ? mpc->dev->name : "<unknown>");
- mpc->in_ops->put(entry);
-}
-
-/*
- * Things get complicated because we have to check if there's an egress
- * shortcut with suitable traffic parameters we could use.
- */
-static void check_qos_and_open_shortcut(struct k_message *msg,
- struct mpoa_client *client,
- in_cache_entry *entry)
-{
- __be32 dst_ip = msg->content.in_info.in_dst_ip;
- struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
- eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
-
- if (eg_entry && eg_entry->shortcut) {
- if (eg_entry->shortcut->qos.txtp.traffic_class &
- msg->qos.txtp.traffic_class &
- (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)) {
- if (eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
- entry->shortcut = eg_entry->shortcut;
- else if (eg_entry->shortcut->qos.txtp.max_pcr > 0)
- entry->shortcut = eg_entry->shortcut;
- }
- if (entry->shortcut) {
- dprintk("(%s) using egress SVC to reach %pI4\n",
- client->dev->name, &dst_ip);
- client->eg_ops->put(eg_entry);
- return;
- }
- }
- if (eg_entry != NULL)
- client->eg_ops->put(eg_entry);
-
- /* No luck in the egress cache we must open an ingress SVC */
- msg->type = OPEN_INGRESS_SVC;
- if (qos &&
- (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class)) {
- msg->qos = qos->qos;
- pr_info("(%s) trying to get a CBR shortcut\n",
- client->dev->name);
- } else
- memset(&msg->qos, 0, sizeof(struct atm_qos));
- msg_to_mpoad(msg, client);
-}
-
-static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
-{
- __be32 dst_ip = msg->content.in_info.in_dst_ip;
- in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
-
- dprintk("(%s) ip %pI4\n",
- mpc->dev->name, &dst_ip);
- ddprintk("(%s) entry = %p",
- mpc->dev->name, entry);
- if (entry == NULL) {
- pr_info("(%s) ARGH, received res. reply for an entry that doesn't exist.\n",
- mpc->dev->name);
- return;
- }
- ddprintk_cont(" entry_state = %d ", entry->entry_state);
-
- if (entry->entry_state == INGRESS_RESOLVED) {
- pr_info("(%s) RESOLVED entry!\n", mpc->dev->name);
- mpc->in_ops->put(entry);
- return;
- }
-
- entry->ctrl_info = msg->content.in_info;
- entry->time = ktime_get_seconds();
- /* Used in refreshing func from now on */
- entry->reply_wait = ktime_get_seconds();
- entry->refresh_time = 0;
- ddprintk_cont("entry->shortcut = %p\n", entry->shortcut);
-
- if (entry->entry_state == INGRESS_RESOLVING &&
- entry->shortcut != NULL) {
- entry->entry_state = INGRESS_RESOLVED;
- mpc->in_ops->put(entry);
- return; /* Shortcut already open... */
- }
-
- if (entry->shortcut != NULL) {
- pr_info("(%s) entry->shortcut != NULL, impossible!\n",
- mpc->dev->name);
- mpc->in_ops->put(entry);
- return;
- }
-
- check_qos_and_open_shortcut(msg, mpc, entry);
- entry->entry_state = INGRESS_RESOLVED;
- mpc->in_ops->put(entry);
-
- return;
-
-}
-
-static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
-{
- __be32 dst_ip = msg->content.in_info.in_dst_ip;
- __be32 mask = msg->ip_mask;
- in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
-
- if (entry == NULL) {
- pr_info("(%s) purge for a non-existing entry, ip = %pI4\n",
- mpc->dev->name, &dst_ip);
- return;
- }
-
- do {
- dprintk("(%s) removing an ingress entry, ip = %pI4\n",
- mpc->dev->name, &dst_ip);
- write_lock_bh(&mpc->ingress_lock);
- mpc->in_ops->remove_entry(entry, mpc);
- write_unlock_bh(&mpc->ingress_lock);
- mpc->in_ops->put(entry);
- entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
- } while (entry != NULL);
-}
-
-static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
-{
- __be32 cache_id = msg->content.eg_info.cache_id;
- eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
-
- if (entry == NULL) {
- dprintk("(%s) purge for a non-existing entry\n",
- mpc->dev->name);
- return;
- }
-
- write_lock_irq(&mpc->egress_lock);
- mpc->eg_ops->remove_entry(entry, mpc);
- write_unlock_irq(&mpc->egress_lock);
-
- mpc->eg_ops->put(entry);
-}
-
-static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
-{
- struct sock *sk;
- struct k_message *purge_msg;
- struct sk_buff *skb;
-
- dprintk("entering\n");
- if (vcc == NULL) {
- pr_info("vcc == NULL\n");
- return;
- }
-
- skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
- if (skb == NULL) {
- pr_info("out of memory\n");
- return;
- }
-
- skb_put(skb, sizeof(struct k_message));
- memset(skb->data, 0, sizeof(struct k_message));
- purge_msg = (struct k_message *)skb->data;
- purge_msg->type = DATA_PLANE_PURGE;
- if (entry != NULL)
- purge_msg->content.eg_info = entry->ctrl_info;
-
- atm_force_charge(vcc, skb->truesize);
-
- sk = sk_atm(vcc);
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk);
- dprintk("exiting\n");
-}
-
-/*
- * Our MPS died. Tell our daemon to send NHRP data plane purge to each
- * of the egress shortcuts we have.
- */
-static void mps_death(struct k_message *msg, struct mpoa_client *mpc)
-{
- eg_cache_entry *entry;
-
- dprintk("(%s)\n", mpc->dev->name);
-
- if (memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)) {
- pr_info("(%s) wrong MPS\n", mpc->dev->name);
- return;
- }
-
- /* FIXME: This knows too much of the cache structure */
- read_lock_irq(&mpc->egress_lock);
- entry = mpc->eg_cache;
- while (entry != NULL) {
- purge_egress_shortcut(entry->shortcut, entry);
- entry = entry->next;
- }
- read_unlock_irq(&mpc->egress_lock);
-
- mpc->in_ops->destroy_cache(mpc);
- mpc->eg_ops->destroy_cache(mpc);
-}
-
-static void MPOA_cache_impos_rcvd(struct k_message *msg,
- struct mpoa_client *mpc)
-{
- uint16_t holding_time;
- eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);
-
- holding_time = msg->content.eg_info.holding_time;
- dprintk("(%s) entry = %p, holding_time = %u\n",
- mpc->dev->name, entry, holding_time);
- if (entry == NULL && !holding_time)
- return;
- if (entry == NULL && holding_time) {
- entry = mpc->eg_ops->add_entry(msg, mpc);
- mpc->eg_ops->put(entry);
- return;
- }
- if (holding_time) {
- mpc->eg_ops->update(entry, holding_time);
- return;
- }
-
- write_lock_irq(&mpc->egress_lock);
- mpc->eg_ops->remove_entry(entry, mpc);
- write_unlock_irq(&mpc->egress_lock);
-
- mpc->eg_ops->put(entry);
-}
-
-static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg,
- struct mpoa_client *mpc)
-{
- struct lec_priv *priv;
- int i, retval ;
-
- uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
-
- tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */
- tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */
- tlv[5] = 0x02; /* MPOA client */
- tlv[6] = 0x00; /* number of MPS MAC addresses */
-
- memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
- memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
-
- dprintk("(%s) setting MPC ctrl ATM address to",
- mpc->dev ? mpc->dev->name : "<unknown>");
- for (i = 7; i < sizeof(tlv); i++)
- dprintk_cont(" %02x", tlv[i]);
- dprintk_cont("\n");
-
- if (mpc->dev) {
- priv = netdev_priv(mpc->dev);
- retval = priv->lane2_ops->associate_req(mpc->dev,
- mpc->dev->dev_addr,
- tlv, sizeof(tlv));
- if (retval == 0)
- pr_info("(%s) MPOA device type TLV association failed\n",
- mpc->dev->name);
- retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
- if (retval < 0)
- pr_info("(%s) targetless LE_ARP request failed\n",
- mpc->dev->name);
- }
-}
-
-static void set_mps_mac_addr_rcvd(struct k_message *msg,
- struct mpoa_client *client)
-{
-
- if (client->number_of_mps_macs)
- kfree(client->mps_macs);
- client->number_of_mps_macs = 0;
- client->mps_macs = kmemdup(msg->MPS_ctrl, ETH_ALEN, GFP_KERNEL);
- if (client->mps_macs == NULL) {
- pr_info("out of memory\n");
- return;
- }
- client->number_of_mps_macs = 1;
-}
-
-/*
- * purge egress cache and tell daemon to 'action' (DIE, RELOAD)
- */
-static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
-{
-
- eg_cache_entry *entry;
- msg->type = SND_EGRESS_PURGE;
-
-
- /* FIXME: This knows too much of the cache structure */
- read_lock_irq(&mpc->egress_lock);
- entry = mpc->eg_cache;
- while (entry != NULL) {
- msg->content.eg_info = entry->ctrl_info;
- dprintk("cache_id %u\n", entry->ctrl_info.cache_id);
- msg_to_mpoad(msg, mpc);
- entry = entry->next;
- }
- read_unlock_irq(&mpc->egress_lock);
-
- msg->type = action;
- msg_to_mpoad(msg, mpc);
-}
-
-static unsigned long checking_time;
-
-static void mpc_timer_refresh(void)
-{
- mpc_timer.expires = jiffies + (MPC_P2 * HZ);
- checking_time = mpc_timer.expires;
- add_timer(&mpc_timer);
-}
-
-static void mpc_cache_check(struct timer_list *unused)
-{
- struct mpoa_client *mpc = mpcs;
- static unsigned long previous_resolving_check_time;
- static unsigned long previous_refresh_time;
-
- while (mpc != NULL) {
- mpc->in_ops->clear_count(mpc);
- mpc->eg_ops->clear_expired(mpc);
- if (checking_time - previous_resolving_check_time >
- mpc->parameters.mpc_p4 * HZ) {
- mpc->in_ops->check_resolving(mpc);
- previous_resolving_check_time = checking_time;
- }
- if (checking_time - previous_refresh_time >
- mpc->parameters.mpc_p5 * HZ) {
- mpc->in_ops->refresh(mpc);
- previous_refresh_time = checking_time;
- }
- mpc = mpc->next;
- }
- mpc_timer_refresh();
-}
-
-static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg)
-{
- int err = 0;
- struct atm_vcc *vcc = ATM_SD(sock);
-
- if (cmd != ATMMPC_CTRL && cmd != ATMMPC_DATA)
- return -ENOIOCTLCMD;
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- switch (cmd) {
- case ATMMPC_CTRL:
- err = atm_mpoa_mpoad_attach(vcc, (int)arg);
- if (err >= 0)
- sock->state = SS_CONNECTED;
- break;
- case ATMMPC_DATA:
- err = atm_mpoa_vcc_attach(vcc, (void __user *)arg);
- break;
- default:
- break;
- }
- return err;
-}
-
-static struct atm_ioctl atm_ioctl_ops = {
- .owner = THIS_MODULE,
- .ioctl = atm_mpoa_ioctl,
-};
-
-static __init int atm_mpoa_init(void)
-{
- register_atm_ioctl(&atm_ioctl_ops);
-
- if (mpc_proc_init() != 0)
- pr_info("failed to initialize /proc/mpoa\n");
-
- pr_info("mpc.c: initialized\n");
-
- return 0;
-}
-
-static void __exit atm_mpoa_cleanup(void)
-{
- struct mpoa_client *mpc, *tmp;
- struct atm_mpoa_qos *qos, *nextqos;
- struct lec_priv *priv;
-
- mpc_proc_clean();
-
- timer_delete_sync(&mpc_timer);
- unregister_netdevice_notifier(&mpoa_notifier);
- deregister_atm_ioctl(&atm_ioctl_ops);
-
- mpc = mpcs;
- mpcs = NULL;
- while (mpc != NULL) {
- tmp = mpc->next;
- if (mpc->dev != NULL) {
- stop_mpc(mpc);
- priv = netdev_priv(mpc->dev);
- if (priv->lane2_ops != NULL)
- priv->lane2_ops->associate_indicator = NULL;
- }
- ddprintk("about to clear caches\n");
- mpc->in_ops->destroy_cache(mpc);
- mpc->eg_ops->destroy_cache(mpc);
- ddprintk("caches cleared\n");
- kfree(mpc->mps_macs);
- memset(mpc, 0, sizeof(struct mpoa_client));
- ddprintk("about to kfree %p\n", mpc);
- kfree(mpc);
- ddprintk("next mpc is at %p\n", tmp);
- mpc = tmp;
- }
-
- qos = qos_head;
- qos_head = NULL;
- while (qos != NULL) {
- nextqos = qos->next;
- dprintk("freeing qos entry %p\n", qos);
- kfree(qos);
- qos = nextqos;
- }
-}
-
-module_init(atm_mpoa_init);
-module_exit(atm_mpoa_cleanup);
-
-MODULE_DESCRIPTION("Multi-Protocol Over ATM (MPOA) driver");
-MODULE_LICENSE("GPL");
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
deleted file mode 100644
index c8d4e6f2e831..000000000000
--- a/net/atm/mpoa_caches.c
+++ /dev/null
@@ -1,565 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/types.h>
-#include <linux/atmmpc.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-
-#include "mpoa_caches.h"
-#include "mpc.h"
-
-/*
- * mpoa_caches.c: Implementation of ingress and egress cache
- * handling functions
- */
-
-#if 0
-#define dprintk(format, args...) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */
-#else
-#define dprintk(format, args...) \
- do { if (0) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\
- } while (0)
-#endif
-
-#if 0
-#define ddprintk(format, args...) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */
-#else
-#define ddprintk(format, args...) \
- do { if (0) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\
- } while (0)
-#endif
-
-static in_cache_entry *in_cache_get(__be32 dst_ip,
- struct mpoa_client *client)
-{
- in_cache_entry *entry;
-
- read_lock_bh(&client->ingress_lock);
- entry = client->in_cache;
- while (entry != NULL) {
- if (entry->ctrl_info.in_dst_ip == dst_ip) {
- refcount_inc(&entry->use);
- read_unlock_bh(&client->ingress_lock);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_bh(&client->ingress_lock);
-
- return NULL;
-}
-
-static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip,
- struct mpoa_client *client,
- __be32 mask)
-{
- in_cache_entry *entry;
-
- read_lock_bh(&client->ingress_lock);
- entry = client->in_cache;
- while (entry != NULL) {
- if ((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask)) {
- refcount_inc(&entry->use);
- read_unlock_bh(&client->ingress_lock);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_bh(&client->ingress_lock);
-
- return NULL;
-
-}
-
-static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
- struct mpoa_client *client)
-{
- in_cache_entry *entry;
-
- read_lock_bh(&client->ingress_lock);
- entry = client->in_cache;
- while (entry != NULL) {
- if (entry->shortcut == vcc) {
- refcount_inc(&entry->use);
- read_unlock_bh(&client->ingress_lock);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_bh(&client->ingress_lock);
-
- return NULL;
-}
-
-static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
- struct mpoa_client *client)
-{
- in_cache_entry *entry = kzalloc_obj(in_cache_entry);
-
- if (entry == NULL) {
- pr_info("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
- return NULL;
- }
-
- dprintk("adding an ingress entry, ip = %pI4\n", &dst_ip);
-
- refcount_set(&entry->use, 1);
- dprintk("new_in_cache_entry: about to lock\n");
- write_lock_bh(&client->ingress_lock);
- entry->next = client->in_cache;
- entry->prev = NULL;
- if (client->in_cache != NULL)
- client->in_cache->prev = entry;
- client->in_cache = entry;
-
- memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
- entry->ctrl_info.in_dst_ip = dst_ip;
- entry->time = ktime_get_seconds();
- entry->retry_time = client->parameters.mpc_p4;
- entry->count = 1;
- entry->entry_state = INGRESS_INVALID;
- entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
- refcount_inc(&entry->use);
-
- write_unlock_bh(&client->ingress_lock);
- dprintk("new_in_cache_entry: unlocked\n");
-
- return entry;
-}
-
-static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
-{
- struct atm_mpoa_qos *qos;
- struct k_message msg;
-
- entry->count++;
- if (entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL)
- return OPEN;
-
- if (entry->entry_state == INGRESS_REFRESHING) {
- if (entry->count > mpc->parameters.mpc_p1) {
- msg.type = SND_MPOA_RES_RQST;
- msg.content.in_info = entry->ctrl_info;
- memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL)
- msg.qos = qos->qos;
- msg_to_mpoad(&msg, mpc);
- entry->reply_wait = ktime_get_seconds();
- entry->entry_state = INGRESS_RESOLVING;
- }
- if (entry->shortcut != NULL)
- return OPEN;
- return CLOSED;
- }
-
- if (entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
- return OPEN;
-
- if (entry->count > mpc->parameters.mpc_p1 &&
- entry->entry_state == INGRESS_INVALID) {
- dprintk("(%s) threshold exceeded for ip %pI4, sending MPOA res req\n",
- mpc->dev->name, &entry->ctrl_info.in_dst_ip);
- entry->entry_state = INGRESS_RESOLVING;
- msg.type = SND_MPOA_RES_RQST;
- memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
- msg.content.in_info = entry->ctrl_info;
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL)
- msg.qos = qos->qos;
- msg_to_mpoad(&msg, mpc);
- entry->reply_wait = ktime_get_seconds();
- }
-
- return CLOSED;
-}
-
-static void in_cache_put(in_cache_entry *entry)
-{
- if (refcount_dec_and_test(&entry->use)) {
- kfree_sensitive(entry);
- }
-}
-
-/*
- * This should be called with write lock on
- */
-static void in_cache_remove_entry(in_cache_entry *entry,
- struct mpoa_client *client)
-{
- struct atm_vcc *vcc;
- struct k_message msg;
-
- vcc = entry->shortcut;
- dprintk("removing an ingress entry, ip = %pI4\n",
- &entry->ctrl_info.in_dst_ip);
-
- if (entry->prev != NULL)
- entry->prev->next = entry->next;
- else
- client->in_cache = entry->next;
- if (entry->next != NULL)
- entry->next->prev = entry->prev;
- client->in_ops->put(entry);
- if (client->in_cache == NULL && client->eg_cache == NULL) {
- msg.type = STOP_KEEP_ALIVE_SM;
- msg_to_mpoad(&msg, client);
- }
-
- /* Check if the egress side still uses this VCC */
- if (vcc != NULL) {
- eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc,
- client);
- if (eg_entry != NULL) {
- client->eg_ops->put(eg_entry);
- return;
- }
- vcc_release_async(vcc, -EPIPE);
- }
-}
-
-/* Call this every MPC-p2 seconds... Not exactly correct solution,
- but an easy one... */
-static void clear_count_and_expired(struct mpoa_client *client)
-{
- in_cache_entry *entry, *next_entry;
- time64_t now;
-
- now = ktime_get_seconds();
-
- write_lock_bh(&client->ingress_lock);
- entry = client->in_cache;
- while (entry != NULL) {
- entry->count = 0;
- next_entry = entry->next;
- if ((now - entry->time) > entry->ctrl_info.holding_time) {
- dprintk("holding time expired, ip = %pI4\n",
- &entry->ctrl_info.in_dst_ip);
- client->in_ops->remove_entry(entry, client);
- }
- entry = next_entry;
- }
- write_unlock_bh(&client->ingress_lock);
-}
-
-/* Call this every MPC-p4 seconds. */
-static void check_resolving_entries(struct mpoa_client *client)
-{
-
- struct atm_mpoa_qos *qos;
- in_cache_entry *entry;
- time64_t now;
- struct k_message msg;
-
- now = ktime_get_seconds();
-
- read_lock_bh(&client->ingress_lock);
- entry = client->in_cache;
- while (entry != NULL) {
- if (entry->entry_state == INGRESS_RESOLVING) {
-
- if ((now - entry->hold_down)
- < client->parameters.mpc_p6) {
- entry = entry->next; /* Entry in hold down */
- continue;
- }
- if ((now - entry->reply_wait) > entry->retry_time) {
- entry->retry_time = MPC_C1 * (entry->retry_time);
- /*
- * Retry time maximum exceeded,
- * put entry in hold down.
- */
- if (entry->retry_time > client->parameters.mpc_p5) {
- entry->hold_down = ktime_get_seconds();
- entry->retry_time = client->parameters.mpc_p4;
- entry = entry->next;
- continue;
- }
- /* Ask daemon to send a resolution request. */
- memset(&entry->hold_down, 0, sizeof(time64_t));
- msg.type = SND_MPOA_RES_RTRY;
- memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
- msg.content.in_info = entry->ctrl_info;
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL)
- msg.qos = qos->qos;
- msg_to_mpoad(&msg, client);
- entry->reply_wait = ktime_get_seconds();
- }
- }
- entry = entry->next;
- }
- read_unlock_bh(&client->ingress_lock);
-}
-
-/* Call this every MPC-p5 seconds. */
-static void refresh_entries(struct mpoa_client *client)
-{
- time64_t now;
- struct in_cache_entry *entry = client->in_cache;
-
- ddprintk("refresh_entries\n");
- now = ktime_get_seconds();
-
- read_lock_bh(&client->ingress_lock);
- while (entry != NULL) {
- if (entry->entry_state == INGRESS_RESOLVED) {
- if (!(entry->refresh_time))
- entry->refresh_time = (2 * (entry->ctrl_info.holding_time))/3;
- if ((now - entry->reply_wait) >
- entry->refresh_time) {
- dprintk("refreshing an entry.\n");
- entry->entry_state = INGRESS_REFRESHING;
-
- }
- }
- entry = entry->next;
- }
- read_unlock_bh(&client->ingress_lock);
-}
-
-static void in_destroy_cache(struct mpoa_client *mpc)
-{
- write_lock_irq(&mpc->ingress_lock);
- while (mpc->in_cache != NULL)
- mpc->in_ops->remove_entry(mpc->in_cache, mpc);
- write_unlock_irq(&mpc->ingress_lock);
-}
-
-static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id,
- struct mpoa_client *mpc)
-{
- eg_cache_entry *entry;
-
- read_lock_irq(&mpc->egress_lock);
- entry = mpc->eg_cache;
- while (entry != NULL) {
- if (entry->ctrl_info.cache_id == cache_id) {
- refcount_inc(&entry->use);
- read_unlock_irq(&mpc->egress_lock);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irq(&mpc->egress_lock);
-
- return NULL;
-}
-
-/* This can be called from any context since it saves CPU flags */
-static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc)
-{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&mpc->egress_lock, flags);
- entry = mpc->eg_cache;
- while (entry != NULL) {
- if (entry->ctrl_info.tag == tag) {
- refcount_inc(&entry->use);
- read_unlock_irqrestore(&mpc->egress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&mpc->egress_lock, flags);
-
- return NULL;
-}
-
-/* This can be called from any context since it saves CPU flags */
-static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc,
- struct mpoa_client *mpc)
-{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&mpc->egress_lock, flags);
- entry = mpc->eg_cache;
- while (entry != NULL) {
- if (entry->shortcut == vcc) {
- refcount_inc(&entry->use);
- read_unlock_irqrestore(&mpc->egress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&mpc->egress_lock, flags);
-
- return NULL;
-}
-
-static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr,
- struct mpoa_client *mpc)
-{
- eg_cache_entry *entry;
-
- read_lock_irq(&mpc->egress_lock);
- entry = mpc->eg_cache;
- while (entry != NULL) {
- if (entry->latest_ip_addr == ipaddr) {
- refcount_inc(&entry->use);
- read_unlock_irq(&mpc->egress_lock);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irq(&mpc->egress_lock);
-
- return NULL;
-}
-
-static void eg_cache_put(eg_cache_entry *entry)
-{
- if (refcount_dec_and_test(&entry->use)) {
- kfree_sensitive(entry);
- }
-}
-
-/*
- * This should be called with write lock on
- */
-static void eg_cache_remove_entry(eg_cache_entry *entry,
- struct mpoa_client *client)
-{
- struct atm_vcc *vcc;
- struct k_message msg;
-
- vcc = entry->shortcut;
- dprintk("removing an egress entry.\n");
- if (entry->prev != NULL)
- entry->prev->next = entry->next;
- else
- client->eg_cache = entry->next;
- if (entry->next != NULL)
- entry->next->prev = entry->prev;
- client->eg_ops->put(entry);
- if (client->in_cache == NULL && client->eg_cache == NULL) {
- msg.type = STOP_KEEP_ALIVE_SM;
- msg_to_mpoad(&msg, client);
- }
-
- /* Check if the ingress side still uses this VCC */
- if (vcc != NULL) {
- in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
- if (in_entry != NULL) {
- client->in_ops->put(in_entry);
- return;
- }
- vcc_release_async(vcc, -EPIPE);
- }
-}
-
-static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
- struct mpoa_client *client)
-{
- eg_cache_entry *entry = kzalloc_obj(eg_cache_entry);
-
- if (entry == NULL) {
- pr_info("out of memory\n");
- return NULL;
- }
-
- dprintk("adding an egress entry, ip = %pI4, this should be our IP\n",
- &msg->content.eg_info.eg_dst_ip);
-
- refcount_set(&entry->use, 1);
- dprintk("new_eg_cache_entry: about to lock\n");
- write_lock_irq(&client->egress_lock);
- entry->next = client->eg_cache;
- entry->prev = NULL;
- if (client->eg_cache != NULL)
- client->eg_cache->prev = entry;
- client->eg_cache = entry;
-
- memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
- entry->ctrl_info = msg->content.eg_info;
- entry->time = ktime_get_seconds();
- entry->entry_state = EGRESS_RESOLVED;
- dprintk("new_eg_cache_entry cache_id %u\n",
- ntohl(entry->ctrl_info.cache_id));
- dprintk("mps_ip = %pI4\n", &entry->ctrl_info.mps_ip);
- refcount_inc(&entry->use);
-
- write_unlock_irq(&client->egress_lock);
- dprintk("new_eg_cache_entry: unlocked\n");
-
- return entry;
-}
-
-static void update_eg_cache_entry(eg_cache_entry *entry, uint16_t holding_time)
-{
- entry->time = ktime_get_seconds();
- entry->entry_state = EGRESS_RESOLVED;
- entry->ctrl_info.holding_time = holding_time;
-}
-
-static void clear_expired(struct mpoa_client *client)
-{
- eg_cache_entry *entry, *next_entry;
- time64_t now;
- struct k_message msg;
-
- now = ktime_get_seconds();
-
- write_lock_irq(&client->egress_lock);
- entry = client->eg_cache;
- while (entry != NULL) {
- next_entry = entry->next;
- if ((now - entry->time) > entry->ctrl_info.holding_time) {
- msg.type = SND_EGRESS_PURGE;
- msg.content.eg_info = entry->ctrl_info;
- dprintk("egress_cache: holding time expired, cache_id = %u.\n",
- ntohl(entry->ctrl_info.cache_id));
- msg_to_mpoad(&msg, client);
- client->eg_ops->remove_entry(entry, client);
- }
- entry = next_entry;
- }
- write_unlock_irq(&client->egress_lock);
-}
-
-static void eg_destroy_cache(struct mpoa_client *mpc)
-{
- write_lock_irq(&mpc->egress_lock);
- while (mpc->eg_cache != NULL)
- mpc->eg_ops->remove_entry(mpc->eg_cache, mpc);
- write_unlock_irq(&mpc->egress_lock);
-}
-
-
-static const struct in_cache_ops ingress_ops = {
- .add_entry = in_cache_add_entry,
- .get = in_cache_get,
- .get_with_mask = in_cache_get_with_mask,
- .get_by_vcc = in_cache_get_by_vcc,
- .put = in_cache_put,
- .remove_entry = in_cache_remove_entry,
- .cache_hit = cache_hit,
- .clear_count = clear_count_and_expired,
- .check_resolving = check_resolving_entries,
- .refresh = refresh_entries,
- .destroy_cache = in_destroy_cache
-};
-
-static const struct eg_cache_ops egress_ops = {
- .add_entry = eg_cache_add_entry,
- .get_by_cache_id = eg_cache_get_by_cache_id,
- .get_by_tag = eg_cache_get_by_tag,
- .get_by_vcc = eg_cache_get_by_vcc,
- .get_by_src_ip = eg_cache_get_by_src_ip,
- .put = eg_cache_put,
- .remove_entry = eg_cache_remove_entry,
- .update = update_eg_cache_entry,
- .clear_expired = clear_expired,
- .destroy_cache = eg_destroy_cache
-};
-
-void atm_mpoa_init_cache(struct mpoa_client *mpc)
-{
- mpc->in_ops = &ingress_ops;
- mpc->eg_ops = &egress_ops;
-}
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
deleted file mode 100644
index aaf64b953915..000000000000
--- a/net/atm/mpoa_proc.c
+++ /dev/null
@@ -1,307 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#ifdef CONFIG_PROC_FS
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/ktime.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/atmmpc.h>
-#include <linux/atm.h>
-#include <linux/gfp.h>
-#include "mpc.h"
-#include "mpoa_caches.h"
-
-/*
- * mpoa_proc.c: Implementation MPOA client's proc
- * file system statistics
- */
-
-#if 1
-#define dprintk(format, args...) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */
-#else
-#define dprintk(format, args...) \
- do { if (0) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\
- } while (0)
-#endif
-
-#if 0
-#define ddprintk(format, args...) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */
-#else
-#define ddprintk(format, args...) \
- do { if (0) \
- printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\
- } while (0)
-#endif
-
-#define STAT_FILE_NAME "mpc" /* Our statistic file's name */
-
-extern struct mpoa_client *mpcs;
-extern struct proc_dir_entry *atm_proc_root; /* from proc.c. */
-
-static int proc_mpc_open(struct inode *inode, struct file *file);
-static ssize_t proc_mpc_write(struct file *file, const char __user *buff,
- size_t nbytes, loff_t *ppos);
-
-static int parse_qos(const char *buff);
-
-static const struct proc_ops mpc_proc_ops = {
- .proc_open = proc_mpc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_write = proc_mpc_write,
- .proc_release = seq_release,
-};
-
-/*
- * Returns the state of an ingress cache entry as a string
- */
-static const char *ingress_state_string(int state)
-{
- switch (state) {
- case INGRESS_RESOLVING:
- return "resolving ";
- case INGRESS_RESOLVED:
- return "resolved ";
- case INGRESS_INVALID:
- return "invalid ";
- case INGRESS_REFRESHING:
- return "refreshing ";
- }
-
- return "";
-}
-
-/*
- * Returns the state of an egress cache entry as a string
- */
-static const char *egress_state_string(int state)
-{
- switch (state) {
- case EGRESS_RESOLVED:
- return "resolved ";
- case EGRESS_PURGE:
- return "purge ";
- case EGRESS_INVALID:
- return "invalid ";
- }
-
- return "";
-}
-
-/*
- * FIXME: mpcs (and per-mpc lists) have no locking whatsoever.
- */
-
-static void *mpc_start(struct seq_file *m, loff_t *pos)
-{
- loff_t l = *pos;
- struct mpoa_client *mpc;
-
- if (!l--)
- return SEQ_START_TOKEN;
- for (mpc = mpcs; mpc; mpc = mpc->next)
- if (!l--)
- return mpc;
- return NULL;
-}
-
-static void *mpc_next(struct seq_file *m, void *v, loff_t *pos)
-{
- struct mpoa_client *p = v;
- (*pos)++;
- return v == SEQ_START_TOKEN ? mpcs : p->next;
-}
-
-static void mpc_stop(struct seq_file *m, void *v)
-{
-}
-
-/*
- * READING function - called when the /proc/atm/mpoa file is read from.
- */
-static int mpc_show(struct seq_file *m, void *v)
-{
- struct mpoa_client *mpc = v;
- int i;
- in_cache_entry *in_entry;
- eg_cache_entry *eg_entry;
- time64_t now;
- unsigned char ip_string[16];
-
- if (v == SEQ_START_TOKEN) {
- atm_mpoa_disp_qos(m);
- return 0;
- }
-
- seq_printf(m, "\nInterface %d:\n\n", mpc->dev_num);
- seq_printf(m, "Ingress Entries:\nIP address State Holding time Packets fwded VPI VCI\n");
- now = ktime_get_seconds();
-
- for (in_entry = mpc->in_cache; in_entry; in_entry = in_entry->next) {
- unsigned long seconds_delta = now - in_entry->time;
-
- sprintf(ip_string, "%pI4", &in_entry->ctrl_info.in_dst_ip);
- seq_printf(m, "%-16s%s%-14lu%-12u",
- ip_string,
- ingress_state_string(in_entry->entry_state),
- in_entry->ctrl_info.holding_time -
- seconds_delta,
- in_entry->packets_fwded);
- if (in_entry->shortcut)
- seq_printf(m, " %-3d %-3d",
- in_entry->shortcut->vpi,
- in_entry->shortcut->vci);
- seq_printf(m, "\n");
- }
-
- seq_printf(m, "\n");
- seq_printf(m, "Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n");
- for (eg_entry = mpc->eg_cache; eg_entry; eg_entry = eg_entry->next) {
- unsigned char *p = eg_entry->ctrl_info.in_MPC_data_ATM_addr;
- unsigned long seconds_delta = now - eg_entry->time;
-
- for (i = 0; i < ATM_ESA_LEN; i++)
- seq_printf(m, "%02x", p[i]);
- seq_printf(m, "\n%-16lu%s%-14lu%-15u",
- (unsigned long)ntohl(eg_entry->ctrl_info.cache_id),
- egress_state_string(eg_entry->entry_state),
- (eg_entry->ctrl_info.holding_time - seconds_delta),
- eg_entry->packets_rcvd);
-
- /* latest IP address */
- sprintf(ip_string, "%pI4", &eg_entry->latest_ip_addr);
- seq_printf(m, "%-16s", ip_string);
-
- if (eg_entry->shortcut)
- seq_printf(m, " %-3d %-3d",
- eg_entry->shortcut->vpi,
- eg_entry->shortcut->vci);
- seq_printf(m, "\n");
- }
- seq_printf(m, "\n");
- return 0;
-}
-
-static const struct seq_operations mpc_op = {
- .start = mpc_start,
- .next = mpc_next,
- .stop = mpc_stop,
- .show = mpc_show
-};
-
-static int proc_mpc_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &mpc_op);
-}
-
-static ssize_t proc_mpc_write(struct file *file, const char __user *buff,
- size_t nbytes, loff_t *ppos)
-{
- char *page, *p;
- unsigned int len;
-
- if (nbytes == 0)
- return 0;
-
- if (nbytes >= PAGE_SIZE)
- nbytes = PAGE_SIZE-1;
-
- page = (char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- for (p = page, len = 0; len < nbytes; p++) {
- if (get_user(*p, buff++)) {
- free_page((unsigned long)page);
- return -EFAULT;
- }
- len += 1;
- if (*p == '\0' || *p == '\n')
- break;
- }
-
- *p = '\0';
-
- if (!parse_qos(page))
- printk("mpoa: proc_mpc_write: could not parse '%s'\n", page);
-
- free_page((unsigned long)page);
-
- return len;
-}
-
-static int parse_qos(const char *buff)
-{
- /* possible lines look like this
- * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu
- */
- unsigned char ip[4];
- int tx_pcr, tx_sdu, rx_pcr, rx_sdu;
- __be32 ipaddr;
- struct atm_qos qos;
-
- memset(&qos, 0, sizeof(struct atm_qos));
-
- if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu",
- ip, ip+1, ip+2, ip+3) == 4) {
- ipaddr = *(__be32 *)ip;
- return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr));
- }
-
- if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=tx",
- ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu) == 6) {
- rx_pcr = tx_pcr;
- rx_sdu = tx_sdu;
- } else if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=%d,%d",
- ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8)
- return 0;
-
- ipaddr = *(__be32 *)ip;
- qos.txtp.traffic_class = ATM_CBR;
- qos.txtp.max_pcr = tx_pcr;
- qos.txtp.max_sdu = tx_sdu;
- qos.rxtp.traffic_class = ATM_CBR;
- qos.rxtp.max_pcr = rx_pcr;
- qos.rxtp.max_sdu = rx_sdu;
- qos.aal = ATM_AAL5;
- dprintk("parse_qos(): setting qos parameters to tx=%d,%d rx=%d,%d\n",
- qos.txtp.max_pcr, qos.txtp.max_sdu,
- qos.rxtp.max_pcr, qos.rxtp.max_sdu);
-
- atm_mpoa_add_qos(ipaddr, &qos);
- return 1;
-}
-
-/*
- * INITIALIZATION function - called when module is initialized/loaded.
- */
-int mpc_proc_init(void)
-{
- struct proc_dir_entry *p;
-
- p = proc_create(STAT_FILE_NAME, 0, atm_proc_root, &mpc_proc_ops);
- if (!p) {
- pr_err("Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
- return -ENOMEM;
- }
- return 0;
-}
-
-/*
- * DELETING function - called when module is removed.
- */
-void mpc_proc_clean(void)
-{
- remove_proc_entry(STAT_FILE_NAME, atm_proc_root);
-}
-
-#endif /* CONFIG_PROC_FS */
diff --git a/net/bridge/br.c b/net/bridge/br.c
index c37e52e2f29a..a5e5b2db110e 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -464,10 +464,6 @@ static int __init br_init(void)
brioctl_set(br_ioctl_stub);
-#if IS_ENABLED(CONFIG_ATM_LANE)
- br_fdb_test_addr_hook = br_fdb_test_addr;
-#endif
-
#if IS_MODULE(CONFIG_BRIDGE_NETFILTER)
pr_info("bridge: filtering via arp/ip/ip6tables is no longer available "
"by default. Update your scripts to load br_netfilter if you "
@@ -506,9 +502,6 @@ static void __exit br_deinit(void)
rcu_barrier(); /* Wait for completion of call_rcu()'s */
br_nf_core_fini();
-#if IS_ENABLED(CONFIG_ATM_LANE)
- br_fdb_test_addr_hook = NULL;
-#endif
br_fdb_fini();
}
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index e2c17f620f00..9bcf6243914b 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -892,35 +892,6 @@ void br_fdb_delete_by_port(struct net_bridge *br,
spin_unlock_bh(&br->hash_lock);
}
-#if IS_ENABLED(CONFIG_ATM_LANE)
-/* Interface used by ATM LANE hook to test
- * if an addr is on some other bridge port */
-int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
-{
- struct net_bridge_fdb_entry *fdb;
- struct net_bridge_port *port;
- int ret;
-
- rcu_read_lock();
- port = br_port_get_rcu(dev);
- if (!port)
- ret = 0;
- else {
- const struct net_bridge_port *dst = NULL;
-
- fdb = br_fdb_find_rcu(port->br, addr, 0);
- if (fdb)
- dst = READ_ONCE(fdb->dst);
-
- ret = dst && dst->dev != dev &&
- dst->state == BR_STATE_FORWARDING;
- }
- rcu_read_unlock();
-
- return ret;
-}
-#endif /* CONFIG_ATM_LANE */
-
/*
* Fill buffer with forwarding table records in
* the API format.
diff --git a/net/core/dev.c b/net/core/dev.c
index e59f6025067c..1be81928d6c7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5862,13 +5862,6 @@ static __latent_entropy void net_tx_action(void)
xfrm_dev_backlog(sd);
}
-#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_ATM_LANE)
-/* This hook is defined here for ATM LANE */
-int (*br_fdb_test_addr_hook)(struct net_device *dev,
- unsigned char *addr) __read_mostly;
-EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook);
-#endif
-
/**
* netdev_is_rx_handler_busy - check if receive handler is registered
* @dev: device to check
diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index 81199dddcde7..950b48c3b111 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -52,10 +52,6 @@ CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_ATALK=m
@@ -108,7 +104,6 @@ CONFIG_ATA=y
CONFIG_PATA_IXP4XX_CF=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
-CONFIG_ATM_TCP=m
CONFIG_IXP4XX_ETH=y
CONFIG_WAN=y
CONFIG_HDLC=y
diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig
index 261730af75c7..ad80ad2eae6b 100644
--- a/arch/mips/configs/gpr_defconfig
+++ b/arch/mips/configs/gpr_defconfig
@@ -87,10 +87,6 @@ CONFIG_BRIDGE_EBT_LOG=m
CONFIG_IP_SCTP=m
CONFIG_TIPC=m
CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_LLC2=m
@@ -156,15 +152,6 @@ CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_NETDEVICES=y
CONFIG_NET_FC=y
CONFIG_NETCONSOLE=m
-CONFIG_ATM_TCP=m
-CONFIG_ATM_LANAI=m
-CONFIG_ATM_ENI=m
-CONFIG_ATM_NICSTAR=m
-CONFIG_ATM_IDT77252=m
-CONFIG_ATM_IA=m
-CONFIG_ATM_FORE200E=m
-CONFIG_ATM_HE=m
-CONFIG_ATM_HE_USE_SUNI=y
CONFIG_MIPS_AU1X00_ENET=y
CONFIG_CICADA_PHY=m
CONFIG_DAVICOM_PHY=m
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 315650c6fe0b..1295164af08e 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -133,10 +133,6 @@ CONFIG_BRIDGE_EBT_LOG=m
CONFIG_IP_SCTP=m
CONFIG_TIPC=m
CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_LLC2=m
@@ -232,15 +228,6 @@ CONFIG_ARCNET_RIM_I=m
CONFIG_ARCNET_COM20020=m
CONFIG_ARCNET_COM20020_PCI=m
CONFIG_ARCNET_COM20020_CS=m
-CONFIG_ATM_TCP=m
-CONFIG_ATM_LANAI=m
-CONFIG_ATM_ENI=m
-CONFIG_ATM_NICSTAR=m
-CONFIG_ATM_IDT77252=m
-CONFIG_ATM_IA=m
-CONFIG_ATM_FORE200E=m
-CONFIG_ATM_HE=m
-CONFIG_ATM_HE_USE_SUNI=y
CONFIG_PCMCIA_3C574=m
CONFIG_PCMCIA_3C589=m
CONFIG_VORTEX=m
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 6f40a275b7a9..02cc17e353a3 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -227,9 +227,6 @@ CONFIG_BRIDGE_EBT_LOG=m
CONFIG_BRIDGE_EBT_NFLOG=m
CONFIG_TIPC=m
CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-CONFIG_ATM_LANE=m
-CONFIG_ATM_BR2684=m
CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_ATALK=m
@@ -398,12 +395,6 @@ CONFIG_NETCONSOLE=m
CONFIG_TUN=m
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
-CONFIG_ATM_TCP=m
-CONFIG_ATM_LANAI=m
-CONFIG_ATM_ENI=m
-CONFIG_ATM_NICSTAR=m
-CONFIG_ATM_IDT77252=m
-CONFIG_ATM_HE=m
CONFIG_EL3=m
CONFIG_PCMCIA_3C574=m
CONFIG_PCMCIA_3C589=m
diff --git a/drivers/atm/.gitignore b/drivers/atm/.gitignore
deleted file mode 100644
index ddd374e91965..000000000000
--- a/drivers/atm/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-fore200e_mkfirm
-fore200e_pca_fw.c
-pca200e.bin
-pca200e_ecd.bin2
diff --git a/drivers/atm/nicstarmac.copyright b/drivers/atm/nicstarmac.copyright
deleted file mode 100644
index 180531a83c62..000000000000
--- a/drivers/atm/nicstarmac.copyright
+++ /dev/null
@@ -1,61 +0,0 @@
-/* nicstar.c v0.22 Jawaid Bazyar (bazyar@hypermall.com)
- * nicstar.c, M. Welsh (matt.welsh@cl.cam.ac.uk)
- *
- * Hacked October, 1997 by Jawaid Bazyar, Interlink Advertising Services Inc.
- * http://www.hypermall.com/
- * 10/1/97 - commented out CFG_PHYIE bit - we don't care when the PHY
- * interrupts us (except possibly for removal/insertion of the cable?)
- * 10/4/97 - began heavy inline documentation of the code. Corrected typos
- * and spelling mistakes.
- * 10/5/97 - added code to handle PHY interrupts, disable PHY on
- * loss of link, and correctly re-enable PHY when link is
- * re-established. (put back CFG_PHYIE)
- *
- * Modified to work with the IDT7721 nicstar -- AAL5 (tested) only.
- *
- * R. D. Rechenmacher <ron@fnal.gov>, Aug. 6, 1997
- *
- * Linux driver for the IDT77201 NICStAR PCI ATM controller.
- * PHY component is expected to be 155 Mbps S/UNI-Lite or IDT 77155;
- * see init_nicstar() for PHY initialization to change this. This driver
- * expects the Linux ATM stack to support scatter-gather lists
- * (skb->atm.iovcnt != 0) for Rx skb's passed to vcc->push.
- *
- * Implementing minimal-copy of received data:
- * IDT always receives data into a small buffer, then large buffers
- * as needed. This means that data must always be copied to create
- * the linear buffer needed by most non-ATM protocol stacks (e.g. IP)
- * Fix is simple: make large buffers large enough to hold entire
- * SDU, and leave <small_buffer_data> bytes empty at the start. Then
- * copy small buffer contents to head of large buffer.
- * Trick is to avoid fragmenting Linux, due to need for a lot of large
- * buffers. This is done by 2 things:
- * 1) skb->destructor / skb->atm.recycle_buffer
- * combined, allow nicstar_free_rx_skb to be called to
- * recycle large data buffers
- * 2) skb_clone of received buffers
- * See nicstar_free_rx_skb and linearize_buffer for implementation
- * details.
- *
- *
- *
- * Copyright (c) 1996 University of Cambridge Computer Laboratory
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * M. Welsh, 6 July 1996
- *
- *
- */
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net-deletions] net: remove unused ATM protocols and legacy ATM device drivers
2026-04-21 2:19 [PATCH net-deletions] net: remove unused ATM protocols and legacy ATM device drivers Jakub Kicinski
@ 2026-04-21 9:26 ` David Woodhouse
2026-04-21 11:49 ` Herbert Xu
0 siblings, 1 reply; 5+ messages in thread
From: David Woodhouse @ 2026-04-21 9:26 UTC (permalink / raw)
To: Jakub Kicinski, davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, corbet, skhan,
linux, tsbogend, maddy, mpe, npiggin, chleroy, 3chas3, razor,
idosch, jani.nikula, mchehab+huawei, tytso, herbert, geert,
ebiggers, johannes.berg, jonathan.cameron, kees, kuniyu,
fourier.thomas, andriy.shevchenko, rdunlap, akpm, linux-doc,
linux-mips, linuxppc-dev, bridge
[-- Attachment #1: Type: text/plain, Size: 1842 bytes --]
On Mon, 2026-04-20 at 19:19 -0700, Jakub Kicinski wrote:
> Remove the ATM protocol modules and PCI/SBUS ATM device drivers
> that are no longer in active use.
>
> The ATM core protocol stack, PPPoATM, and USB DSL modem drivers
> (drivers/usb/atm/) are retained in-tree to maintain PPP over ATM
> (PPPoA) support for DSL connections.
>
> Removed ATM protocol modules:
> - net/atm/clip.c - Classical IP over ATM (RFC 2225)
> - net/atm/br2684.c - RFC 2684 bridged protocols
I believe PPPoE over BR2684 is also used on ADSL lines.
https://git.kernel.org/torvalds/c/ae088d663bee strongly seems to imply
that I used to use it myself, or at least was *able* to switch to it
for testing (although I could have sworn I mostly used PPPoA).
> - net/atm/lec.c - LAN Emulation Client (LANE)
> - net/atm/mpc.c, mpoa_caches.c, mpoa_proc.c - Multi-Protocol Over ATM
>
> Removed PCI/SBUS ATM device drivers (drivers/atm/):
> - adummy, atmtcp - software/testing ATM devices
> - eni - Efficient Networks ENI155P (OC-3, ~1995)
> - fore200e - FORE Systems 200E PCI/SBUS (OC-3, ~1999)
> - he - ForeRunner HE (OC-3/OC-12, ~2000)
> - idt77105 - IDT 77105 25 Mbps ATM PHY
> - idt77252 - IDT 77252 NICStAR II (OC-3, ~2000)
> - iphase - Interphase ATM PCI (OC-3/DS3/E3)
> - lanai - Efficient Networks Speedstream 3010
> - nicstar - IDT 77201 NICStAR (155/25 Mbps, ~1999)
> - solos-pci - Traverse Technologies ADSL2+ PCI (defunct vendor)
Traverse still exists: https://traverse.com.au/
I suspect they don't have a huge amount of interest in the Solos any
more, or the Geode-based SBC they sold with two of them on-board. But
OpenWrt does still support them, and I even have one here (although no
ADSL line to test it with). They were briefly popular as fully Linux-
supported ADSL routers.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-deletions] net: remove unused ATM protocols and legacy ATM device drivers
2026-04-21 9:26 ` David Woodhouse
@ 2026-04-21 11:49 ` Herbert Xu
2026-04-21 11:57 ` Geert Uytterhoeven
0 siblings, 1 reply; 5+ messages in thread
From: Herbert Xu @ 2026-04-21 11:49 UTC (permalink / raw)
To: David Woodhouse
Cc: Jakub Kicinski, davem, netdev, edumazet, pabeni, andrew+netdev,
horms, corbet, skhan, linux, tsbogend, maddy, mpe, npiggin,
chleroy, 3chas3, razor, idosch, jani.nikula, mchehab+huawei,
tytso, geert, ebiggers, johannes.berg, jonathan.cameron, kees,
kuniyu, fourier.thomas, andriy.shevchenko, rdunlap, akpm,
linux-doc, linux-mips, linuxppc-dev, bridge
On Tue, Apr 21, 2026 at 10:26:18AM +0100, David Woodhouse wrote:
>
> I suspect they don't have a huge amount of interest in the Solos any
> more, or the Geode-based SBC they sold with two of them on-board. But
> OpenWrt does still support them, and I even have one here (although no
> ADSL line to test it with). They were briefly popular as fully Linux-
> supported ADSL routers.
ADSL is history, it only ever made sense in rich countries where
physical copper cables were pre-installed in homes. While rich
countries have moved to fibre, the rest of the world won't use
ADSL either because there is no copper cable to begin with. So
it's actually cheaper to just lay a fibre cable for a new install.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-deletions] net: remove unused ATM protocols and legacy ATM device drivers
2026-04-21 11:49 ` Herbert Xu
@ 2026-04-21 11:57 ` Geert Uytterhoeven
2026-04-21 12:06 ` David Woodhouse
0 siblings, 1 reply; 5+ messages in thread
From: Geert Uytterhoeven @ 2026-04-21 11:57 UTC (permalink / raw)
To: Herbert Xu
Cc: David Woodhouse, Jakub Kicinski, davem, netdev, edumazet, pabeni,
andrew+netdev, horms, corbet, skhan, linux, tsbogend, maddy, mpe,
npiggin, chleroy, 3chas3, razor, idosch, jani.nikula,
mchehab+huawei, tytso, ebiggers, johannes.berg, jonathan.cameron,
kees, kuniyu, fourier.thomas, andriy.shevchenko, rdunlap, akpm,
linux-doc, linux-mips, linuxppc-dev, bridge
Hi Herbert,
On Tue, 21 Apr 2026 at 13:51, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Apr 21, 2026 at 10:26:18AM +0100, David Woodhouse wrote:
> > I suspect they don't have a huge amount of interest in the Solos any
> > more, or the Geode-based SBC they sold with two of them on-board. But
> > OpenWrt does still support them, and I even have one here (although no
> > ADSL line to test it with). They were briefly popular as fully Linux-
> > supported ADSL routers.
>
> ADSL is history, it only ever made sense in rich countries where
> physical copper cables were pre-installed in homes. While rich
> countries have moved to fibre, the rest of the world won't use
> ADSL either because there is no copper cable to begin with. So
> it's actually cheaper to just lay a fibre cable for a new install.
I am afraid the move to fibre hasn't been completed yet.
ADSL (VDSL2?) is still being used.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-deletions] net: remove unused ATM protocols and legacy ATM device drivers
2026-04-21 11:57 ` Geert Uytterhoeven
@ 2026-04-21 12:06 ` David Woodhouse
0 siblings, 0 replies; 5+ messages in thread
From: David Woodhouse @ 2026-04-21 12:06 UTC (permalink / raw)
To: Geert Uytterhoeven, Herbert Xu
Cc: Jakub Kicinski, davem, netdev, edumazet, pabeni, andrew+netdev,
horms, corbet, skhan, linux, tsbogend, maddy, mpe, npiggin,
chleroy, 3chas3, razor, idosch, jani.nikula, mchehab+huawei,
tytso, ebiggers, johannes.berg, jonathan.cameron, kees, kuniyu,
fourier.thomas, andriy.shevchenko, rdunlap, akpm, linux-doc,
linux-mips, linuxppc-dev, bridge
[-- Attachment #1: Type: text/plain, Size: 1154 bytes --]
On Tue, 2026-04-21 at 13:57 +0200, Geert Uytterhoeven wrote:
> Hi Herbert,
>
> On Tue, 21 Apr 2026 at 13:51, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> > On Tue, Apr 21, 2026 at 10:26:18AM +0100, David Woodhouse wrote:
> > > I suspect they don't have a huge amount of interest in the Solos any
> > > more, or the Geode-based SBC they sold with two of them on-board. But
> > > OpenWrt does still support them, and I even have one here (although no
> > > ADSL line to test it with). They were briefly popular as fully Linux-
> > > supported ADSL routers.
> >
> > ADSL is history, it only ever made sense in rich countries where
> > physical copper cables were pre-installed in homes. While rich
> > countries have moved to fibre, the rest of the world won't use
> > ADSL either because there is no copper cable to begin with. So
> > it's actually cheaper to just lay a fibre cable for a new install.
>
> I am afraid the move to fibre hasn't been completed yet.
> ADSL (VDSL2?) is still being used.
VSDL is different, and isn't ATM-based. But even ADSL is still in use;
in the UK some rural areas haven't got fibre yet.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-21 12:07 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-21 2:19 [PATCH net-deletions] net: remove unused ATM protocols and legacy ATM device drivers Jakub Kicinski
2026-04-21 9:26 ` David Woodhouse
2026-04-21 11:49 ` Herbert Xu
2026-04-21 11:57 ` Geert Uytterhoeven
2026-04-21 12:06 ` David Woodhouse
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox