11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok Intel PRO/100 Linux driver 40abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok Copyright(c) 1999 - 2006 Intel Corporation. 50547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 60547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg This program is free software; you can redistribute it and/or modify it 70abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok under the terms and conditions of the GNU General Public License, 80abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok version 2, as published by the Free Software Foundation. 90547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 100abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok This program is distributed in the hope it will be useful, but WITHOUT 110547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 120547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds more details. 140547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License along with 160abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok this program; if not, write to the Free Software Foundation, Inc., 170abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 180547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 190abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok The full GNU General Public License is included in this distribution in 200abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok the file called "COPYING". 210547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Contact Information: 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Linux NICS <linux.nics@intel.com> 240abb6eb12806cf99ea815810d470423083c3b9f4Auke Kok e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*******************************************************************************/ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * e100.c: Intel(R) PRO/100 ethernet driver 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (Re)written 2003 by scott.feldman@intel.com. Based loosely on 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * original e100 driver, but better described as a munging of 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * e100, e1000, eepro100, tg3, 8139cp, and other drivers. 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * References: 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Intel 8255x 10/100 Mbps Ethernet Controller Family, 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Open Source Software Developers Manual, 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * http://sourceforge.net/projects/e1000 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Theory of Operation 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I. General 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controller family, which includes the 82557, 82558, 82559, 82550, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 82551, and 82562 devices. 82558 and greater controllers 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * integrate the Intel 82555 PHY. The controllers are used in 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * server and client network interface cards, as well as in 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configurations. 8255x supports a 32-bit linear addressing 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mode and operates at 33Mhz PCI clock rate. 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * II. Driver Operation 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Memory-mapped mode is used exclusively to access the device's 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * shared-memory structure, the Control/Status Registers (CSR). All 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * setup, configuration, and control of the device, including queuing 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of Tx, Rx, and configuration commands is through the CSR. 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cmd_lock serializes accesses to the CSR command register. cb_lock 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * protects the shared Command Block List (CBL). 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8255x is highly MII-compliant and all access to the PHY go 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * through the Management Data Interface (MDI). Consequently, the 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver leverages the mii.c library shared with other MII-compliant 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * devices. 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Big- and Little-Endian byte order as well as 32- and 64-bit 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * archs are supported. Weak-ordered memory and non-cache-coherent 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * archs are supported. 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * III. Transmit 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A Tx skb is mapped and hangs off of a TCB. TCBs are linked 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * together in a fixed-size ring (CBL) thus forming the flexible mode 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * memory structure. A TCB marked with the suspend-bit indicates 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the end of the ring. The last TCB processed suspends the 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controller, and the controller can be restarted by issue a CU 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * resume command to continue from the suspend point, or a CU start 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command to start at a given position in the ring. 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Non-Tx commands (config, multicast setup, etc) are linked 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into the CBL ring along with Tx commands. The common structure 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * used for both Tx and non-Tx commands is the Command Block (CB). 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cb_to_use is the next CB to use for queuing a command; cb_to_clean 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is the next CB to check for completion; cb_to_send is the first 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CB to start on in case of a previous failure to resume. CB clean 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * up happens in interrupt context in response to a CU interrupt. 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cbs_avail keeps track of number of free CB resources available. 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Hardware padding of short packets to minimum packet size is 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * enabled. 82557 pads with 7Eh, while the later controllers pad 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with 00h. 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 970a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr * IV. Receive 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The Receive Frame Area (RFA) comprises a ring of Receive Frame 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Descriptors (RFD) + data buffer, thus forming the simplified mode 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * memory structure. Rx skbs are allocated to contain both the RFD 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the data buffer, but the RFD is pulled off before the skb is 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * indicated. The data buffer is aligned such that encapsulated 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * protocol headers are u32-aligned. Since the RFD is part of the 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mapped shared memory, and completion status is contained within 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the RFD, the RFD must be dma_sync'ed to maintain a consistent 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * view from software and hardware. 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1097734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * In order to keep updates to the RFD link field from colliding with 1107734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * hardware writes to mark packets complete, we use the feature that 1117734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * hardware will not write to a size 0 descriptor and mark the previous 1127734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * packet as end-of-list (EL). After updating the link, we remove EL 1137734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * and only then restore the size such that hardware may use the 1147734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * previous-to-end RFD. 1157734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Under typical operation, the receive unit (RU) is start once, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the controller happily fills RFDs as frames arrive. If 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * replacement RFDs cannot be allocated, or the RU goes non-active, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the RU must be restarted. Frame arrival generates an interrupt, 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and Rx indication and re-allocation happen in the same context, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * therefore no locking is required. A software-generated interrupt 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is generated from the watchdog to recover from a failed allocation 1230a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr * scenario where all Rx resources have been indicated and none re- 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * placed. 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * V. Miscellaneous 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VLAN offloading of tagging, stripping and filtering is not 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * supported, but driver will accommodate the extra 4-byte VLAN tag 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for processing by upper layers. Tx/Rx Checksum offloading is not 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * supported. Tx Scatter/Gather is not supported. Jumbo Frames is 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not supported (hardware limitation). 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MagicPacket(tm) WoL support is enabled/disabled via ethtool. 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thanks to JC (jchapman@katalix.com) for helping with 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * testing/troubleshooting the development driver. 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TODO: 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * o several entry points race with dev->close 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * o check for tx-no-resources/stop Q races with tx clean/wake Q 142ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * 143ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * FIXES: 144ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com> 145ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * - Stratus87247: protect MDI control register manipulations 146720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * 2009/06/01 - Andreas Mohr <andi at lisas dot de> 147720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * - add clean lowlevel I/O emulation for cards with MII-lacking PHYs 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 150fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 151fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches 152a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/hardirq.h> 153a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h> 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 158d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/sched.h> 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 1631e7f0bd8c8f2d0496ad338be5e69ff4395d77da4Domen Puncer#include <linux/dma-mapping.h> 16498468efddb101f8a29af974101c17ba513b07be1Roger Oksanen#include <linux/dmapool.h> 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mii.h> 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/if_vlan.h> 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ethtool.h> 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 1729ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput#include <linux/firmware.h> 173401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox#include <linux/rtnetlink.h> 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unaligned.h> 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_NAME "e100" 1784e1dc97d5e0dd5b1cf78e67ea8f12ca9697c9eeeAuke Kok#define DRV_EXT "-NAPI" 179b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define DRV_VERSION "3.5.24-k2"DRV_EXT 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" 1814e1dc97d5e0dd5b1cf78e67ea8f12ca9697c9eeeAuke Kok#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E100_WATCHDOG_PERIOD (2 * HZ) 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E100_NAPI_WEIGHT 16 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1869ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput#define FIRMWARE_D101M "e100/d101m_ucode.bin" 1879ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput#define FIRMWARE_D101S "e100/d101s_ucode.bin" 1889ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput#define FIRMWARE_D102E "e100/d102e_ucode.bin" 1899ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRV_DESCRIPTION); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR(DRV_COPYRIGHT); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(DRV_VERSION); 1949ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh RajputMODULE_FIRMWARE(FIRMWARE_D101M); 1959ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh RajputMODULE_FIRMWARE(FIRMWARE_D101S); 1969ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh RajputMODULE_FIRMWARE(FIRMWARE_D102E); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug = 3; 1998fb6f732c389847dece403b7470d6d3d2778804aDavid S. Millerstatic int eeprom_bad_csum_allow = 0; 20027345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburgstatic int use_io = 0; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0); 2028fb6f732c389847dece403b7470d6d3d2778804aDavid S. Millermodule_param(eeprom_bad_csum_allow, int, 0); 20327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburgmodule_param(use_io, int, 0); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); 2058fb6f732c389847dece403b7470d6d3d2778804aDavid S. MillerMODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); 20627345bb684140f5f306963e0d6e25a60c7857dfeJesse BrandeburgMODULE_PARM_DESC(use_io, "Force use of i/o access mode"); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } 2119baa3c34ac4e27f7e062f266f50cc5dbea26a6c1Benoit Tainestatic const struct pci_device_id e100_id_table[] = { 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), 242042e2fb70006f135469d546726451b7d14768980Malli Chilakala INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), 243042e2fb70006f135469d546726451b7d14768980Malli Chilakala INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), 244042e2fb70006f135469d546726451b7d14768980Malli Chilakala INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), 245042e2fb70006f135469d546726451b7d14768980Malli Chilakala INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), 246042e2fb70006f135469d546726451b7d14768980Malli Chilakala INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), 247b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), 253042e2fb70006f135469d546726451b7d14768980Malli Chilakala INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, } 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, e100_id_table); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum mac { 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82557_D100_A = 0, 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82557_D100_B = 1, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82557_D100_C = 2, 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82558_D101_A4 = 4, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82558_D101_B0 = 5, 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82559_D101M = 8, 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82559_D101S = 9, 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82550_D102 = 12, 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82550_D102_C = 13, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82551_E = 14, 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82551_F = 15, 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_82551_10 = 16, 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mac_unknown = 0xFF, 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum phy { 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_100a = 0x000003E0, 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_100c = 0x035002A8, 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_82555_tx = 0x015002A8, 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_nsc_tx = 0x5C002000, 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_82562_et = 0x033002A8, 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_82562_em = 0x032002A8, 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_82562_ek = 0x031002A8, 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_82562_eh = 0x017002A8, 283b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan phy_82552_v = 0xd061004d, 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phy_unknown = 0xFFFFFFFF, 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CSR (Control/Status Registers) */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct csr { 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct { 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 status; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 stat_ack; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 cmd_lo; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 cmd_hi; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 gen_ptr; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } scb; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 port; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 flash_ctrl; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 eeprom_ctrl_lo; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 eeprom_ctrl_hi; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mdi_ctrl; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rx_dma_count; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum scb_status { 3057734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker rus_no_res = 0x08, 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rus_ready = 0x10, 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rus_mask = 0x3C, 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 310ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzikenum ru_state { 311ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik RU_SUSPENDED = 0, 312ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik RU_RUNNING = 1, 313ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik RU_UNINITIALIZED = -1, 314ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik}; 315ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum scb_stat_ack { 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_not_ours = 0x00, 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_sw_gen = 0x04, 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_rnr = 0x10, 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_cu_idle = 0x20, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_frame_rx = 0x40, 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_cu_cmd_done = 0x80, 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_not_present = 0xFF, 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum scb_cmd_hi { 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_mask_none = 0x00, 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_mask_all = 0x01, 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_sw_gen = 0x02, 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum scb_cmd_lo { 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_nop = 0x00, 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ruc_start = 0x01, 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ruc_load_base = 0x06, 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_start = 0x10, 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_resume = 0x20, 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_dump_addr = 0x40, 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_dump_stats = 0x50, 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_load_base = 0x60, 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_dump_reset = 0x70, 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum cuc_dump { 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_dump_complete = 0x0000A005, 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cuc_dump_reset_complete = 0x0000A007, 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3500547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum port { 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds software_reset = 0x0000, 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds selftest = 0x0001, 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds selective_reset = 0x0002, 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum eeprom_ctrl_lo { 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eesk = 0x01, 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eecs = 0x02, 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eedi = 0x04, 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eedo = 0x08, 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum mdi_ctrl { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdi_write = 0x04000000, 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdi_read = 0x08000000, 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdi_ready = 0x10000000, 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum eeprom_op { 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op_write = 0x05, 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op_read = 0x06, 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op_ewds = 0x10, 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op_ewen = 0x13, 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum eeprom_offsets { 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_cnfg_mdix = 0x03, 379720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr eeprom_phy_iface = 0x06, 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_id = 0x0A, 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_config_asf = 0x0D, 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_smbus_addr = 0x90, 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum eeprom_cnfg_mdix { 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_mdix_enabled = 0x0080, 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 389720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrenum eeprom_phy_iface { 390720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr NoSuchPhy = 0, 391720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr I82553AB, 392720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr I82553C, 393720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr I82503, 394720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr DP83840, 395720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr S80C240, 396720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr S80C24, 397720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr I82555, 398720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr DP83840A = 10, 399720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr}; 400720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum eeprom_id { 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_id_wol = 0x0020, 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum eeprom_config_asf { 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_asf = 0x8000, 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom_gcl = 0x4000, 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum cb_status { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_complete = 0x8000, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_ok = 0x2000, 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41575f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear/** 41675f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear * cb_command - Command Block flags 41775f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear * @cb_tx_nc: 0: controler does CRC (normal), 1: CRC from skb memory 41875f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum cb_command { 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_nop = 0x0000, 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_iaaddr = 0x0001, 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_config = 0x0002, 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_multi = 0x0003, 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_tx = 0x0004, 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_ucode = 0x0005, 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_dump = 0x0006, 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_tx_sf = 0x0008, 42875f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear cb_tx_nc = 0x0010, 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_cid = 0x1f00, 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_i = 0x2000, 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_s = 0x4000, 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_el = 0x8000, 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct rfd { 436aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 status; 437aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 command; 438aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 link; 439aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 rbd; 440aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 actual_size; 441aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 size; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct rx { 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rx *next, *prev; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t dma_addr; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(__BIG_ENDIAN_BITFIELD) 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define X(a,b) b,a 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define X(a,b) a,b 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct config { 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0*/ u8 X(byte_count:6, pad0:2); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*2*/ u8 adaptive_ifs; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds term_write_cache_line:1), pad3:4); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*4*/ u8 X(rx_dma_max_count:7, pad4:1); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), 4650bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear rx_save_overruns : 1), rx_save_bad_frames : 1); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_dynamic_tbd:1); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link_status_wake:1), arp_wake:1), mcmatch_wake:1); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loopback:2); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*11*/ u8 X(linear_priority:3, pad11:5); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*13*/ u8 ip_addr_lo; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*14*/ u8 ip_addr_hi; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pad15_2:1), crs_or_cdt:1); 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*16*/ u8 fc_delay_lo; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*17*/ u8 fc_delay_hi; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_long_ok:1), fc_priority_threshold:3), pad18:1); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds full_duplex_force:1), full_duplex_pin:1); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 pad_d102[9]; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E100_MAX_MULTICAST_ADDRS 64 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct multi { 496aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 count; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Important: keep total struct u32-aligned */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UCODE_SIZE 134 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cb { 503aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 status; 504aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 command; 505aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 link; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union { 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 iaaddr[ETH_ALEN]; 508aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 ucode[UCODE_SIZE]; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct config config; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct multi multi; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct { 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tbd_array; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 tcb_byte_count; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 threshold; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 tbd_count; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct { 517aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 buf_addr; 518aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 size; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 eol; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } tbd; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } tcb; 522aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 dump_buffer_addr; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } u; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *next, *prev; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t dma_addr; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum loopback { 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lb_none = 0, lb_mac = 1, lb_phy = 3, 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct stats { 534aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 tx_good_frames, tx_max_collisions, tx_late_collisions, 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_multiple_collisions, tx_total_collisions; 537aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 rx_good_frames, rx_crc_errors, rx_alignment_errors, 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_resource_errors, rx_overrun_errors, rx_cdt_errors, 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_short_frame_errors; 540aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; 541aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 xmt_tco_frames, rcv_tco_frames; 542aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 complete; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mem { 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct { 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 signature; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 result; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } selftest; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct stats stats; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 dump_buf[596]; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct param_range { 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 min; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 max; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 count; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct params { 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct param_range rfds; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct param_range cbs; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct nic { 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Begin: frequently used values: keep adjacent for cache effect */ 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 msg_enable ____cacheline_aligned; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *pdev; 570720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rx *rxs ____cacheline_aligned; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rx *rx_to_use; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rx *rx_to_clean; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfd blank_rfd; 576ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik enum ru_state ru_running; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t cb_lock ____cacheline_aligned; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t cmd_lock; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct csr __iomem *csr; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum scb_cmd_lo cuc_cmd; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cbs_avail; 583bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger struct napi_struct napi; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cbs; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cb_to_use; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cb_to_send; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cb_to_clean; 588aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 tx_command; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* End: frequently used values: keep adjacent for cache effect */ 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum { 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ich = (1 << 0), 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds promiscuous = (1 << 1), 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds multicast_all = (1 << 2), 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wol_magic = (1 << 3), 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ich_10h_workaround = (1 << 4), 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } flags ____cacheline_aligned; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum mac mac; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum phy phy; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct params params; 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct timer_list watchdog; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mii_if_info mii; 6042acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala struct work_struct tx_timeout_task; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum loopback loopback; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mem *mem; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t dma_addr; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61098468efddb101f8a29af974101c17ba513b07be1Roger Oksanen struct pci_pool *cbs_pool; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t cbs_dma_addr; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 adaptive_ifs; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 tx_threshold; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_frames; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_collisions; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_deferred; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_single_collisions; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_multiple_collisions; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_fc_pause; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_tco_frames; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rx_fc_pause; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rx_fc_unsupported; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rx_tco_frames; 625d24d65eda97fe51f2996538148e85d309e2460e4Ben Greear u32 rx_short_frame_errors; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rx_over_length_errors; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 eeprom_wc; 629aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le16 eeprom[256]; 630ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael spinlock_t mdio_lock; 6317e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham const struct firmware *fw; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void e100_write_flush(struct nic *nic) 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Flush previous PCI writes through intermediate bridges 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by doing a benign read */ 63827345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg (void)ioread8(&nic->csr->scb.status); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void e100_enable_irq(struct nic *nic) 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&nic->cmd_lock, flags); 64627345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); 648ad8c48ad3bbef078616ed4d2652d362dfd962f09Catalin(ux aka Dino) BOIE spin_unlock_irqrestore(&nic->cmd_lock, flags); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void e100_disable_irq(struct nic *nic) 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&nic->cmd_lock, flags); 65627345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi); 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); 658ad8c48ad3bbef078616ed4d2652d362dfd962f09Catalin(ux aka Dino) BOIE spin_unlock_irqrestore(&nic->cmd_lock, flags); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_hw_reset(struct nic *nic) 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Put CU and RU into idle with a selective reset to get 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device off of PCI bus */ 66527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite32(selective_reset, &nic->csr->port); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(20); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now fully reset device */ 66927345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite32(software_reset, &nic->csr->port); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(20); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask off our interrupt line - it's unmasked after reset */ 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_disable_irq(nic); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_self_test(struct nic *nic) 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Passing the self-test is a pretty good indication 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that the device can DMA to/from host memory */ 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mem->selftest.signature = 0; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mem->selftest.result = 0xFFFFFFFF; 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 68627345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite32(selftest | dma_addr, &nic->csr->port); 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wait 10 msec for self-test to complete */ 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Interrupts are enabled after self-test */ 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_disable_irq(nic); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check results of self-test */ 695f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mem->selftest.result != 0) { 696fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, hw, nic->netdev, 697fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "Self-test failed: result=0x%08X\n", 698fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches nic->mem->selftest.result); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ETIMEDOUT; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 701f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mem->selftest.signature == 0) { 702fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, hw, nic->netdev, "Self-test failed: timed out\n"); 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ETIMEDOUT; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 709aaf918ba8cf941a6aa7dc52c307470b48259a751Al Virostatic void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data) 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 cmd_addr_data[3]; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 ctrl; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Three cmds: write/erase enable, write data, write/erase disable */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd_addr_data[0] = op_ewen << (addr_len - 2); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | 718aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro le16_to_cpu(data); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd_addr_data[2] = op_ewds << (addr_len - 2); 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Bit-bang cmds to write word to eeprom */ 722f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (j = 0; j < 3; j++) { 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Chip select */ 72527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 728f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (i = 31; i >= 0; i--) { 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl = (cmd_addr_data[j] & (1 << i)) ? 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eecs | eedi : eecs; 73127345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 73427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wait 10 msec for cmd to complete */ 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Chip deselect */ 74127345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(0, &nic->csr->eeprom_ctrl_lo); 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* General technique stolen from the eepro100 driver - very clever */ 747aaf918ba8cf941a6aa7dc52c307470b48259a751Al Virostatic __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 cmd_addr_data; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 data = 0; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 ctrl; 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd_addr_data = ((op_read << *addr_len) | addr) << 16; 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Chip select */ 75727345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Bit-bang to read word from eeprom */ 761f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (i = 31; i >= 0; i--) { 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; 76327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7650547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 76627345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7680547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Eeprom drives a dummy zero to EEDO after receiving 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete address. Use this to adjust addr_len. */ 77127345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); 772f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!(ctrl & eedo) && i > 16) { 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *addr_len -= (i - 16); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 17; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7760547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = (data << 1) | (ctrl & eedo ? 1 : 0); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Chip deselect */ 78127345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(0, &nic->csr->eeprom_ctrl_lo); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); udelay(4); 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 784aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro return cpu_to_le16(data); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Load entire EEPROM image into driver cache and validate checksum */ 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_eeprom_load(struct nic *nic) 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 addr, addr_len = 8, checksum = 0; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try reading with an 8-bit addr len to discover actual addr len */ 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_eeprom_read(nic, &addr_len, 0); 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->eeprom_wc = 1 << addr_len; 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 796f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (addr = 0; addr < nic->eeprom_wc; addr++) { 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); 798f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (addr < nic->eeprom_wc - 1) 799aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro checksum += le16_to_cpu(nic->eeprom[addr]); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The checksum, stored in the last word, is calculated such that 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the sum of words should be 0xBABA */ 804aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) { 805fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n"); 8068fb6f732c389847dece403b7470d6d3d2778804aDavid S. Miller if (!eeprom_bad_csum_allow) 8078fb6f732c389847dece403b7470d6d3d2778804aDavid S. Miller return -EAGAIN; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Save (portion of) driver EEPROM cache to device and update checksum */ 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_eeprom_save(struct nic *nic, u16 start, u16 count) 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 addr, addr_len = 8, checksum = 0; 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try reading with an 8-bit addr len to discover actual addr len */ 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_eeprom_read(nic, &addr_len, 0); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->eeprom_wc = 1 << addr_len; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 822f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (start + count >= nic->eeprom_wc) 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 825f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (addr = start; addr < start + count; addr++) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The checksum, stored in the last word, is calculated such that 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the sum of words should be 0xBABA */ 830f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (addr = 0; addr < nic->eeprom_wc - 1; addr++) 831aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro checksum += le16_to_cpu(nic->eeprom[addr]); 832aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->eeprom[nic->eeprom_wc - 1]); 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 839962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ 840e6280f26b43775d8fa0c54e50c92491cfccbf738Malli Chilakala#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ 841858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&nic->cmd_lock, flags); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Previous command is accepted when SCB clears */ 850f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { 851f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (likely(!ioread8(&nic->csr->scb.cmd_lo))) 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_relax(); 854f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(i > E100_WAIT_SCB_FAST)) 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(5); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 857f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EAGAIN; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_unlock; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 862f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(cmd != cuc_resume)) 86327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite32(dma_addr, &nic->csr->scb.gen_ptr); 86427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(cmd, &nic->csr->scb.cmd_lo); 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_unlock: 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&nic->cmd_lock, flags); 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 872858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_exec_cb(struct nic *nic, struct sk_buff *skb, 87361a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman int (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cb; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&nic->cb_lock, flags); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(!nic->cbs_avail)) { 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_unlock; 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb = nic->cb_to_use; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cb_to_use = cb->next; 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs_avail--; 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->skb = skb; 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89161a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman err = cb_prepare(nic, cb, skb); 89261a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman if (err) 89361a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman goto err_unlock; 89461a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman 895f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(!nic->cbs_avail)) 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOSPC; 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Order is important otherwise we'll be in a race with h/w: 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set S-bit in current first, then clear S-bit in previous. */ 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->command |= cpu_to_le16(cb_s); 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->prev->command &= cpu_to_le16(~cb_s); 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 905f26251eb68ea766a98fed922593c154d15127621Bruce Allan while (nic->cb_to_send != nic->cb_to_use) { 906f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cb_to_send->dma_addr))) { 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ok, here's where things get sticky. It's 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * possible that we can't schedule the command 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * because the controller is too busy, so 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * let's just queue the command and try again 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when another command is scheduled. */ 913f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (err == -ENOSPC) { 914962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala //request a reset 915962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala schedule_work(&nic->tx_timeout_task); 916962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala } 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cuc_cmd = cuc_resume; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cb_to_send = nic->cb_to_send->next; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_unlock: 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&nic->cb_lock, flags); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 930720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic int mdio_read(struct net_device *netdev, int addr, int reg) 931720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{ 932720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr struct nic *nic = netdev_priv(netdev); 933720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0); 934720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr} 935720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 936720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic void mdio_write(struct net_device *netdev, int addr, int reg, int data) 937720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{ 938720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr struct nic *nic = netdev_priv(netdev); 939720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 940720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr nic->mdio_ctrl(nic, addr, mdi_write, reg, data); 941720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr} 942720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 943720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr/* the standard mdio_ctrl() function for usual MII-compliant hardware */ 944720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 data_out = 0; 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i; 948ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael unsigned long flags; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 950ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael 951ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael /* 952ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * Stratus87247: we shouldn't be writing the MDI control 953ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * register until the Ready bit shows True. Also, since 954ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * manipulation of the MDI control registers is a multi-step 955ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael * procedure it should be done under lock. 956ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael */ 957ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael spin_lock_irqsave(&nic->mdio_lock, flags); 958ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael for (i = 100; i; --i) { 95927345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) 960ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael break; 961ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael udelay(20); 962ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael } 963ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael if (unlikely(!i)) { 964fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n"); 965ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael spin_unlock_irqrestore(&nic->mdio_lock, flags); 966ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael return 0; /* No way to indicate timeout error */ 967ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael } 96827345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 970ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael for (i = 0; i < 100; i++) { 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(20); 97227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 975ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael spin_unlock_irqrestore(&nic->mdio_lock, flags); 976fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, hw, KERN_DEBUG, nic->netdev, 977fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", 978fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches dir == mdi_read ? "READ" : "WRITE", 979fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches addr, reg, data, data_out); 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (u16)data_out; 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 983720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ 984720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic u16 mdio_ctrl_phy_82552_v(struct nic *nic, 985720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u32 addr, 986720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u32 dir, 987720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u32 reg, 988720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u16 data) 989720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{ 990720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr if ((reg == MII_BMCR) && (dir == mdi_write)) { 991720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) { 992720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u16 advert = mdio_read(nic->netdev, nic->mii.phy_id, 993720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr MII_ADVERTISE); 994720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 995720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* 996720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * Workaround Si issue where sometimes the part will not 997720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * autoneg to 100Mbps even when advertised. 998720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr */ 999720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr if (advert & ADVERTISE_100FULL) 1000720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr data |= BMCR_SPEED100 | BMCR_FULLDPLX; 1001720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr else if (advert & ADVERTISE_100HALF) 1002720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr data |= BMCR_SPEED100; 1003720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } 1004720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } 1005720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return mdio_ctrl_hw(nic, addr, dir, reg, data); 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1008720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr/* Fully software-emulated mdio_ctrl() function for cards without 1009720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * MII-compliant PHYs. 1010720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * For now, this is mainly geared towards 80c24 support; in case of further 1011720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * requirements for other types (i82503, ...?) either extend this mechanism 1012720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * or split it, whichever is cleaner. 1013720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr */ 1014720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic u16 mdio_ctrl_phy_mii_emulated(struct nic *nic, 1015720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u32 addr, 1016720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u32 dir, 1017720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u32 reg, 1018720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u16 data) 1019720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{ 1020720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* might need to allocate a netdev_priv'ed register array eventually 1021720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * to be able to record state changes, but for now 1022720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * some fully hardcoded register handling ought to be ok I guess. */ 1023720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 1024720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr if (dir == mdi_read) { 1025720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr switch (reg) { 1026720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr case MII_BMCR: 1027720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* Auto-negotiation, right? */ 1028720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return BMCR_ANENABLE | 1029720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr BMCR_FULLDPLX; 1030720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr case MII_BMSR: 1031720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return BMSR_LSTATUS /* for mii_link_ok() */ | 1032720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr BMSR_ANEGCAPABLE | 1033720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr BMSR_10FULL; 1034720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr case MII_ADVERTISE: 1035720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* 80c24 is a "combo card" PHY, right? */ 1036720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return ADVERTISE_10HALF | 1037720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr ADVERTISE_10FULL; 1038720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr default: 1039fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, hw, KERN_DEBUG, nic->netdev, 1040fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", 1041fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches dir == mdi_read ? "READ" : "WRITE", 1042fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches addr, reg, data); 1043720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return 0xFFFF; 1044720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } 1045720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } else { 1046720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr switch (reg) { 1047720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr default: 1048fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, hw, KERN_DEBUG, nic->netdev, 1049fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n", 1050fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches dir == mdi_read ? "READ" : "WRITE", 1051fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches addr, reg, data); 1052720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return 0xFFFF; 1053720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } 1054b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan } 1055720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr} 1056720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic inline int e100_phy_supports_mii(struct nic *nic) 1057720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{ 1058720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* for now, just check it by comparing whether we 1059720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr are using MII software emulation. 1060720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr */ 1061720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated); 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_defaults(struct nic *nic) 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10662afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; 10672afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ 107044c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; 1071f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mac == mac_unknown) 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mac = mac_82557_D100_A; 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->params.rfds = rfds; 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->params.cbs = cbs; 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Quadwords to DMA into FIFO before starting frame transmit */ 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_threshold = 0xE0; 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10800a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr /* no interrupt for every tx completion, delay = 256us if not 557 */ 1081962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | 1082962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Template for a freshly allocated RFD */ 10857734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker nic->blank_rfd.command = 0; 10861172899a30d0c26df934d63cc98241cd53fe7130Al Viro nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); 1087719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN); 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* MII setup */ 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mii.phy_id_mask = 0x1F; 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mii.reg_num_mask = 0x1F; 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mii.dev = nic->netdev; 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mii.mdio_read = mdio_read; 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mii.mdio_write = mdio_write; 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 109761a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Hormanstatic int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct config *config = &cb->u.config; 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *c = (u8 *)config; 1101719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear struct net_device *netdev = nic->netdev; 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->command = cpu_to_le16(cb_config); 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(config, 0, sizeof(struct config)); 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->byte_count = 0x16; /* bytes in this struct */ 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->direct_rx_dma = 0x1; /* reserved */ 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->standard_tcb = 0x1; /* 1=standard, 0=extended */ 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->tx_underrun_retry = 0x3; /* # of underrun retries */ 1114720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr if (e100_phy_supports_mii(nic)) 1115720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr config->mii_mode = 1; /* 1=MII mode, 0=i82503 mode */ 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->pad10 = 0x6; 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->ifs = 0x6; /* x16 = inter frame spacing */ 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->pad15_1 = 0x1; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->pad15_2 = 0x1; 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->fc_delay_hi = 0x40; /* time delay for fc frame */ 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->tx_padding = 0x1; /* 1=pad short frames */ 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->pad18 = 0x1; 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->pad20_1 = 0x1F; 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->pad21_1 = 0x5; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->adaptive_ifs = nic->adaptive_ifs; 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->loopback = nic->loopback; 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1136f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mii.force_media && nic->mii.full_duplex) 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->full_duplex_force = 0x1; /* 1=force, 0=auto */ 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1139f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->flags & promiscuous || nic->loopback) { 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->promiscuous_mode = 0x1; /* 1=on, 0=off */ 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1145719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear if (unlikely(netdev->features & NETIF_F_RXFCS)) 1146719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear config->rx_crc_transfer = 0x1; /* 1=save, 0=discard */ 1147719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear 1148f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->flags & multicast_all) 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->multicast_all = 0x1; /* 1=accept, 0=no */ 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11516bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala /* disable WoL when up */ 1152f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->magic_packet_disable = 0x1; /* 1=off, 0=on */ 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1155f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mac >= mac_82558_D101_A4) { 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->mwi_enable = 0x1; /* 1=enable, 0=disable */ 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->standard_tcb = 0x0; /* 1=standard, 0=extended */ 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ 116044e4925e4601961b9bd1982008a55fce865d318cDavid Graham if (nic->mac >= mac_82559_D101M) { 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->tno_intr = 0x1; /* TCO stats enable */ 116244e4925e4601961b9bd1982008a55fce865d318cDavid Graham /* Enable TCO in extended config */ 116344e4925e4601961b9bd1982008a55fce865d318cDavid Graham if (nic->mac >= mac_82551_10) { 116444e4925e4601961b9bd1982008a55fce865d318cDavid Graham config->byte_count = 0x20; /* extended bytes */ 116544e4925e4601961b9bd1982008a55fce865d318cDavid Graham config->rx_d102_mode = 0x1; /* GMRC for TCO */ 116644e4925e4601961b9bd1982008a55fce865d318cDavid Graham } 116744e4925e4601961b9bd1982008a55fce865d318cDavid Graham } else { 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config->standard_stat_counter = 0x0; 116944e4925e4601961b9bd1982008a55fce865d318cDavid Graham } 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11720bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear if (netdev->features & NETIF_F_RXALL) { 11730bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear config->rx_save_overruns = 0x1; /* 1=save, 0=discard */ 11740bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ 11750bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ 11760bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear } 11770bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear 1178ab90695a1a1185e0c5aff04ac16d39c5712f28bdAndy Shevchenko netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "[00-07]=%8ph\n", 1179ab90695a1a1185e0c5aff04ac16d39c5712f28bdAndy Shevchenko c + 0); 1180ab90695a1a1185e0c5aff04ac16d39c5712f28bdAndy Shevchenko netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "[08-15]=%8ph\n", 1181ab90695a1a1185e0c5aff04ac16d39c5712f28bdAndy Shevchenko c + 8); 1182ab90695a1a1185e0c5aff04ac16d39c5712f28bdAndy Shevchenko netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "[16-23]=%8ph\n", 1183ab90695a1a1185e0c5aff04ac16d39c5712f28bdAndy Shevchenko c + 16); 118461a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman return 0; 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11872afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg/************************************************************************* 11882afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* CPUSaver parameters 11892afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* 11902afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* All CPUSaver parameters are 16-bit literals that are part of a 11912afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* "move immediate value" instruction. By changing the value of 11922afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* the literal in the instruction before the code is loaded, the 11932afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* driver can change the algorithm. 11942afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* 11950779bf2d2ecc4d9b1e9437ae659f50e6776a7666Matt LaPlante* INTDELAY - This loads the dead-man timer with its initial value. 11960547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg* When this timer expires the interrupt is asserted, and the 11972afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* timer is reset each time a new packet is received. (see 11982afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* BUNDLEMAX below to set the limit on number of chained packets) 11992afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* The current default is 0x600 or 1536. Experiments show that 12002afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* the value should probably stay within the 0x200 - 0x1000. 12012afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* 12020547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg* BUNDLEMAX - 12032afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* This sets the maximum number of frames that will be bundled. In 12042afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* some situations, such as the TCP windowing algorithm, it may be 12052afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* better to limit the growth of the bundle size than let it go as 12062afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* high as it can, because that could cause too much added latency. 12072afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* The default is six, because this is the number of packets in the 12082afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* default TCP window size. A value of 1 would make CPUSaver indicate 12092afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* an interrupt for every frame received. If you do not want to put 12102afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* a limit on the bundle size, set this value to xFFFF. 12112afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* 12120547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg* BUNDLESMALL - 12132afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* This contains a bit-mask describing the minimum size frame that 12142afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* will be bundled. The default masks the lower 7 bits, which means 12152afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* that any frame less than 128 bytes in length will not be bundled, 12162afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* but will instead immediately generate an interrupt. This does 12172afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* not affect the current bundle in any way. Any frame that is 128 12182afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* bytes or large will be bundled normally. This feature is meant 12192afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* to provide immediate indication of ACK frames in a TCP environment. 12202afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* Customers were seeing poor performance when a machine with CPUSaver 12212afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* enabled was sending but not receiving. The delay introduced when 12222afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* the ACKs were received was enough to reduce total throughput, because 12232afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* the sender would sit idle until the ACK was finally seen. 12242afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* 12252afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* The current default is 0xFF80, which masks out the lower 7 bits. 12262afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* This means that any frame which is x7F (127) bytes or smaller 12270547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg* will cause an immediate interrupt. Because this value must be a 12282afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* bit mask, there are only a few valid values that can be used. To 12292afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* turn this feature off, the driver can write the value xFFFF to the 12302afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* lower word of this instruction (in the same way that the other 12312afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* parameters are used). Likewise, a value of 0xF800 (2047) would 12322afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* cause an interrupt to be generated for every frame, because all 12332afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg* standard Ethernet frames are <= 2047 bytes in length. 12342afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*************************************************************************/ 12352afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg 12360547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg/* if you wish to disable the ucode functionality, while maintaining the 12372afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * workarounds it provides, set the following defines to: 12382afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * BUNDLESMALL 0 12392afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * BUNDLEMAX 1 12402afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * INTDELAY 1 12412afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg */ 12422afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg#define BUNDLESMALL 1 12432afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg#define BUNDLEMAX (u16)6 12442afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg#define INTDELAY (u16)1536 /* 0x600 */ 12452afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg 12469ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput/* Initialize firmware */ 12479ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajputstatic const struct firmware *e100_request_firmware(struct nic *nic) 12489ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput{ 12499ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput const char *fw_name; 12507e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham const struct firmware *fw = nic->fw; 12519ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput u8 timer, bundle, min_size; 12527e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham int err = 0; 12538b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork bool required = false; 12549ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 12552afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg /* do not load u-code for ICH devices */ 12562afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg if (nic->flags & ich) 12579ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput return NULL; 12582afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg 12598b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork /* Search for ucode match against h/w revision 12608b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * 12618b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * Based on comments in the source code for the FreeBSD fxp 12628b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * driver, the FIRMWARE_D102E ucode includes both CPUSaver and 12638b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * 12648b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * "fixes for bugs in the B-step hardware (specifically, bugs 12658b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * with Inline Receive)." 12668b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * 12678b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * So we must fail if it cannot be loaded. 12688b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * 12698b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * The other microcode files are only required for the optional 12708b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork * CPUSaver feature. Nice to have, but no reason to fail. 12718b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork */ 12728b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork if (nic->mac == mac_82559_D101M) { 12739ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput fw_name = FIRMWARE_D101M; 12748b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork } else if (nic->mac == mac_82559_D101S) { 12759ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput fw_name = FIRMWARE_D101S; 12768b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork } else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) { 12779ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput fw_name = FIRMWARE_D102E; 12788b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork required = true; 12798b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork } else { /* No ucode on other devices */ 12809ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput return NULL; 12818b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork } 12829ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 12837e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham /* If the firmware has not previously been loaded, request a pointer 12847e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham * to it. If it was previously loaded, we are reinitializing the 12857e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham * adapter, possibly in a resume from hibernate, in which case 12867e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham * request_firmware() cannot be used. 12877e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham */ 12887e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham if (!fw) 12897e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham err = request_firmware(&fw, fw_name, &nic->pdev->dev); 12907e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham 12919ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput if (err) { 12928b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork if (required) { 12938b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork netif_err(nic, probe, nic->netdev, 12948b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork "Failed to load firmware \"%s\": %d\n", 12958b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork fw_name, err); 12968b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork return ERR_PTR(err); 12978b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork } else { 12988b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork netif_info(nic, probe, nic->netdev, 12998b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork "CPUSaver disabled. Needs \"%s\": %d\n", 13008b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork fw_name, err); 13018b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork return NULL; 13028b0d2f9ed3d8e92feada7c5d70fa85be46e6f948Bjørn Mork } 13039ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput } 13047e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham 13059ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput /* Firmware should be precisely UCODE_SIZE (words) plus three bytes 13069ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ 13079ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput if (fw->size != UCODE_SIZE * 4 + 3) { 1308fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, 1309fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "Firmware \"%s\" has wrong size %zu\n", 1310fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches fw_name, fw->size); 13119ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput release_firmware(fw); 13129ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput return ERR_PTR(-EINVAL); 13132afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg } 13142afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg 13159ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput /* Read timer, bundle and min_size from end of firmware blob */ 13169ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput timer = fw->data[UCODE_SIZE * 4]; 13179ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput bundle = fw->data[UCODE_SIZE * 4 + 1]; 13189ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput min_size = fw->data[UCODE_SIZE * 4 + 2]; 13199ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13209ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || 13219ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput min_size >= UCODE_SIZE) { 1322fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, 1323fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", 1324fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches fw_name, timer, bundle, min_size); 13259ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput release_firmware(fw); 13269ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput return ERR_PTR(-EINVAL); 13279ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput } 13287e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham 13297e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham /* OK, firmware is validated and ready to use. Save a pointer 13307e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham * to it in the nic */ 13317e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham nic->fw = fw; 13329ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput return fw; 133324180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg} 133424180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg 133561a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Hormanstatic int e100_setup_ucode(struct nic *nic, struct cb *cb, 13369ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput struct sk_buff *skb) 133724180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg{ 13389ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput const struct firmware *fw = (void *)skb; 13399ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput u8 timer, bundle, min_size; 13409ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13419ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput /* It's not a real skb; we just abused the fact that e100_exec_cb 13429ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput will pass it through to here... */ 13439ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->skb = NULL; 13449ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13459ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput /* firmware is stored as little endian already */ 13469ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); 13479ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13489ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput /* Read timer, bundle and min_size from end of firmware blob */ 13499ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput timer = fw->data[UCODE_SIZE * 4]; 13509ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput bundle = fw->data[UCODE_SIZE * 4 + 1]; 13519ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput min_size = fw->data[UCODE_SIZE * 4 + 2]; 13529ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13539ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput /* Insert user-tunable settings in cb->u.ucode */ 13549ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); 13559ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); 13569ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); 13579ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); 13589ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); 13599ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); 13609ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13619ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput cb->command = cpu_to_le16(cb_ucode | cb_el); 136261a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman return 0; 13639ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput} 13649ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13659ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajputstatic inline int e100_load_ucode_wait(struct nic *nic) 13669ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput{ 13679ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput const struct firmware *fw; 136824180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg int err = 0, counter = 50; 136924180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg struct cb *cb = nic->cb_to_clean; 137024180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg 13719ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput fw = e100_request_firmware(nic); 13729ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput /* If it's NULL, then no ucode is required */ 13739ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput if (!fw || IS_ERR(fw)) 13749ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput return PTR_ERR(fw); 13759ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput 13769ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) 1377fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, 1378fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "ucode cmd failed with error %d\n", err); 13790547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 138024180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg /* must restart cuc */ 138124180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg nic->cuc_cmd = cuc_start; 138224180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg 138324180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg /* wait for completion */ 138424180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg e100_write_flush(nic); 138524180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg udelay(10); 138624180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg 138724180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg /* wait for possibly (ouch) 500ms */ 138824180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg while (!(cb->status & cpu_to_le16(cb_complete))) { 138924180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg msleep(10); 139024180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg if (!--counter) break; 139124180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg } 13920547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 13933a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. Day /* ack any interrupts, something could have been set */ 139427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(~0, &nic->csr->scb.stat_ack); 139524180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg 139624180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg /* if the command failed, or is not OK, notify and return */ 139724180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg if (!counter || !(cb->status & cpu_to_le16(cb_ok))) { 1398fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "ucode load failed\n"); 139924180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg err = -EPERM; 140024180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg } 14010547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 140224180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg return err; 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 140561a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Hormanstatic int e100_setup_iaaddr(struct nic *nic, struct cb *cb, 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb) 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->command = cpu_to_le16(cb_iaaddr); 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); 141061a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman return 0; 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141361a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Hormanstatic int e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->command = cpu_to_le16(cb_dump); 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offsetof(struct mem, dump_buf)); 141861a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman return 0; 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic int e100_phy_check_without_mii(struct nic *nic) 1422720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{ 1423720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr u8 phy_type; 1424720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr int without_mii; 1425720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 1426720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; 1427720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 1428720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr switch (phy_type) { 1429720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ 1430720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr case I82503: /* Non-MII PHY; UNTESTED! */ 1431720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr case S80C24: /* Non-MII PHY; tested and working */ 1432720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": 1433720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter 1434720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * doesn't have a programming interface of any sort. The 1435720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * media is sensed automatically based on how the link partner 1436720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * is configured. This is, in essence, manual configuration. 1437720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr */ 1438fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_info(nic, probe, nic->netdev, 1439fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "found MII-less i82503 or 80c24 or other PHY\n"); 1440720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 1441720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated; 1442720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */ 1443720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 1444720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* these might be needed for certain MII-less cards... 1445720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * nic->flags |= ich; 1446720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * nic->flags |= ich_10h_workaround; */ 1447720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 1448720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr without_mii = 1; 1449720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr break; 1450720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr default: 1451720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr without_mii = 0; 1452720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr break; 1453720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } 1454720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return without_mii; 1455720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr} 1456720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NCONFIG_AUTO_SWITCH 0x0080 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_NSC_CONG MII_RESV1 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NSC_CONG_ENABLE 0x0100 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NSC_CONG_TXREADY 0x0400 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADVERTISE_FC_SUPPORTED 0x0400 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_phy_init(struct nic *nic) 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev = nic->netdev; 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 addr; 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 bmcr, stat, id_lo, id_hi, cong; 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ 1469f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (addr = 0; addr < 32; addr++) { 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); 1474f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1477720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr if (addr == 32) { 1478720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* uhoh, no PHY detected: check whether we seem to be some 1479720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * weird, rare variant which is *known* to not have any MII. 1480720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * But do this AFTER MII checking only, since this does 1481720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * lookup of EEPROM values which may easily be unreliable. */ 1482720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr if (e100_phy_check_without_mii(nic)) 1483720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return 0; /* simply return and hope for the best */ 1484720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr else { 1485720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* for unknown cases log a fatal error */ 1486fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, hw, nic->netdev, 1487fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "Failed to locate any known PHY, aborting\n"); 1488720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr return -EAGAIN; 1489720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } 1490720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr } else 1491fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, hw, KERN_DEBUG, nic->netdev, 1492fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "phy_addr = %d\n", nic->mii.phy_id); 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get phy ID */ 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->phy = (u32)id_hi << 16 | (u32)id_lo; 1498fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, hw, KERN_DEBUG, nic->netdev, 1499fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "phy ID = 0x%08X\n", nic->phy); 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15018fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan /* Select the phy and isolate the rest */ 15028fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan for (addr = 0; addr < 32; addr++) { 15038fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan if (addr != nic->mii.phy_id) { 15048fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); 15058fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan } else if (nic->phy != phy_82552_v) { 15068fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan bmcr = mdio_read(netdev, addr, MII_BMCR); 15078fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan mdio_write(netdev, addr, MII_BMCR, 15088fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan bmcr & ~BMCR_ISOLATE); 15098fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan } 15108fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan } 15118fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan /* 15128fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan * Workaround for 82552: 15138fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan * Clear the ISOLATE bit on selected phy_id last (mirrored on all 15148fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan * other phy_id's) using bmcr value from addr discovery loop above. 15158fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan */ 15168fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan if (nic->phy == phy_82552_v) 15178fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan mdio_write(netdev, nic->mii.phy_id, MII_BMCR, 15188fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan bmcr & ~BMCR_ISOLATE); 15198fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Handle National tx phys */ 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NCS_PHY_MODEL_MASK 0xFFF0FFFF 1522f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Disable congestion control */ 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cong |= NSC_CONG_TXREADY; 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cong &= ~NSC_CONG_ENABLE; 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1530b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan if (nic->phy == phy_82552_v) { 1531b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); 1532b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan 1533720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr /* assign special tweaked mdio_ctrl() function */ 1534720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr nic->mdio_ctrl = mdio_ctrl_phy_82552_v; 1535720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr 1536b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan /* Workaround Si not advertising flow-control during autoneg */ 1537b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; 1538b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); 1539b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan 1540b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan /* Reset for the above changes to take effect */ 1541b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); 1542b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan bmcr |= BMCR_RESET; 1543b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); 1544b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && 154560ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && 154660ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { 154760ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher /* enable/disable MDI/MDI-X auto-switching. */ 154860ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 154960ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); 1550648951451e6d2d532d4ace2f8e9c5cdf1d563e83Malli Chilakala } 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_hw_init(struct nic *nic) 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1557dca97ad2ec37aa98c45dfe1d531d9ba7048e814eEmil Tantilov int err = 0; 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_hw_reset(nic); 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, hw, nic->netdev, "e100_hw_init\n"); 1562f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!in_interrupt() && (err = e100_self_test(nic))) 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1565f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_phy_init(nic))) 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1567f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1569f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 15719ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput if ((err = e100_load_ucode_wait(nic))) 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1573f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_exec_cb(nic, NULL, e100_configure))) 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1575f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1577f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_exec_cmd(nic, cuc_dump_addr, 15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->dma_addr + offsetof(struct mem, stats)))) 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1580f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_disable_irq(nic); 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 158861a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Hormanstatic int e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev = nic->netdev; 159122bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 15924cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->command = cpu_to_le16(cb_multi); 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); 159648e2f183cb1709600012265a2e723f45a350d5feJiri Pirko i = 0; 159722bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, netdev) { 159848e2f183cb1709600012265a2e723f45a350d5feJiri Pirko if (i == count) 159948e2f183cb1709600012265a2e723f45a350d5feJiri Pirko break; 160022bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr, 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ETH_ALEN); 160248e2f183cb1709600012265a2e723f45a350d5feJiri Pirko } 160361a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman return 0; 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_set_multicast_list(struct net_device *netdev) 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1610fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, hw, KERN_DEBUG, nic->netdev, 1611fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "mc_count=%d, flags=0x%04X\n", 1612fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netdev_mc_count(netdev), netdev->flags); 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1614f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netdev->flags & IFF_PROMISC) 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags |= promiscuous; 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags &= ~promiscuous; 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1619f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netdev->flags & IFF_ALLMULTI || 16204cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS) 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags |= multicast_all; 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags &= ~multicast_all; 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_exec_cb(nic, NULL, e100_configure); 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_exec_cb(nic, NULL, e100_multi); 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_update_stats(struct nic *nic) 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 163109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device *dev = nic->netdev; 163209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device_stats *ns = &dev->stats; 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct stats *s = &nic->mem->stats; 1634aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro __le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : 1635aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro (nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames : 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &s->complete; 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Device's stats reporting may take several microseconds to 16390a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr * complete, so we're always waiting for results of the 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * previous command. */ 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1642f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *complete = 0; 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_frames = le32_to_cpu(s->tx_good_frames); 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->collisions += nic->tx_collisions; 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(s->tx_lost_crs); 1653d24d65eda97fe51f2996538148e85d309e2460e4Ben Greear nic->rx_short_frame_errors += 1654d24d65eda97fe51f2996538148e85d309e2460e4Ben Greear le32_to_cpu(s->rx_short_frame_errors); 1655d24d65eda97fe51f2996538148e85d309e2460e4Ben Greear ns->rx_length_errors = nic->rx_short_frame_errors + 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_over_length_errors; 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); 1661ecf7130b087a9bd1b9d03dbf452630243210d22eJohn W. Linville ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(s->rx_alignment_errors) + 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(s->rx_short_frame_errors) + 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(s->rx_cdt_errors); 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_deferred += le32_to_cpu(s->tx_deferred); 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_single_collisions += 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(s->tx_single_collisions); 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_multiple_collisions += 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(s->tx_multiple_collisions); 1671f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mac >= mac_82558_D101_A4) { 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_fc_unsupported += 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(s->fc_rcv_unsupported); 1676f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mac >= mac_82559_D101M) { 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->tx_tco_frames += 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le16_to_cpu(s->xmt_tco_frames); 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_tco_frames += 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le16_to_cpu(s->rcv_tco_frames); 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16850547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg 1686f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (e100_exec_cmd(nic, cuc_dump_reset, 0)) 1687fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, 1688fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "exec cuc_dump_reset failed\n"); 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Adjust inter-frame-spacing (IFS) between two transmits if 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we're getting collisions on a half-duplex connection. */ 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1696f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (duplex == DUPLEX_HALF) { 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 prev = nic->adaptive_ifs; 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 min_frames = (speed == SPEED_100) ? 1000 : 100; 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1700f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((nic->tx_frames / 32 < nic->tx_collisions) && 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nic->tx_frames > min_frames)) { 1702f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->adaptive_ifs < 60) 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->adaptive_ifs += 5; 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (nic->tx_frames < min_frames) { 1705f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->adaptive_ifs >= 5) 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->adaptive_ifs -= 5; 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1708f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->adaptive_ifs != prev) 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_exec_cb(nic, NULL, e100_configure); 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_watchdog(unsigned long data) 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = (struct nic *)data; 17168ae6daca85c8bbd6a32c382db5e2a2a989f8bed2David Decotigny struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; 171725db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny u32 speed; 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1719fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, timer, KERN_DEBUG, nic->netdev, 1720fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "right now = %ld\n", jiffies); 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mii library handles link maintenance tasks */ 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mii_ethtool_gset(&nic->mii, &cmd); 172525db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny speed = ethtool_cmd_speed(&cmd); 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1727f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { 1728fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n", 172925db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny speed == SPEED_100 ? 100 : 10, 1730fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); 1731f26251eb68ea766a98fed922593c154d15127621Bruce Allan } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { 1732fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netdev_info(nic->netdev, "NIC Link is Down\n"); 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mii_check_link(&nic->mii); 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Software generated interrupt to recover from (rare) Rx 17380547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg * allocation failure. 17390547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg * Unfortunately have to use a spinlock to not re-enable interrupts 17400547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg * accidentally, due to hardware that shares a register between the 17410547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg * interrupt mask bit and the SW Interrupt generation bit */ 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&nic->cmd_lock); 174327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_write_flush(nic); 1745ad8c48ad3bbef078616ed4d2652d362dfd962f09Catalin(ux aka Dino) BOIE spin_unlock_irq(&nic->cmd_lock); 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_update_stats(nic); 174825db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny e100_adjust_adaptive_ifs(nic, speed, cmd.duplex); 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1750f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mac <= mac_82557_D100_C) 17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Issue a multicast command to workaround a 557 lock up */ 17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_set_multicast_list(nic->netdev); 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175425db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny if (nic->flags & ich && speed == SPEED_10 && cmd.duplex == DUPLEX_HALF) 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags |= ich_10h_workaround; 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags &= ~ich_10h_workaround; 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 176034c6417b7087a4818e7dca2e5d66c3361cee80a1Stephen Hemminger mod_timer(&nic->watchdog, 176134c6417b7087a4818e7dca2e5d66c3361cee80a1Stephen Hemminger round_jiffies(jiffies + E100_WATCHDOG_PERIOD)); 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 176461a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Hormanstatic int e100_xmit_prepare(struct nic *nic, struct cb *cb, 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb) 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 176761a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman dma_addr_t dma_addr; 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->command = nic->tx_command; 176975f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear 177061a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman dma_addr = pci_map_single(nic->pdev, 177161a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman skb->data, skb->len, PCI_DMA_TODEVICE); 177261a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman /* If we can't map the skb, have the upper layer try later */ 177361a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman if (pci_dma_mapping_error(nic->pdev, dma_addr)) 177461a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman return -ENOMEM; 177561a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman 177675f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear /* 177775f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear * Use the last 4 bytes of the SKB payload packet as the CRC, used for 177875f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear * testing, ie sending frames with bad CRC. 177975f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear */ 178075f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear if (unlikely(skb->no_fcs)) 17813d2372eb146efdd9a31ac29cdfc9812fad4faa67Joe Perches cb->command |= cpu_to_le16(cb_tx_nc); 178275f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear else 17833d2372eb146efdd9a31ac29cdfc9812fad4faa67Joe Perches cb->command &= ~cpu_to_le16(cb_tx_nc); 178475f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear 1785962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala /* interrupt every 16 packets regardless of delay */ 1786f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((nic->cbs_avail & ~15) == nic->cbs_avail) 1787996ec3533ae15424e339089a8045ca1c998f8a87Malli Chilakala cb->command |= cpu_to_le16(cb_i); 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->u.tcb.tcb_byte_count = 0; 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->u.tcb.threshold = nic->tx_threshold; 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->u.tcb.tbd_count = 1; 179261a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman cb->u.tcb.tbd.buf_addr = cpu_to_le32(dma_addr); 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->u.tcb.tbd.size = cpu_to_le16(skb->len); 179448425b14929ef185377e3827ba7135d88343faceRichard Cochran skb_tx_timestamp(skb); 179561a0f6efc8932e9914e1782ff3a027e23c687fc6Neil Horman return 0; 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17983b29a56d31d585d39bf9ffe9ef1f10bd637ee0f1Stephen Hemmingerstatic netdev_tx_t e100_xmit_frame(struct sk_buff *skb, 17993b29a56d31d585d39bf9ffe9ef1f10bd637ee0f1Stephen Hemminger struct net_device *netdev) 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1804f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->flags & ich_10h_workaround) { 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Issue a NOP command followed by a 1us delay before 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds issuing the Tx command. */ 1808f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (e100_exec_cmd(nic, cuc_nop, 0)) 1809fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, 1810fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "exec cuc_nop failed\n"); 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1); 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = e100_exec_cb(nic, skb, e100_xmit_prepare); 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1816f26251eb68ea766a98fed922593c154d15127621Bruce Allan switch (err) { 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOSPC: 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We queued the skb, but now we're out of space. */ 1819fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, 1820fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "No space for CB\n"); 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(netdev); 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -ENOMEM: 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is a hard error - log it. */ 1825fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, 1826fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "Out of Tx resources, returning skb\n"); 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(netdev); 18285b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy return NETDEV_TX_BUSY; 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18316ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1834858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_tx_clean(struct nic *nic) 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 183609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device *dev = nic->netdev; 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cb; 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tx_cleaned = 0; 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&nic->cb_lock); 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clean CBs marked complete */ 1843f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (cb = nic->cb_to_clean; 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->status & cpu_to_le16(cb_complete); 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb = nic->cb_to_clean = cb->next) { 18462d0bb1c1f4524befe9f0fcf0d0cd3081a451223fJeff Kirsher rmb(); /* read skb after status */ 1847fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, 1848fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "cb[%d]->status = 0x%04X\n", 1849fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), 1850fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches cb->status); 1851dc45010e28bc4a1bfa6043eee31d1c59e93e1546Jesse Brandeburg 1852f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (likely(cb->skb != NULL)) { 185309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_packets++; 185409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_bytes += cb->skb->len; 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(nic->pdev, 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(cb->u.tcb.tbd.buf_addr), 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le16_to_cpu(cb->u.tcb.tbd.size), 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DMA_TODEVICE); 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_any(cb->skb); 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->skb = NULL; 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_cleaned = 1; 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->status = 0; 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs_avail++; 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&nic->cb_lock); 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Recover from running out of Tx resources in xmit_frame */ 1871f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue(nic->netdev); 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return tx_cleaned; 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_clean_cbs(struct nic *nic) 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1879f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->cbs) { 1880f26251eb68ea766a98fed922593c154d15127621Bruce Allan while (nic->cbs_avail != nic->params.cbs.count) { 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cb = nic->cb_to_clean; 1882f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (cb->skb) { 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(nic->pdev, 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(cb->u.tcb.tbd.buf_addr), 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le16_to_cpu(cb->u.tcb.tbd.size), 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DMA_TODEVICE); 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(cb->skb); 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cb_to_clean = nic->cb_to_clean->next; 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs_avail++; 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 189298468efddb101f8a29af974101c17ba513b07be1Roger Oksanen pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr); 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs = NULL; 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs_avail = 0; 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cuc_cmd = cuc_start; 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs; 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_alloc_cbs(struct nic *nic) 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cb *cb; 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i, count = nic->params.cbs.count; 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cuc_cmd = cuc_start; 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs_avail = 0; 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191098468efddb101f8a29af974101c17ba513b07be1Roger Oksanen nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL, 191198468efddb101f8a29af974101c17ba513b07be1Roger Oksanen &nic->cbs_dma_addr); 1912f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!nic->cbs) 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 191470abc8cb90e679d8519721e2761d8366a18212a6Roger Oksanen memset(nic->cbs, 0, count * sizeof(struct cb)); 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1916f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (cb = nic->cbs, i = 0; i < count; cb++, i++) { 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb->link = cpu_to_le32(nic->cbs_dma_addr + 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((i+1) % count) * sizeof(struct cb)); 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->cbs_avail = count; 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzikstatic inline void e100_start_receiver(struct nic *nic, struct rx *rx) 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1933f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!nic->rxs) return; 1934f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (RU_SUSPENDED != nic->ru_running) return; 1935ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 1936ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik /* handle init time starts */ 1937f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!rx) rx = nic->rxs; 1938ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 1939ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik /* (Re)start RU if suspended or idle and RFA is non-NULL */ 1940f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (rx->skb) { 1941ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik e100_exec_cmd(nic, ruc_start, rx->dma_addr); 1942ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik nic->ru_running = RU_RUNNING; 1943ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik } 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1946719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) 1947858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 194989d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 195289d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet /* Init, and map the RFD. */ 195327d7ff46a3498d3debc6ba68fb8014c702b81170Arnaldo Carvalho de Melo skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd)); 19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19578d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) { 19581f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala dev_kfree_skb_any(rx->skb); 1959097688ef4710648db335c3c4fa243751f60b330aLuiz Fernando Capitulino rx->skb = NULL; 19601f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala rx->dma_addr = 0; 19611f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala return -ENOMEM; 19621f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala } 19631f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Link the RFD to end of RFA by linking previous RFD to 19657734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * this one. We are safe to touch the previous RFD because 19667734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * it is protected by the before last buffer's el bit being set */ 1967aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro if (rx->prev->skb) { 19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; 19696caf52a453d5fe0bc584a2895bfd39a3d9054829Harvey Harrison put_unaligned_le32(rx->dma_addr, &prev_rfd->link); 19701923815d855e1daec931fc9f2221fb73ca708870Kevin Hao pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, 1971773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); 19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1977858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_rx_indicate(struct nic *nic, struct rx *rx, 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int *work_done, unsigned int work_to_do) 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 198009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device *dev = nic->netdev; 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = rx->skb; 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfd *rfd = (struct rfd *)skb->data; 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 rfd_status, actual_size; 1984719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear u16 fcs_pad = 0; 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1986f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(work_done && *work_done >= work_to_do)) 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Need to sync before taking a peek at cb_complete bit */ 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, 1991773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfd_status = le16_to_cpu(rfd->status); 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1994fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, 1995fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "status=0x%04X\n", rfd_status); 19962d0bb1c1f4524befe9f0fcf0d0cd3081a451223fJeff Kirsher rmb(); /* read size after status bit */ 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If data isn't ready, nothing to indicate */ 19997734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker if (unlikely(!(rfd_status & cb_complete))) { 20007734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker /* If the next buffer has the el bit, but we think the receiver 20017734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * is still running, check to see if it really stopped while 20027734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * we had interrupts off. 20037734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * This allows for a fast restart without re-enabling 20047734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * interrupts */ 20057734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker if ((le16_to_cpu(rfd->command) & cb_el) && 20067734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker (RU_RUNNING == nic->ru_running)) 20077734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker 200817393dd67c06c3912ff47b31268b648929715336Jiri Slaby if (ioread8(&nic->csr->scb.status) & rus_no_res) 20097734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker nic->ru_running = RU_SUSPENDED; 2010303d67c288319768b19ed8dbed429fef7eb7c275Krzysztof Halasa pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, 2011303d67c288319768b19ed8dbed429fef7eb7c275Krzysztof Halasa sizeof(struct rfd), 20126ff9c2e7fa8ca63a575792534b63c5092099c286Krzysztof Hałasa PCI_DMA_FROMDEVICE); 20131f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala return -ENODATA; 20147734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker } 20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get actual data size */ 2017719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear if (unlikely(dev->features & NETIF_F_RXFCS)) 2018719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear fcs_pad = 4; 20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; 2020f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds actual_size = RFD_BUF_LEN - sizeof(struct rfd); 20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get data */ 20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(nic->pdev, rx->dma_addr, 2025773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20277734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker /* If this buffer has the el bit, but we think the receiver 20287734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * is still running, check to see if it really stopped while 20297734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * we had interrupts off. 20307734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * This allows for a fast restart without re-enabling interrupts. 20317734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * This can happen when the RU sees the size change but also sees 20327734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * the el bit set. */ 20337734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker if ((le16_to_cpu(rfd->command) & cb_el) && 20347734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker (RU_RUNNING == nic->ru_running)) { 20357734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker 203617393dd67c06c3912ff47b31268b648929715336Jiri Slaby if (ioread8(&nic->csr->scb.status) & rus_no_res) 2037ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik nic->ru_running = RU_SUSPENDED; 20387734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker } 2039ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Pull off the RFD and put the actual data (minus eth hdr) */ 20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve(skb, sizeof(struct rfd)); 20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put(skb, actual_size); 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->protocol = eth_type_trans(skb, nic->netdev); 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20450bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear /* If we are receiving all frames, then don't bother 20460bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear * checking for errors. 20470bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear */ 20480bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear if (unlikely(dev->features & NETIF_F_RXALL)) { 20490bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad) 20500bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear /* Received oversized frame, but keep it. */ 20510bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear nic->rx_over_length_errors++; 20520bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear goto process_skb; 20530bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear } 20540bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear 2055f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(!(rfd_status & cb_ok))) { 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't indicate if hardware indicates errors */ 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_any(skb); 2058719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad) { 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't indicate oversized frames */ 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_over_length_errors++; 20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_any(skb); 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 20630bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greearprocess_skb: 206409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_packets++; 2065719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear dev->stats.rx_bytes += (actual_size - fcs_pad); 20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_receive_skb(skb); 2067f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (work_done) 20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*work_done)++; 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx->skb = NULL; 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2076858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void e100_rx_clean(struct nic *nic, unsigned int *work_done, 20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int work_to_do) 20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rx *rx; 20807734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker int restart_required = 0, err = 0; 20817734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker struct rx *old_before_last_rx, *new_before_last_rx; 20827734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker struct rfd *old_before_last_rfd, *new_before_last_rfd; 20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Indicate newly arrived packets */ 2085f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { 20867734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker err = e100_rx_indicate(nic, rx, work_done, work_to_do); 20877734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker /* Hit quota or no more to clean */ 20887734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker if (-EAGAIN == err || -ENODATA == err) 2089ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik break; 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20927734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker 20937734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker /* On EAGAIN, hit quota so have more work to do, restart once 20947734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * cleanup is complete. 20957734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * Else, are we already rnr? then pay attention!!! this ensures that 20967734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * the state machine progression never allows a start with a 20977734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * partially cleaned list, avoiding a race between hardware 20987734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * and rx_to_clean when in NAPI mode */ 20997734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running) 21007734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker restart_required = 1; 21017734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker 21027734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker old_before_last_rx = nic->rx_to_use->prev->prev; 21037734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; 2104ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Alloc new skbs to refill list */ 2106f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { 2107f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (unlikely(e100_rx_alloc_skb(nic, rx))) 21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* Better luck next time (see watchdog) */ 21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2110ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 21117734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker new_before_last_rx = nic->rx_to_use->prev->prev; 21127734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker if (new_before_last_rx != old_before_last_rx) { 21137734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker /* Set the el-bit on the buffer that is before the last buffer. 21147734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * This lets us update the next pointer on the last buffer 21157734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * without worrying about hardware touching it. 21167734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * We set the size to 0 to prevent hardware from touching this 21177734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * buffer. 21187734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * When the hardware hits the before last buffer with el-bit 21197734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * and size of 0, it will RNR interrupt, the RUS will go into 21207734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * the No Resources state. It will not complete nor write to 21217734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * this buffer. */ 21227734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker new_before_last_rfd = 21237734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker (struct rfd *)new_before_last_rx->skb->data; 21247734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker new_before_last_rfd->size = 0; 21257734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker new_before_last_rfd->command |= cpu_to_le16(cb_el); 21267734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker pci_dma_sync_single_for_device(nic->pdev, 21277734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker new_before_last_rx->dma_addr, sizeof(struct rfd), 2128773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg PCI_DMA_BIDIRECTIONAL); 21297734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker 21307734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker /* Now that we have a new stopping point, we can clear the old 21317734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * stopping point. We must sync twice to get the proper 21327734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * ordering on the hardware side of things. */ 21337734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker old_before_last_rfd->command &= ~cpu_to_le16(cb_el); 21347734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker pci_dma_sync_single_for_device(nic->pdev, 21357734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker old_before_last_rx->dma_addr, sizeof(struct rfd), 2136773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg PCI_DMA_BIDIRECTIONAL); 2137719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN 2138719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear + ETH_FCS_LEN); 21397734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker pci_dma_sync_single_for_device(nic->pdev, 21407734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker old_before_last_rx->dma_addr, sizeof(struct rfd), 2141773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg PCI_DMA_BIDIRECTIONAL); 21427734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker } 21437734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker 2144f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (restart_required) { 2145ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik // ack the rnr? 2146915e91d734d33ad303313e05582769dbbefff3b2Jiri Slaby iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); 21477734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker e100_start_receiver(nic, nic->rx_to_clean); 2148f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (work_done) 2149ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik (*work_done)++; 2150ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik } 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_rx_clean_list(struct nic *nic) 21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rx *rx; 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i, count = nic->params.rfds.count; 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2158ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik nic->ru_running = RU_UNINITIALIZED; 2159ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 2160f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->rxs) { 2161f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (rx = nic->rxs, i = 0; i < count; rx++, i++) { 2162f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (rx->skb) { 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(nic->pdev, rx->dma_addr, 2164773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); 21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(rx->skb); 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(nic->rxs); 21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rxs = NULL; 21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_to_use = nic->rx_to_clean = NULL; 21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_rx_alloc_list(struct nic *nic) 21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rx *rx; 21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i, count = nic->params.rfds.count; 21797734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker struct rfd *before_last; 21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_to_use = nic->rx_to_clean = NULL; 2182ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik nic->ru_running = RU_UNINITIALIZED; 21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2184f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) 21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2187f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (rx = nic->rxs, i = 0; i < count; rx++, i++) { 21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; 21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; 2190f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (e100_rx_alloc_skb(nic, rx)) { 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_rx_clean_list(nic); 21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21957734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker /* Set the el-bit on the buffer that is before the last buffer. 21967734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * This lets us update the next pointer on the last buffer without 21977734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * worrying about hardware touching it. 21987734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * We set the size to 0 to prevent hardware from touching this buffer. 21997734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * When the hardware hits the before last buffer with el-bit and size 22007734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * of 0, it will RNR interrupt, the RU will go into the No Resources 22017734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker * state. It will not complete nor write to this buffer. */ 22027734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker rx = nic->rxs->prev->prev; 22037734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker before_last = (struct rfd *)rx->skb->data; 22047734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker before_last->command |= cpu_to_le16(cb_el); 22057734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker before_last->size = 0; 22067734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, 2207773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->rx_to_use = nic->rx_to_clean = nic->rxs; 2210ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik nic->ru_running = RU_SUSPENDED; 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22157d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t e100_intr(int irq, void *dev_id) 22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev = dev_id; 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 221927345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg u8 stat_ack = ioread8(&nic->csr->scb.stat_ack); 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2221fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, intr, KERN_DEBUG, nic->netdev, 2222fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "stat_ack = 0x%02X\n", stat_ack); 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2224f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_ack == stat_ack_not_present) /* Hardware is ejected */ 22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ack interrupt(s) */ 222927345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg iowrite8(stat_ack, &nic->csr->scb.stat_ack); 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik /* We hit Receive No Resource (RNR); restart RU after cleaning */ 2232f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (stat_ack & stat_ack_rnr) 2233ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik nic->ru_running = RU_SUSPENDED; 2234ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik 2235288379f050284087578b77e04f040b57db3db3f8Ben Hutchings if (likely(napi_schedule_prep(&nic->napi))) { 22360685c31b58a69e41393e974f6e6b8e0a4eadcf0bMalli Chilakala e100_disable_irq(nic); 2237288379f050284087578b77e04f040b57db3db3f8Ben Hutchings __napi_schedule(&nic->napi); 22380685c31b58a69e41393e974f6e6b8e0a4eadcf0bMalli Chilakala } 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2243bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int e100_poll(struct napi_struct *napi, int budget) 22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2245bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger struct nic *nic = container_of(napi, struct nic, napi); 2246ddfce6bb43c6bf1c9956e7a65ce1b2e19a156bd2Stephen Hemminger unsigned int work_done = 0; 22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2248bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger e100_rx_clean(nic, &work_done, budget); 224953e52c729cc169db82a6105fac7a166e10c2ec36David S. Miller e100_tx_clean(nic); 22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 225153e52c729cc169db82a6105fac7a166e10c2ec36David S. Miller /* If budget not fully consumed, exit the polling mode */ 225253e52c729cc169db82a6105fac7a166e10c2ec36David S. Miller if (work_done < budget) { 2253288379f050284087578b77e04f040b57db3db3f8Ben Hutchings napi_complete(napi); 22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_enable_irq(nic); 22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2257bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger return work_done; 22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NET_POLL_CONTROLLER 22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_netpoll(struct net_device *netdev) 22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 2264611494dccacb3e42f55359df74d604b67312598bMalli Chilakala 22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_disable_irq(nic); 22667d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells e100_intr(nic->pdev->irq, netdev); 22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_tx_clean(nic); 22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_enable_irq(nic); 22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_mac_address(struct net_device *netdev, void *p) 22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 22751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr *addr = p; 22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!is_valid_ether_addr(addr->sa_data)) 22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EADDRNOTAVAIL; 22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); 22811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_exec_cb(nic, NULL, e100_setup_iaaddr); 22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_change_mtu(struct net_device *netdev, int new_mtu) 22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2288f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) 22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev->mtu = new_mtu; 22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_asf(struct nic *nic) 22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ASF can be enabled from eeprom */ 2297807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && 22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (nic->eeprom[eeprom_config_asf] & eeprom_asf) && 22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && 2300807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE); 23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_up(struct nic *nic) 23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2307f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_rx_alloc_list(nic))) 23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2309f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_alloc_cbs(nic))) 23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_rx_clean_list; 2311f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_hw_init(nic))) 23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_clean_cbs; 23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_set_multicast_list(nic->netdev); 2314ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik e100_start_receiver(nic, NULL); 23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod_timer(&nic->watchdog, jiffies); 2316f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, 23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->netdev->name, nic->netdev))) 23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_no_irq; 23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue(nic->netdev); 2320bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger napi_enable(&nic->napi); 23210236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala /* enable ints _after_ enabling poll, preventing a race between 23220236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala * disable ints+schedule */ 23230236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala e100_enable_irq(nic); 23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_no_irq: 23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(&nic->watchdog); 23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_clean_cbs: 23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_clean_cbs(nic); 23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_rx_clean_list: 23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_rx_clean_list(nic); 23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_down(struct nic *nic) 23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23370236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala /* wait here for poll to complete */ 2338bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger napi_disable(&nic->napi); 23390236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala netif_stop_queue(nic->netdev); 23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_hw_reset(nic); 23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(nic->pdev->irq, nic->netdev); 23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(&nic->watchdog); 23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_off(nic->netdev); 23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_clean_cbs(nic); 23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_rx_clean_list(nic); 23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_tx_timeout(struct net_device *netdev) 23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23520547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg /* Reset outside of interrupt context, to avoid request_irq 23532acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala * in interrupt context */ 23542acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala schedule_work(&nic->tx_timeout_task); 23552acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala} 23562acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala 2357c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void e100_tx_timeout_task(struct work_struct *work) 23582acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala{ 2359c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct nic *nic = container_of(work, struct nic, tx_timeout_task); 2360c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct net_device *netdev = nic->netdev; 23612acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala 2362fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, 2363fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "scb.status=0x%02X\n", ioread8(&nic->csr->scb.status)); 2364401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox 2365401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox rtnl_lock(); 2366401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox if (netif_running(netdev)) { 2367401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox e100_down(netdev_priv(netdev)); 2368401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox e100_up(netdev_priv(netdev)); 2369401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox } 2370401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox rtnl_unlock(); 23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) 23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Use driver resources to perform internal MAC or PHY 23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * loopback test. A single packet is prepared and transmitted 23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in loopback mode, and the test passes if the received 23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * packet compares byte-for-byte to the transmitted packet. */ 23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2383f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_rx_alloc_list(nic))) 23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2385f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_alloc_cbs(nic))) 23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_clean_rx; 23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ICH PHY loopback is broken so do MAC loopback instead */ 2389f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->flags & ich && loopback_mode == lb_phy) 23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loopback_mode = lb_mac; 23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->loopback = loopback_mode; 2393f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_hw_init(nic))) 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_loopback_none; 23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2396f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (loopback_mode == lb_phy) 23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BMCR_LOOPBACK); 23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2400ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik e100_start_receiver(nic, NULL); 24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2402f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { 24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_loopback_none; 24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put(skb, ETH_DATA_LEN); 24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(skb->data, 0xFF, ETH_DATA_LEN); 24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_xmit_frame(skb, nic->netdev); 24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2412aa49cdd93be6328113f0c146fc72be173d578d27Jesse Brandeburg pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, 2413773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); 2414aa49cdd93be6328113f0c146fc72be173d578d27Jesse Brandeburg 2415f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), 24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->data, ETH_DATA_LEN)) 24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EAGAIN; 24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_loopback_none: 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); 24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->loopback = lb_none; 24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_clean_cbs(nic); 2423aa49cdd93be6328113f0c146fc72be173d578d27Jesse Brandeburg e100_hw_reset(nic); 24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_clean_rx: 24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_rx_clean_list(nic); 24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_LED_CONTROL 0x1B 2430b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_LED_OVERRIDE 0x19 2431b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ 2432b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ 24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) 24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mii_ethtool_gset(&nic->mii, cmd); 24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) 24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); 24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = mii_ethtool_sset(&nic->mii, cmd); 24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_exec_cb(nic, NULL, e100_configure); 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_drvinfo(struct net_device *netdev, 24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_drvinfo *info) 24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 245623020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 245723020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 245823020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones strlcpy(info->bus_info, pci_name(nic->pdev), 245923020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones sizeof(info->bus_info)); 24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2462abf9b902059fb1d569b64e8645a76f0fccbdbbe5Auke Kok#define E100_PHY_REGS 0x1C 24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_regs_len(struct net_device *netdev) 24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 2466abf9b902059fb1d569b64e8645a76f0fccbdbbe5Auke Kok return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); 24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_regs(struct net_device *netdev, 24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_regs *regs, void *p) 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 *buff = p; 24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 247644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok regs->version = (1 << 24) | nic->pdev->revision; 247727345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | 247827345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg ioread8(&nic->csr->scb.cmd_lo) << 16 | 247927345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg ioread16(&nic->csr->scb.status); 2480f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (i = E100_PHY_REGS; i >= 0; i--) 24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buff[1 + E100_PHY_REGS - i] = 24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdio_read(netdev, nic->mii.phy_id, i); 24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); 24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_exec_cb(nic, NULL, e100_dump); 24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, 24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(nic->mem->dump_buf)); 24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) 24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; 24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; 24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) || 2502bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki !device_can_wakeup(&nic->pdev->dev)) 25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2505f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (wol->wolopts) 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags |= wol_magic; 25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags &= ~wol_magic; 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2510bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts); 2511bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki 25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_exec_cb(nic, NULL, e100_configure); 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 e100_get_msglevel(struct net_device *netdev) 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return nic->msg_enable; 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_set_msglevel(struct net_device *netdev, u32 value) 25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->msg_enable = value; 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_nway_reset(struct net_device *netdev) 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mii_nway_restart(&nic->mii); 25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 e100_get_link(struct net_device *netdev) 25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mii_link_ok(&nic->mii); 25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_eeprom_len(struct net_device *netdev) 25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return nic->eeprom_wc << 1; 25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E100_EEPROM_MAGIC 0x1234 25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_eeprom(struct net_device *netdev, 25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_eeprom *eeprom, u8 *bytes) 25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eeprom->magic = E100_EEPROM_MAGIC; 25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); 25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_eeprom(struct net_device *netdev, 25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_eeprom *eeprom, u8 *bytes) 25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2564f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (eeprom->magic != E100_EEPROM_MAGIC) 25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); 25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return e100_eeprom_save(nic, eeprom->offset >> 1, 25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (eeprom->len >> 1) + 1); 25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_ringparam(struct net_device *netdev, 25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_ringparam *ring) 25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct param_range *rfds = &nic->params.rfds; 25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct param_range *cbs = &nic->params.cbs; 25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->rx_max_pending = rfds->max; 25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->tx_max_pending = cbs->max; 25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->rx_pending = rfds->count; 25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->tx_pending = cbs->count; 25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_ringparam(struct net_device *netdev, 25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_ringparam *ring) 25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct param_range *rfds = &nic->params.rfds; 25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct param_range *cbs = &nic->params.cbs; 25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25930547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2596f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netif_running(netdev)) 25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_down(nic); 25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfds->count = max(ring->rx_pending, rfds->min); 25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfds->count = min(rfds->count, rfds->max); 26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cbs->count = max(ring->tx_pending, cbs->min); 26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cbs->count = min(cbs->count, cbs->max); 2602fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_info(nic, drv, nic->netdev, "Ring Param settings: rx: %d, tx %d\n", 2603fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches rfds->count, cbs->count); 2604f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netif_running(netdev)) 26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_up(nic); 26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char e100_gstrings_test[][ETH_GSTRING_LEN] = { 26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Link test (on/offline)", 26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Eeprom test (on/offline)", 26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Self test (offline)", 26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Mac loopback (offline)", 26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Phy loopback (offline)", 26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 26174c3616cdda0632a3d0e39069765f9ea0e6bd093eAlejandro Martinez Ruiz#define E100_TEST_LEN ARRAY_SIZE(e100_gstrings_test) 26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_diag_test(struct net_device *netdev, 26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_test *test, u64 *data) 26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_cmd cmd; 26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, err; 26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(data, 0, E100_TEST_LEN * sizeof(u64)); 26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[0] = !mii_link_ok(&nic->mii); 26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[1] = e100_eeprom_load(nic); 2629f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (test->flags & ETH_TEST_FL_OFFLINE) { 26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save speed, duplex & autoneg settings */ 26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = mii_ethtool_gset(&nic->mii, &cmd); 26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2634f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netif_running(netdev)) 26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_down(nic); 26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[2] = e100_self_test(nic); 26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[3] = e100_loopback_test(nic, lb_mac); 26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[4] = e100_loopback_test(nic, lb_phy); 26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* restore speed, duplex & autoneg settings */ 26411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = mii_ethtool_sset(&nic->mii, &cmd); 26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2643f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netif_running(netdev)) 26441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_up(nic); 26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2646f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (i = 0; i < E100_TEST_LEN; i++) 26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; 2648a074fb860846937a4a46dbbf439cbbb2e2ba960cMalli Chilakala 2649a074fb860846937a4a46dbbf439cbbb2e2ba960cMalli Chilakala msleep_interruptible(4 * 1000); 26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2652a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsherstatic int e100_set_phys_id(struct net_device *netdev, 2653a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher enum ethtool_phys_id_state state) 26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 2656a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher enum led_state { 2657a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher led_on = 0x01, 2658a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher led_off = 0x04, 2659a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher led_on_559 = 0x05, 2660a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher led_on_557 = 0x07, 2661a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher }; 2662b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : 2663a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher MII_LED_CONTROL; 2664a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher u16 leds = 0; 2665a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher 2666a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher switch (state) { 2667a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher case ETHTOOL_ID_ACTIVE: 2668a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher return 2; 26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2670a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher case ETHTOOL_ID_ON: 2671a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher leds = (nic->phy == phy_82552_v) ? E100_82552_LED_ON : 2672a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; 2673a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher break; 2674a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher 2675a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher case ETHTOOL_ID_OFF: 2676a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher leds = (nic->phy == phy_82552_v) ? E100_82552_LED_OFF : led_off; 2677a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher break; 2678a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher 2679a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher case ETHTOOL_ID_INACTIVE: 2680a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher break; 2681a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher } 26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2683a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher mdio_write(netdev, nic->mii.phy_id, led_reg, leds); 26841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { 26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", 26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", 26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "rx_length_errors", "rx_over_errors", "rx_crc_errors", 26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", 26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", 26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tx_heartbeat_errors", "tx_window_errors", 26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* device-specific stats */ 26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tx_deferred", "tx_single_collisions", "tx_multi_collisions", 26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tx_flow_control_pause", "rx_flow_control_pause", 26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", 26986f66342c1ecd59467d4579176dd81a4e837a06efBen Greear "rx_short_frame_errors", "rx_over_length_errors", 26991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E100_NET_STATS_LEN 21 27014c3616cdda0632a3d0e39069765f9ea0e6bd093eAlejandro Martinez Ruiz#define E100_STATS_LEN ARRAY_SIZE(e100_gstrings_stats) 27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2703b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzikstatic int e100_get_sset_count(struct net_device *netdev, int sset) 27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2705b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik switch (sset) { 2706b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik case ETH_SS_TEST: 2707b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik return E100_TEST_LEN; 2708b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik case ETH_SS_STATS: 2709b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik return E100_STATS_LEN; 2710b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik default: 2711b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik return -EOPNOTSUPP; 2712b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik } 27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_ethtool_stats(struct net_device *netdev, 27161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_stats *stats, u64 *data) 27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721f26251eb68ea766a98fed922593c154d15127621Bruce Allan for (i = 0; i < E100_NET_STATS_LEN; i++) 272209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik data[i] = ((unsigned long *)&netdev->stats)[i]; 27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->tx_deferred; 27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->tx_single_collisions; 27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->tx_multiple_collisions; 27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->tx_fc_pause; 27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->rx_fc_pause; 27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->rx_fc_unsupported; 27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->tx_tco_frames; 27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[i++] = nic->rx_tco_frames; 27326f66342c1ecd59467d4579176dd81a4e837a06efBen Greear data[i++] = nic->rx_short_frame_errors; 27336f66342c1ecd59467d4579176dd81a4e837a06efBen Greear data[i++] = nic->rx_over_length_errors; 27341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) 27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2738f26251eb68ea766a98fed922593c154d15127621Bruce Allan switch (stringset) { 27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ETH_SS_TEST: 27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); 27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ETH_SS_STATS: 27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); 27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27487282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops e100_ethtool_ops = { 27491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_settings = e100_get_settings, 27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_settings = e100_set_settings, 27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_drvinfo = e100_get_drvinfo, 27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_regs_len = e100_get_regs_len, 27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_regs = e100_get_regs, 27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_wol = e100_get_wol, 27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_wol = e100_set_wol, 27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_msglevel = e100_get_msglevel, 27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_msglevel = e100_set_msglevel, 27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nway_reset = e100_nway_reset, 27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_link = e100_get_link, 27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_eeprom_len = e100_get_eeprom_len, 27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_eeprom = e100_get_eeprom, 27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_eeprom = e100_set_eeprom, 27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_ringparam = e100_get_ringparam, 27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_ringparam = e100_set_ringparam, 27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .self_test = e100_diag_test, 27661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_strings = e100_get_strings, 2767a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher .set_phys_id = e100_set_phys_id, 27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_ethtool_stats = e100_get_ethtool_stats, 2769b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik .get_sset_count = e100_get_sset_count, 2770abe0c5d165a422c438db51c0817b54eba1c4e85cRichard Cochran .get_ts_info = ethtool_op_get_ts_info, 27711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 27721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 27741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL); 27781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_alloc(struct nic *nic) 27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), 27831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &nic->dma_addr); 27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return nic->mem ? 0 : -ENOMEM; 27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_free(struct nic *nic) 27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2789f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (nic->mem) { 27901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_free_consistent(nic->pdev, sizeof(struct mem), 27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mem, nic->dma_addr); 27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->mem = NULL; 27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 27941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_open(struct net_device *netdev) 27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_off(netdev); 2802f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_up(nic))) 2803fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n"); 28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_close(struct net_device *netdev) 28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_down(netdev_priv(netdev)); 28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2813719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greearstatic int e100_set_features(struct net_device *netdev, 2814719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear netdev_features_t features) 2815719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear{ 2816719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear struct nic *nic = netdev_priv(netdev); 2817719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear netdev_features_t changed = features ^ netdev->features; 2818719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear 28190bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear if (!(changed & (NETIF_F_RXFCS | NETIF_F_RXALL))) 2820719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear return 0; 2821719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear 2822719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear netdev->features = features; 2823719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear e100_exec_cb(nic, NULL, e100_configure); 2824719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear return 0; 2825719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear} 2826719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear 2827acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemmingerstatic const struct net_device_ops e100_netdev_ops = { 2828acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_open = e100_open, 2829acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_stop = e100_close, 2830008298231abbeb91bc7be9e8b078607b816d1a4aStephen Hemminger .ndo_start_xmit = e100_xmit_frame, 2831acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_validate_addr = eth_validate_addr, 2832afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = e100_set_multicast_list, 2833acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_set_mac_address = e100_set_mac_address, 2834acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_change_mtu = e100_change_mtu, 2835acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_do_ioctl = e100_do_ioctl, 2836acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_tx_timeout = e100_tx_timeout, 2837acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger#ifdef CONFIG_NET_POLL_CONTROLLER 2838acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger .ndo_poll_controller = e100_netpoll, 2839acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger#endif 2840719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear .ndo_set_features = e100_set_features, 2841acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger}; 2842acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger 28431dd06ae8db716e17ec7e06244b858606edf378c0Greg Kroah-Hartmanstatic int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev; 28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic; 28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 284941de8d4cff21a2e81e3d9ff66f5f7c903f9c3ab1Joe Perches if (!(netdev = alloc_etherdev(sizeof(struct nic)))) 28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2852719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear netdev->hw_features |= NETIF_F_RXFCS; 285375f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear netdev->priv_flags |= IFF_SUPP_NOFCS; 28540bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear netdev->hw_features |= NETIF_F_RXALL; 2855719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear 2856acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger netdev->netdev_ops = &e100_netdev_ops; 28577ad24ea4bf620a32631d7b3069c3e30c078b0c3eWilfried Klaebe netdev->ethtool_ops = &e100_ethtool_ops; 28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; 28590eb5a34cdf34ad07b6db2df1e523aaf6574601b4Auke Kok strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); 28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic = netdev_priv(netdev); 2862bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT); 28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->netdev = netdev; 28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->pdev = pdev; 28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->msg_enable = (1 << debug) - 1; 2866720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr nic->mdio_ctrl = mdio_ctrl_hw; 28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pdev, netdev); 28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2869f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = pci_enable_device(pdev))) { 2870fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Cannot enable PCI device, aborting\n"); 28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_dev; 28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2874f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 2875fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Cannot find proper PCI device base address, aborting\n"); 28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENODEV; 28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_disable_pdev; 28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2880f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = pci_request_regions(pdev, DRV_NAME))) { 2881fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Cannot obtain PCI resources, aborting\n"); 28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_disable_pdev; 28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2885284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { 2886fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "No usable DMA configuration, aborting\n"); 28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_res; 28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_NETDEV_DEV(netdev, &pdev->dev); 28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg if (use_io) 2893fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_info(nic, probe, nic->netdev, "using i/o access mode\n"); 289427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg 289527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); 2896f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (!nic->csr) { 2897fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Cannot map device registers, aborting\n"); 28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_res; 29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2902f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (ent->driver_data) 29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags |= ich; 29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags &= ~ich; 29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_get_defaults(nic); 29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2909243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg /* D100 MAC doesn't allow rx of vlan packets with normal MTU */ 2910243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg if (nic->mac < mac_82558_D101_A4) 2911243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg netdev->features |= NETIF_F_VLAN_CHALLENGED; 2912243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg 29131f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala /* locks must be initialized before calling hw_reset */ 29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&nic->cb_lock); 29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&nic->cmd_lock); 2916ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael spin_lock_init(&nic->mdio_lock); 29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset the device before pci_set_master() in case device is in some 29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * funky state and has an interrupt pending - hint: we don't have the 29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interrupt handler registered yet. */ 29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_hw_reset(nic); 29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_master(pdev); 29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&nic->watchdog); 29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->watchdog.function = e100_watchdog; 29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->watchdog.data = (unsigned long)nic; 29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2929c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); 29302acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala 2931f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_alloc(nic))) { 2932fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n"); 29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_iounmap; 29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2936f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = e100_eeprom_load(nic))) 29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free; 29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2939f92d872876617cddbb0532291034f88941e855fdMalli Chilakala e100_phy_init(nic); 2940f92d872876617cddbb0532291034f88941e855fdMalli Chilakala 29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); 2942aaeb6cdfa5c07533c2cd6d2c381374c69f7db9dcJiri Pirko if (!is_valid_ether_addr(netdev->dev_addr)) { 2943948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg if (!eeprom_bad_csum_allow) { 2944fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n"); 2945948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg err = -EAGAIN; 2946948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg goto err_out_free; 2947948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg } else { 2948fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n"); 2949948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg } 29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wol magic packet can be enabled from eeprom */ 2953f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((nic->mac >= mac_82558_D101_A4) && 2954bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki (nic->eeprom[eeprom_id] & eeprom_id_wol)) { 29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nic->flags |= wol_magic; 2956bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki device_set_wakeup_enable(&pdev->dev, true); 2957bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki } 29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29596bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala /* ack any pending wake events, disable PME */ 2960e7272403d2f9be3dbb7cc185fcc390e781b1af6bRafael J. Wysocki pci_pme_active(pdev, false); 29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(netdev->name, "eth%d"); 2963f26251eb68ea766a98fed922593c154d15127621Bruce Allan if ((err = register_netdev(netdev))) { 2964fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_err(nic, probe, nic->netdev, "Cannot register net device, aborting\n"); 29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free; 29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 296798468efddb101f8a29af974101c17ba513b07be1Roger Oksanen nic->cbs_pool = pci_pool_create(netdev->name, 296898468efddb101f8a29af974101c17ba513b07be1Roger Oksanen nic->pdev, 2969211a0d941b1924e667483f822a55e2cc694cd212David S. Miller nic->params.cbs.max * sizeof(struct cb), 297098468efddb101f8a29af974101c17ba513b07be1Roger Oksanen sizeof(u32), 297198468efddb101f8a29af974101c17ba513b07be1Roger Oksanen 0); 2972fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches netif_info(nic, probe, nic->netdev, 2973fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches "addr 0x%llx, irq %d, MAC addr %pM\n", 2974fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0), 2975fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches pdev->irq, netdev->dev_addr); 29761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free: 29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_free(nic); 29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_iounmap: 298227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg pci_iounmap(pdev, nic->csr); 29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free_res: 29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_release_regions(pdev); 29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_disable_pdev: 29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_disable_device(pdev); 29871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free_dev: 29881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(netdev); 29891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 29901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29929f9a12f8ca79839c948464a37c5b557808278708Bill Pembertonstatic void e100_remove(struct pci_dev *pdev) 29931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 29941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev = pci_get_drvdata(pdev); 29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2996f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (netdev) { 29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(netdev); 29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_free(nic); 3000915e91d734d33ad303313e05582769dbbefff3b2Jiri Slaby pci_iounmap(pdev, nic->csr); 300198468efddb101f8a29af974101c17ba513b07be1Roger Oksanen pci_pool_destroy(nic->cbs_pool); 30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(netdev); 30031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_release_regions(pdev); 30041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_disable_device(pdev); 30051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3008b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ 3009b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ 3010b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ 3011ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardostatic void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) 30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev = pci_get_drvdata(pdev); 30141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3016824545e7031541f83245d254caca012bf6bdc6cdAuke Kok if (netif_running(netdev)) 3017f902283bbe68639142a00dd23d80ee31e1b00759Auke Kok e100_down(nic); 3018518d83382568964ca9657511140398ebac925ecdAuke Kok netif_device_detach(netdev); 3019a53a33da864a81a238ee84055c8ced775ee25350Auke Kok 30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_save_state(pdev); 3021e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok 3022e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok if ((nic->flags & wol_magic) | e100_asf(nic)) { 3023b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan /* enable reverse auto-negotiation */ 3024b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan if (nic->phy == phy_82552_v) { 3025b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, 3026b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan E100_82552_SMARTSPEED); 3027b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan 3028b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan mdio_write(netdev, nic->mii.phy_id, 3029b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan E100_82552_SMARTSPEED, smartspeed | 3030b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan E100_82552_REV_ANEG | E100_82552_ANEG_NOW); 3031b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan } 3032ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo *enable_wake = true; 3033e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok } else { 3034ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo *enable_wake = false; 3035e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok } 3036975b366af66280ed5b852a1a0446586ce71e306eAuke Kok 30372b6e0ca175fe4a20f21ba82b1e7ccc71029c4dd4Michele Baldessari pci_clear_master(pdev); 3038ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo} 30391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3040ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardostatic int __e100_power_off(struct pci_dev *pdev, bool wake) 3041ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo{ 30426905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki if (wake) 3043ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo return pci_prepare_to_sleep(pdev); 30446905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki 30456905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki pci_wake_from_d3(pdev, false); 30466905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki pci_set_power_state(pdev, PCI_D3hot); 30476905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki 30486905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki return 0; 30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051f902283bbe68639142a00dd23d80ee31e1b00759Auke Kok#ifdef CONFIG_PM 3052ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardostatic int e100_suspend(struct pci_dev *pdev, pm_message_t state) 3053ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo{ 3054ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo bool wake; 3055ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo __e100_shutdown(pdev, &wake); 3056ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo return __e100_power_off(pdev, wake); 3057ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo} 3058ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo 30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_resume(struct pci_dev *pdev) 30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *netdev = pci_get_drvdata(pdev); 30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nic *nic = netdev_priv(netdev); 30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3064975b366af66280ed5b852a1a0446586ce71e306eAuke Kok pci_set_power_state(pdev, PCI_D0); 30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_restore_state(pdev); 30666bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala /* ack any pending wake events, disable PME */ 30671ca01512a2a95aa061c3fc24b7c5d7fad9f606bfYijing Wang pci_enable_wake(pdev, PCI_D0, 0); 30681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30694b512d26f425be1c779c8319249b42ce3c3424d2Thadeu Lima de Souza Cascardo /* disable reverse auto-negotiation */ 3070b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan if (nic->phy == phy_82552_v) { 3071b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, 3072b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan E100_82552_SMARTSPEED); 3073b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan 3074b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan mdio_write(netdev, nic->mii.phy_id, 3075b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan E100_82552_SMARTSPEED, 3076b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan smartspeed & ~(E100_82552_REV_ANEG)); 3077b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan } 3078b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan 30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_device_attach(netdev); 3080975b366af66280ed5b852a1a0446586ce71e306eAuke Kok if (netif_running(netdev)) 30811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e100_up(nic); 30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 30841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3085975b366af66280ed5b852a1a0446586ce71e306eAuke Kok#endif /* CONFIG_PM */ 30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3087d18c3db58bc544fce6662ca7edba616ca9788a70Greg Kroah-Hartmanstatic void e100_shutdown(struct pci_dev *pdev) 30886bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala{ 3089ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo bool wake; 3090ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo __e100_shutdown(pdev, &wake); 3091ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo if (system_state == SYSTEM_POWER_OFF) 3092ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo __e100_power_off(pdev, wake); 30936bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala} 30946bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala 30952cc304923d87403abc103a741382b9af08b6deccAuke Kok/* ------------------ PCI Error Recovery infrastructure -------------- */ 30962cc304923d87403abc103a741382b9af08b6deccAuke Kok/** 30972cc304923d87403abc103a741382b9af08b6deccAuke Kok * e100_io_error_detected - called when PCI error is detected. 30982cc304923d87403abc103a741382b9af08b6deccAuke Kok * @pdev: Pointer to PCI device 30990a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr * @state: The current pci connection state 31002cc304923d87403abc103a741382b9af08b6deccAuke Kok */ 31012cc304923d87403abc103a741382b9af08b6deccAuke Kokstatic pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) 31022cc304923d87403abc103a741382b9af08b6deccAuke Kok{ 31032cc304923d87403abc103a741382b9af08b6deccAuke Kok struct net_device *netdev = pci_get_drvdata(pdev); 3104bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger struct nic *nic = netdev_priv(netdev); 31052cc304923d87403abc103a741382b9af08b6deccAuke Kok 31062cc304923d87403abc103a741382b9af08b6deccAuke Kok netif_device_detach(netdev); 3107ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch 3108ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch if (state == pci_channel_io_perm_failure) 3109ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch return PCI_ERS_RESULT_DISCONNECT; 3110ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch 3111ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch if (netif_running(netdev)) 3112ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch e100_down(nic); 3113b1d26f24e864204dfaa82b1252477e981ba9ef24Linas Vepstas pci_disable_device(pdev); 31142cc304923d87403abc103a741382b9af08b6deccAuke Kok 31152cc304923d87403abc103a741382b9af08b6deccAuke Kok /* Request a slot reset. */ 31162cc304923d87403abc103a741382b9af08b6deccAuke Kok return PCI_ERS_RESULT_NEED_RESET; 31172cc304923d87403abc103a741382b9af08b6deccAuke Kok} 31182cc304923d87403abc103a741382b9af08b6deccAuke Kok 31192cc304923d87403abc103a741382b9af08b6deccAuke Kok/** 31202cc304923d87403abc103a741382b9af08b6deccAuke Kok * e100_io_slot_reset - called after the pci bus has been reset. 31212cc304923d87403abc103a741382b9af08b6deccAuke Kok * @pdev: Pointer to PCI device 31222cc304923d87403abc103a741382b9af08b6deccAuke Kok * 31232cc304923d87403abc103a741382b9af08b6deccAuke Kok * Restart the card from scratch. 31242cc304923d87403abc103a741382b9af08b6deccAuke Kok */ 31252cc304923d87403abc103a741382b9af08b6deccAuke Kokstatic pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) 31262cc304923d87403abc103a741382b9af08b6deccAuke Kok{ 31272cc304923d87403abc103a741382b9af08b6deccAuke Kok struct net_device *netdev = pci_get_drvdata(pdev); 31282cc304923d87403abc103a741382b9af08b6deccAuke Kok struct nic *nic = netdev_priv(netdev); 31292cc304923d87403abc103a741382b9af08b6deccAuke Kok 31302cc304923d87403abc103a741382b9af08b6deccAuke Kok if (pci_enable_device(pdev)) { 3131fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches pr_err("Cannot re-enable PCI device after reset\n"); 31322cc304923d87403abc103a741382b9af08b6deccAuke Kok return PCI_ERS_RESULT_DISCONNECT; 31332cc304923d87403abc103a741382b9af08b6deccAuke Kok } 31342cc304923d87403abc103a741382b9af08b6deccAuke Kok pci_set_master(pdev); 31352cc304923d87403abc103a741382b9af08b6deccAuke Kok 31362cc304923d87403abc103a741382b9af08b6deccAuke Kok /* Only one device per card can do a reset */ 31372cc304923d87403abc103a741382b9af08b6deccAuke Kok if (0 != PCI_FUNC(pdev->devfn)) 31382cc304923d87403abc103a741382b9af08b6deccAuke Kok return PCI_ERS_RESULT_RECOVERED; 31392cc304923d87403abc103a741382b9af08b6deccAuke Kok e100_hw_reset(nic); 31402cc304923d87403abc103a741382b9af08b6deccAuke Kok e100_phy_init(nic); 31412cc304923d87403abc103a741382b9af08b6deccAuke Kok 31422cc304923d87403abc103a741382b9af08b6deccAuke Kok return PCI_ERS_RESULT_RECOVERED; 31432cc304923d87403abc103a741382b9af08b6deccAuke Kok} 31442cc304923d87403abc103a741382b9af08b6deccAuke Kok 31452cc304923d87403abc103a741382b9af08b6deccAuke Kok/** 31462cc304923d87403abc103a741382b9af08b6deccAuke Kok * e100_io_resume - resume normal operations 31472cc304923d87403abc103a741382b9af08b6deccAuke Kok * @pdev: Pointer to PCI device 31482cc304923d87403abc103a741382b9af08b6deccAuke Kok * 31492cc304923d87403abc103a741382b9af08b6deccAuke Kok * Resume normal operations after an error recovery 31502cc304923d87403abc103a741382b9af08b6deccAuke Kok * sequence has been completed. 31512cc304923d87403abc103a741382b9af08b6deccAuke Kok */ 31522cc304923d87403abc103a741382b9af08b6deccAuke Kokstatic void e100_io_resume(struct pci_dev *pdev) 31532cc304923d87403abc103a741382b9af08b6deccAuke Kok{ 31542cc304923d87403abc103a741382b9af08b6deccAuke Kok struct net_device *netdev = pci_get_drvdata(pdev); 31552cc304923d87403abc103a741382b9af08b6deccAuke Kok struct nic *nic = netdev_priv(netdev); 31562cc304923d87403abc103a741382b9af08b6deccAuke Kok 31572cc304923d87403abc103a741382b9af08b6deccAuke Kok /* ack any pending wake events, disable PME */ 31581ca01512a2a95aa061c3fc24b7c5d7fad9f606bfYijing Wang pci_enable_wake(pdev, PCI_D0, 0); 31592cc304923d87403abc103a741382b9af08b6deccAuke Kok 31602cc304923d87403abc103a741382b9af08b6deccAuke Kok netif_device_attach(netdev); 31612cc304923d87403abc103a741382b9af08b6deccAuke Kok if (netif_running(netdev)) { 31622cc304923d87403abc103a741382b9af08b6deccAuke Kok e100_open(netdev); 31632cc304923d87403abc103a741382b9af08b6deccAuke Kok mod_timer(&nic->watchdog, jiffies); 31642cc304923d87403abc103a741382b9af08b6deccAuke Kok } 31652cc304923d87403abc103a741382b9af08b6deccAuke Kok} 31662cc304923d87403abc103a741382b9af08b6deccAuke Kok 31673646f0e5c97703cecfd96cdabb085e78d9b7f680Stephen Hemmingerstatic const struct pci_error_handlers e100_err_handler = { 31682cc304923d87403abc103a741382b9af08b6deccAuke Kok .error_detected = e100_io_error_detected, 31692cc304923d87403abc103a741382b9af08b6deccAuke Kok .slot_reset = e100_io_slot_reset, 31702cc304923d87403abc103a741382b9af08b6deccAuke Kok .resume = e100_io_resume, 31712cc304923d87403abc103a741382b9af08b6deccAuke Kok}; 31726bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala 31731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver e100_driver = { 31741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = DRV_NAME, 31751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = e100_id_table, 31761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = e100_probe, 31779f9a12f8ca79839c948464a37c5b557808278708Bill Pemberton .remove = e100_remove, 3178e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok#ifdef CONFIG_PM 3179975b366af66280ed5b852a1a0446586ce71e306eAuke Kok /* Power Management hooks */ 31801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = e100_suspend, 31811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = e100_resume, 31821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 31830547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg .shutdown = e100_shutdown, 31842cc304923d87403abc103a741382b9af08b6deccAuke Kok .err_handler = &e100_err_handler, 31851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 31861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init e100_init_module(void) 31881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3189f26251eb68ea766a98fed922593c154d15127621Bruce Allan if (((1 << debug) - 1) & NETIF_MSG_DRV) { 3190fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); 3191fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches pr_info("%s\n", DRV_COPYRIGHT); 31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3193299176206b266f204be859adf9e66efd06628ab2Jeff Garzik return pci_register_driver(&e100_driver); 31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit e100_cleanup_module(void) 31971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver(&e100_driver); 31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(e100_init_module); 32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(e100_cleanup_module); 3203