e100.c revision 0bf61e66a09793aba617e8918fbf739cd5db8e78
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 }
211a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(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;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 rx_over_length_errors;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 eeprom_wc;
628aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro	__le16 eeprom[256];
629ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	spinlock_t mdio_lock;
6307e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	const struct firmware *fw;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void e100_write_flush(struct nic *nic)
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Flush previous PCI writes through intermediate bridges
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * by doing a benign read */
63727345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	(void)ioread8(&nic->csr->scb.status);
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
640858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void e100_enable_irq(struct nic *nic)
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&nic->cmd_lock, flags);
64527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic);
647ad8c48ad3bbef078616ed4d2652d362dfd962f09Catalin(ux aka Dino) BOIE	spin_unlock_irqrestore(&nic->cmd_lock, flags);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
650858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void e100_disable_irq(struct nic *nic)
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&nic->cmd_lock, flags);
65527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi);
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic);
657ad8c48ad3bbef078616ed4d2652d362dfd962f09Catalin(ux aka Dino) BOIE	spin_unlock_irqrestore(&nic->cmd_lock, flags);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_hw_reset(struct nic *nic)
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Put CU and RU into idle with a selective reset to get
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device off of PCI bus */
66427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite32(selective_reset, &nic->csr->port);
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic); udelay(20);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now fully reset device */
66827345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite32(software_reset, &nic->csr->port);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic); udelay(20);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Mask off our interrupt line - it's unmasked after reset */
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_disable_irq(nic);
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_self_test(struct nic *nic)
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest);
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Passing the self-test is a pretty good indication
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that the device can DMA to/from host memory */
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mem->selftest.signature = 0;
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mem->selftest.result = 0xFFFFFFFF;
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
68527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite32(selftest | dma_addr, &nic->csr->port);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Wait 10 msec for self-test to complete */
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(10);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Interrupts are enabled after self-test */
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_disable_irq(nic);
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check results of self-test */
694f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->mem->selftest.result != 0) {
695fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, hw, nic->netdev,
696fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  "Self-test failed: result=0x%08X\n",
697fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  nic->mem->selftest.result);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ETIMEDOUT;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
700f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->mem->selftest.signature == 0) {
701fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, hw, nic->netdev, "Self-test failed: timed out\n");
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ETIMEDOUT;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
708aaf918ba8cf941a6aa7dc52c307470b48259a751Al Virostatic void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data)
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 cmd_addr_data[3];
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 ctrl;
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Three cmds: write/erase enable, write data, write/erase disable */
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd_addr_data[0] = op_ewen << (addr_len - 2);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) |
717aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro		le16_to_cpu(data);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd_addr_data[2] = op_ewds << (addr_len - 2);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Bit-bang cmds to write word to eeprom */
721f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (j = 0; j < 3; j++) {
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Chip select */
72427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_write_flush(nic); udelay(4);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
727f26251eb68ea766a98fed922593c154d15127621Bruce Allan		for (i = 31; i >= 0; i--) {
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ctrl = (cmd_addr_data[j] & (1 << i)) ?
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				eecs | eedi : eecs;
73027345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg			iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e100_write_flush(nic); udelay(4);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
73327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg			iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e100_write_flush(nic); udelay(4);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Wait 10 msec for cmd to complete */
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(10);
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Chip deselect */
74027345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		iowrite8(0, &nic->csr->eeprom_ctrl_lo);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_write_flush(nic); udelay(4);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* General technique stolen from the eepro100 driver - very clever */
746aaf918ba8cf941a6aa7dc52c307470b48259a751Al Virostatic __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 cmd_addr_data;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data = 0;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 ctrl;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd_addr_data = ((op_read << *addr_len) | addr) << 16;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Chip select */
75627345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic); udelay(4);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Bit-bang to read word from eeprom */
760f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (i = 31; i >= 0; i--) {
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
76227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_write_flush(nic); udelay(4);
7640547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg
76527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_write_flush(nic); udelay(4);
7670547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Eeprom drives a dummy zero to EEDO after receiving
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * complete address.  Use this to adjust addr_len. */
77027345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		ctrl = ioread8(&nic->csr->eeprom_ctrl_lo);
771f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (!(ctrl & eedo) && i > 16) {
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*addr_len -= (i - 16);
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i = 17;
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7750547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = (data << 1) | (ctrl & eedo ? 1 : 0);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Chip deselect */
78027345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(0, &nic->csr->eeprom_ctrl_lo);
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic); udelay(4);
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
783aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro	return cpu_to_le16(data);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Load entire EEPROM image into driver cache and validate checksum */
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_eeprom_load(struct nic *nic)
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 addr, addr_len = 8, checksum = 0;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Try reading with an 8-bit addr len to discover actual addr len */
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_eeprom_read(nic, &addr_len, 0);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->eeprom_wc = 1 << addr_len;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
795f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (addr = 0; addr < nic->eeprom_wc; addr++) {
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
797f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (addr < nic->eeprom_wc - 1)
798aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro			checksum += le16_to_cpu(nic->eeprom[addr]);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The checksum, stored in the last word, is calculated such that
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the sum of words should be 0xBABA */
803aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro	if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) {
804fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n");
8058fb6f732c389847dece403b7470d6d3d2778804aDavid S. Miller		if (!eeprom_bad_csum_allow)
8068fb6f732c389847dece403b7470d6d3d2778804aDavid S. Miller			return -EAGAIN;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Save (portion of) driver EEPROM cache to device and update checksum */
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 addr, addr_len = 8, checksum = 0;
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Try reading with an 8-bit addr len to discover actual addr len */
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_eeprom_read(nic, &addr_len, 0);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->eeprom_wc = 1 << addr_len;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (start + count >= nic->eeprom_wc)
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
824f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (addr = start; addr < start + count; addr++)
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]);
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The checksum, stored in the last word, is calculated such that
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the sum of words should be 0xBABA */
829f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (addr = 0; addr < nic->eeprom_wc - 1; addr++)
830aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro		checksum += le16_to_cpu(nic->eeprom[addr]);
831aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro	nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->eeprom[nic->eeprom_wc - 1]);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
838962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
839e6280f26b43775d8fa0c54e50c92491cfccbf738Malli Chilakala#define E100_WAIT_SCB_FAST 20       /* delay like the old code */
840858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&nic->cmd_lock, flags);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Previous command is accepted when SCB clears */
849f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
850f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (likely(!ioread8(&nic->csr->scb.cmd_lo)))
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
853f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (unlikely(i > E100_WAIT_SCB_FAST))
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(5);
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
856f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EAGAIN;
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_unlock;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(cmd != cuc_resume))
86227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		iowrite32(dma_addr, &nic->csr->scb.gen_ptr);
86327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(cmd, &nic->csr->scb.cmd_lo);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_unlock:
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&nic->cmd_lock, flags);
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cb *cb;
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&nic->cb_lock, flags);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
880f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(!nic->cbs_avail)) {
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_unlock;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb = nic->cb_to_use;
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cb_to_use = cb->next;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cbs_avail--;
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->skb = skb;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
890f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(!nic->cbs_avail))
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOSPC;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb_prepare(nic, cb, skb);
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Order is important otherwise we'll be in a race with h/w:
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * set S-bit in current first, then clear S-bit in previous. */
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->command |= cpu_to_le16(cb_s);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->prev->command &= cpu_to_le16(~cb_s);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901f26251eb68ea766a98fed922593c154d15127621Bruce Allan	while (nic->cb_to_send != nic->cb_to_use) {
902f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->cb_to_send->dma_addr))) {
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Ok, here's where things get sticky.  It's
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * possible that we can't schedule the command
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * because the controller is too busy, so
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * let's just queue the command and try again
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * when another command is scheduled. */
909f26251eb68ea766a98fed922593c154d15127621Bruce Allan			if (err == -ENOSPC) {
910962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala				//request a reset
911962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala				schedule_work(&nic->tx_timeout_task);
912962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala			}
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->cuc_cmd = cuc_resume;
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->cb_to_send = nic->cb_to_send->next;
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_unlock:
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&nic->cb_lock, flags);
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
926720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic int mdio_read(struct net_device *netdev, int addr, int reg)
927720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{
928720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	struct nic *nic = netdev_priv(netdev);
929720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0);
930720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr}
931720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
932720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic void mdio_write(struct net_device *netdev, int addr, int reg, int data)
933720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{
934720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	struct nic *nic = netdev_priv(netdev);
935720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
936720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	nic->mdio_ctrl(nic, addr, mdi_write, reg, data);
937720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr}
938720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
939720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr/* the standard mdio_ctrl() function for usual MII-compliant hardware */
940720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 data_out = 0;
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i;
944ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	unsigned long flags;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
946ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael
947ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	/*
948ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	 * Stratus87247: we shouldn't be writing the MDI control
949ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	 * register until the Ready bit shows True.  Also, since
950ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	 * manipulation of the MDI control registers is a multi-step
951ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	 * procedure it should be done under lock.
952ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	 */
953ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	spin_lock_irqsave(&nic->mdio_lock, flags);
954ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	for (i = 100; i; --i) {
95527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready)
956ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael			break;
957ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael		udelay(20);
958ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	}
959ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	if (unlikely(!i)) {
960fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n");
961ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael		spin_unlock_irqrestore(&nic->mdio_lock, flags);
962ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael		return 0;		/* No way to indicate timeout error */
963ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	}
96427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
966ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	for (i = 0; i < 100; i++) {
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(20);
96827345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready)
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
971ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	spin_unlock_irqrestore(&nic->mdio_lock, flags);
972fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
973fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
974fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     dir == mdi_read ? "READ" : "WRITE",
975fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     addr, reg, data, data_out);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (u16)data_out;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
979720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */
980720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic u16 mdio_ctrl_phy_82552_v(struct nic *nic,
981720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				 u32 addr,
982720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				 u32 dir,
983720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				 u32 reg,
984720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				 u16 data)
985720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{
986720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	if ((reg == MII_BMCR) && (dir == mdi_write)) {
987720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) {
988720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			u16 advert = mdio_read(nic->netdev, nic->mii.phy_id,
989720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr							MII_ADVERTISE);
990720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
991720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			/*
992720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			 * Workaround Si issue where sometimes the part will not
993720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			 * autoneg to 100Mbps even when advertised.
994720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			 */
995720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			if (advert & ADVERTISE_100FULL)
996720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				data |= BMCR_SPEED100 | BMCR_FULLDPLX;
997720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			else if (advert & ADVERTISE_100HALF)
998720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				data |= BMCR_SPEED100;
999720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		}
1000720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	}
1001720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	return mdio_ctrl_hw(nic, addr, dir, reg, data);
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1004720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr/* Fully software-emulated mdio_ctrl() function for cards without
1005720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * MII-compliant PHYs.
1006720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * For now, this is mainly geared towards 80c24 support; in case of further
1007720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * requirements for other types (i82503, ...?) either extend this mechanism
1008720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr * or split it, whichever is cleaner.
1009720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr */
1010720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic u16 mdio_ctrl_phy_mii_emulated(struct nic *nic,
1011720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				      u32 addr,
1012720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				      u32 dir,
1013720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				      u32 reg,
1014720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				      u16 data)
1015720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{
1016720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	/* might need to allocate a netdev_priv'ed register array eventually
1017720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	 * to be able to record state changes, but for now
1018720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	 * some fully hardcoded register handling ought to be ok I guess. */
1019720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
1020720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	if (dir == mdi_read) {
1021720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		switch (reg) {
1022720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		case MII_BMCR:
1023720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			/* Auto-negotiation, right? */
1024720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			return  BMCR_ANENABLE |
1025720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				BMCR_FULLDPLX;
1026720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		case MII_BMSR:
1027720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			return	BMSR_LSTATUS /* for mii_link_ok() */ |
1028720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				BMSR_ANEGCAPABLE |
1029720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				BMSR_10FULL;
1030720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		case MII_ADVERTISE:
1031720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			/* 80c24 is a "combo card" PHY, right? */
1032720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			return	ADVERTISE_10HALF |
1033720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr				ADVERTISE_10FULL;
1034720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		default:
1035fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1036fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				     "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
1037fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				     dir == mdi_read ? "READ" : "WRITE",
1038fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				     addr, reg, data);
1039720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			return 0xFFFF;
1040720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		}
1041720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	} else {
1042720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		switch (reg) {
1043720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		default:
1044fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1045fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				     "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
1046fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				     dir == mdi_read ? "READ" : "WRITE",
1047fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				     addr, reg, data);
1048720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			return 0xFFFF;
1049720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		}
1050b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan	}
1051720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr}
1052720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic inline int e100_phy_supports_mii(struct nic *nic)
1053720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{
1054720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	/* for now, just check it by comparing whether we
1055720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	   are using MII software emulation.
1056720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	*/
1057720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated);
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_defaults(struct nic *nic)
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10622afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg	struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
10632afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg	struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
106644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
1067f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->mac == mac_unknown)
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->mac = mac_82557_D100_A;
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->params.rfds = rfds;
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->params.cbs = cbs;
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Quadwords to DMA into FIFO before starting frame transmit */
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->tx_threshold = 0xE0;
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10760a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr	/* no interrupt for every tx completion, delay = 256us if not 557 */
1077962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala	nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf |
1078962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala		((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Template for a freshly allocated RFD */
10817734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	nic->blank_rfd.command = 0;
10821172899a30d0c26df934d63cc98241cd53fe7130Al Viro	nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF);
1083719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN);
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* MII setup */
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mii.phy_id_mask = 0x1F;
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mii.reg_num_mask = 0x1F;
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mii.dev = nic->netdev;
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mii.mdio_read = mdio_read;
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mii.mdio_write = mdio_write;
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct config *config = &cb->u.config;
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *c = (u8 *)config;
1097719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	struct net_device *netdev = nic->netdev;
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->command = cpu_to_le16(cb_config);
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(config, 0, sizeof(struct config));
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->byte_count = 0x16;		/* bytes in this struct */
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->rx_fifo_limit = 0x8;		/* bytes in FIFO before DMA */
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->direct_rx_dma = 0x1;		/* reserved */
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->standard_tcb = 0x1;		/* 1=standard, 0=extended */
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->standard_stat_counter = 0x1;	/* 1=standard, 0=extended */
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->rx_discard_short_frames = 0x1;	/* 1=discard, 0=pass */
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->tx_underrun_retry = 0x3;	/* # of underrun retries */
1110720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	if (e100_phy_supports_mii(nic))
1111720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		config->mii_mode = 1;           /* 1=MII mode, 0=i82503 mode */
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->pad10 = 0x6;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->no_source_addr_insertion = 0x1;	/* 1=no, 0=yes */
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->preamble_length = 0x2;		/* 0=1, 1=3, 2=7, 3=15 bytes */
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->ifs = 0x6;			/* x16 = inter frame spacing */
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->ip_addr_hi = 0xF2;		/* ARP IP filter - not used */
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->pad15_1 = 0x1;
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->pad15_2 = 0x1;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->crs_or_cdt = 0x0;		/* 0=CRS only, 1=CRS or CDT */
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->fc_delay_hi = 0x40;		/* time delay for fc frame */
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->tx_padding = 0x1;		/* 1=pad short frames */
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->fc_priority_threshold = 0x7;	/* 7=priority fc disabled */
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->pad18 = 0x1;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->full_duplex_pin = 0x1;		/* 1=examine FDX# pin */
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->pad20_1 = 0x1F;
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->fc_priority_location = 0x1;	/* 1=byte#31, 0=byte#19 */
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->pad21_1 = 0x5;
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->adaptive_ifs = nic->adaptive_ifs;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config->loopback = nic->loopback;
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1132f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->mii.force_media && nic->mii.full_duplex)
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->full_duplex_force = 0x1;	/* 1=force, 0=auto */
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1135f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->flags & promiscuous || nic->loopback) {
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->rx_save_bad_frames = 0x1;	/* 1=save, 0=discard */
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->rx_discard_short_frames = 0x0;	/* 1=discard, 0=save */
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->promiscuous_mode = 0x1;		/* 1=on, 0=off */
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	if (unlikely(netdev->features & NETIF_F_RXFCS))
1142719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear		config->rx_crc_transfer = 0x1;	/* 1=save, 0=discard */
1143719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear
1144f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->flags & multicast_all)
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->multicast_all = 0x1;		/* 1=accept, 0=no */
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11476bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala	/* disable WoL when up */
1148f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (netif_running(nic->netdev) || !(nic->flags & wol_magic))
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->magic_packet_disable = 0x1;	/* 1=off, 0=on */
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->mac >= mac_82558_D101_A4) {
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->fc_disable = 0x1;	/* 1=Tx fc off, 0=Tx fc on */
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->mwi_enable = 0x1;	/* 1=enable, 0=disable */
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->standard_tcb = 0x0;	/* 1=standard, 0=extended */
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config->rx_long_ok = 0x1;	/* 1=VLANs ok, 0=standard */
115644e4925e4601961b9bd1982008a55fce865d318cDavid Graham		if (nic->mac >= mac_82559_D101M) {
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			config->tno_intr = 0x1;		/* TCO stats enable */
115844e4925e4601961b9bd1982008a55fce865d318cDavid Graham			/* Enable TCO in extended config */
115944e4925e4601961b9bd1982008a55fce865d318cDavid Graham			if (nic->mac >= mac_82551_10) {
116044e4925e4601961b9bd1982008a55fce865d318cDavid Graham				config->byte_count = 0x20; /* extended bytes */
116144e4925e4601961b9bd1982008a55fce865d318cDavid Graham				config->rx_d102_mode = 0x1; /* GMRC for TCO */
116244e4925e4601961b9bd1982008a55fce865d318cDavid Graham			}
116344e4925e4601961b9bd1982008a55fce865d318cDavid Graham		} else {
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			config->standard_stat_counter = 0x0;
116544e4925e4601961b9bd1982008a55fce865d318cDavid Graham		}
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11680bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	if (netdev->features & NETIF_F_RXALL) {
11690bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear		config->rx_save_overruns = 0x1; /* 1=save, 0=discard */
11700bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear		config->rx_save_bad_frames = 0x1;       /* 1=save, 0=discard */
11710bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear		config->rx_discard_short_frames = 0x0;  /* 1=discard, 0=save */
11720bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	}
11730bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear
1174fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1175fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
1176fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
1177fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1178fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
1179fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
1180fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1181fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
1182fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11852afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg/*************************************************************************
11862afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*  CPUSaver parameters
11872afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*
11882afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*  All CPUSaver parameters are 16-bit literals that are part of a
11892afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*  "move immediate value" instruction.  By changing the value of
11902afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*  the literal in the instruction before the code is loaded, the
11912afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*  driver can change the algorithm.
11922afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*
11930779bf2d2ecc4d9b1e9437ae659f50e6776a7666Matt LaPlante*  INTDELAY - This loads the dead-man timer with its initial value.
11940547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg*    When this timer expires the interrupt is asserted, and the
11952afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    timer is reset each time a new packet is received.  (see
11962afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    BUNDLEMAX below to set the limit on number of chained packets)
11972afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    The current default is 0x600 or 1536.  Experiments show that
11982afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    the value should probably stay within the 0x200 - 0x1000.
11992afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*
12000547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg*  BUNDLEMAX -
12012afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    This sets the maximum number of frames that will be bundled.  In
12022afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    some situations, such as the TCP windowing algorithm, it may be
12032afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    better to limit the growth of the bundle size than let it go as
12042afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    high as it can, because that could cause too much added latency.
12052afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    The default is six, because this is the number of packets in the
12062afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    default TCP window size.  A value of 1 would make CPUSaver indicate
12072afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    an interrupt for every frame received.  If you do not want to put
12082afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    a limit on the bundle size, set this value to xFFFF.
12092afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*
12100547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg*  BUNDLESMALL -
12112afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    This contains a bit-mask describing the minimum size frame that
12122afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    will be bundled.  The default masks the lower 7 bits, which means
12132afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    that any frame less than 128 bytes in length will not be bundled,
12142afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    but will instead immediately generate an interrupt.  This does
12152afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    not affect the current bundle in any way.  Any frame that is 128
12162afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    bytes or large will be bundled normally.  This feature is meant
12172afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    to provide immediate indication of ACK frames in a TCP environment.
12182afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    Customers were seeing poor performance when a machine with CPUSaver
12192afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    enabled was sending but not receiving.  The delay introduced when
12202afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    the ACKs were received was enough to reduce total throughput, because
12212afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    the sender would sit idle until the ACK was finally seen.
12222afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*
12232afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    The current default is 0xFF80, which masks out the lower 7 bits.
12242afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    This means that any frame which is x7F (127) bytes or smaller
12250547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg*    will cause an immediate interrupt.  Because this value must be a
12262afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    bit mask, there are only a few valid values that can be used.  To
12272afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    turn this feature off, the driver can write the value xFFFF to the
12282afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    lower word of this instruction (in the same way that the other
12292afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    parameters are used).  Likewise, a value of 0xF800 (2047) would
12302afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    cause an interrupt to be generated for every frame, because all
12312afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*    standard Ethernet frames are <= 2047 bytes in length.
12322afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg*************************************************************************/
12332afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg
12340547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg/* if you wish to disable the ucode functionality, while maintaining the
12352afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * workarounds it provides, set the following defines to:
12362afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * BUNDLESMALL 0
12372afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * BUNDLEMAX 1
12382afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg * INTDELAY 1
12392afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg */
12402afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg#define BUNDLESMALL 1
12412afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg#define BUNDLEMAX (u16)6
12422afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg#define INTDELAY (u16)1536 /* 0x600 */
12432afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg
12449ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput/* Initialize firmware */
12459ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajputstatic const struct firmware *e100_request_firmware(struct nic *nic)
12469ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput{
12479ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	const char *fw_name;
12487e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	const struct firmware *fw = nic->fw;
12499ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	u8 timer, bundle, min_size;
12507e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	int err = 0;
12519ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
12522afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg	/* do not load u-code for ICH devices */
12532afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg	if (nic->flags & ich)
12549ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		return NULL;
12552afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg
125644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	/* Search for ucode match against h/w revision */
12579ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	if (nic->mac == mac_82559_D101M)
12589ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		fw_name = FIRMWARE_D101M;
12599ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	else if (nic->mac == mac_82559_D101S)
12609ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		fw_name = FIRMWARE_D101S;
12619ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10)
12629ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		fw_name = FIRMWARE_D102E;
12639ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	else /* No ucode on other devices */
12649ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		return NULL;
12659ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
12667e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	/* If the firmware has not previously been loaded, request a pointer
12677e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	 * to it. If it was previously loaded, we are reinitializing the
12687e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	 * adapter, possibly in a resume from hibernate, in which case
12697e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	 * request_firmware() cannot be used.
12707e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	 */
12717e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	if (!fw)
12727e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham		err = request_firmware(&fw, fw_name, &nic->pdev->dev);
12737e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham
12749ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	if (err) {
1275fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev,
1276fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  "Failed to load firmware \"%s\": %d\n",
1277fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  fw_name, err);
12789ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		return ERR_PTR(err);
12799ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	}
12807e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham
12819ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	/* Firmware should be precisely UCODE_SIZE (words) plus three bytes
12829ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	   indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */
12839ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	if (fw->size != UCODE_SIZE * 4 + 3) {
1284fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev,
1285fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  "Firmware \"%s\" has wrong size %zu\n",
1286fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  fw_name, fw->size);
12879ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		release_firmware(fw);
12889ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		return ERR_PTR(-EINVAL);
12892afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg	}
12902afecc047e9077d8dc9e312b32e944955e71ce53Jesse Brandeburg
12919ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	/* Read timer, bundle and min_size from end of firmware blob */
12929ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	timer = fw->data[UCODE_SIZE * 4];
12939ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	bundle = fw->data[UCODE_SIZE * 4 + 1];
12949ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	min_size = fw->data[UCODE_SIZE * 4 + 2];
12959ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
12969ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE ||
12979ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	    min_size >= UCODE_SIZE) {
1298fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev,
1299fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n",
1300fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  fw_name, timer, bundle, min_size);
13019ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		release_firmware(fw);
13029ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		return ERR_PTR(-EINVAL);
13039ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	}
13047e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham
13057e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	/* OK, firmware is validated and ready to use. Save a pointer
13067e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	 * to it in the nic */
13077e15b0c9991dfe0bf05a2f8fab9154bb7827622eDavid Graham	nic->fw = fw;
13089ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	return fw;
130924180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg}
131024180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg
13119ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajputstatic void e100_setup_ucode(struct nic *nic, struct cb *cb,
13129ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput			     struct sk_buff *skb)
131324180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg{
13149ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	const struct firmware *fw = (void *)skb;
13159ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	u8 timer, bundle, min_size;
13169ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
13179ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	/* It's not a real skb; we just abused the fact that e100_exec_cb
13189ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	   will pass it through to here... */
13199ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->skb = NULL;
13209ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
13219ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	/* firmware is stored as little endian already */
13229ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4);
13239ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
13249ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	/* Read timer, bundle and min_size from end of firmware blob */
13259ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	timer = fw->data[UCODE_SIZE * 4];
13269ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	bundle = fw->data[UCODE_SIZE * 4 + 1];
13279ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	min_size = fw->data[UCODE_SIZE * 4 + 2];
13289ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
13299ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	/* Insert user-tunable settings in cb->u.ucode */
13309ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000);
13319ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->u.ucode[timer] |= cpu_to_le32(INTDELAY);
13329ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000);
13339ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX);
13349ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000);
13359ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);
13369ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
13379ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	cb->command = cpu_to_le16(cb_ucode | cb_el);
13389ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput}
13399ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
13409ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajputstatic inline int e100_load_ucode_wait(struct nic *nic)
13419ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput{
13429ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	const struct firmware *fw;
134324180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	int err = 0, counter = 50;
134424180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	struct cb *cb = nic->cb_to_clean;
134524180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg
13469ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	fw = e100_request_firmware(nic);
13479ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	/* If it's NULL, then no ucode is required */
13489ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	if (!fw || IS_ERR(fw))
13499ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput		return PTR_ERR(fw);
13509ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput
13519ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode)))
1352fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev,
1353fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			  "ucode cmd failed with error %d\n", err);
13540547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg
135524180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	/* must restart cuc */
135624180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	nic->cuc_cmd = cuc_start;
135724180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg
135824180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	/* wait for completion */
135924180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	e100_write_flush(nic);
136024180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	udelay(10);
136124180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg
136224180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	/* wait for possibly (ouch) 500ms */
136324180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	while (!(cb->status & cpu_to_le16(cb_complete))) {
136424180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg		msleep(10);
136524180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg		if (!--counter) break;
136624180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	}
13670547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg
13683a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. Day	/* ack any interrupts, something could have been set */
136927345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(~0, &nic->csr->scb.stat_ack);
137024180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg
137124180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	/* if the command failed, or is not OK, notify and return */
137224180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
1373fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "ucode load failed\n");
137424180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg		err = -EPERM;
137524180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	}
13760547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg
137724180333206519e6b0c4633eab81e773b4527cacJesse Brandeburg	return err;
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb)
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->command = cpu_to_le16(cb_iaaddr);
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN);
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->command = cpu_to_le16(cb_dump);
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr +
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		offsetof(struct mem, dump_buf));
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1394720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohrstatic int e100_phy_check_without_mii(struct nic *nic)
1395720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr{
1396720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	u8 phy_type;
1397720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	int without_mii;
1398720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
1399720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f;
1400720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
1401720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	switch (phy_type) {
1402720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	case NoSuchPhy: /* Non-MII PHY; UNTESTED! */
1403720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	case I82503: /* Non-MII PHY; UNTESTED! */
1404720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	case S80C24: /* Non-MII PHY; tested and working */
1405720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		/* paragraph from the FreeBSD driver, "FXP_PHY_80C24":
1406720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter
1407720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * doesn't have a programming interface of any sort.  The
1408720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * media is sensed automatically based on how the link partner
1409720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * is configured.  This is, in essence, manual configuration.
1410720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 */
1411fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_info(nic, probe, nic->netdev,
1412fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			   "found MII-less i82503 or 80c24 or other PHY\n");
1413720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
1414720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated;
1415720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */
1416720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
1417720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		/* these might be needed for certain MII-less cards...
1418720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * nic->flags |= ich;
1419720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * nic->flags |= ich_10h_workaround; */
1420720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
1421720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		without_mii = 1;
1422720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		break;
1423720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	default:
1424720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		without_mii = 0;
1425720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		break;
1426720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	}
1427720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	return without_mii;
1428720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr}
1429720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NCONFIG_AUTO_SWITCH	0x0080
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_NSC_CONG		MII_RESV1
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NSC_CONG_ENABLE		0x0100
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NSC_CONG_TXREADY	0x0400
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADVERTISE_FC_SUPPORTED	0x0400
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_phy_init(struct nic *nic)
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *netdev = nic->netdev;
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 addr;
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 bmcr, stat, id_lo, id_hi, cong;
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
1442f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (addr = 0; addr < 32; addr++) {
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
1447f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1450720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	if (addr == 32) {
1451720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		/* uhoh, no PHY detected: check whether we seem to be some
1452720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * weird, rare variant which is *known* to not have any MII.
1453720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * But do this AFTER MII checking only, since this does
1454720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		 * lookup of EEPROM values which may easily be unreliable. */
1455720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		if (e100_phy_check_without_mii(nic))
1456720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			return 0; /* simply return and hope for the best */
1457720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		else {
1458720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			/* for unknown cases log a fatal error */
1459fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			netif_err(nic, hw, nic->netdev,
1460fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				  "Failed to locate any known PHY, aborting\n");
1461720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr			return -EAGAIN;
1462720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		}
1463720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	} else
1464fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1465fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			     "phy_addr = %d\n", nic->mii.phy_id);
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get phy ID */
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->phy = (u32)id_hi << 16 | (u32)id_lo;
1471fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1472fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "phy ID = 0x%08X\n", nic->phy);
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14748fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	/* Select the phy and isolate the rest */
14758fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	for (addr = 0; addr < 32; addr++) {
14768fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan		if (addr != nic->mii.phy_id) {
14778fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan			mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
14788fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan		} else if (nic->phy != phy_82552_v) {
14798fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan			bmcr = mdio_read(netdev, addr, MII_BMCR);
14808fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan			mdio_write(netdev, addr, MII_BMCR,
14818fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan				bmcr & ~BMCR_ISOLATE);
14828fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan		}
14838fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	}
14848fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	/*
14858fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	 * Workaround for 82552:
14868fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	 * Clear the ISOLATE bit on selected phy_id last (mirrored on all
14878fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	 * other phy_id's) using bmcr value from addr discovery loop above.
14888fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	 */
14898fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan	if (nic->phy == phy_82552_v)
14908fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan		mdio_write(netdev, nic->mii.phy_id, MII_BMCR,
14918fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan			bmcr & ~BMCR_ISOLATE);
14928fbd962e39517dfb2bfd363eba4b51cdfa299593Bruce Allan
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Handle National tx phys */
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NCS_PHY_MODEL_MASK	0xFFF0FFFF
1495f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable congestion control */
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG);
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cong |= NSC_CONG_TXREADY;
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cong &= ~NSC_CONG_ENABLE;
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1503b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan	if (nic->phy == phy_82552_v) {
1504b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
1505b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan
1506720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		/* assign special tweaked mdio_ctrl() function */
1507720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr		nic->mdio_ctrl = mdio_ctrl_phy_82552_v;
1508720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr
1509b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		/* Workaround Si not advertising flow-control during autoneg */
1510b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1511b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);
1512b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan
1513b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		/* Reset for the above changes to take effect */
1514b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
1515b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		bmcr |= BMCR_RESET;
1516b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
1517b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan	} else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
151860ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
151960ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher		!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
152060ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher		/* enable/disable MDI/MDI-X auto-switching. */
152160ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
152260ffa478759f39a2eb3be1ed179bc3764804b2c8Jeff Kirsher				nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
1523648951451e6d2d532d4ace2f8e9c5cdf1d563e83Malli Chilakala	}
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_hw_init(struct nic *nic)
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1530dca97ad2ec37aa98c45dfe1d531d9ba7048e814eEmil Tantilov	int err = 0;
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_hw_reset(nic);
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1534fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_err(nic, hw, nic->netdev, "e100_hw_init\n");
1535f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!in_interrupt() && (err = e100_self_test(nic)))
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1538f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_phy_init(nic)))
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1540f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_exec_cmd(nic, cuc_load_base, 0)))
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1542f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_exec_cmd(nic, ruc_load_base, 0)))
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
15449ac32e1bc0518b01b47dd34a733dce8634a38ed3Jaswinder Singh Rajput	if ((err = e100_load_ucode_wait(nic)))
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1546f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_exec_cb(nic, NULL, e100_configure)))
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1548f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1550f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_exec_cmd(nic, cuc_dump_addr,
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->dma_addr + offsetof(struct mem, stats))))
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1553f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_disable_irq(nic);
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *netdev = nic->netdev;
156422bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	struct netdev_hw_addr *ha;
15654cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko	u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS);
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->command = cpu_to_le16(cb_multi);
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
156948e2f183cb1709600012265a2e723f45a350d5feJiri Pirko	i = 0;
157022bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	netdev_for_each_mc_addr(ha, netdev) {
157148e2f183cb1709600012265a2e723f45a350d5feJiri Pirko		if (i == count)
157248e2f183cb1709600012265a2e723f45a350d5feJiri Pirko			break;
157322bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko		memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr,
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ETH_ALEN);
157548e2f183cb1709600012265a2e723f45a350d5feJiri Pirko	}
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_set_multicast_list(struct net_device *netdev)
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1582fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
1583fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "mc_count=%d, flags=0x%04X\n",
1584fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     netdev_mc_count(netdev), netdev->flags);
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1586f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (netdev->flags & IFF_PROMISC)
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags |= promiscuous;
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags &= ~promiscuous;
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (netdev->flags & IFF_ALLMULTI ||
15924cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko		netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS)
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags |= multicast_all;
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags &= ~multicast_all;
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_exec_cb(nic, NULL, e100_configure);
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_exec_cb(nic, NULL, e100_multi);
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_update_stats(struct nic *nic)
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
160309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik	struct net_device *dev = nic->netdev;
160409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik	struct net_device_stats *ns = &dev->stats;
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct stats *s = &nic->mem->stats;
1606aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro	__le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause :
1607aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro		(nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames :
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		&s->complete;
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Device's stats reporting may take several microseconds to
16110a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr	 * complete, so we're always waiting for results of the
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * previous command. */
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1614f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (*complete == cpu_to_le32(cuc_dump_reset_complete)) {
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*complete = 0;
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->tx_frames = le32_to_cpu(s->tx_good_frames);
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions);
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions);
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs);
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns);
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->collisions += nic->tx_collisions;
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(s->tx_lost_crs);
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->rx_over_length_errors;
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
1631ecf7130b087a9bd1b9d03dbf452630243210d22eJohn W. Linville		ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(s->rx_alignment_errors) +
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(s->rx_short_frame_errors) +
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(s->rx_cdt_errors);
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->tx_deferred += le32_to_cpu(s->tx_deferred);
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->tx_single_collisions +=
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(s->tx_single_collisions);
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->tx_multiple_collisions +=
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le32_to_cpu(s->tx_multiple_collisions);
1641f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (nic->mac >= mac_82558_D101_A4) {
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause);
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause);
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->rx_fc_unsupported +=
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				le32_to_cpu(s->fc_rcv_unsupported);
1646f26251eb68ea766a98fed922593c154d15127621Bruce Allan			if (nic->mac >= mac_82559_D101M) {
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				nic->tx_tco_frames +=
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					le16_to_cpu(s->xmt_tco_frames);
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				nic->rx_tco_frames +=
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					le16_to_cpu(s->rcv_tco_frames);
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16550547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg
1656f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (e100_exec_cmd(nic, cuc_dump_reset, 0))
1657fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
1658fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			     "exec cuc_dump_reset failed\n");
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Adjust inter-frame-spacing (IFS) between two transmits if
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we're getting collisions on a half-duplex connection. */
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1666f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (duplex == DUPLEX_HALF) {
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 prev = nic->adaptive_ifs;
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 min_frames = (speed == SPEED_100) ? 1000 : 100;
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1670f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if ((nic->tx_frames / 32 < nic->tx_collisions) &&
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   (nic->tx_frames > min_frames)) {
1672f26251eb68ea766a98fed922593c154d15127621Bruce Allan			if (nic->adaptive_ifs < 60)
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				nic->adaptive_ifs += 5;
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (nic->tx_frames < min_frames) {
1675f26251eb68ea766a98fed922593c154d15127621Bruce Allan			if (nic->adaptive_ifs >= 5)
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				nic->adaptive_ifs -= 5;
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1678f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (nic->adaptive_ifs != prev)
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e100_exec_cb(nic, NULL, e100_configure);
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_watchdog(unsigned long data)
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = (struct nic *)data;
16868ae6daca85c8bbd6a32c382db5e2a2a989f8bed2David Decotigny	struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
168725db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny	u32 speed;
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1689fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, timer, KERN_DEBUG, nic->netdev,
1690fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "right now = %ld\n", jiffies);
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* mii library handles link maintenance tasks */
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mii_ethtool_gset(&nic->mii, &cmd);
169525db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny	speed = ethtool_cmd_speed(&cmd);
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1697f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
1698fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n",
169925db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny			    speed == SPEED_100 ? 100 : 10,
1700fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			    cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
1701f26251eb68ea766a98fed922593c154d15127621Bruce Allan	} else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
1702fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netdev_info(nic->netdev, "NIC Link is Down\n");
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mii_check_link(&nic->mii);
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Software generated interrupt to recover from (rare) Rx
17080547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg	 * allocation failure.
17090547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg	 * Unfortunately have to use a spinlock to not re-enable interrupts
17100547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg	 * accidentally, due to hardware that shares a register between the
17110547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg	 * interrupt mask bit and the SW Interrupt generation bit */
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irq(&nic->cmd_lock);
171327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_write_flush(nic);
1715ad8c48ad3bbef078616ed4d2652d362dfd962f09Catalin(ux aka Dino) BOIE	spin_unlock_irq(&nic->cmd_lock);
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_update_stats(nic);
171825db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny	e100_adjust_adaptive_ifs(nic, speed, cmd.duplex);
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1720f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->mac <= mac_82557_D100_C)
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Issue a multicast command to workaround a 557 lock up */
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_set_multicast_list(nic->netdev);
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
172425db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny	if (nic->flags & ich && speed == SPEED_10 && cmd.duplex == DUPLEX_HALF)
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags |= ich_10h_workaround;
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags &= ~ich_10h_workaround;
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
173034c6417b7087a4818e7dca2e5d66c3361cee80a1Stephen Hemminger	mod_timer(&nic->watchdog,
173134c6417b7087a4818e7dca2e5d66c3361cee80a1Stephen Hemminger		  round_jiffies(jiffies + E100_WATCHDOG_PERIOD));
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1734858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void e100_xmit_prepare(struct nic *nic, struct cb *cb,
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb)
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->command = nic->tx_command;
173875f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear
173975f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear	/*
174075f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear	 * Use the last 4 bytes of the SKB payload packet as the CRC, used for
174175f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear	 * testing, ie sending frames with bad CRC.
174275f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear	 */
174375f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear	if (unlikely(skb->no_fcs))
174475f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear		cb->command |= __constant_cpu_to_le16(cb_tx_nc);
174575f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear	else
174675f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear		cb->command &= ~__constant_cpu_to_le16(cb_tx_nc);
174775f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear
1748962082b6df11fe8cabafd2971b07c914cd52ee2aMalli Chilakala	/* interrupt every 16 packets regardless of delay */
1749f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((nic->cbs_avail & ~15) == nic->cbs_avail)
1750996ec3533ae15424e339089a8045ca1c998f8a87Malli Chilakala		cb->command |= cpu_to_le16(cb_i);
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.tcb.tcb_byte_count = 0;
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.tcb.threshold = nic->tx_threshold;
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.tcb.tbd_count = 1;
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb->data, skb->len, PCI_DMA_TODEVICE));
1757611494dccacb3e42f55359df74d604b67312598bMalli Chilakala	/* check for mapping failure? */
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17613b29a56d31d585d39bf9ffe9ef1f10bd637ee0f1Stephen Hemmingerstatic netdev_tx_t e100_xmit_frame(struct sk_buff *skb,
17623b29a56d31d585d39bf9ffe9ef1f10bd637ee0f1Stephen Hemminger				   struct net_device *netdev)
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1767f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->flags & ich_10h_workaround) {
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   Issue a NOP command followed by a 1us delay before
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   issuing the Tx command. */
1771f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (e100_exec_cmd(nic, cuc_nop, 0))
1772fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
1773fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches				     "exec cuc_nop failed\n");
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(1);
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = e100_exec_cb(nic, skb, e100_xmit_prepare);
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1779f26251eb68ea766a98fed922593c154d15127621Bruce Allan	switch (err) {
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case -ENOSPC:
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We queued the skb, but now we're out of space. */
1782fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
1783fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			     "No space for CB\n");
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_stop_queue(netdev);
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case -ENOMEM:
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* This is a hard error - log it. */
1788fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
1789fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			     "Out of Tx resources, returning skb\n");
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_stop_queue(netdev);
17915b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy		return NETDEV_TX_BUSY;
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17946ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1797858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_tx_clean(struct nic *nic)
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
179909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik	struct net_device *dev = nic->netdev;
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cb *cb;
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int tx_cleaned = 0;
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&nic->cb_lock);
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clean CBs marked complete */
1806f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (cb = nic->cb_to_clean;
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    cb->status & cpu_to_le16(cb_complete);
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    cb = nic->cb_to_clean = cb->next) {
18092d0bb1c1f4524befe9f0fcf0d0cd3081a451223fJeff Kirsher		rmb(); /* read skb after status */
1810fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev,
1811fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			     "cb[%d]->status = 0x%04X\n",
1812fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			     (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)),
1813fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			     cb->status);
1814dc45010e28bc4a1bfa6043eee31d1c59e93e1546Jesse Brandeburg
1815f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (likely(cb->skb != NULL)) {
181609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.tx_packets++;
181709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.tx_bytes += cb->skb->len;
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_unmap_single(nic->pdev,
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				le32_to_cpu(cb->u.tcb.tbd.buf_addr),
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				le16_to_cpu(cb->u.tcb.tbd.size),
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				PCI_DMA_TODEVICE);
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_kfree_skb_any(cb->skb);
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cb->skb = NULL;
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tx_cleaned = 1;
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cb->status = 0;
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->cbs_avail++;
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&nic->cb_lock);
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Recover from running out of Tx resources in xmit_frame */
1834f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_wake_queue(nic->netdev);
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return tx_cleaned;
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_clean_cbs(struct nic *nic)
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1842f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->cbs) {
1843f26251eb68ea766a98fed922593c154d15127621Bruce Allan		while (nic->cbs_avail != nic->params.cbs.count) {
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct cb *cb = nic->cb_to_clean;
1845f26251eb68ea766a98fed922593c154d15127621Bruce Allan			if (cb->skb) {
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_unmap_single(nic->pdev,
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					le32_to_cpu(cb->u.tcb.tbd.buf_addr),
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					le16_to_cpu(cb->u.tcb.tbd.size),
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					PCI_DMA_TODEVICE);
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev_kfree_skb(cb->skb);
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->cb_to_clean = nic->cb_to_clean->next;
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->cbs_avail++;
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
185598468efddb101f8a29af974101c17ba513b07be1Roger Oksanen		pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr);
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->cbs = NULL;
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->cbs_avail = 0;
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cuc_cmd = cuc_start;
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean =
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->cbs;
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_alloc_cbs(struct nic *nic)
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cb *cb;
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i, count = nic->params.cbs.count;
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cuc_cmd = cuc_start;
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL;
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cbs_avail = 0;
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
187398468efddb101f8a29af974101c17ba513b07be1Roger Oksanen	nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL,
187498468efddb101f8a29af974101c17ba513b07be1Roger Oksanen				  &nic->cbs_dma_addr);
1875f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!nic->cbs)
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
187770abc8cb90e679d8519721e2761d8366a18212a6Roger Oksanen	memset(nic->cbs, 0, count * sizeof(struct cb));
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1879f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cb->link = cpu_to_le32(nic->cbs_dma_addr +
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((i+1) % count) * sizeof(struct cb));
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->cbs_avail = count;
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1894ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzikstatic inline void e100_start_receiver(struct nic *nic, struct rx *rx)
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1896f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!nic->rxs) return;
1897f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (RU_SUSPENDED != nic->ru_running) return;
1898ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik
1899ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	/* handle init time starts */
1900f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!rx) rx = nic->rxs;
1901ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik
1902ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	/* (Re)start RU if suspended or idle and RFA is non-NULL */
1903f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (rx->skb) {
1904ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik		e100_exec_cmd(nic, ruc_start, rx->dma_addr);
1905ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik		nic->ru_running = RU_RUNNING;
1906ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	}
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1909719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
1910858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
191289d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet	if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN)))
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191589d71a66c40d629e3b1285def543ab1425558cd5Eric Dumazet	/* Init, and map the RFD. */
191627d7ff46a3498d3debc6ba68fb8014c702b81170Arnaldo Carvalho de Melo	skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd));
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19208d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori	if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) {
19211f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala		dev_kfree_skb_any(rx->skb);
1922097688ef4710648db335c3c4fa243751f60b330aLuiz Fernando Capitulino		rx->skb = NULL;
19231f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala		rx->dma_addr = 0;
19241f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala		return -ENOMEM;
19251f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala	}
19261f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Link the RFD to end of RFA by linking previous RFD to
19287734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * this one.  We are safe to touch the previous RFD because
19297734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * it is protected by the before last buffer's el bit being set */
1930aaf918ba8cf941a6aa7dc52c307470b48259a751Al Viro	if (rx->prev->skb) {
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
19326caf52a453d5fe0bc584a2895bfd39a3d9054829Harvey Harrison		put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
19331923815d855e1daec931fc9f2221fb73ca708870Kevin Hao		pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
1934773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg			sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1940858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic int e100_rx_indicate(struct nic *nic, struct rx *rx,
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int *work_done, unsigned int work_to_do)
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
194309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik	struct net_device *dev = nic->netdev;
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = rx->skb;
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct rfd *rfd = (struct rfd *)skb->data;
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 rfd_status, actual_size;
1947719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	u16 fcs_pad = 0;
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1949f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(work_done && *work_done >= work_to_do))
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EAGAIN;
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Need to sync before taking a peek at cb_complete bit */
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr,
1954773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg		sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rfd_status = le16_to_cpu(rfd->status);
19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1957fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev,
1958fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "status=0x%04X\n", rfd_status);
19592d0bb1c1f4524befe9f0fcf0d0cd3081a451223fJeff Kirsher	rmb(); /* read size after status bit */
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If data isn't ready, nothing to indicate */
19627734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	if (unlikely(!(rfd_status & cb_complete))) {
19637734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		/* If the next buffer has the el bit, but we think the receiver
19647734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * is still running, check to see if it really stopped while
19657734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * we had interrupts off.
19667734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * This allows for a fast restart without re-enabling
19677734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * interrupts */
19687734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		if ((le16_to_cpu(rfd->command) & cb_el) &&
19697734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		    (RU_RUNNING == nic->ru_running))
19707734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker
197117393dd67c06c3912ff47b31268b648929715336Jiri Slaby			if (ioread8(&nic->csr->scb.status) & rus_no_res)
19727734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker				nic->ru_running = RU_SUSPENDED;
1973303d67c288319768b19ed8dbed429fef7eb7c275Krzysztof Halasa		pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
1974303d67c288319768b19ed8dbed429fef7eb7c275Krzysztof Halasa					       sizeof(struct rfd),
19756ff9c2e7fa8ca63a575792534b63c5092099c286Krzysztof Hałasa					       PCI_DMA_FROMDEVICE);
19761f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala		return -ENODATA;
19777734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	}
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get actual data size */
1980719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	if (unlikely(dev->features & NETIF_F_RXFCS))
1981719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear		fcs_pad = 4;
19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
1983f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		actual_size = RFD_BUF_LEN - sizeof(struct rfd);
19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get data */
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unmap_single(nic->pdev, rx->dma_addr,
1988773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19907734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	/* If this buffer has the el bit, but we think the receiver
19917734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * is still running, check to see if it really stopped while
19927734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * we had interrupts off.
19937734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * This allows for a fast restart without re-enabling interrupts.
19947734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * This can happen when the RU sees the size change but also sees
19957734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * the el bit set. */
19967734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	if ((le16_to_cpu(rfd->command) & cb_el) &&
19977734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	    (RU_RUNNING == nic->ru_running)) {
19987734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker
199917393dd67c06c3912ff47b31268b648929715336Jiri Slaby	    if (ioread8(&nic->csr->scb.status) & rus_no_res)
2000ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik		nic->ru_running = RU_SUSPENDED;
20017734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	}
2002ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Pull off the RFD and put the actual data (minus eth hdr) */
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_reserve(skb, sizeof(struct rfd));
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_put(skb, actual_size);
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb->protocol = eth_type_trans(skb, nic->netdev);
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20080bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	/* If we are receiving all frames, then don't bother
20090bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	 * checking for errors.
20100bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	 */
20110bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	if (unlikely(dev->features & NETIF_F_RXALL)) {
20120bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear		if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad)
20130bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear			/* Received oversized frame, but keep it. */
20140bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear			nic->rx_over_length_errors++;
20150bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear		goto process_skb;
20160bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	}
20170bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear
2018f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (unlikely(!(rfd_status & cb_ok))) {
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Don't indicate if hardware indicates errors */
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_kfree_skb_any(skb);
2021719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	} else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad) {
20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Don't indicate oversized frames */
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->rx_over_length_errors++;
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_kfree_skb_any(skb);
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
20260bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greearprocess_skb:
202709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik		dev->stats.rx_packets++;
2028719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear		dev->stats.rx_bytes += (actual_size - fcs_pad);
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_receive_skb(skb);
2030f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (work_done)
20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(*work_done)++;
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rx->skb = NULL;
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2039858119e159384308a5dde67776691a2ebf70df0fArjan van de Venstatic void e100_rx_clean(struct nic *nic, unsigned int *work_done,
20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int work_to_do)
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct rx *rx;
20437734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	int restart_required = 0, err = 0;
20447734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	struct rx *old_before_last_rx, *new_before_last_rx;
20457734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	struct rfd *old_before_last_rfd, *new_before_last_rfd;
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Indicate newly arrived packets */
2048f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
20497734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		err = e100_rx_indicate(nic, rx, work_done, work_to_do);
20507734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		/* Hit quota or no more to clean */
20517734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		if (-EAGAIN == err || -ENODATA == err)
2052ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik			break;
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20557734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker
20567734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	/* On EAGAIN, hit quota so have more work to do, restart once
20577734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * cleanup is complete.
20587734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * Else, are we already rnr? then pay attention!!! this ensures that
20597734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * the state machine progression never allows a start with a
20607734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * partially cleaned list, avoiding a race between hardware
20617734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * and rx_to_clean when in NAPI mode */
20627734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running)
20637734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		restart_required = 1;
20647734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker
20657734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	old_before_last_rx = nic->rx_to_use->prev->prev;
20667734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;
2067ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik
20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Alloc new skbs to refill list */
2069f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
2070f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (unlikely(e100_rx_alloc_skb(nic, rx)))
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break; /* Better luck next time (see watchdog) */
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2073ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik
20747734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	new_before_last_rx = nic->rx_to_use->prev->prev;
20757734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	if (new_before_last_rx != old_before_last_rx) {
20767734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		/* Set the el-bit on the buffer that is before the last buffer.
20777734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * This lets us update the next pointer on the last buffer
20787734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * without worrying about hardware touching it.
20797734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * We set the size to 0 to prevent hardware from touching this
20807734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * buffer.
20817734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * When the hardware hits the before last buffer with el-bit
20827734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * and size of 0, it will RNR interrupt, the RUS will go into
20837734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * the No Resources state.  It will not complete nor write to
20847734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * this buffer. */
20857734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		new_before_last_rfd =
20867734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker			(struct rfd *)new_before_last_rx->skb->data;
20877734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		new_before_last_rfd->size = 0;
20887734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		new_before_last_rfd->command |= cpu_to_le16(cb_el);
20897734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		pci_dma_sync_single_for_device(nic->pdev,
20907734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker			new_before_last_rx->dma_addr, sizeof(struct rfd),
2091773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg			PCI_DMA_BIDIRECTIONAL);
20927734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker
20937734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		/* Now that we have a new stopping point, we can clear the old
20947734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * stopping point.  We must sync twice to get the proper
20957734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		 * ordering on the hardware side of things. */
20967734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
20977734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		pci_dma_sync_single_for_device(nic->pdev,
20987734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker			old_before_last_rx->dma_addr, sizeof(struct rfd),
2099773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg			PCI_DMA_BIDIRECTIONAL);
2100719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear		old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN
2101719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear							+ ETH_FCS_LEN);
21027734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		pci_dma_sync_single_for_device(nic->pdev,
21037734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker			old_before_last_rx->dma_addr, sizeof(struct rfd),
2104773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg			PCI_DMA_BIDIRECTIONAL);
21057734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	}
21067734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker
2107f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (restart_required) {
2108ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik		// ack the rnr?
2109915e91d734d33ad303313e05582769dbbefff3b2Jiri Slaby		iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
21107734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker		e100_start_receiver(nic, nic->rx_to_clean);
2111f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (work_done)
2112ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik			(*work_done)++;
2113ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	}
21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_rx_clean_list(struct nic *nic)
21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct rx *rx;
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i, count = nic->params.rfds.count;
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	nic->ru_running = RU_UNINITIALIZED;
2122ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik
2123f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->rxs) {
2124f26251eb68ea766a98fed922593c154d15127621Bruce Allan		for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
2125f26251eb68ea766a98fed922593c154d15127621Bruce Allan			if (rx->skb) {
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_unmap_single(nic->pdev, rx->dma_addr,
2127773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg					RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev_kfree_skb(rx->skb);
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(nic->rxs);
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->rxs = NULL;
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->rx_to_use = nic->rx_to_clean = NULL;
21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_rx_alloc_list(struct nic *nic)
21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct rx *rx;
21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i, count = nic->params.rfds.count;
21427734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	struct rfd *before_last;
21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->rx_to_use = nic->rx_to_clean = NULL;
2145ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	nic->ru_running = RU_UNINITIALIZED;
21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2147f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2150f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;
2153f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (e100_rx_alloc_skb(nic, rx)) {
21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e100_rx_clean_list(nic);
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21587734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	/* Set the el-bit on the buffer that is before the last buffer.
21597734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * This lets us update the next pointer on the last buffer without
21607734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * worrying about hardware touching it.
21617734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * We set the size to 0 to prevent hardware from touching this buffer.
21627734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * When the hardware hits the before last buffer with el-bit and size
21637734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * of 0, it will RNR interrupt, the RU will go into the No Resources
21647734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	 * state.  It will not complete nor write to this buffer. */
21657734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	rx = nic->rxs->prev->prev;
21667734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	before_last = (struct rfd *)rx->skb->data;
21677734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	before_last->command |= cpu_to_le16(cb_el);
21687734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	before_last->size = 0;
21697734f6e6bcd7ba78b00e93e74a4ddafd9886cdeaDavid Acker	pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
2170773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg		sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->rx_to_use = nic->rx_to_clean = nic->rxs;
2173ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	nic->ru_running = RU_SUSPENDED;
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21787d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t e100_intr(int irq, void *dev_id)
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *netdev = dev_id;
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
218227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	u8 stat_ack = ioread8(&nic->csr->scb.stat_ack);
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2184fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, intr, KERN_DEBUG, nic->netdev,
2185fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "stat_ack = 0x%02X\n", stat_ack);
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2187f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (stat_ack == stat_ack_not_ours ||	/* Not our interrupt */
21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   stat_ack == stat_ack_not_present)	/* Hardware is ejected */
21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_NONE;
21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Ack interrupt(s) */
219227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	iowrite8(stat_ack, &nic->csr->scb.stat_ack);
21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2194ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	/* We hit Receive No Resource (RNR); restart RU after cleaning */
2195f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (stat_ack & stat_ack_rnr)
2196ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik		nic->ru_running = RU_SUSPENDED;
2197ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik
2198288379f050284087578b77e04f040b57db3db3f8Ben Hutchings	if (likely(napi_schedule_prep(&nic->napi))) {
21990685c31b58a69e41393e974f6e6b8e0a4eadcf0bMalli Chilakala		e100_disable_irq(nic);
2200288379f050284087578b77e04f040b57db3db3f8Ben Hutchings		__napi_schedule(&nic->napi);
22010685c31b58a69e41393e974f6e6b8e0a4eadcf0bMalli Chilakala	}
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2206bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int e100_poll(struct napi_struct *napi, int budget)
22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2208bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	struct nic *nic = container_of(napi, struct nic, napi);
2209ddfce6bb43c6bf1c9956e7a65ce1b2e19a156bd2Stephen Hemminger	unsigned int work_done = 0;
22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	e100_rx_clean(nic, &work_done, budget);
221253e52c729cc169db82a6105fac7a166e10c2ec36David S. Miller	e100_tx_clean(nic);
22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221453e52c729cc169db82a6105fac7a166e10c2ec36David S. Miller	/* If budget not fully consumed, exit the polling mode */
221553e52c729cc169db82a6105fac7a166e10c2ec36David S. Miller	if (work_done < budget) {
2216288379f050284087578b77e04f040b57db3db3f8Ben Hutchings		napi_complete(napi);
22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_enable_irq(nic);
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2220bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	return work_done;
22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_NET_POLL_CONTROLLER
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_netpoll(struct net_device *netdev)
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
2227611494dccacb3e42f55359df74d604b67312598bMalli Chilakala
22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_disable_irq(nic);
22297d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells	e100_intr(nic->pdev->irq, netdev);
22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_tx_clean(nic);
22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_enable_irq(nic);
22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_mac_address(struct net_device *netdev, void *p)
22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sockaddr *addr = p;
22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!is_valid_ether_addr(addr->sa_data))
22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EADDRNOTAVAIL;
22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_exec_cb(nic, NULL, e100_setup_iaaddr);
22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_change_mtu(struct net_device *netdev, int new_mtu)
22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2251f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netdev->mtu = new_mtu;
22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_asf(struct nic *nic)
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ASF can be enabled from eeprom */
2260807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
2263807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE);
22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_up(struct nic *nic)
22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2270f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_rx_alloc_list(nic)))
22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
2272f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_alloc_cbs(nic)))
22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_rx_clean_list;
2274f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_hw_init(nic)))
22751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_clean_cbs;
22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_set_multicast_list(nic->netdev);
2277ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	e100_start_receiver(nic, NULL);
22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mod_timer(&nic->watchdog, jiffies);
2279f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->netdev->name, nic->netdev)))
22811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_no_irq;
22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_wake_queue(nic->netdev);
2283bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	napi_enable(&nic->napi);
22840236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala	/* enable ints _after_ enabling poll, preventing a race between
22850236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala	 * disable ints+schedule */
22860236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala	e100_enable_irq(nic);
22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_no_irq:
22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer_sync(&nic->watchdog);
22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_clean_cbs:
22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_clean_cbs(nic);
22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_rx_clean_list:
22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_rx_clean_list(nic);
22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_down(struct nic *nic)
22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23000236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala	/* wait here for poll to complete */
2301bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	napi_disable(&nic->napi);
23020236ebb7ae85935b3b96eef7e8a4e203ea9958a0Malli Chilakala	netif_stop_queue(nic->netdev);
23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_hw_reset(nic);
23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(nic->pdev->irq, nic->netdev);
23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer_sync(&nic->watchdog);
23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_carrier_off(nic->netdev);
23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_clean_cbs(nic);
23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_rx_clean_list(nic);
23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_tx_timeout(struct net_device *netdev)
23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23150547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg	/* Reset outside of interrupt context, to avoid request_irq
23162acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala	 * in interrupt context */
23172acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala	schedule_work(&nic->tx_timeout_task);
23182acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala}
23192acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala
2320c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void e100_tx_timeout_task(struct work_struct *work)
23212acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala{
2322c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct nic *nic = container_of(work, struct nic, tx_timeout_task);
2323c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct net_device *netdev = nic->netdev;
23242acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala
2325fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
2326fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		     "scb.status=0x%02X\n", ioread8(&nic->csr->scb.status));
2327401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox
2328401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox	rtnl_lock();
2329401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox	if (netif_running(netdev)) {
2330401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox		e100_down(netdev_priv(netdev));
2331401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox		e100_up(netdev_priv(netdev));
2332401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox	}
2333401da6aea31ef69c2fcd260382adabdcf7ce820aAlan Cox	rtnl_unlock();
23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Use driver resources to perform internal MAC or PHY
23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * loopback test.  A single packet is prepared and transmitted
23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * in loopback mode, and the test passes if the received
23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * packet compares byte-for-byte to the transmitted packet. */
23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2346f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_rx_alloc_list(nic)))
23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
2348f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_alloc_cbs(nic)))
23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_clean_rx;
23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ICH PHY loopback is broken so do MAC loopback instead */
2352f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->flags & ich && loopback_mode == lb_phy)
23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		loopback_mode = lb_mac;
23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->loopback = loopback_mode;
2356f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_hw_init(nic)))
23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_loopback_none;
23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2359f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (loopback_mode == lb_phy)
23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BMCR_LOOPBACK);
23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2363ca93ca428b8e09973f19e2725bf19cb3f1836034Jeff Garzik	e100_start_receiver(nic, NULL);
23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2365f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_loopback_none;
23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_put(skb, ETH_DATA_LEN);
23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(skb->data, 0xFF, ETH_DATA_LEN);
23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_xmit_frame(skb, nic->netdev);
23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(10);
23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2375aa49cdd93be6328113f0c146fc72be173d578d27Jesse Brandeburg	pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
2376773c9c1f77174429ad2feb1735a3beb33ff3b6c0Jesse Brandeburg			RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
2377aa49cdd93be6328113f0c146fc72be173d578d27Jesse Brandeburg
2378f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   skb->data, ETH_DATA_LEN))
23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EAGAIN;
23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_loopback_none:
23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->loopback = lb_none;
23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_clean_cbs(nic);
2386aa49cdd93be6328113f0c146fc72be173d578d27Jesse Brandeburg	e100_hw_reset(nic);
23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_clean_rx:
23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_rx_clean_list(nic);
23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_LED_CONTROL	0x1B
2393b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_LED_OVERRIDE 0x19
2394b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_LED_ON       0x000F /* LEDTX and LED_RX both on */
2395b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_LED_OFF      0x000A /* LEDTX and LED_RX both off */
23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mii_ethtool_gset(&nic->mii, cmd);
24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET);
24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mii_ethtool_sset(&nic->mii, cmd);
24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_exec_cb(nic, NULL, e100_configure);
24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_drvinfo(struct net_device *netdev,
24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_drvinfo *info)
24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
241923020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
242023020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
242123020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->bus_info, pci_name(nic->pdev),
242223020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones		sizeof(info->bus_info));
24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2425abf9b902059fb1d569b64e8645a76f0fccbdbbe5Auke Kok#define E100_PHY_REGS 0x1C
24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_regs_len(struct net_device *netdev)
24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
2429abf9b902059fb1d569b64e8645a76f0fccbdbbe5Auke Kok	return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf);
24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_regs(struct net_device *netdev,
24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_regs *regs, void *p)
24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 *buff = p;
24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
243944c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	regs->version = (1 << 24) | nic->pdev->revision;
244027345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
244127345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		ioread8(&nic->csr->scb.cmd_lo) << 16 |
244227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg		ioread16(&nic->csr->scb.status);
2443f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (i = E100_PHY_REGS; i >= 0; i--)
24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buff[1 + E100_PHY_REGS - i] =
24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mdio_read(netdev, nic->mii.phy_id, i);
24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_exec_cb(nic, NULL, e100_dump);
24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(10);
24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sizeof(nic->mem->dump_buf));
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wol->supported = (nic->mac >= mac_82558_D101_A4) ?  WAKE_MAGIC : 0;
24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0;
24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2464bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki	if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) ||
2465bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki	    !device_can_wakeup(&nic->pdev->dev))
24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EOPNOTSUPP;
24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2468f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (wol->wolopts)
24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags |= wol_magic;
24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags &= ~wol_magic;
24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2473bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki	device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts);
2474bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki
24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_exec_cb(nic, NULL, e100_configure);
24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 e100_get_msglevel(struct net_device *netdev)
24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return nic->msg_enable;
24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_set_msglevel(struct net_device *netdev, u32 value)
24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->msg_enable = value;
24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_nway_reset(struct net_device *netdev)
24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mii_nway_restart(&nic->mii);
24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 e100_get_link(struct net_device *netdev)
24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mii_link_ok(&nic->mii);
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_eeprom_len(struct net_device *netdev)
25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return nic->eeprom_wc << 1;
25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E100_EEPROM_MAGIC	0x1234
25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_get_eeprom(struct net_device *netdev,
25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_eeprom *eeprom, u8 *bytes)
25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeprom->magic = E100_EEPROM_MAGIC;
25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len);
25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_eeprom(struct net_device *netdev,
25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_eeprom *eeprom, u8 *bytes)
25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2527f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (eeprom->magic != E100_EEPROM_MAGIC)
25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len);
25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e100_eeprom_save(nic, eeprom->offset >> 1,
25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(eeprom->len >> 1) + 1);
25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_ringparam(struct net_device *netdev,
25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_ringparam *ring)
25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct param_range *rfds = &nic->params.rfds;
25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct param_range *cbs = &nic->params.cbs;
25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->rx_max_pending = rfds->max;
25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->tx_max_pending = cbs->max;
25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->rx_pending = rfds->count;
25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->tx_pending = cbs->count;
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_set_ringparam(struct net_device *netdev,
25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_ringparam *ring)
25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct param_range *rfds = &nic->params.rfds;
25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct param_range *cbs = &nic->params.cbs;
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25560547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2559f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (netif_running(netdev))
25601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_down(nic);
25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rfds->count = max(ring->rx_pending, rfds->min);
25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rfds->count = min(rfds->count, rfds->max);
25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cbs->count = max(ring->tx_pending, cbs->min);
25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cbs->count = min(cbs->count, cbs->max);
2565fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_info(nic, drv, nic->netdev, "Ring Param settings: rx: %d, tx %d\n",
2566fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		   rfds->count, cbs->count);
2567f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (netif_running(netdev))
25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_up(nic);
25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
25711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char e100_gstrings_test[][ETH_GSTRING_LEN] = {
25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Link test     (on/offline)",
25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Eeprom test   (on/offline)",
25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Self test        (offline)",
25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Mac loopback     (offline)",
25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Phy loopback     (offline)",
25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
25804c3616cdda0632a3d0e39069765f9ea0e6bd093eAlejandro Martinez Ruiz#define E100_TEST_LEN	ARRAY_SIZE(e100_gstrings_test)
25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_diag_test(struct net_device *netdev,
25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_test *test, u64 *data)
25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_cmd cmd;
25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, err;
25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(data, 0, E100_TEST_LEN * sizeof(u64));
25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[0] = !mii_link_ok(&nic->mii);
25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[1] = e100_eeprom_load(nic);
2592f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (test->flags & ETH_TEST_FL_OFFLINE) {
25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* save speed, duplex & autoneg settings */
25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = mii_ethtool_gset(&nic->mii, &cmd);
25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2597f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (netif_running(netdev))
25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e100_down(nic);
25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data[2] = e100_self_test(nic);
26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data[3] = e100_loopback_test(nic, lb_mac);
26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data[4] = e100_loopback_test(nic, lb_phy);
26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* restore speed, duplex & autoneg settings */
26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = mii_ethtool_sset(&nic->mii, &cmd);
26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2606f26251eb68ea766a98fed922593c154d15127621Bruce Allan		if (netif_running(netdev))
26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e100_up(nic);
26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2609f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (i = 0; i < E100_TEST_LEN; i++)
26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
2611a074fb860846937a4a46dbbf439cbbb2e2ba960cMalli Chilakala
2612a074fb860846937a4a46dbbf439cbbb2e2ba960cMalli Chilakala	msleep_interruptible(4 * 1000);
26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2615a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsherstatic int e100_set_phys_id(struct net_device *netdev,
2616a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher			    enum ethtool_phys_id_state state)
26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
2619a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	enum led_state {
2620a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		led_on     = 0x01,
2621a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		led_off    = 0x04,
2622a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		led_on_559 = 0x05,
2623a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		led_on_557 = 0x07,
2624a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	};
2625b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan	u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE :
2626a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		MII_LED_CONTROL;
2627a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	u16 leds = 0;
2628a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher
2629a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	switch (state) {
2630a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	case ETHTOOL_ID_ACTIVE:
2631a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		return 2;
26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2633a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	case ETHTOOL_ID_ON:
2634a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		leds = (nic->phy == phy_82552_v) ? E100_82552_LED_ON :
2635a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		       (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559;
2636a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		break;
2637a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher
2638a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	case ETHTOOL_ID_OFF:
2639a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		leds = (nic->phy == phy_82552_v) ? E100_82552_LED_OFF : led_off;
2640a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		break;
2641a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher
2642a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	case ETHTOOL_ID_INACTIVE:
2643a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher		break;
2644a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	}
26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2646a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	mdio_write(netdev, nic->mii.phy_id, led_reg, leds);
26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
26481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
26521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
26531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
26561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"tx_heartbeat_errors", "tx_window_errors",
26571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* device-specific stats */
26581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"tx_deferred", "tx_single_collisions", "tx_multi_collisions",
26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"tx_flow_control_pause", "rx_flow_control_pause",
26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets",
26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E100_NET_STATS_LEN	21
26634c3616cdda0632a3d0e39069765f9ea0e6bd093eAlejandro Martinez Ruiz#define E100_STATS_LEN	ARRAY_SIZE(e100_gstrings_stats)
26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2665b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzikstatic int e100_get_sset_count(struct net_device *netdev, int sset)
26661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2667b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	switch (sset) {
2668b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	case ETH_SS_TEST:
2669b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik		return E100_TEST_LEN;
2670b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	case ETH_SS_STATS:
2671b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik		return E100_STATS_LEN;
2672b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	default:
2673b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik		return -EOPNOTSUPP;
2674b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	}
26751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_ethtool_stats(struct net_device *netdev,
26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ethtool_stats *stats, u64 *data)
26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2683f26251eb68ea766a98fed922593c154d15127621Bruce Allan	for (i = 0; i < E100_NET_STATS_LEN; i++)
268409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik		data[i] = ((unsigned long *)&netdev->stats)[i];
26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->tx_deferred;
26871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->tx_single_collisions;
26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->tx_multiple_collisions;
26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->tx_fc_pause;
26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->rx_fc_pause;
26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->rx_fc_unsupported;
26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->tx_tco_frames;
26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[i++] = nic->rx_tco_frames;
26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2698f26251eb68ea766a98fed922593c154d15127621Bruce Allan	switch (stringset) {
26991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ETH_SS_TEST:
27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test));
27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ETH_SS_STATS:
27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats));
27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27087282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops e100_ethtool_ops = {
27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_settings		= e100_get_settings,
27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_settings		= e100_set_settings,
27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_drvinfo		= e100_get_drvinfo,
27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_regs_len		= e100_get_regs_len,
27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_regs		= e100_get_regs,
27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_wol		= e100_get_wol,
27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_wol		= e100_set_wol,
27161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_msglevel		= e100_get_msglevel,
27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_msglevel		= e100_set_msglevel,
27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.nway_reset		= e100_nway_reset,
27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_link		= e100_get_link,
27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_eeprom_len		= e100_get_eeprom_len,
27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_eeprom		= e100_get_eeprom,
27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_eeprom		= e100_set_eeprom,
27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_ringparam		= e100_get_ringparam,
27241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_ringparam		= e100_set_ringparam,
27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.self_test		= e100_diag_test,
27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_strings		= e100_get_strings,
2727a70b86ae206fdd3bef13c5ac148c22a805e83896Jeff Kirsher	.set_phys_id		= e100_set_phys_id,
27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_ethtool_stats	= e100_get_ethtool_stats,
2729b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	.get_sset_count		= e100_get_sset_count,
27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
27351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL);
27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_alloc(struct nic *nic)
27401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem),
27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		&nic->dma_addr);
27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return nic->mem ? 0 : -ENOMEM;
27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void e100_free(struct nic *nic)
27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2748f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (nic->mem) {
27491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(nic->pdev, sizeof(struct mem),
27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nic->mem, nic->dma_addr);
27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->mem = NULL;
27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_open(struct net_device *netdev)
27561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_carrier_off(netdev);
2761f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_up(nic)))
2762fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n");
27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_close(struct net_device *netdev)
27671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_down(netdev_priv(netdev));
27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
27701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2772719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greearstatic int e100_set_features(struct net_device *netdev,
2773719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear			     netdev_features_t features)
2774719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear{
2775719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	struct nic *nic = netdev_priv(netdev);
2776719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	netdev_features_t changed = features ^ netdev->features;
2777719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear
27780bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	if (!(changed & (NETIF_F_RXFCS | NETIF_F_RXALL)))
2779719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear		return 0;
2780719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear
2781719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	netdev->features = features;
2782719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	e100_exec_cb(nic, NULL, e100_configure);
2783719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	return 0;
2784719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear}
2785719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear
2786acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemmingerstatic const struct net_device_ops e100_netdev_ops = {
2787acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_open		= e100_open,
2788acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_stop		= e100_close,
2789008298231abbeb91bc7be9e8b078607b816d1a4aStephen Hemminger	.ndo_start_xmit		= e100_xmit_frame,
2790acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_validate_addr	= eth_validate_addr,
2791afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= e100_set_multicast_list,
2792acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_set_mac_address	= e100_set_mac_address,
2793acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_change_mtu		= e100_change_mtu,
2794acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_do_ioctl		= e100_do_ioctl,
2795acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_tx_timeout		= e100_tx_timeout,
2796acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger#ifdef CONFIG_NET_POLL_CONTROLLER
2797acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	.ndo_poll_controller	= e100_netpoll,
2798acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger#endif
2799719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	.ndo_set_features	= e100_set_features,
2800acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger};
2801acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger
28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit e100_probe(struct pci_dev *pdev,
28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *ent)
28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *netdev;
28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic;
28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
280941de8d4cff21a2e81e3d9ff66f5f7c903f9c3ab1Joe Perches	if (!(netdev = alloc_etherdev(sizeof(struct nic))))
28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2812719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear	netdev->hw_features |= NETIF_F_RXFCS;
281375f58a537674cdff2122789cfd3cc7a76956ece5Ben Greear	netdev->priv_flags |= IFF_SUPP_NOFCS;
28140bf61e66a09793aba617e8918fbf739cd5db8e78Ben Greear	netdev->hw_features |= NETIF_F_RXALL;
2815719cdac54e0237837251a32a3d690bfe9c1e9bedBen Greear
2816acc784263b0c46f3052fb4f155fdfe39b7001c98Stephen Hemminger	netdev->netdev_ops = &e100_netdev_ops;
28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
28190eb5a34cdf34ad07b6db2df1e523aaf6574601b4Auke Kok	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic = netdev_priv(netdev);
2822bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT);
28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->netdev = netdev;
28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->pdev = pdev;
28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->msg_enable = (1 << debug) - 1;
2826720017623ab294b66c8a95d7bc5ccf75a581ebe4Andreas Mohr	nic->mdio_ctrl = mdio_ctrl_hw;
28271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, netdev);
28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2829f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = pci_enable_device(pdev))) {
2830fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "Cannot enable PCI device, aborting\n");
28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free_dev;
28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2834f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
2835fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "Cannot find proper PCI device base address, aborting\n");
28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENODEV;
28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_disable_pdev;
28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2840f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = pci_request_regions(pdev, DRV_NAME))) {
2841fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "Cannot obtain PCI resources, aborting\n");
28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_disable_pdev;
28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2845284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang	if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
2846fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "No usable DMA configuration, aborting\n");
28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free_res;
28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SET_NETDEV_DEV(netdev, &pdev->dev);
28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
285227345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	if (use_io)
2853fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_info(nic, probe, nic->netdev, "using i/o access mode\n");
285427345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg
285527345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr));
2856f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (!nic->csr) {
2857fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "Cannot map device registers, aborting\n");
28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free_res;
28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2862f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (ent->driver_data)
28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags |= ich;
28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags &= ~ich;
28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_get_defaults(nic);
28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2869243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg	/* D100 MAC doesn't allow rx of vlan packets with normal MTU */
2870243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg	if (nic->mac < mac_82558_D101_A4)
2871243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg		netdev->features |= NETIF_F_VLAN_CHALLENGED;
2872243559f436f26b571ea3a4e70ff082892dc58f16Jesse Brandeburg
28731f53367d5d75ba37f258f6e955d6fc24814051a0Malli Chilakala	/* locks must be initialized before calling hw_reset */
28741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&nic->cb_lock);
28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&nic->cmd_lock);
2876ac7c66698a2c51e4c6a34b84621c79e7cb89e07dODonnell, Michael	spin_lock_init(&nic->mdio_lock);
28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reset the device before pci_set_master() in case device is in some
28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * funky state and has an interrupt pending - hint: we don't have the
28801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * interrupt handler registered yet. */
28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_hw_reset(nic);
28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_master(pdev);
28841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_timer(&nic->watchdog);
28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->watchdog.function = e100_watchdog;
28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nic->watchdog.data = (unsigned long)nic;
28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2889c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task);
28902acdb1e05c1a92e05ee710ed8f226a8f3183d5a0Malli Chilakala
2891f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_alloc(nic))) {
2892fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n");
28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_iounmap;
28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
28951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2896f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = e100_eeprom_load(nic)))
28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free;
28981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2899f92d872876617cddbb0532291034f88941e855fdMalli Chilakala	e100_phy_init(nic);
2900f92d872876617cddbb0532291034f88941e855fdMalli Chilakala
29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
2902a92dd9233ad185904daf95d040cf88c3da2d7ef6John W. Linville	memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
2903948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg	if (!is_valid_ether_addr(netdev->perm_addr)) {
2904948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg		if (!eeprom_bad_csum_allow) {
2905fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n");
2906948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg			err = -EAGAIN;
2907948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg			goto err_out_free;
2908948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg		} else {
2909fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches			netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n");
2910948cd43fed7c7d919fa30e0609b2b5852c4503efJesse Brandeburg		}
29111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Wol magic packet can be enabled from eeprom */
2914f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((nic->mac >= mac_82558_D101_A4) &&
2915bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki	   (nic->eeprom[eeprom_id] & eeprom_id_wol)) {
29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nic->flags |= wol_magic;
2917bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki		device_set_wakeup_enable(&pdev->dev, true);
2918bc79fc8409b3dccbde072e8113cc1fb3fd876fc5Rafael J. Wysocki	}
29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29206bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala	/* ack any pending wake events, disable PME */
2921e7272403d2f9be3dbb7cc185fcc390e781b1af6bRafael J. Wysocki	pci_pme_active(pdev, false);
29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(netdev->name, "eth%d");
2924f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if ((err = register_netdev(netdev))) {
2925fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		netif_err(nic, probe, nic->netdev, "Cannot register net device, aborting\n");
29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free;
29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
292898468efddb101f8a29af974101c17ba513b07be1Roger Oksanen	nic->cbs_pool = pci_pool_create(netdev->name,
292998468efddb101f8a29af974101c17ba513b07be1Roger Oksanen			   nic->pdev,
2930211a0d941b1924e667483f822a55e2cc694cd212David S. Miller			   nic->params.cbs.max * sizeof(struct cb),
293198468efddb101f8a29af974101c17ba513b07be1Roger Oksanen			   sizeof(u32),
293298468efddb101f8a29af974101c17ba513b07be1Roger Oksanen			   0);
2933fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches	netif_info(nic, probe, nic->netdev,
2934fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		   "addr 0x%llx, irq %d, MAC addr %pM\n",
2935fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		   (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0),
2936fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		   pdev->irq, netdev->dev_addr);
29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free:
29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e100_free(nic);
29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_iounmap:
294327345bb684140f5f306963e0d6e25a60c7857dfeJesse Brandeburg	pci_iounmap(pdev, nic->csr);
29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free_res:
29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_release_regions(pdev);
29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_disable_pdev:
29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(pdev);
29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free_dev:
29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, NULL);
29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_netdev(netdev);
29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit e100_remove(struct pci_dev *pdev)
29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *netdev = pci_get_drvdata(pdev);
29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2958f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (netdev) {
29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct nic *nic = netdev_priv(netdev);
29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unregister_netdev(netdev);
29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_free(nic);
2962915e91d734d33ad303313e05582769dbbefff3b2Jiri Slaby		pci_iounmap(pdev, nic->csr);
296398468efddb101f8a29af974101c17ba513b07be1Roger Oksanen		pci_pool_destroy(nic->cbs_pool);
29641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_netdev(netdev);
29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_release_regions(pdev);
29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_disable_device(pdev);
29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_set_drvdata(pdev, NULL);
29681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_SMARTSPEED   0x14   /* SmartSpeed Ctrl register */
2972b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_REV_ANEG     0x0200 /* Reverse auto-negotiation */
2973b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan#define E100_82552_ANEG_NOW     0x0400 /* Auto-negotiate now */
2974ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardostatic void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake)
29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *netdev = pci_get_drvdata(pdev);
29771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
29781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2979824545e7031541f83245d254caca012bf6bdc6cdAuke Kok	if (netif_running(netdev))
2980f902283bbe68639142a00dd23d80ee31e1b00759Auke Kok		e100_down(nic);
2981518d83382568964ca9657511140398ebac925ecdAuke Kok	netif_device_detach(netdev);
2982a53a33da864a81a238ee84055c8ced775ee25350Auke Kok
29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_save_state(pdev);
2984e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok
2985e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok	if ((nic->flags & wol_magic) | e100_asf(nic)) {
2986b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		/* enable reverse auto-negotiation */
2987b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		if (nic->phy == phy_82552_v) {
2988b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan			u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
2989b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan			                           E100_82552_SMARTSPEED);
2990b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan
2991b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan			mdio_write(netdev, nic->mii.phy_id,
2992b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan			           E100_82552_SMARTSPEED, smartspeed |
2993b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan			           E100_82552_REV_ANEG | E100_82552_ANEG_NOW);
2994b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		}
2995ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo		*enable_wake = true;
2996e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok	} else {
2997ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo		*enable_wake = false;
2998e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok	}
2999975b366af66280ed5b852a1a0446586ce71e306eAuke Kok
30008543da6672b0994921f014f2250e27ae81645580Auke Kok	pci_disable_device(pdev);
3001ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo}
30021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3003ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardostatic int __e100_power_off(struct pci_dev *pdev, bool wake)
3004ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo{
30056905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki	if (wake)
3006ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo		return pci_prepare_to_sleep(pdev);
30076905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki
30086905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki	pci_wake_from_d3(pdev, false);
30096905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki	pci_set_power_state(pdev, PCI_D3hot);
30106905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki
30116905b1f1a03a48dcf115a2927f7b87dba8d5e566Rafael J. Wysocki	return 0;
30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
30131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3014f902283bbe68639142a00dd23d80ee31e1b00759Auke Kok#ifdef CONFIG_PM
3015ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardostatic int e100_suspend(struct pci_dev *pdev, pm_message_t state)
3016ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo{
3017ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo	bool wake;
3018ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo	__e100_shutdown(pdev, &wake);
3019ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo	return __e100_power_off(pdev, wake);
3020ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo}
3021ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo
30221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int e100_resume(struct pci_dev *pdev)
30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *netdev = pci_get_drvdata(pdev);
30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nic *nic = netdev_priv(netdev);
30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3027975b366af66280ed5b852a1a0446586ce71e306eAuke Kok	pci_set_power_state(pdev, PCI_D0);
30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_restore_state(pdev);
30296bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala	/* ack any pending wake events, disable PME */
3030975b366af66280ed5b852a1a0446586ce71e306eAuke Kok	pci_enable_wake(pdev, 0, 0);
30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30324b512d26f425be1c779c8319249b42ce3c3424d2Thadeu Lima de Souza Cascardo	/* disable reverse auto-negotiation */
3033b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan	if (nic->phy == phy_82552_v) {
3034b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
3035b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		                           E100_82552_SMARTSPEED);
3036b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan
3037b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		mdio_write(netdev, nic->mii.phy_id,
3038b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		           E100_82552_SMARTSPEED,
3039b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan		           smartspeed & ~(E100_82552_REV_ANEG));
3040b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan	}
3041b55de80e49892002a1878013ab9aee1a30970be6Bruce Allan
30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_device_attach(netdev);
3043975b366af66280ed5b852a1a0446586ce71e306eAuke Kok	if (netif_running(netdev))
30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e100_up(nic);
30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3048975b366af66280ed5b852a1a0446586ce71e306eAuke Kok#endif /* CONFIG_PM */
30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3050d18c3db58bc544fce6662ca7edba616ca9788a70Greg Kroah-Hartmanstatic void e100_shutdown(struct pci_dev *pdev)
30516bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala{
3052ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo	bool wake;
3053ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo	__e100_shutdown(pdev, &wake);
3054ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo	if (system_state == SYSTEM_POWER_OFF)
3055ac7c992cac0c8f276aa8e4a8273204a6db707bb3Thadeu Lima de Souza Cascardo		__e100_power_off(pdev, wake);
30566bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala}
30576bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala
30582cc304923d87403abc103a741382b9af08b6deccAuke Kok/* ------------------ PCI Error Recovery infrastructure  -------------- */
30592cc304923d87403abc103a741382b9af08b6deccAuke Kok/**
30602cc304923d87403abc103a741382b9af08b6deccAuke Kok * e100_io_error_detected - called when PCI error is detected.
30612cc304923d87403abc103a741382b9af08b6deccAuke Kok * @pdev: Pointer to PCI device
30620a0863af0d41e2eea1391e4e5f375a47c5019ab7Andreas Mohr * @state: The current pci connection state
30632cc304923d87403abc103a741382b9af08b6deccAuke Kok */
30642cc304923d87403abc103a741382b9af08b6deccAuke Kokstatic pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
30652cc304923d87403abc103a741382b9af08b6deccAuke Kok{
30662cc304923d87403abc103a741382b9af08b6deccAuke Kok	struct net_device *netdev = pci_get_drvdata(pdev);
3067bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	struct nic *nic = netdev_priv(netdev);
30682cc304923d87403abc103a741382b9af08b6deccAuke Kok
30692cc304923d87403abc103a741382b9af08b6deccAuke Kok	netif_device_detach(netdev);
3070ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch
3071ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch	if (state == pci_channel_io_perm_failure)
3072ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch		return PCI_ERS_RESULT_DISCONNECT;
3073ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch
3074ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch	if (netif_running(netdev))
3075ef681ce1e8b3e63317cd724c200b2fd39286c005Andre Detsch		e100_down(nic);
3076b1d26f24e864204dfaa82b1252477e981ba9ef24Linas Vepstas	pci_disable_device(pdev);
30772cc304923d87403abc103a741382b9af08b6deccAuke Kok
30782cc304923d87403abc103a741382b9af08b6deccAuke Kok	/* Request a slot reset. */
30792cc304923d87403abc103a741382b9af08b6deccAuke Kok	return PCI_ERS_RESULT_NEED_RESET;
30802cc304923d87403abc103a741382b9af08b6deccAuke Kok}
30812cc304923d87403abc103a741382b9af08b6deccAuke Kok
30822cc304923d87403abc103a741382b9af08b6deccAuke Kok/**
30832cc304923d87403abc103a741382b9af08b6deccAuke Kok * e100_io_slot_reset - called after the pci bus has been reset.
30842cc304923d87403abc103a741382b9af08b6deccAuke Kok * @pdev: Pointer to PCI device
30852cc304923d87403abc103a741382b9af08b6deccAuke Kok *
30862cc304923d87403abc103a741382b9af08b6deccAuke Kok * Restart the card from scratch.
30872cc304923d87403abc103a741382b9af08b6deccAuke Kok */
30882cc304923d87403abc103a741382b9af08b6deccAuke Kokstatic pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
30892cc304923d87403abc103a741382b9af08b6deccAuke Kok{
30902cc304923d87403abc103a741382b9af08b6deccAuke Kok	struct net_device *netdev = pci_get_drvdata(pdev);
30912cc304923d87403abc103a741382b9af08b6deccAuke Kok	struct nic *nic = netdev_priv(netdev);
30922cc304923d87403abc103a741382b9af08b6deccAuke Kok
30932cc304923d87403abc103a741382b9af08b6deccAuke Kok	if (pci_enable_device(pdev)) {
3094fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		pr_err("Cannot re-enable PCI device after reset\n");
30952cc304923d87403abc103a741382b9af08b6deccAuke Kok		return PCI_ERS_RESULT_DISCONNECT;
30962cc304923d87403abc103a741382b9af08b6deccAuke Kok	}
30972cc304923d87403abc103a741382b9af08b6deccAuke Kok	pci_set_master(pdev);
30982cc304923d87403abc103a741382b9af08b6deccAuke Kok
30992cc304923d87403abc103a741382b9af08b6deccAuke Kok	/* Only one device per card can do a reset */
31002cc304923d87403abc103a741382b9af08b6deccAuke Kok	if (0 != PCI_FUNC(pdev->devfn))
31012cc304923d87403abc103a741382b9af08b6deccAuke Kok		return PCI_ERS_RESULT_RECOVERED;
31022cc304923d87403abc103a741382b9af08b6deccAuke Kok	e100_hw_reset(nic);
31032cc304923d87403abc103a741382b9af08b6deccAuke Kok	e100_phy_init(nic);
31042cc304923d87403abc103a741382b9af08b6deccAuke Kok
31052cc304923d87403abc103a741382b9af08b6deccAuke Kok	return PCI_ERS_RESULT_RECOVERED;
31062cc304923d87403abc103a741382b9af08b6deccAuke Kok}
31072cc304923d87403abc103a741382b9af08b6deccAuke Kok
31082cc304923d87403abc103a741382b9af08b6deccAuke Kok/**
31092cc304923d87403abc103a741382b9af08b6deccAuke Kok * e100_io_resume - resume normal operations
31102cc304923d87403abc103a741382b9af08b6deccAuke Kok * @pdev: Pointer to PCI device
31112cc304923d87403abc103a741382b9af08b6deccAuke Kok *
31122cc304923d87403abc103a741382b9af08b6deccAuke Kok * Resume normal operations after an error recovery
31132cc304923d87403abc103a741382b9af08b6deccAuke Kok * sequence has been completed.
31142cc304923d87403abc103a741382b9af08b6deccAuke Kok */
31152cc304923d87403abc103a741382b9af08b6deccAuke Kokstatic void e100_io_resume(struct pci_dev *pdev)
31162cc304923d87403abc103a741382b9af08b6deccAuke Kok{
31172cc304923d87403abc103a741382b9af08b6deccAuke Kok	struct net_device *netdev = pci_get_drvdata(pdev);
31182cc304923d87403abc103a741382b9af08b6deccAuke Kok	struct nic *nic = netdev_priv(netdev);
31192cc304923d87403abc103a741382b9af08b6deccAuke Kok
31202cc304923d87403abc103a741382b9af08b6deccAuke Kok	/* ack any pending wake events, disable PME */
31212cc304923d87403abc103a741382b9af08b6deccAuke Kok	pci_enable_wake(pdev, 0, 0);
31222cc304923d87403abc103a741382b9af08b6deccAuke Kok
31232cc304923d87403abc103a741382b9af08b6deccAuke Kok	netif_device_attach(netdev);
31242cc304923d87403abc103a741382b9af08b6deccAuke Kok	if (netif_running(netdev)) {
31252cc304923d87403abc103a741382b9af08b6deccAuke Kok		e100_open(netdev);
31262cc304923d87403abc103a741382b9af08b6deccAuke Kok		mod_timer(&nic->watchdog, jiffies);
31272cc304923d87403abc103a741382b9af08b6deccAuke Kok	}
31282cc304923d87403abc103a741382b9af08b6deccAuke Kok}
31292cc304923d87403abc103a741382b9af08b6deccAuke Kok
31302cc304923d87403abc103a741382b9af08b6deccAuke Kokstatic struct pci_error_handlers e100_err_handler = {
31312cc304923d87403abc103a741382b9af08b6deccAuke Kok	.error_detected = e100_io_error_detected,
31322cc304923d87403abc103a741382b9af08b6deccAuke Kok	.slot_reset = e100_io_slot_reset,
31332cc304923d87403abc103a741382b9af08b6deccAuke Kok	.resume = e100_io_resume,
31342cc304923d87403abc103a741382b9af08b6deccAuke Kok};
31356bdacb1ad58bb6b772a4fc18f21684437bd5f439Malli Chilakala
31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver e100_driver = {
31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name =         DRV_NAME,
31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table =     e100_id_table,
31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe =        e100_probe,
31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove =       __devexit_p(e100_remove),
3141e8e82b76e0312827f5ae04b573a05b02854a447eAuke Kok#ifdef CONFIG_PM
3142975b366af66280ed5b852a1a0446586ce71e306eAuke Kok	/* Power Management hooks */
31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend =      e100_suspend,
31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume =       e100_resume,
31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
31460547993820378ef8140b0470b604737bf1fa6c85Jesse Brandeburg	.shutdown =     e100_shutdown,
31472cc304923d87403abc103a741382b9af08b6deccAuke Kok	.err_handler = &e100_err_handler,
31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init e100_init_module(void)
31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3152f26251eb68ea766a98fed922593c154d15127621Bruce Allan	if (((1 << debug) - 1) & NETIF_MSG_DRV) {
3153fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
3154fa05e1ad1b61b37fb64a66794c11ab478e975c56Joe Perches		pr_info("%s\n", DRV_COPYRIGHT);
31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3156299176206b266f204be859adf9e66efd06628ab2Jeff Garzik	return pci_register_driver(&e100_driver);
31571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit e100_cleanup_module(void)
31601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unregister_driver(&e100_driver);
31621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(e100_init_module);
31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(e100_cleanup_module);
3166