Netdev List
 help / color / mirror / Atom feed
* Re: [DEBUG INFO]IPv6: sleeping function called from invalid context.
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-11-18  0:47 UTC (permalink / raw)
  To: yanzheng; +Cc: netdev, linux-kernel, yoshfuji
In-Reply-To: <437D23EB.4020204@21cn.com>

In article <437D23EB.4020204@21cn.com> (at Fri, 18 Nov 2005 08:44:27 +0800), Yan Zheng <yanzheng@21cn.com> says:

> I get follow message when switch to single user mode and the kernel version is 2.6.15-rc1-git5.
:
> Nov 18 08:26:23 localhost kernel: Debug: sleeping function called from invalid context at mm/slab.c:2472
> Nov 18 08:26:23 localhost kernel: in_atomic():1, irqs_disabled():0
> Nov 18 08:26:23 localhost kernel:  [<c0149d5a>] kmem_cache_alloc+0x5a/0x70
> Nov 18 08:26:23 localhost kernel:  [<e0f47336>] inet6_dump_fib+0xb6/0x110 [ipv6]

I remember someone replaced GFP_ATOMIC with GFP_KERNEL...

--yoshfuji

^ permalink raw reply

* [RFC: 2.6 patch] remove drivers/net/eepro100.c
From: Adrian Bunk @ 2005-11-18  3:33 UTC (permalink / raw)
  To: saw; +Cc: jgarzik, linux-kernel, netdev

This patch removes the obsolete drivers/net/eepro100.c driver.

Is there any reason why it should be kept?


Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

 MAINTAINERS            |    5 
 drivers/net/Kconfig    |   14 
 drivers/net/Makefile   |    1 
 drivers/net/eepro100.c | 2412 -----------------------------------------
 4 files changed, 2432 deletions(-)

--- linux-2.6.15-rc1-mm1-full/MAINTAINERS.old	2005-11-18 03:49:44.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/MAINTAINERS	2005-11-18 03:49:50.000000000 +0100
@@ -868,11 +868,6 @@
 W:	http://ebtables.sourceforge.net/
 S:	Maintained
 
-EEPRO100 NETWORK DRIVER
-P:	Andrey V. Savochkin
-M:	saw@saw.sw.com.sg
-S:	Maintained
-
 EMU10K1 SOUND DRIVER
 P:	James Courtier-Dutton
 M:	James@superbug.demon.co.uk
--- linux-2.6.15-rc1-mm1-full/drivers/net/Kconfig.old	2005-11-18 03:49:59.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/drivers/net/Kconfig	2005-11-18 03:50:13.000000000 +0100
@@ -1405,20 +1405,6 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module
 	  will be called dgrs.
 
-config EEPRO100
-	tristate "EtherExpressPro/100 support (eepro100, original Becker driver)"
-	depends on NET_PCI && PCI
-	select MII
-	help
-	  If you have an Intel EtherExpress PRO/100 PCI network (Ethernet)
-	  card, say Y and read the Ethernet-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  To compile this driver as a module, choose M here and read
-	  <file:Documentation/networking/net-modules.txt>.  The module
-	  will be called eepro100.
-
-
 config E100
 	tristate "Intel(R) PRO/100+ support"
 	depends on NET_PCI && PCI
--- linux-2.6.15-rc1-mm1-full/drivers/net/Makefile.old	2005-11-18 03:50:22.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/drivers/net/Makefile	2005-11-18 03:50:26.000000000 +0100
@@ -40,7 +40,6 @@
 obj-$(CONFIG_TYPHOON) += typhoon.o
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_EEPRO100) += eepro100.o
 obj-$(CONFIG_E100) += e100.o
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_EPIC100) += epic100.o
--- linux-2.6.15-rc1-mm1-full/drivers/net/eepro100.c	2005-10-28 02:02:08.000000000 +0200
+++ /dev/null	2005-11-08 19:07:57.000000000 +0100
@@ -1,2412 +0,0 @@
-/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
-/*
-	Written 1996-1999 by Donald Becker.
-
-	The driver also contains updates by different kernel developers
-	(see incomplete list below).
-	Current maintainer is Andrey V. Savochkin <saw@saw.sw.com.sg>.
-	Please use this email address and linux-kernel mailing list for bug reports.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	This driver is for the Intel EtherExpress Pro100 (Speedo3) design.
-	It should work with all i82557/558/559 boards.
-
-	Version history:
-	1998 Apr - 2000 Feb  Andrey V. Savochkin <saw@saw.sw.com.sg>
-		Serious fixes for multicast filter list setting, TX timeout routine;
-		RX ring refilling logic;  other stuff
-	2000 Feb  Jeff Garzik <jgarzik@pobox.com>
-		Convert to new PCI driver interface
-	2000 Mar 24  Dragan Stancevic <visitor@valinux.com>
-		Disabled FC and ER, to avoid lockups when when we get FCP interrupts.
-	2000 Jul 17 Goutham Rao <goutham.rao@intel.com>
-		PCI DMA API fixes, adding pci_dma_sync_single calls where neccesary
-	2000 Aug 31 David Mosberger <davidm@hpl.hp.com>
-		rx_align support: enables rx DMA without causing unaligned accesses.
-*/
-
-static const char *version =
-"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n"
-"eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
-
-/* A few user-configurable values that apply to all boards.
-   First set is undocumented and spelled per Intel recommendations. */
-
-static int congenb /* = 0 */; /* Enable congestion control in the DP83840. */
-static int txfifo = 8;		/* Tx FIFO threshold in 4 byte units, 0-15 */
-static int rxfifo = 8;		/* Rx FIFO threshold, default 32 bytes. */
-/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
-static int txdmacount = 128;
-static int rxdmacount /* = 0 */;
-
-#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \
-	defined(__arm__)
-  /* align rx buffers to 2 bytes so that IP header is aligned */
-# define rx_align(skb)		skb_reserve((skb), 2)
-# define RxFD_ALIGNMENT		__attribute__ ((aligned (2), packed))
-#else
-# define rx_align(skb)
-# define RxFD_ALIGNMENT
-#endif
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
-   Lower values use more memory, but are faster. */
-static int rx_copybreak = 200;
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
-static int multicast_filter_limit = 64;
-
-/* 'options' is used to pass a transceiver override or full-duplex flag
-   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* A few values that may be tweaked. */
-/* The ring sizes should be a power of two for efficiency. */
-#define TX_RING_SIZE	64
-#define RX_RING_SIZE	64
-/* How much slots multicast filter setup may take.
-   Do not descrease without changing set_rx_mode() implementaion. */
-#define TX_MULTICAST_SIZE   2
-#define TX_MULTICAST_RESERV (TX_MULTICAST_SIZE*2)
-/* Actual number of TX packets queued, must be
-   <= TX_RING_SIZE-TX_MULTICAST_RESERV. */
-#define TX_QUEUE_LIMIT  (TX_RING_SIZE-TX_MULTICAST_RESERV)
-/* Hysteresis marking queue as no longer full. */
-#define TX_QUEUE_UNFULL (TX_QUEUE_LIMIT-4)
-
-/* Operational parameters that usually are not changed. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT		(2*HZ)
-/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
-#define PKT_BUF_SZ		1536
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-
-static int use_io;
-static int debug = -1;
-#define DEBUG_DEFAULT		(NETIF_MSG_DRV		| \
-				 NETIF_MSG_HW		| \
-				 NETIF_MSG_RX_ERR	| \
-				 NETIF_MSG_TX_ERR)
-#define DEBUG			((debug >= 0) ? (1<<debug)-1 : DEBUG_DEFAULT)
-
-
-MODULE_AUTHOR("Maintainer: Andrey V. Savochkin <saw@saw.sw.com.sg>");
-MODULE_DESCRIPTION("Intel i82557/i82558/i82559 PCI EtherExpressPro driver");
-MODULE_LICENSE("GPL");
-module_param(use_io, int, 0);
-module_param(debug, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-module_param(congenb, int, 0);
-module_param(txfifo, int, 0);
-module_param(rxfifo, int, 0);
-module_param(txdmacount, int, 0);
-module_param(rxdmacount, int, 0);
-module_param(rx_copybreak, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param(multicast_filter_limit, int, 0);
-MODULE_PARM_DESC(debug, "debug level (0-6)");
-MODULE_PARM_DESC(options, "Bits 0-3: transceiver type, bit 4: full duplex, bit 5: 100Mbps");
-MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
-MODULE_PARM_DESC(congenb, "Enable congestion control (1)");
-MODULE_PARM_DESC(txfifo, "Tx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(rxfifo, "Rx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(txdmacount, "Tx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rxdmacount, "Rx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rx_copybreak, "copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-MODULE_PARM_DESC(multicast_filter_limit, "maximum number of filtered multicast addresses");
-
-#define RUN_AT(x) (jiffies + (x))
-
-#define netdevice_start(dev)
-#define netdevice_stop(dev)
-#define netif_set_tx_timeout(dev, tf, tm) \
-								do { \
-									(dev)->tx_timeout = (tf); \
-									(dev)->watchdog_timeo = (tm); \
-								} while(0)
-
-
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the Intel i82557 "Speedo3" chip, Intel's
-single-chip fast Ethernet controller for PCI, as used on the Intel
-EtherExpress Pro 100 adapter.
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS should be set to assign the
-PCI INTA signal to an otherwise unused system IRQ line.  While it's
-possible to share PCI interrupt lines, it negatively impacts performance and
-only recent kernels support it.
-
-III. Driver operation
-
-IIIA. General
-The Speedo3 is very similar to other Intel network chips, that is to say
-"apparently designed on a different planet".  This chips retains the complex
-Rx and Tx descriptors and multiple buffers pointers as previous chips, but
-also has simplified Tx and Rx buffer modes.  This driver uses the "flexible"
-Tx mode, but in a simplified lower-overhead manner: it associates only a
-single buffer descriptor with each frame descriptor.
-
-Despite the extra space overhead in each receive skbuff, the driver must use
-the simplified Rx buffer mode to assure that only a single data buffer is
-associated with each RxFD. The driver implements this by reserving space
-for the Rx descriptor at the head of each Rx skbuff.
-
-The Speedo-3 has receive and command unit base addresses that are added to
-almost all descriptor pointers.  The driver sets these to zero, so that all
-pointer fields are absolute addresses.
-
-The System Control Block (SCB) of some previous Intel chips exists on the
-chip in both PCI I/O and memory space.  This driver uses the I/O space
-registers, but might switch to memory mapped mode to better support non-x86
-processors.
-
-IIIB. Transmit structure
-
-The driver must use the complex Tx command+descriptor mode in order to
-have a indirect pointer to the skbuff data section.  Each Tx command block
-(TxCB) is associated with two immediately appended Tx Buffer Descriptor
-(TxBD).  A fixed ring of these TxCB+TxBD pairs are kept as part of the
-speedo_private data structure for each adapter instance.
-
-The newer i82558 explicitly supports this structure, and can read the two
-TxBDs in the same PCI burst as the TxCB.
-
-This ring structure is used for all normal transmit packets, but the
-transmit packet descriptors aren't long enough for most non-Tx commands such
-as CmdConfigure.  This is complicated by the possibility that the chip has
-already loaded the link address in the previous descriptor.  So for these
-commands we convert the next free descriptor on the ring to a NoOp, and point
-that descriptor's link to the complex command.
-
-An additional complexity of these non-transmit commands are that they may be
-added asynchronous to the normal transmit queue, so we disable interrupts
-whenever the Tx descriptor ring is manipulated.
-
-A notable aspect of these special configure commands is that they do
-work with the normal Tx ring entry scavenge method.  The Tx ring scavenge
-is done at interrupt time using the 'dirty_tx' index, and checking for the
-command-complete bit.  While the setup frames may have the NoOp command on the
-Tx ring marked as complete, but not have completed the setup command, this
-is not a problem.  The tx_ring entry can be still safely reused, as the
-tx_skbuff[] entry is always empty for config_cmd and mc_setup frames.
-
-Commands may have bits set e.g. CmdSuspend in the command word to either
-suspend or stop the transmit/command unit.  This driver always flags the last
-command with CmdSuspend, erases the CmdSuspend in the previous command, and
-then issues a CU_RESUME.
-Note: Watch out for the potential race condition here: imagine
-	erasing the previous suspend
-		the chip processes the previous command
-		the chip processes the final command, and suspends
-	doing the CU_RESUME
-		the chip processes the next-yet-valid post-final-command.
-So blindly sending a CU_RESUME is only safe if we do it immediately after
-after erasing the previous CmdSuspend, without the possibility of an
-intervening delay.  Thus the resume command is always within the
-interrupts-disabled region.  This is a timing dependence, but handling this
-condition in a timing-independent way would considerably complicate the code.
-
-Note: In previous generation Intel chips, restarting the command unit was a
-notoriously slow process.  This is presumably no longer true.
-
-IIIC. Receive structure
-
-Because of the bus-master support on the Speedo3 this driver uses the new
-SKBUFF_RX_COPYBREAK scheme, rather than a fixed intermediate receive buffer.
-This scheme allocates full-sized skbuffs as receive buffers.  The value
-SKBUFF_RX_COPYBREAK is used as the copying breakpoint: it is chosen to
-trade-off the memory wasted by passing the full-sized skbuff to the queue
-layer for all frames vs. the copying cost of copying a frame to a
-correctly-sized skbuff.
-
-For small frames the copying cost is negligible (esp. considering that we
-are pre-loading the cache with immediately useful header information), so we
-allocate a new, minimally-sized skbuff.  For large frames the copying cost
-is non-trivial, and the larger copy might flush the cache of useful data, so
-we pass up the skbuff the packet was received into.
-
-IV. Notes
-
-Thanks to Steve Williams of Intel for arranging the non-disclosure agreement
-that stated that I could disclose the information.  But I still resent
-having to sign an Intel NDA when I'm helping Intel sell their own product!
-
-*/
-
-static int speedo_found1(struct pci_dev *pdev, void __iomem *ioaddr, int fnd_cnt, int acpi_idle_state);
-
-enum pci_flags_bit {
-	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
-};
-
-/* Offsets to the various registers.
-   All accesses need not be longword aligned. */
-enum speedo_offsets {
-	SCBStatus = 0, SCBCmd = 2,	/* Rx/Command Unit command and status. */
-	SCBIntmask = 3,
-	SCBPointer = 4,				/* General purpose pointer. */
-	SCBPort = 8,				/* Misc. commands and operands.  */
-	SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
-	SCBCtrlMDI = 16,			/* MDI interface control. */
-	SCBEarlyRx = 20,			/* Early receive byte count. */
-};
-/* Commands that can be put in a command list entry. */
-enum commands {
-	CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000,
-	CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000,
-	CmdDump = 0x60000, CmdDiagnose = 0x70000,
-	CmdSuspend = 0x40000000,	/* Suspend after completion. */
-	CmdIntr = 0x20000000,		/* Interrupt after completion. */
-	CmdTxFlex = 0x00080000,		/* Use "Flexible mode" for CmdTx command. */
-};
-/* Clear CmdSuspend (1<<30) avoiding interference with the card access to the
-   status bits.  Previous driver versions used separate 16 bit fields for
-   commands and statuses.  --SAW
- */
-#if defined(__alpha__)
-# define clear_suspend(cmd)  clear_bit(30, &(cmd)->cmd_status);
-#else
-# if defined(__LITTLE_ENDIAN)
-#  define clear_suspend(cmd)  ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x4000
-# elif defined(__BIG_ENDIAN)
-#  define clear_suspend(cmd)  ((__u16 *)&(cmd)->cmd_status)[1] &= ~0x0040
-# else
-#  error Unsupported byteorder
-# endif
-#endif
-
-enum SCBCmdBits {
-	SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
-	SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
-	SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
-	/* The rest are Rx and Tx commands. */
-	CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
-	CUCmdBase=0x0060,	/* CU Base address (set to zero) . */
-	CUDumpStats=0x0070, /* Dump then reset stats counters. */
-	RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
-	RxResumeNoResources=0x0007,
-};
-
-enum SCBPort_cmds {
-	PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,
-};
-
-/* The Speedo3 Rx and Tx frame/buffer descriptors. */
-struct descriptor {			    /* A generic descriptor. */
-	volatile s32 cmd_status;	/* All command and status fields. */
-	u32 link;				    /* struct descriptor *  */
-	unsigned char params[0];
-};
-
-/* The Speedo3 Rx and Tx buffer descriptors. */
-struct RxFD {					/* Receive frame descriptor. */
-	volatile s32 status;
-	u32 link;					/* struct RxFD * */
-	u32 rx_buf_addr;			/* void * */
-	u32 count;
-} RxFD_ALIGNMENT;
-
-/* Selected elements of the Tx/RxFD.status word. */
-enum RxFD_bits {
-	RxComplete=0x8000, RxOK=0x2000,
-	RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
-	RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
-	TxUnderrun=0x1000,  StatusComplete=0x8000,
-};
-
-#define CONFIG_DATA_SIZE 22
-struct TxFD {					/* Transmit frame descriptor set. */
-	s32 status;
-	u32 link;					/* void * */
-	u32 tx_desc_addr;			/* Always points to the tx_buf_addr element. */
-	s32 count;					/* # of TBD (=1), Tx start thresh., etc. */
-	/* This constitutes two "TBD" entries -- we only use one. */
-#define TX_DESCR_BUF_OFFSET 16
-	u32 tx_buf_addr0;			/* void *, frame to be transmitted.  */
-	s32 tx_buf_size0;			/* Length of Tx frame. */
-	u32 tx_buf_addr1;			/* void *, frame to be transmitted.  */
-	s32 tx_buf_size1;			/* Length of Tx frame. */
-	/* the structure must have space for at least CONFIG_DATA_SIZE starting
-	 * from tx_desc_addr field */
-};
-
-/* Multicast filter setting block.  --SAW */
-struct speedo_mc_block {
-	struct speedo_mc_block *next;
-	unsigned int tx;
-	dma_addr_t frame_dma;
-	unsigned int len;
-	struct descriptor frame __attribute__ ((__aligned__(16)));
-};
-
-/* Elements of the dump_statistics block. This block must be lword aligned. */
-struct speedo_stats {
-	u32 tx_good_frames;
-	u32 tx_coll16_errs;
-	u32 tx_late_colls;
-	u32 tx_underruns;
-	u32 tx_lost_carrier;
-	u32 tx_deferred;
-	u32 tx_one_colls;
-	u32 tx_multi_colls;
-	u32 tx_total_colls;
-	u32 rx_good_frames;
-	u32 rx_crc_errs;
-	u32 rx_align_errs;
-	u32 rx_resource_errs;
-	u32 rx_overrun_errs;
-	u32 rx_colls_errs;
-	u32 rx_runt_errs;
-	u32 done_marker;
-};
-
-enum Rx_ring_state_bits {
-	RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8,
-};
-
-/* Do not change the position (alignment) of the first few elements!
-   The later elements are grouped for cache locality.
-
-   Unfortunately, all the positions have been shifted since there.
-   A new re-alignment is required.  2000/03/06  SAW */
-struct speedo_private {
-    void __iomem *regs;
-	struct TxFD	*tx_ring;		/* Commands (usually CmdTxPacket). */
-	struct RxFD *rx_ringp[RX_RING_SIZE];	/* Rx descriptor, used as ring. */
-	/* The addresses of a Tx/Rx-in-place packets/buffers. */
-	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	struct sk_buff *rx_skbuff[RX_RING_SIZE];
-	/* Mapped addresses of the rings. */
-	dma_addr_t tx_ring_dma;
-#define TX_RING_ELEM_DMA(sp, n) ((sp)->tx_ring_dma + (n)*sizeof(struct TxFD))
-	dma_addr_t rx_ring_dma[RX_RING_SIZE];
-	struct descriptor *last_cmd;		/* Last command sent. */
-	unsigned int cur_tx, dirty_tx;		/* The ring entries to be free()ed. */
-	spinlock_t lock;			/* Group with Tx control cache line. */
-	u32 tx_threshold;			/* The value for txdesc.count. */
-	struct RxFD *last_rxf;			/* Last filled RX buffer. */
-	dma_addr_t last_rxf_dma;
-	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */
-	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */
-	struct net_device_stats stats;
-	struct speedo_stats *lstats;
-	dma_addr_t lstats_dma;
-	int chip_id;
-	struct pci_dev *pdev;
-	struct timer_list timer;		/* Media selection timer. */
-	struct speedo_mc_block *mc_setup_head;	/* Multicast setup frame list head. */
-	struct speedo_mc_block *mc_setup_tail;	/* Multicast setup frame list tail. */
-	long in_interrupt;			/* Word-aligned dev->interrupt */
-	unsigned char acpi_pwr;
-	signed char rx_mode;			/* Current PROMISC/ALLMULTI setting. */
-	unsigned int tx_full:1;			/* The Tx queue is full. */
-	unsigned int flow_ctrl:1;		/* Use 802.3x flow control. */
-	unsigned int rx_bug:1;			/* Work around receiver hang errata. */
-	unsigned char default_port:8;		/* Last dev->if_port value. */
-	unsigned char rx_ring_state;		/* RX ring status flags. */
-	unsigned short phy[2];			/* PHY media interfaces available. */
-	unsigned short partner;			/* Link partner caps. */
-	struct mii_if_info mii_if;		/* MII API hooks, info */
-	u32 msg_enable;				/* debug message level */
-};
-
-/* The parameters for a CmdConfigure operation.
-   There are so many options that it would be difficult to document each bit.
-   We mostly use the default or recommended settings. */
-static const char i82557_config_cmd[CONFIG_DATA_SIZE] = {
-	22, 0x08, 0, 0,  0, 0, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
-	0, 0x2E, 0,  0x60, 0,
-	0xf2, 0x48,   0, 0x40, 0xf2, 0x80, 		/* 0x40=Force full-duplex */
-	0x3f, 0x05, };
-static const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
-	22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
-	0, 0x2E, 0,  0x60, 0x08, 0x88,
-	0x68, 0, 0x40, 0xf2, 0x84,		/* Disable FC */
-	0x31, 0x05, };
-
-/* PHY media interface chips. */
-static const char *phys[] = {
-	"None", "i82553-A/B", "i82553-C", "i82503",
-	"DP83840", "80c240", "80c24", "i82555",
-	"unknown-8", "unknown-9", "DP83840A", "unknown-11",
-	"unknown-12", "unknown-13", "unknown-14", "unknown-15", };
-enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
-					 S80C24, I82555, DP83840A=10, };
-static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
-#define EE_READ_CMD		(6)
-
-static int eepro100_init_one(struct pci_dev *pdev,
-		const struct pci_device_id *ent);
-
-static int do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static int speedo_open(struct net_device *dev);
-static void speedo_resume(struct net_device *dev);
-static void speedo_timer(unsigned long data);
-static void speedo_init_rx_ring(struct net_device *dev);
-static void speedo_tx_timeout(struct net_device *dev);
-static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void speedo_refill_rx_buffers(struct net_device *dev, int force);
-static int speedo_rx(struct net_device *dev);
-static void speedo_tx_buffer_gc(struct net_device *dev);
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int speedo_close(struct net_device *dev);
-static struct net_device_stats *speedo_get_stats(struct net_device *dev);
-static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void set_rx_mode(struct net_device *dev);
-static void speedo_show_state(struct net_device *dev);
-static struct ethtool_ops ethtool_ops;
-
-\f
-
-#ifdef honor_default_port
-/* Optional driver feature to allow forcing the transceiver setting.
-   Not recommended. */
-static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
-						   0x2000, 0x2100, 0x0400, 0x3100};
-#endif
-
-/* How to wait for the command unit to accept a command.
-   Typically this takes 0 ticks. */
-static inline unsigned char wait_for_cmd_done(struct net_device *dev,
-											  	struct speedo_private *sp)
-{
-	int wait = 1000;
-	void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
-	unsigned char r;
-
-	do  {
-		udelay(1);
-		r = ioread8(cmd_ioaddr);
-	} while(r && --wait >= 0);
-
-	if (wait < 0)
-		printk(KERN_ALERT "%s: wait_for_cmd_done timeout!\n", dev->name);
-	return r;
-}
-
-static int __devinit eepro100_init_one (struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	void __iomem *ioaddr;
-	int irq, pci_bar;
-	int acpi_idle_state = 0, pm;
-	static int cards_found /* = 0 */;
-	unsigned long pci_base;
-
-#ifndef MODULE
-	/* when built-in, we only print version if device is found */
-	static int did_version;
-	if (did_version++ == 0)
-		printk(version);
-#endif
-
-	/* save power state before pci_enable_device overwrites it */
-	pm = pci_find_capability(pdev, PCI_CAP_ID_PM);
-	if (pm) {
-		u16 pwr_command;
-		pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command);
-		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
-	}
-
-	if (pci_enable_device(pdev))
-		goto err_out_free_mmio_region;
-
-	pci_set_master(pdev);
-
-	if (!request_region(pci_resource_start(pdev, 1),
-			pci_resource_len(pdev, 1), "eepro100")) {
-		printk (KERN_ERR "eepro100: cannot reserve I/O ports\n");
-		goto err_out_none;
-	}
-	if (!request_mem_region(pci_resource_start(pdev, 0),
-			pci_resource_len(pdev, 0), "eepro100")) {
-		printk (KERN_ERR "eepro100: cannot reserve MMIO region\n");
-		goto err_out_free_pio_region;
-	}
-
-	irq = pdev->irq;
-	pci_bar = use_io ? 1 : 0;
-	pci_base = pci_resource_start(pdev, pci_bar);
-	if (DEBUG & NETIF_MSG_PROBE)
-		printk("Found Intel i82557 PCI Speedo at %#lx, IRQ %d.\n",
-		       pci_base, irq);
-
-	ioaddr = pci_iomap(pdev, pci_bar, 0);
-	if (!ioaddr) {
-		printk (KERN_ERR "eepro100: cannot remap IO\n");
-		goto err_out_free_mmio_region;
-	}
-
-	if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
-		cards_found++;
-	else
-		goto err_out_iounmap;
-
-	return 0;
-
-err_out_iounmap: ;
-	pci_iounmap(pdev, ioaddr);
-err_out_free_mmio_region:
-	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_out_free_pio_region:
-	release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
-err_out_none:
-	return -ENODEV;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-
-static void poll_speedo (struct net_device *dev)
-{
-	/* disable_irq is not very nice, but with the funny lockless design
-	   we have no other choice. */
-	disable_irq(dev->irq);
-	speedo_interrupt (dev->irq, dev, NULL);
-	enable_irq(dev->irq);
-}
-#endif
-
-static int __devinit speedo_found1(struct pci_dev *pdev,
-		void __iomem *ioaddr, int card_idx, int acpi_idle_state)
-{
-	struct net_device *dev;
-	struct speedo_private *sp;
-	const char *product;
-	int i, option;
-	u16 eeprom[0x100];
-	int size;
-	void *tx_ring_space;
-	dma_addr_t tx_ring_dma;
-
-	size = TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats);
-	tx_ring_space = pci_alloc_consistent(pdev, size, &tx_ring_dma);
-	if (tx_ring_space == NULL)
-		return -1;
-
-	dev = alloc_etherdev(sizeof(struct speedo_private));
-	if (dev == NULL) {
-		printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n");
-		pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma);
-		return -1;
-	}
-
-	SET_MODULE_OWNER(dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	if (dev->mem_start > 0)
-		option = dev->mem_start;
-	else if (card_idx >= 0  &&  options[card_idx] >= 0)
-		option = options[card_idx];
-	else
-		option = 0;
-
-	rtnl_lock();
-	if (dev_alloc_name(dev, dev->name) < 0) 
-		goto err_free_unlock;
-
-	/* Read the station address EEPROM before doing the reset.
-	   Nominally his should even be done before accepting the device, but
-	   then we wouldn't have a device name with which to report the error.
-	   The size test is for 6 bit vs. 8 bit address serial EEPROMs.
-	*/
-	{
-		void __iomem *iobase;
-		int read_cmd, ee_size;
-		u16 sum;
-		int j;
-
-		/* Use IO only to avoid postponed writes and satisfy EEPROM timing
-		   requirements. */
-		iobase = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
-		if (!iobase)
-			goto err_free_unlock;
-		if ((do_eeprom_cmd(iobase, EE_READ_CMD << 24, 27) & 0xffe0000)
-			== 0xffe0000) {
-			ee_size = 0x100;
-			read_cmd = EE_READ_CMD << 24;
-		} else {
-			ee_size = 0x40;
-			read_cmd = EE_READ_CMD << 22;
-		}
-
-		for (j = 0, i = 0, sum = 0; i < ee_size; i++) {
-			u16 value = do_eeprom_cmd(iobase, read_cmd | (i << 16), 27);
-			eeprom[i] = value;
-			sum += value;
-			if (i < 3) {
-				dev->dev_addr[j++] = value;
-				dev->dev_addr[j++] = value >> 8;
-			}
-		}
-		if (sum != 0xBABA)
-			printk(KERN_WARNING "%s: Invalid EEPROM checksum %#4.4x, "
-				   "check settings before activating this device!\n",
-				   dev->name, sum);
-		/* Don't  unregister_netdev(dev);  as the EEPro may actually be
-		   usable, especially if the MAC address is set later.
-		   On the other hand, it may be unusable if MDI data is corrupted. */
-
-		pci_iounmap(pdev, iobase);
-	}
-
-	/* Reset the chip: stop Tx and Rx processes and clear counters.
-	   This takes less than 10usec and will easily finish before the next
-	   action. */
-	iowrite32(PortReset, ioaddr + SCBPort);
-	ioread32(ioaddr + SCBPort);
-	udelay(10);
-
-	if (eeprom[3] & 0x0100)
-		product = "OEM i82557/i82558 10/100 Ethernet";
-	else
-		product = pci_name(pdev);
-
-	printk(KERN_INFO "%s: %s, ", dev->name, product);
-
-	for (i = 0; i < 5; i++)
-		printk("%2.2X:", dev->dev_addr[i]);
-	printk("%2.2X, ", dev->dev_addr[i]);
-	printk("IRQ %d.\n", pdev->irq);
-
-	sp = netdev_priv(dev);
-
-	/* we must initialize this early, for mdio_{read,write} */
-	sp->regs = ioaddr;
-
-#if 1 || defined(kernel_bloat)
-	/* OK, this is pure kernel bloat.  I don't like it when other drivers
-	   waste non-pageable kernel space to emit similar messages, but I need
-	   them for bug reports. */
-	{
-		const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"};
-		/* The self-test results must be paragraph aligned. */
-		volatile s32 *self_test_results;
-		int boguscnt = 16000;	/* Timeout for set-test. */
-		if ((eeprom[3] & 0x03) != 0x03)
-			printk(KERN_INFO "  Receiver lock-up bug exists -- enabling"
-				   " work-around.\n");
-		printk(KERN_INFO "  Board assembly %4.4x%2.2x-%3.3d, Physical"
-			   " connectors present:",
-			   eeprom[8], eeprom[9]>>8, eeprom[9] & 0xff);
-		for (i = 0; i < 4; i++)
-			if (eeprom[5] & (1<<i))
-				printk(connectors[i]);
-		printk("\n"KERN_INFO"  Primary interface chip %s PHY #%d.\n",
-			   phys[(eeprom[6]>>8)&15], eeprom[6] & 0x1f);
-		if (eeprom[7] & 0x0700)
-			printk(KERN_INFO "    Secondary interface chip %s.\n",
-				   phys[(eeprom[7]>>8)&7]);
-		if (((eeprom[6]>>8) & 0x3f) == DP83840
-			||  ((eeprom[6]>>8) & 0x3f) == DP83840A) {
-			int mdi_reg23 = mdio_read(dev, eeprom[6] & 0x1f, 23) | 0x0422;
-			if (congenb)
-			  mdi_reg23 |= 0x0100;
-			printk(KERN_INFO"  DP83840 specific setup, setting register 23 to %4.4x.\n",
-				   mdi_reg23);
-			mdio_write(dev, eeprom[6] & 0x1f, 23, mdi_reg23);
-		}
-		if ((option >= 0) && (option & 0x70)) {
-			printk(KERN_INFO "  Forcing %dMbs %s-duplex operation.\n",
-				   (option & 0x20 ? 100 : 10),
-				   (option & 0x10 ? "full" : "half"));
-			mdio_write(dev, eeprom[6] & 0x1f, MII_BMCR,
-					   ((option & 0x20) ? 0x2000 : 0) | 	/* 100mbps? */
-					   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
-		}
-
-		/* Perform a system self-test. */
-		self_test_results = (s32*) ((((long) tx_ring_space) + 15) & ~0xf);
-		self_test_results[0] = 0;
-		self_test_results[1] = -1;
-		iowrite32(tx_ring_dma | PortSelfTest, ioaddr + SCBPort);
-		do {
-			udelay(10);
-		} while (self_test_results[1] == -1  &&  --boguscnt >= 0);
-
-		if (boguscnt < 0) {		/* Test optimized out. */
-			printk(KERN_ERR "Self test failed, status %8.8x:\n"
-				   KERN_ERR " Failure to initialize the i82557.\n"
-				   KERN_ERR " Verify that the card is a bus-master"
-				   " capable slot.\n",
-				   self_test_results[1]);
-		} else
-			printk(KERN_INFO "  General self-test: %s.\n"
-				   KERN_INFO "  Serial sub-system self-test: %s.\n"
-				   KERN_INFO "  Internal registers self-test: %s.\n"
-				   KERN_INFO "  ROM checksum self-test: %s (%#8.8x).\n",
-				   self_test_results[1] & 0x1000 ? "failed" : "passed",
-				   self_test_results[1] & 0x0020 ? "failed" : "passed",
-				   self_test_results[1] & 0x0008 ? "failed" : "passed",
-				   self_test_results[1] & 0x0004 ? "failed" : "passed",
-				   self_test_results[0]);
-	}
-#endif  /* kernel_bloat */
-
-	iowrite32(PortReset, ioaddr + SCBPort);
-	ioread32(ioaddr + SCBPort);
-	udelay(10);
-
-	/* Return the chip to its original power state. */
-	pci_set_power_state(pdev, acpi_idle_state);
-
-	pci_set_drvdata (pdev, dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	dev->irq = pdev->irq;
-
-	sp->pdev = pdev;
-	sp->msg_enable = DEBUG;
-	sp->acpi_pwr = acpi_idle_state;
-	sp->tx_ring = tx_ring_space;
-	sp->tx_ring_dma = tx_ring_dma;
-	sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
-	sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
-	init_timer(&sp->timer); /* used in ioctl() */
-	spin_lock_init(&sp->lock);
-
-	sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
-	if (card_idx >= 0) {
-		if (full_duplex[card_idx] >= 0)
-			sp->mii_if.full_duplex = full_duplex[card_idx];
-	}
-	sp->default_port = option >= 0 ? (option & 0x0f) : 0;
-
-	sp->phy[0] = eeprom[6];
-	sp->phy[1] = eeprom[7];
-
-	sp->mii_if.phy_id = eeprom[6] & 0x1f;
-	sp->mii_if.phy_id_mask = 0x1f;
-	sp->mii_if.reg_num_mask = 0x1f;
-	sp->mii_if.dev = dev;
-	sp->mii_if.mdio_read = mdio_read;
-	sp->mii_if.mdio_write = mdio_write;
-	
-	sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1;
-	if (((pdev->device > 0x1030 && (pdev->device < 0x103F))) 
-	    || (pdev->device == 0x2449) || (pdev->device == 0x2459) 
-            || (pdev->device == 0x245D)) {
-	    	sp->chip_id = 1;
-	}
-
-	if (sp->rx_bug)
-		printk(KERN_INFO "  Receiver lock-up workaround activated.\n");
-
-	/* The Speedo-specific entries in the device structure. */
-	dev->open = &speedo_open;
-	dev->hard_start_xmit = &speedo_start_xmit;
-	netif_set_tx_timeout(dev, &speedo_tx_timeout, TX_TIMEOUT);
-	dev->stop = &speedo_close;
-	dev->get_stats = &speedo_get_stats;
-	dev->set_multicast_list = &set_rx_mode;
-	dev->do_ioctl = &speedo_ioctl;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = &poll_speedo;
-#endif
-
-	if (register_netdevice(dev))
-		goto err_free_unlock;
-	rtnl_unlock();
-
-	return 0;
-
- err_free_unlock:
-	rtnl_unlock();
-	free_netdev(dev);
-	return -1;
-}
-
-static void do_slow_command(struct net_device *dev, struct speedo_private *sp, int cmd)
-{
-	void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
-	int wait = 0;
-	do
-		if (ioread8(cmd_ioaddr) == 0) break;
-	while(++wait <= 200);
-	if (wait > 100)
-		printk(KERN_ERR "Command %4.4x never accepted (%d polls)!\n",
-		       ioread8(cmd_ioaddr), wait);
-
-	iowrite8(cmd, cmd_ioaddr);
-
-	for (wait = 0; wait <= 100; wait++)
-		if (ioread8(cmd_ioaddr) == 0) return;
-	for (; wait <= 20000; wait++)
-		if (ioread8(cmd_ioaddr) == 0) return;
-		else udelay(1);
-	printk(KERN_ERR "Command %4.4x was not accepted after %d polls!"
-	       "  Current status %8.8x.\n",
-	       cmd, wait, ioread32(sp->regs + SCBStatus));
-}
-
-/* Serial EEPROM section.
-   A "bit" grungy, but we work our way through bit-by-bit :->. */
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x01	/* EEPROM shift clock. */
-#define EE_CS			0x02	/* EEPROM chip select. */
-#define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */
-#define EE_DATA_READ	0x08	/* EEPROM chip data out. */
-#define EE_ENB			(0x4800 | EE_CS)
-#define EE_WRITE_0		0x4802
-#define EE_WRITE_1		0x4806
-#define EE_OFFSET		SCBeeprom
-
-/* The fixes for the code were kindly provided by Dragan Stancevic
-   <visitor@valinux.com> to strictly follow Intel specifications of EEPROM
-   access timing.
-   The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
-   interval for serial EEPROM.  However, it looks like that there is an
-   additional requirement dictating larger udelay's in the code below.
-   2000/05/24  SAW */
-static int __devinit do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len)
-{
-	unsigned retval = 0;
-	void __iomem *ee_addr = ioaddr + SCBeeprom;
-
-	iowrite16(EE_ENB, ee_addr); udelay(2);
-	iowrite16(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
-
-	/* Shift the command bits out. */
-	do {
-		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
-		iowrite16(dataval, ee_addr); udelay(2);
-		iowrite16(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
-		retval = (retval << 1) | ((ioread16(ee_addr) & EE_DATA_READ) ? 1 : 0);
-	} while (--cmd_len >= 0);
-	iowrite16(EE_ENB, ee_addr); udelay(2);
-
-	/* Terminate the EEPROM access. */
-	iowrite16(EE_ENB & ~EE_CS, ee_addr);
-	return retval;
-}
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
-	iowrite32(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
-	do {
-		val = ioread32(ioaddr + SCBCtrlMDI);
-		if (--boguscnt < 0) {
-			printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);
-			break;
-		}
-	} while (! (val & 0x10000000));
-	return val & 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
-	iowrite32(0x04000000 | (location<<16) | (phy_id<<21) | value,
-		 ioaddr + SCBCtrlMDI);
-	do {
-		val = ioread32(ioaddr + SCBCtrlMDI);
-		if (--boguscnt < 0) {
-			printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);
-			break;
-		}
-	} while (! (val & 0x10000000));
-}
-
-static int
-speedo_open(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int retval;
-
-	if (netif_msg_ifup(sp))
-		printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
-
-	pci_set_power_state(sp->pdev, PCI_D0);
-
-	/* Set up the Tx queue early.. */
-	sp->cur_tx = 0;
-	sp->dirty_tx = 0;
-	sp->last_cmd = NULL;
-	sp->tx_full = 0;
-	sp->in_interrupt = 0;
-
-	/* .. we can safely take handler calls during init. */
-	retval = request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev);
-	if (retval) {
-		return retval;
-	}
-
-	dev->if_port = sp->default_port;
-
-#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us
-	/* Retrigger negotiation to reset previous errors. */
-	if ((sp->phy[0] & 0x8000) == 0) {
-		int phy_addr = sp->phy[0] & 0x1f ;
-		/* Use 0x3300 for restarting NWay, other values to force xcvr:
-		   0x0000 10-HD
-		   0x0100 10-FD
-		   0x2000 100-HD
-		   0x2100 100-FD
-		*/
-#ifdef honor_default_port
-		mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
-#else
-		mdio_write(dev, phy_addr, MII_BMCR, 0x3300);
-#endif
-	}
-#endif
-
-	speedo_init_rx_ring(dev);
-
-	/* Fire up the hardware. */
-	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-	speedo_resume(dev);
-
-	netdevice_start(dev);
-	netif_start_queue(dev);
-
-	/* Setup the chip and configure the multicast list. */
-	sp->mc_setup_head = NULL;
-	sp->mc_setup_tail = NULL;
-	sp->flow_ctrl = sp->partner = 0;
-	sp->rx_mode = -1;			/* Invalid -> always reset the mode. */
-	set_rx_mode(dev);
-	if ((sp->phy[0] & 0x8000) == 0)
-		sp->mii_if.advertising = mdio_read(dev, sp->phy[0] & 0x1f, MII_ADVERTISE);
-
-	mii_check_link(&sp->mii_if);
-
-	if (netif_msg_ifup(sp)) {
-		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-	}
-
-	/* Set the timer.  The timer serves a dual purpose:
-	   1) to monitor the media interface (e.g. link beat) and perhaps switch
-	   to an alternate media type
-	   2) to monitor Rx activity, and restart the Rx process if the receiver
-	   hangs. */
-	sp->timer.expires = RUN_AT((24*HZ)/10); 			/* 2.4 sec. */
-	sp->timer.data = (unsigned long)dev;
-	sp->timer.function = &speedo_timer;					/* timer handler */
-	add_timer(&sp->timer);
-
-	/* No need to wait for the command unit to accept here. */
-	if ((sp->phy[0] & 0x8000) == 0)
-		mdio_read(dev, sp->phy[0] & 0x1f, MII_BMCR);
-
-	return 0;
-}
-
-/* Start the chip hardware after a full reset. */
-static void speedo_resume(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-
-	/* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
-	sp->tx_threshold = 0x01208000;
-
-	/* Set the segment registers to '0'. */
-	if (wait_for_cmd_done(dev, sp) != 0) {
-		iowrite32(PortPartialReset, ioaddr + SCBPort);
-		udelay(10);
-	}
-
-        iowrite32(0, ioaddr + SCBPointer);
-        ioread32(ioaddr + SCBPointer);			/* Flush to PCI. */
-        udelay(10);			/* Bogus, but it avoids the bug. */
-
-        /* Note: these next two operations can take a while. */
-        do_slow_command(dev, sp, RxAddrLoad);
-        do_slow_command(dev, sp, CUCmdBase);
-
-	/* Load the statistics block and rx ring addresses. */
-	iowrite32(sp->lstats_dma, ioaddr + SCBPointer);
-	ioread32(ioaddr + SCBPointer);			/* Flush to PCI */
-
-	iowrite8(CUStatsAddr, ioaddr + SCBCmd);
-	sp->lstats->done_marker = 0;
-	wait_for_cmd_done(dev, sp);
-
-	if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
-		if (netif_msg_rx_err(sp))
-			printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
-					dev->name);
-	} else {
-		iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
-			 ioaddr + SCBPointer);
-		ioread32(ioaddr + SCBPointer);		/* Flush to PCI */
-	}
-
-	/* Note: RxStart should complete instantly. */
-	do_slow_command(dev, sp, RxStart);
-	do_slow_command(dev, sp, CUDumpStats);
-
-	/* Fill the first command with our physical address. */
-	{
-		struct descriptor *ias_cmd;
-
-		ias_cmd =
-			(struct descriptor *)&sp->tx_ring[sp->cur_tx++ % TX_RING_SIZE];
-		/* Avoid a bug(?!) here by marking the command already completed. */
-		ias_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000);
-		ias_cmd->link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE));
-		memcpy(ias_cmd->params, dev->dev_addr, 6);
-		if (sp->last_cmd)
-			clear_suspend(sp->last_cmd);
-		sp->last_cmd = ias_cmd;
-	}
-
-	/* Start the chip's Tx process and unmask interrupts. */
-	iowrite32(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE),
-		 ioaddr + SCBPointer);
-	/* We are not ACK-ing FCP and ER in the interrupt handler yet so they should
-	   remain masked --Dragan */
-	iowrite16(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd);
-}
-
-/*
- * Sometimes the receiver stops making progress.  This routine knows how to
- * get it going again, without losing packets or being otherwise nasty like
- * a chip reset would be.  Previously the driver had a whole sequence
- * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
- * do another, etc.  But those things don't really matter.  Separate logic
- * in the ISR provides for allocating buffers--the other half of operation
- * is just making sure the receiver is active.  speedo_rx_soft_reset does that.
- * This problem with the old, more involved algorithm is shown up under
- * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
- */
-static void
-speedo_rx_soft_reset(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct RxFD *rfd;
-	void __iomem *ioaddr;
-
-	ioaddr = sp->regs;
-	if (wait_for_cmd_done(dev, sp) != 0) {
-		printk("%s: previous command stalled\n", dev->name);
-		return;
-	}
-	/*
-	* Put the hardware into a known state.
-	*/
-	iowrite8(RxAbort, ioaddr + SCBCmd);
-
-	rfd = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
-
-	rfd->rx_buf_addr = 0xffffffff;
-
-	if (wait_for_cmd_done(dev, sp) != 0) {
-		printk("%s: RxAbort command stalled\n", dev->name);
-		return;
-	}
-	iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
-		ioaddr + SCBPointer);
-	iowrite8(RxStart, ioaddr + SCBCmd);
-}
-
-
-/* Media monitoring and control. */
-static void speedo_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int phy_num = sp->phy[0] & 0x1f;
-
-	/* We have MII and lost link beat. */
-	if ((sp->phy[0] & 0x8000) == 0) {
-		int partner = mdio_read(dev, phy_num, MII_LPA);
-		if (partner != sp->partner) {
-			int flow_ctrl = sp->mii_if.advertising & partner & 0x0400 ? 1 : 0;
-			if (netif_msg_link(sp)) {
-				printk(KERN_DEBUG "%s: Link status change.\n", dev->name);
-				printk(KERN_DEBUG "%s: Old partner %x, new %x, adv %x.\n",
-					   dev->name, sp->partner, partner, sp->mii_if.advertising);
-			}
-			sp->partner = partner;
-			if (flow_ctrl != sp->flow_ctrl) {
-				sp->flow_ctrl = flow_ctrl;
-				sp->rx_mode = -1;	/* Trigger a reload. */
-			}
-		}
-	}
-	mii_check_link(&sp->mii_if);
-	if (netif_msg_timer(sp)) {
-		printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-	}
-	if (sp->rx_mode < 0  ||
-		(sp->rx_bug  && jiffies - sp->last_rx_time > 2*HZ)) {
-		/* We haven't received a packet in a Long Time.  We might have been
-		   bitten by the receiver hang bug.  This can be cleared by sending
-		   a set multicast list command. */
-		if (netif_msg_timer(sp))
-			printk(KERN_DEBUG "%s: Sending a multicast list set command"
-				   " from a timer routine,"
-				   " m=%d, j=%ld, l=%ld.\n",
-				   dev->name, sp->rx_mode, jiffies, sp->last_rx_time);
-		set_rx_mode(dev);
-	}
-	/* We must continue to monitor the media. */
-	sp->timer.expires = RUN_AT(2*HZ); 			/* 2.0 sec. */
-	add_timer(&sp->timer);
-}
-
-static void speedo_show_state(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int i;
-
-	if (netif_msg_pktdata(sp)) {
-		printk(KERN_DEBUG "%s: Tx ring dump,  Tx queue %u / %u:\n", 
-		    dev->name, sp->cur_tx, sp->dirty_tx);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(KERN_DEBUG "%s:  %c%c%2d %8.8x.\n", dev->name,
-			    i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ',
-			    i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ',
-			    i, sp->tx_ring[i].status);
-
-		printk(KERN_DEBUG "%s: Printing Rx ring"
-		    " (next to receive into %u, dirty index %u).\n",
-		    dev->name, sp->cur_rx, sp->dirty_rx);
-		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(KERN_DEBUG "%s: %c%c%c%2d %8.8x.\n", dev->name,
-			    sp->rx_ringp[i] == sp->last_rxf ? 'l' : ' ',
-			    i == sp->dirty_rx % RX_RING_SIZE ? '*' : ' ',
-			    i == sp->cur_rx % RX_RING_SIZE ? '=' : ' ',
-			    i, (sp->rx_ringp[i] != NULL) ?
-			    (unsigned)sp->rx_ringp[i]->status : 0);
-	}
-
-#if 0
-	{
-		void __iomem *ioaddr = sp->regs;
-		int phy_num = sp->phy[0] & 0x1f;
-		for (i = 0; i < 16; i++) {
-			/* FIXME: what does it mean?  --SAW */
-			if (i == 6) i = 21;
-			printk(KERN_DEBUG "%s:  PHY index %d register %d is %4.4x.\n",
-				   dev->name, phy_num, i, mdio_read(dev, phy_num, i));
-		}
-	}
-#endif
-
-}
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void
-speedo_init_rx_ring(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct RxFD *rxf, *last_rxf = NULL;
-	dma_addr_t last_rxf_dma = 0 /* to shut up the compiler */;
-	int i;
-
-	sp->cur_rx = 0;
-
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb;
-		skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-		if (skb)
-			rx_align(skb);        /* Align IP on 16 byte boundary */
-		sp->rx_skbuff[i] = skb;
-		if (skb == NULL)
-			break;			/* OK.  Just initially short of Rx bufs. */
-		skb->dev = dev;			/* Mark as being used by this device. */
-		rxf = (struct RxFD *)skb->data;
-		sp->rx_ringp[i] = rxf;
-		sp->rx_ring_dma[i] =
-			pci_map_single(sp->pdev, rxf,
-					PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_BIDIRECTIONAL);
-		skb_reserve(skb, sizeof(struct RxFD));
-		if (last_rxf) {
-			last_rxf->link = cpu_to_le32(sp->rx_ring_dma[i]);
-			pci_dma_sync_single_for_device(sp->pdev, last_rxf_dma,
-										   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-		}
-		last_rxf = rxf;
-		last_rxf_dma = sp->rx_ring_dma[i];
-		rxf->status = cpu_to_le32(0x00000001);	/* '1' is flag value only. */
-		rxf->link = 0;						/* None yet. */
-		/* This field unused by i82557. */
-		rxf->rx_buf_addr = 0xffffffff;
-		rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
-		pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[i],
-									   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	}
-	sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-	/* Mark the last entry as end-of-list. */
-	last_rxf->status = cpu_to_le32(0xC0000002);	/* '2' is flag value only. */
-	pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[RX_RING_SIZE-1],
-								   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	sp->last_rxf = last_rxf;
-	sp->last_rxf_dma = last_rxf_dma;
-}
-
-static void speedo_purge_tx(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int entry;
-
-	while ((int)(sp->cur_tx - sp->dirty_tx) > 0) {
-		entry = sp->dirty_tx % TX_RING_SIZE;
-		if (sp->tx_skbuff[entry]) {
-			sp->stats.tx_errors++;
-			pci_unmap_single(sp->pdev,
-					le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
-					sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb_irq(sp->tx_skbuff[entry]);
-			sp->tx_skbuff[entry] = NULL;
-		}
-		sp->dirty_tx++;
-	}
-	while (sp->mc_setup_head != NULL) {
-		struct speedo_mc_block *t;
-		if (netif_msg_tx_err(sp))
-			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
-		pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
-				sp->mc_setup_head->len, PCI_DMA_TODEVICE);
-		t = sp->mc_setup_head->next;
-		kfree(sp->mc_setup_head);
-		sp->mc_setup_head = t;
-	}
-	sp->mc_setup_tail = NULL;
-	sp->tx_full = 0;
-	netif_wake_queue(dev);
-}
-
-static void reset_mii(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-
-	/* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */
-	if ((sp->phy[0] & 0x8000) == 0) {
-		int phy_addr = sp->phy[0] & 0x1f;
-		int advertising = mdio_read(dev, phy_addr, MII_ADVERTISE);
-		int mii_bmcr = mdio_read(dev, phy_addr, MII_BMCR);
-		mdio_write(dev, phy_addr, MII_BMCR, 0x0400);
-		mdio_write(dev, phy_addr, MII_BMSR, 0x0000);
-		mdio_write(dev, phy_addr, MII_ADVERTISE, 0x0000);
-		mdio_write(dev, phy_addr, MII_BMCR, 0x8000);
-#ifdef honor_default_port
-		mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
-#else
-		mdio_read(dev, phy_addr, MII_BMCR);
-		mdio_write(dev, phy_addr, MII_BMCR, mii_bmcr);
-		mdio_write(dev, phy_addr, MII_ADVERTISE, advertising);
-#endif
-	}
-}
-
-static void speedo_tx_timeout(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int status = ioread16(ioaddr + SCBStatus);
-	unsigned long flags;
-
-	if (netif_msg_tx_err(sp)) {
-		printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
-		   " %4.4x at %d/%d command %8.8x.\n",
-		   dev->name, status, ioread16(ioaddr + SCBCmd),
-		   sp->dirty_tx, sp->cur_tx,
-		   sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
-
-	}
-	speedo_show_state(dev);
-#if 0
-	if ((status & 0x00C0) != 0x0080
-		&&  (status & 0x003C) == 0x0010) {
-		/* Only the command unit has stopped. */
-		printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
-			   dev->name);
-		iowrite32(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]),
-			 ioaddr + SCBPointer);
-		iowrite16(CUStart, ioaddr + SCBCmd);
-		reset_mii(dev);
-	} else {
-#else
-	{
-#endif
-		del_timer_sync(&sp->timer);
-		/* Reset the Tx and Rx units. */
-		iowrite32(PortReset, ioaddr + SCBPort);
-		/* We may get spurious interrupts here.  But I don't think that they
-		   may do much harm.  1999/12/09 SAW */
-		udelay(10);
-		/* Disable interrupts. */
-		iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-		synchronize_irq(dev->irq);
-		speedo_tx_buffer_gc(dev);
-		/* Free as much as possible.
-		   It helps to recover from a hang because of out-of-memory.
-		   It also simplifies speedo_resume() in case TX ring is full or
-		   close-to-be full. */
-		speedo_purge_tx(dev);
-		speedo_refill_rx_buffers(dev, 1);
-		spin_lock_irqsave(&sp->lock, flags);
-		speedo_resume(dev);
-		sp->rx_mode = -1;
-		dev->trans_start = jiffies;
-		spin_unlock_irqrestore(&sp->lock, flags);
-		set_rx_mode(dev); /* it takes the spinlock itself --SAW */
-		/* Reset MII transceiver.  Do it before starting the timer to serialize
-		   mdio_xxx operations.  Yes, it's a paranoya :-)  2000/05/09 SAW */
-		reset_mii(dev);
-		sp->timer.expires = RUN_AT(2*HZ);
-		add_timer(&sp->timer);
-	}
-	return;
-}
-
-static int
-speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int entry;
-
-	/* Prevent interrupts from changing the Tx ring from underneath us. */
-	unsigned long flags;
-
-	spin_lock_irqsave(&sp->lock, flags);
-
-	/* Check if there are enough space. */
-	if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-		printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", dev->name);
-		netif_stop_queue(dev);
-		sp->tx_full = 1;
-		spin_unlock_irqrestore(&sp->lock, flags);
-		return 1;
-	}
-
-	/* Calculate the Tx descriptor entry. */
-	entry = sp->cur_tx++ % TX_RING_SIZE;
-
-	sp->tx_skbuff[entry] = skb;
-	sp->tx_ring[entry].status =
-		cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex);
-	if (!(entry & ((TX_RING_SIZE>>2)-1)))
-		sp->tx_ring[entry].status |= cpu_to_le32(CmdIntr);
-	sp->tx_ring[entry].link =
-		cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE));
-	sp->tx_ring[entry].tx_desc_addr =
-		cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET);
-	/* The data region is always in one buffer descriptor. */
-	sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold);
-	sp->tx_ring[entry].tx_buf_addr0 =
-		cpu_to_le32(pci_map_single(sp->pdev, skb->data,
-					   skb->len, PCI_DMA_TODEVICE));
-	sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len);
-
-	/* workaround for hardware bug on 10 mbit half duplex */
-
-	if ((sp->partner == 0) && (sp->chip_id == 1)) {
-		wait_for_cmd_done(dev, sp);
-		iowrite8(0 , ioaddr + SCBCmd);
-		udelay(1);
-	}
-
-	/* Trigger the command unit resume. */
-	wait_for_cmd_done(dev, sp);
-	clear_suspend(sp->last_cmd);
-	/* We want the time window between clearing suspend flag on the previous
-	   command and resuming CU to be as small as possible.
-	   Interrupts in between are very undesired.  --SAW */
-	iowrite8(CUResume, ioaddr + SCBCmd);
-	sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
-	/* Leave room for set_rx_mode(). If there is no more space than reserved
-	   for multicast filter mark the ring as full. */
-	if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-		netif_stop_queue(dev);
-		sp->tx_full = 1;
-	}
-
-	spin_unlock_irqrestore(&sp->lock, flags);
-
-	dev->trans_start = jiffies;
-
-	return 0;
-}
-
-static void speedo_tx_buffer_gc(struct net_device *dev)
-{
-	unsigned int dirty_tx;
-	struct speedo_private *sp = netdev_priv(dev);
-
-	dirty_tx = sp->dirty_tx;
-	while ((int)(sp->cur_tx - dirty_tx) > 0) {
-		int entry = dirty_tx % TX_RING_SIZE;
-		int status = le32_to_cpu(sp->tx_ring[entry].status);
-
-		if (netif_msg_tx_done(sp))
-			printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
-				   entry, status);
-		if ((status & StatusComplete) == 0)
-			break;			/* It still hasn't been processed. */
-		if (status & TxUnderrun)
-			if (sp->tx_threshold < 0x01e08000) {
-				if (netif_msg_tx_err(sp))
-					printk(KERN_DEBUG "%s: TX underrun, threshold adjusted.\n",
-						   dev->name);
-				sp->tx_threshold += 0x00040000;
-			}
-		/* Free the original skb. */
-		if (sp->tx_skbuff[entry]) {
-			sp->stats.tx_packets++;	/* Count only user packets. */
-			sp->stats.tx_bytes += sp->tx_skbuff[entry]->len;
-			pci_unmap_single(sp->pdev,
-					le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
-					sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb_irq(sp->tx_skbuff[entry]);
-			sp->tx_skbuff[entry] = NULL;
-		}
-		dirty_tx++;
-	}
-
-	if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) {
-		printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d,"
-			   " full=%d.\n",
-			   dirty_tx, sp->cur_tx, sp->tx_full);
-		dirty_tx += TX_RING_SIZE;
-	}
-
-	while (sp->mc_setup_head != NULL
-		   && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) {
-		struct speedo_mc_block *t;
-		if (netif_msg_tx_err(sp))
-			printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
-		pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
-				sp->mc_setup_head->len, PCI_DMA_TODEVICE);
-		t = sp->mc_setup_head->next;
-		kfree(sp->mc_setup_head);
-		sp->mc_setup_head = t;
-	}
-	if (sp->mc_setup_head == NULL)
-		sp->mc_setup_tail = NULL;
-
-	sp->dirty_tx = dirty_tx;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *)dev_instance;
-	struct speedo_private *sp;
-	void __iomem *ioaddr;
-	long boguscnt = max_interrupt_work;
-	unsigned short status;
-	unsigned int handled = 0;
-
-	sp = netdev_priv(dev);
-	ioaddr = sp->regs;
-
-#ifndef final_version
-	/* A lock to prevent simultaneous entry on SMP machines. */
-	if (test_and_set_bit(0, (void*)&sp->in_interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		sp->in_interrupt = 0;	/* Avoid halting machine. */
-		return IRQ_NONE;
-	}
-#endif
-
-	do {
-		status = ioread16(ioaddr + SCBStatus);
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		/* Will change from 0xfc00 to 0xff00 when we start handling
-		   FCP and ER interrupts --Dragan */
-		iowrite16(status & 0xfc00, ioaddr + SCBStatus);
-
-		if (netif_msg_intr(sp))
-			printk(KERN_DEBUG "%s: interrupt  status=%#4.4x.\n",
-				   dev->name, status);
-
-		if ((status & 0xfc00) == 0)
-			break;
-		handled = 1;
-
-
-		if ((status & 0x5000) ||	/* Packet received, or Rx error. */
-			(sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)
-									/* Need to gather the postponed packet. */
-			speedo_rx(dev);
-
-		/* Always check if all rx buffers are allocated.  --SAW */
-		speedo_refill_rx_buffers(dev, 0);
-		
-		spin_lock(&sp->lock);
-		/*
-		 * The chip may have suspended reception for various reasons.
-		 * Check for that, and re-prime it should this be the case.
-		 */
-		switch ((status >> 2) & 0xf) {
-		case 0: /* Idle */
-			break;
-		case 1:	/* Suspended */
-		case 2:	/* No resources (RxFDs) */
-		case 9:	/* Suspended with no more RBDs */
-		case 10: /* No resources due to no RBDs */
-		case 12: /* Ready with no RBDs */
-			speedo_rx_soft_reset(dev);
-			break;
-		case 3:  case 5:  case 6:  case 7:  case 8:
-		case 11:  case 13:  case 14:  case 15:
-			/* these are all reserved values */
-			break;
-		}
-		
-		
-		/* User interrupt, Command/Tx unit interrupt or CU not active. */
-		if (status & 0xA400) {
-			speedo_tx_buffer_gc(dev);
-			if (sp->tx_full
-				&& (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) {
-				/* The ring is no longer full. */
-				sp->tx_full = 0;
-				netif_wake_queue(dev); /* Attention: under a spinlock.  --SAW */
-			}
-		}
-		
-		spin_unlock(&sp->lock);
-
-		if (--boguscnt < 0) {
-			printk(KERN_ERR "%s: Too much work at interrupt, status=0x%4.4x.\n",
-				   dev->name, status);
-			/* Clear all interrupt sources. */
-			/* Will change from 0xfc00 to 0xff00 when we start handling
-			   FCP and ER interrupts --Dragan */
-			iowrite16(0xfc00, ioaddr + SCBStatus);
-			break;
-		}
-	} while (1);
-
-	if (netif_msg_intr(sp))
-		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-
-	clear_bit(0, (void*)&sp->in_interrupt);
-	return IRQ_RETVAL(handled);
-}
-
-static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct RxFD *rxf;
-	struct sk_buff *skb;
-	/* Get a fresh skbuff to replace the consumed one. */
-	skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-	if (skb)
-		rx_align(skb);		/* Align IP on 16 byte boundary */
-	sp->rx_skbuff[entry] = skb;
-	if (skb == NULL) {
-		sp->rx_ringp[entry] = NULL;
-		return NULL;
-	}
-	rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->data;
-	sp->rx_ring_dma[entry] =
-		pci_map_single(sp->pdev, rxf,
-					   PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
-	skb->dev = dev;
-	skb_reserve(skb, sizeof(struct RxFD));
-	rxf->rx_buf_addr = 0xffffffff;
-	pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
-								   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	return rxf;
-}
-
-static inline void speedo_rx_link(struct net_device *dev, int entry,
-								  struct RxFD *rxf, dma_addr_t rxf_dma)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	rxf->status = cpu_to_le32(0xC0000001); 	/* '1' for driver use only. */
-	rxf->link = 0;			/* None yet. */
-	rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
-	sp->last_rxf->link = cpu_to_le32(rxf_dma);
-	sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
-	pci_dma_sync_single_for_device(sp->pdev, sp->last_rxf_dma,
-								   sizeof(struct RxFD), PCI_DMA_TODEVICE);
-	sp->last_rxf = rxf;
-	sp->last_rxf_dma = rxf_dma;
-}
-
-static int speedo_refill_rx_buf(struct net_device *dev, int force)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int entry;
-	struct RxFD *rxf;
-
-	entry = sp->dirty_rx % RX_RING_SIZE;
-	if (sp->rx_skbuff[entry] == NULL) {
-		rxf = speedo_rx_alloc(dev, entry);
-		if (rxf == NULL) {
-			unsigned int forw;
-			int forw_entry;
-			if (netif_msg_rx_err(sp) || !(sp->rx_ring_state & RrOOMReported)) {
-				printk(KERN_WARNING "%s: can't fill rx buffer (force %d)!\n",
-						dev->name, force);
-				sp->rx_ring_state |= RrOOMReported;
-			}
-			speedo_show_state(dev);
-			if (!force)
-				return -1;	/* Better luck next time!  */
-			/* Borrow an skb from one of next entries. */
-			for (forw = sp->dirty_rx + 1; forw != sp->cur_rx; forw++)
-				if (sp->rx_skbuff[forw % RX_RING_SIZE] != NULL)
-					break;
-			if (forw == sp->cur_rx)
-				return -1;
-			forw_entry = forw % RX_RING_SIZE;
-			sp->rx_skbuff[entry] = sp->rx_skbuff[forw_entry];
-			sp->rx_skbuff[forw_entry] = NULL;
-			rxf = sp->rx_ringp[forw_entry];
-			sp->rx_ringp[forw_entry] = NULL;
-			sp->rx_ringp[entry] = rxf;
-		}
-	} else {
-		rxf = sp->rx_ringp[entry];
-	}
-	speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]);
-	sp->dirty_rx++;
-	sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); /* Mark the progress. */
-	return 0;
-}
-
-static void speedo_refill_rx_buffers(struct net_device *dev, int force)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-
-	/* Refill the RX ring. */
-	while ((int)(sp->cur_rx - sp->dirty_rx) > 0 &&
-			speedo_refill_rx_buf(dev, force) != -1);
-}
-
-static int
-speedo_rx(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int entry = sp->cur_rx % RX_RING_SIZE;
-	int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
-	int alloc_ok = 1;
-	int npkts = 0;
-
-	if (netif_msg_intr(sp))
-		printk(KERN_DEBUG " In speedo_rx().\n");
-	/* If we own the next entry, it's a new packet. Send it up. */
-	while (sp->rx_ringp[entry] != NULL) {
-		int status;
-		int pkt_len;
-
-		pci_dma_sync_single_for_cpu(sp->pdev, sp->rx_ring_dma[entry],
-									sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
-		status = le32_to_cpu(sp->rx_ringp[entry]->status);
-		pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
-
-		if (!(status & RxComplete))
-			break;
-
-		if (--rx_work_limit < 0)
-			break;
-
-		/* Check for a rare out-of-memory case: the current buffer is
-		   the last buffer allocated in the RX ring.  --SAW */
-		if (sp->last_rxf == sp->rx_ringp[entry]) {
-			/* Postpone the packet.  It'll be reaped at an interrupt when this
-			   packet is no longer the last packet in the ring. */
-			if (netif_msg_rx_err(sp))
-				printk(KERN_DEBUG "%s: RX packet postponed!\n",
-					   dev->name);
-			sp->rx_ring_state |= RrPostponed;
-			break;
-		}
-
-		if (netif_msg_rx_status(sp))
-			printk(KERN_DEBUG "  speedo_rx() status %8.8x len %d.\n", status,
-				   pkt_len);
-		if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) {
-			if (status & RxErrTooBig)
-				printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, "
-					   "status %8.8x!\n", dev->name, status);
-			else if (! (status & RxOK)) {
-				/* There was a fatal error.  This *should* be impossible. */
-				sp->stats.rx_errors++;
-				printk(KERN_ERR "%s: Anomalous event in speedo_rx(), "
-					   "status %8.8x.\n",
-					   dev->name, status);
-			}
-		} else {
-			struct sk_buff *skb;
-
-			/* Check if the packet is long enough to just accept without
-			   copying to a properly sized skbuff. */
-			if (pkt_len < rx_copybreak
-				&& (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
-				skb->dev = dev;
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				pci_dma_sync_single_for_cpu(sp->pdev, sp->rx_ring_dma[entry],
-											sizeof(struct RxFD) + pkt_len,
-											PCI_DMA_FROMDEVICE);
-
-#if 1 || USE_IP_CSUM
-				/* Packet is in one chunk -- we can copy + cksum. */
-				eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0);
-				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->data,
-					   pkt_len);
-#endif
-				pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
-											   sizeof(struct RxFD) + pkt_len,
-											   PCI_DMA_FROMDEVICE);
-				npkts++;
-			} else {
-				/* Pass up the already-filled skbuff. */
-				skb = sp->rx_skbuff[entry];
-				if (skb == NULL) {
-					printk(KERN_ERR "%s: Inconsistent Rx descriptor chain.\n",
-						   dev->name);
-					break;
-				}
-				sp->rx_skbuff[entry] = NULL;
-				skb_put(skb, pkt_len);
-				npkts++;
-				sp->rx_ringp[entry] = NULL;
-				pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
-								 PKT_BUF_SZ + sizeof(struct RxFD),
-								 PCI_DMA_FROMDEVICE);
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			sp->stats.rx_packets++;
-			sp->stats.rx_bytes += pkt_len;
-		}
-		entry = (++sp->cur_rx) % RX_RING_SIZE;
-		sp->rx_ring_state &= ~RrPostponed;
-		/* Refill the recently taken buffers.
-		   Do it one-by-one to handle traffic bursts better. */
-		if (alloc_ok && speedo_refill_rx_buf(dev, 0) == -1)
-			alloc_ok = 0;
-	}
-
-	/* Try hard to refill the recently taken buffers. */
-	speedo_refill_rx_buffers(dev, 1);
-
-	if (npkts)
-		sp->last_rx_time = jiffies;
-
-	return 0;
-}
-
-static int
-speedo_close(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	int i;
-
-	netdevice_stop(dev);
-	netif_stop_queue(dev);
-
-	if (netif_msg_ifdown(sp))
-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
-			   dev->name, ioread16(ioaddr + SCBStatus));
-
-	/* Shut off the media monitoring timer. */
-	del_timer_sync(&sp->timer);
-
-	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-
-	/* Shutting down the chip nicely fails to disable flow control. So.. */
-	iowrite32(PortPartialReset, ioaddr + SCBPort);
-	ioread32(ioaddr + SCBPort); /* flush posted write */
-	/*
-	 * The chip requires a 10 microsecond quiet period.  Wait here!
-	 */
-	udelay(10);
-
-	free_irq(dev->irq, dev);
-	speedo_show_state(dev);
-
-    /* Free all the skbuffs in the Rx and Tx queues. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = sp->rx_skbuff[i];
-		sp->rx_skbuff[i] = NULL;
-		/* Clear the Rx descriptors. */
-		if (skb) {
-			pci_unmap_single(sp->pdev,
-					 sp->rx_ring_dma[i],
-					 PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
-			dev_kfree_skb(skb);
-		}
-	}
-
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		struct sk_buff *skb = sp->tx_skbuff[i];
-		sp->tx_skbuff[i] = NULL;
-		/* Clear the Tx descriptors. */
-		if (skb) {
-			pci_unmap_single(sp->pdev,
-					 le32_to_cpu(sp->tx_ring[i].tx_buf_addr0),
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(skb);
-		}
-	}
-
-	/* Free multicast setting blocks. */
-	for (i = 0; sp->mc_setup_head != NULL; i++) {
-		struct speedo_mc_block *t;
-		t = sp->mc_setup_head->next;
-		kfree(sp->mc_setup_head);
-		sp->mc_setup_head = t;
-	}
-	sp->mc_setup_tail = NULL;
-	if (netif_msg_ifdown(sp))
-		printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i);
-
-	pci_set_power_state(sp->pdev, PCI_D2);
-
-	return 0;
-}
-
-/* The Speedo-3 has an especially awkward and unusable method of getting
-   statistics out of the chip.  It takes an unpredictable length of time
-   for the dump-stats command to complete.  To avoid a busy-wait loop we
-   update the stats with the previous dump results, and then trigger a
-   new dump.
-
-   Oh, and incoming frames are dropped while executing dump-stats!
-   */
-static struct net_device_stats *
-speedo_get_stats(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-
-	/* Update only if the previous dump finished. */
-	if (sp->lstats->done_marker == le32_to_cpu(0xA007)) {
-		sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats->tx_coll16_errs);
-		sp->stats.tx_window_errors += le32_to_cpu(sp->lstats->tx_late_colls);
-		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_underruns);
-		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_lost_carrier);
-		/*sp->stats.tx_deferred += le32_to_cpu(sp->lstats->tx_deferred);*/
-		sp->stats.collisions += le32_to_cpu(sp->lstats->tx_total_colls);
-		sp->stats.rx_crc_errors += le32_to_cpu(sp->lstats->rx_crc_errs);
-		sp->stats.rx_frame_errors += le32_to_cpu(sp->lstats->rx_align_errs);
-		sp->stats.rx_over_errors += le32_to_cpu(sp->lstats->rx_resource_errs);
-		sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats->rx_overrun_errs);
-		sp->stats.rx_length_errors += le32_to_cpu(sp->lstats->rx_runt_errs);
-		sp->lstats->done_marker = 0x0000;
-		if (netif_running(dev)) {
-			unsigned long flags;
-			/* Take a spinlock to make wait_for_cmd_done and sending the
-			   command atomic.  --SAW */
-			spin_lock_irqsave(&sp->lock, flags);
-			wait_for_cmd_done(dev, sp);
-			iowrite8(CUDumpStats, ioaddr + SCBCmd);
-			spin_unlock_irqrestore(&sp->lock, flags);
-		}
-	}
-	return &sp->stats;
-}
-
-static void speedo_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	strncpy(info->driver, "eepro100", sizeof(info->driver)-1);
-	strncpy(info->version, version, sizeof(info->version)-1);
-	if (sp->pdev)
-		strcpy(info->bus_info, pci_name(sp->pdev));
-}
-
-static int speedo_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	spin_lock_irq(&sp->lock);
-	mii_ethtool_gset(&sp->mii_if, ecmd);
-	spin_unlock_irq(&sp->lock);
-	return 0;
-}
-
-static int speedo_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	int res;
-	spin_lock_irq(&sp->lock);
-	res = mii_ethtool_sset(&sp->mii_if, ecmd);
-	spin_unlock_irq(&sp->lock);
-	return res;
-}
-
-static int speedo_nway_reset(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	return mii_nway_restart(&sp->mii_if);
-}
-
-static u32 speedo_get_link(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	return mii_link_ok(&sp->mii_if);
-}
-
-static u32 speedo_get_msglevel(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	return sp->msg_enable;
-}
-
-static void speedo_set_msglevel(struct net_device *dev, u32 v)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	sp->msg_enable = v;
-}
-
-static struct ethtool_ops ethtool_ops = {
-	.get_drvinfo = speedo_get_drvinfo,
-	.get_settings = speedo_get_settings,
-	.set_settings = speedo_set_settings,
-	.nway_reset = speedo_nway_reset,
-	.get_link = speedo_get_link,
-	.get_msglevel = speedo_get_msglevel,
-	.set_msglevel = speedo_set_msglevel,
-};
-
-static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(rq);
-	int phy = sp->phy[0] & 0x1f;
-	int saved_acpi;
-	int t;
-
-    switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-		data->phy_id = phy;
-
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-		/* FIXME: these operations need to be serialized with MDIO
-		   access from the timeout handler.
-		   They are currently serialized only with MDIO access from the
-		   timer routine.  2000/05/09 SAW */
-		saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
-		t = del_timer_sync(&sp->timer);
-		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
-		if (t)
-			add_timer(&sp->timer); /* may be set to the past  --SAW */
-		pci_set_power_state(sp->pdev, saved_acpi);
-		return 0;
-
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
-		t = del_timer_sync(&sp->timer);
-		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
-		if (t)
-			add_timer(&sp->timer); /* may be set to the past  --SAW */
-		pci_set_power_state(sp->pdev, saved_acpi);
-		return 0;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   This is very ugly with Intel chips -- we usually have to execute an
-   entire configuration command, plus process a multicast command.
-   This is complicated.  We must put a large configuration command and
-   an arbitrarily-sized multicast command in the transmit list.
-   To minimize the disruption -- the previous command might have already
-   loaded the link -- we convert the current command block, normally a Tx
-   command, into a no-op and link it to the new command.
-*/
-static void set_rx_mode(struct net_device *dev)
-{
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-	struct descriptor *last_cmd;
-	char new_rx_mode;
-	unsigned long flags;
-	int entry, i;
-
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		new_rx_mode = 3;
-	} else if ((dev->flags & IFF_ALLMULTI)  ||
-			   dev->mc_count > multicast_filter_limit) {
-		new_rx_mode = 1;
-	} else
-		new_rx_mode = 0;
-
-	if (netif_msg_rx_status(sp))
-		printk(KERN_DEBUG "%s: set_rx_mode %d -> %d\n", dev->name,
-				sp->rx_mode, new_rx_mode);
-
-	if ((int)(sp->cur_tx - sp->dirty_tx) > TX_RING_SIZE - TX_MULTICAST_SIZE) {
-	    /* The Tx ring is full -- don't add anything!  Hope the mode will be
-		 * set again later. */
-		sp->rx_mode = -1;
-		return;
-	}
-
-	if (new_rx_mode != sp->rx_mode) {
-		u8 *config_cmd_data;
-
-		spin_lock_irqsave(&sp->lock, flags);
-		entry = sp->cur_tx++ % TX_RING_SIZE;
-		last_cmd = sp->last_cmd;
-		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
-		sp->tx_skbuff[entry] = NULL;			/* Redundant. */
-		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure);
-		sp->tx_ring[entry].link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
-		config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
-		/* Construct a full CmdConfig frame. */
-		memcpy(config_cmd_data, i82558_config_cmd, CONFIG_DATA_SIZE);
-		config_cmd_data[1] = (txfifo << 4) | rxfifo;
-		config_cmd_data[4] = rxdmacount;
-		config_cmd_data[5] = txdmacount + 0x80;
-		config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0;
-		/* 0x80 doesn't disable FC 0x84 does.
-		   Disable Flow control since we are not ACK-ing any FC interrupts
-		   for now. --Dragan */
-		config_cmd_data[19] = 0x84;
-		config_cmd_data[19] |= sp->mii_if.full_duplex ? 0x40 : 0;
-		config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
-		if (sp->phy[0] & 0x8000) {			/* Use the AUI port instead. */
-			config_cmd_data[15] |= 0x80;
-			config_cmd_data[8] = 0;
-		}
-		/* Trigger the command unit resume. */
-		wait_for_cmd_done(dev, sp);
-		clear_suspend(last_cmd);
-		iowrite8(CUResume, ioaddr + SCBCmd);
-		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-			netif_stop_queue(dev);
-			sp->tx_full = 1;
-		}
-		spin_unlock_irqrestore(&sp->lock, flags);
-	}
-
-	if (new_rx_mode == 0  &&  dev->mc_count < 4) {
-		/* The simple case of 0-3 multicast list entries occurs often, and
-		   fits within one tx_ring[] entry. */
-		struct dev_mc_list *mclist;
-		u16 *setup_params, *eaddrs;
-
-		spin_lock_irqsave(&sp->lock, flags);
-		entry = sp->cur_tx++ % TX_RING_SIZE;
-		last_cmd = sp->last_cmd;
-		sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
-		sp->tx_skbuff[entry] = NULL;
-		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList);
-		sp->tx_ring[entry].link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
-		sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
-		setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr;
-		*setup_params++ = cpu_to_le16(dev->mc_count*6);
-		/* Fill in the multicast addresses. */
-		for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
-			 i++, mclist = mclist->next) {
-			eaddrs = (u16 *)mclist->dmi_addr;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-		}
-
-		wait_for_cmd_done(dev, sp);
-		clear_suspend(last_cmd);
-		/* Immediately trigger the command unit resume. */
-		iowrite8(CUResume, ioaddr + SCBCmd);
-
-		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-			netif_stop_queue(dev);
-			sp->tx_full = 1;
-		}
-		spin_unlock_irqrestore(&sp->lock, flags);
-	} else if (new_rx_mode == 0) {
-		struct dev_mc_list *mclist;
-		u16 *setup_params, *eaddrs;
-		struct speedo_mc_block *mc_blk;
-		struct descriptor *mc_setup_frm;
-		int i;
-
-		mc_blk = kmalloc(sizeof(*mc_blk) + 2 + multicast_filter_limit*6,
-						 GFP_ATOMIC);
-		if (mc_blk == NULL) {
-			printk(KERN_ERR "%s: Failed to allocate a setup frame.\n",
-				   dev->name);
-			sp->rx_mode = -1; /* We failed, try again. */
-			return;
-		}
-		mc_blk->next = NULL;
-		mc_blk->len = 2 + multicast_filter_limit*6;
-		mc_blk->frame_dma =
-			pci_map_single(sp->pdev, &mc_blk->frame, mc_blk->len,
-					PCI_DMA_TODEVICE);
-		mc_setup_frm = &mc_blk->frame;
-
-		/* Fill the setup frame. */
-		if (netif_msg_ifup(sp))
-			printk(KERN_DEBUG "%s: Constructing a setup frame at %p.\n",
-				   dev->name, mc_setup_frm);
-		mc_setup_frm->cmd_status =
-			cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList);
-		/* Link set below. */
-		setup_params = (u16 *)&mc_setup_frm->params;
-		*setup_params++ = cpu_to_le16(dev->mc_count*6);
-		/* Fill in the multicast addresses. */
-		for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
-			 i++, mclist = mclist->next) {
-			eaddrs = (u16 *)mclist->dmi_addr;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-			*setup_params++ = *eaddrs++;
-		}
-
-		/* Disable interrupts while playing with the Tx Cmd list. */
-		spin_lock_irqsave(&sp->lock, flags);
-
-		if (sp->mc_setup_tail)
-			sp->mc_setup_tail->next = mc_blk;
-		else
-			sp->mc_setup_head = mc_blk;
-		sp->mc_setup_tail = mc_blk;
-		mc_blk->tx = sp->cur_tx;
-
-		entry = sp->cur_tx++ % TX_RING_SIZE;
-		last_cmd = sp->last_cmd;
-		sp->last_cmd = mc_setup_frm;
-
-		/* Change the command to a NoOp, pointing to the CmdMulti command. */
-		sp->tx_skbuff[entry] = NULL;
-		sp->tx_ring[entry].status = cpu_to_le32(CmdNOp);
-		sp->tx_ring[entry].link = cpu_to_le32(mc_blk->frame_dma);
-
-		/* Set the link in the setup frame. */
-		mc_setup_frm->link =
-			cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
-
-		pci_dma_sync_single_for_device(sp->pdev, mc_blk->frame_dma,
-									   mc_blk->len, PCI_DMA_TODEVICE);
-
-		wait_for_cmd_done(dev, sp);
-		clear_suspend(last_cmd);
-		/* Immediately trigger the command unit resume. */
-		iowrite8(CUResume, ioaddr + SCBCmd);
-
-		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
-			netif_stop_queue(dev);
-			sp->tx_full = 1;
-		}
-		spin_unlock_irqrestore(&sp->lock, flags);
-
-		if (netif_msg_rx_status(sp))
-			printk(" CmdMCSetup frame length %d in entry %d.\n",
-				   dev->mc_count, entry);
-	}
-
-	sp->rx_mode = new_rx_mode;
-}
-\f
-#ifdef CONFIG_PM
-static int eepro100_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-
-	pci_save_state(pdev);
-
-	if (!netif_running(dev))
-		return 0;
-		
-	del_timer_sync(&sp->timer);
-
-	netif_device_detach(dev);
-	iowrite32(PortPartialReset, ioaddr + SCBPort);
-	
-	/* XXX call pci_set_power_state ()? */
-	pci_disable_device(pdev);
-	pci_set_power_state (pdev, PCI_D3hot);
-	return 0;
-}
-
-static int eepro100_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct speedo_private *sp = netdev_priv(dev);
-	void __iomem *ioaddr = sp->regs;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_enable_device(pdev);
-	pci_set_master(pdev);
-
-	if (!netif_running(dev))
-		return 0;
-
-	/* I'm absolutely uncertain if this part of code may work.
-	   The problems are:
-	    - correct hardware reinitialization;
-		- correct driver behavior between different steps of the
-		  reinitialization;
-		- serialization with other driver calls.
-	   2000/03/08  SAW */
-	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-	speedo_resume(dev);
-	netif_device_attach(dev);
-	sp->rx_mode = -1;
-	sp->flow_ctrl = sp->partner = 0;
-	set_rx_mode(dev);
-	sp->timer.expires = RUN_AT(2*HZ);
-	add_timer(&sp->timer);
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static void __devexit eepro100_remove_one (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct speedo_private *sp = netdev_priv(dev);
-	
-	unregister_netdev(dev);
-
-	release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
-	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-
-	pci_iounmap(pdev, sp->regs);
-	pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
-								+ sizeof(struct speedo_stats),
-						sp->tx_ring, sp->tx_ring_dma);
-	pci_disable_device(pdev);
-	free_netdev(dev);
-}
-\f
-static struct pci_device_id eepro100_pci_tbl[] = {
-	{ PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0,}
-};
-MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl);
-	
-static struct pci_driver eepro100_driver = {
-	.name		= "eepro100",
-	.id_table	= eepro100_pci_tbl,
-	.probe		= eepro100_init_one,
-	.remove		= __devexit_p(eepro100_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= eepro100_suspend,
-	.resume		= eepro100_resume,
-#endif /* CONFIG_PM */
-};
-
-static int __init eepro100_init_module(void)
-{
-#ifdef MODULE
-	printk(version);
-#endif
-	return pci_module_init(&eepro100_driver);
-}
-
-static void __exit eepro100_cleanup_module(void)
-{
-	pci_unregister_driver(&eepro100_driver);
-}
-
-module_init(eepro100_init_module);
-module_exit(eepro100_cleanup_module);
-\f
-/*
- * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */

^ permalink raw reply

* [RFC: 2.6 patch] remove drivers/net/tulip/xircom_tulip_cb.c
From: Adrian Bunk @ 2005-11-18  3:33 UTC (permalink / raw)
  To: jgarzik; +Cc: tulip-users, linux-kernel, netdev

This patch removes the obsolete drivers/net/tulip/xircom_tulip_cb.c 
driver.

Is there any reason why it should be kept?


Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

 drivers/net/tulip/Kconfig           |   16 
 drivers/net/tulip/Makefile          |    1 
 drivers/net/tulip/xircom_tulip_cb.c | 1748 ----------------------------
 3 files changed, 1 insertion(+), 1764 deletions(-)

--- linux-2.6.15-rc1-mm1-full/drivers/net/tulip/Kconfig.old	2005-11-18 03:45:53.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/drivers/net/tulip/Kconfig	2005-11-18 03:46:20.000000000 +0100
@@ -148,7 +148,7 @@
 	  be called uli526x.
 	  
 config PCMCIA_XIRCOM
-	tristate "Xircom CardBus support (new driver)"
+	tristate "Xircom CardBus support"
 	depends on NET_TULIP && CARDBUS
 	---help---
 	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@@ -160,19 +160,5 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module will
 	  be called xircom_cb.  If unsure, say N.
 
-config PCMCIA_XIRTULIP
-	tristate "Xircom Tulip-like CardBus support (old driver)"
-	depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP
-	select CRC32
-	---help---
-	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
-	  It should work with most DEC 21*4*-based chips/ethercards, as well
-	  as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
-	  ASIX.
-
-	  To compile this driver as a module, choose M here and read
-	  <file:Documentation/networking/net-modules.txt>.  The module will
-	  be called xircom_tulip_cb.  If unsure, say N.
-
 endmenu
 
--- linux-2.6.15-rc1-mm1-full/drivers/net/tulip/Makefile.old	2005-11-18 03:46:32.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/drivers/net/tulip/Makefile	2005-11-18 03:46:41.000000000 +0100
@@ -2,7 +2,6 @@
 # Makefile for the Linux "Tulip" family network device drivers.
 #
 
-obj-$(CONFIG_PCMCIA_XIRTULIP)	+= xircom_tulip_cb.o
 obj-$(CONFIG_PCMCIA_XIRCOM)	+= xircom_cb.o
 obj-$(CONFIG_DM9102)		+= dmfe.o
 obj-$(CONFIG_WINBOND_840)	+= winbond-840.o
--- linux-2.6.15-rc1-mm1-full/drivers/net/tulip/xircom_tulip_cb.c	2005-10-28 02:02:08.000000000 +0200
+++ /dev/null	2005-11-08 19:07:57.000000000 +0100
@@ -1,1748 +0,0 @@
-/* xircom_tulip_cb.c: A Xircom CBE-100 ethernet driver for Linux. */
-/*
-	Written/copyright 1994-1999 by Donald Becker.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-	-----------------------------------------------------------
-
-	Linux kernel-specific changes:
-
-	LK1.0 (Ion Badulescu)
-	- Major cleanup
-	- Use 2.4 PCI API
-	- Support ethtool
-	- Rewrite perfect filter/hash code
-	- Use interrupts for media changes
-
-	LK1.1 (Ion Badulescu)
-	- Disallow negotiation of unsupported full-duplex modes
-*/
-
-#define DRV_NAME	"xircom_tulip_cb"
-#define DRV_VERSION	"0.91+LK1.1"
-#define DRV_RELDATE	"October 11, 2001"
-
-#define CARDBUS 1
-
-/* A few user-configurable values. */
-
-#define xircom_debug debug
-#ifdef XIRCOM_DEBUG
-static int xircom_debug = XIRCOM_DEBUG;
-#else
-static int xircom_debug = 1;
-#endif
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 25;
-
-#define MAX_UNITS 4
-/* Used to pass the full-duplex flag, etc. */
-static int full_duplex[MAX_UNITS];
-static int options[MAX_UNITS];
-static int mtu[MAX_UNITS];			/* Jumbo MTU for interfaces. */
-
-/* Keep the ring sizes a power of two for efficiency.
-   Making the Tx ring too large decreases the effectiveness of channel
-   bonding and packet priority.
-   There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	32
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
-#ifdef __alpha__
-static int rx_copybreak = 1518;
-#else
-static int rx_copybreak = 100;
-#endif
-
-/*
-  Set the bus performance register.
-	Typical: Set 16 longword cache alignment, no burst limit.
-	Cache alignment bits 15:14	     Burst length 13:8
-		0000	No alignment  0x00000000 unlimited		0800 8 longwords
-		4000	8  longwords		0100 1 longword		1000 16 longwords
-		8000	16 longwords		0200 2 longwords	2000 32 longwords
-		C000	32  longwords		0400 4 longwords
-	Warning: many older 486 systems are broken and require setting 0x00A04800
-	   8 longword cache alignment, 8 longword burst.
-	ToDo: Non-Intel setting could be better.
-*/
-
-#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
-static int csr0 = 0x01A00000 | 0xE000;
-#elif defined(__powerpc__)
-static int csr0 = 0x01B00000 | 0x8000;
-#elif defined(__sparc__)
-static int csr0 = 0x01B00080 | 0x8000;
-#elif defined(__i386__)
-static int csr0 = 0x01A00000 | 0x8000;
-#else
-#warning Processor architecture undefined!
-static int csr0 = 0x00A00000 | 0x4800;
-#endif
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT		(4 * HZ)
-#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
-#define PKT_SETUP_SZ		192			/* Size of the setup frame */
-
-/* PCI registers */
-#define PCI_POWERMGMT 	0x40
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/crc32.h>
-
-#include <asm/io.h>
-#include <asm/processor.h>	/* Processor type for cache alignment. */
-#include <asm/uaccess.h>
-
-
-/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
-KERN_INFO DRV_NAME ".c derived from tulip.c:v0.91 4/14/99 becker@scyld.com\n"
-KERN_INFO " unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "\n";
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("Xircom CBE-100 ethernet driver");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRV_VERSION);
-
-module_param(debug, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param(rx_copybreak, int, 0);
-module_param(csr0, int, 0);
-
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-
-#define RUN_AT(x) (jiffies + (x))
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver was forked from the driver for the DECchip "Tulip",
-Digital's single-chip ethernet controllers for PCI.  It supports Xircom's
-almost-Tulip-compatible CBE-100 CardBus adapters.
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS preferably should assign the
-PCI INTA signal to an otherwise unused system IRQ line.
-
-III. Driver operation
-
-IIIa. Ring buffers
-
-The Xircom can use either ring buffers or lists of Tx and Rx descriptors.
-This driver uses statically allocated rings of Rx and Tx descriptors, set at
-compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
-for the Rx ring buffers at open() time and passes the skb->data field to the
-Xircom as receive data buffers.  When an incoming frame is less than
-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
-copied to the new skbuff.  When the incoming frame is larger, the skbuff is
-passed directly up the protocol stack and replaced by a newly allocated
-skbuff.
-
-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
-using a full-sized skbuff for small frames vs. the copying costs of larger
-frames.  For small frames the copying cost is negligible (esp. considering
-that we are pre-loading the cache with immediately useful header
-information).  For large frames the copying cost is non-trivial, and the
-larger copy might flush the cache of useful data.  A subtle aspect of this
-choice is that the Xircom only receives into longword aligned buffers, thus
-the IP header at offset 14 isn't longword aligned for further processing.
-Copied frames are put into the new skbuff at an offset of "+2", thus copying
-has the beneficial effect of aligning the IP header and preloading the
-cache.
-
-IIIC. Synchronization
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'tp->tx_full' flag.
-
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
-stats.)	 After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
-tx_full and tbusy flags.
-
-IV. Notes
-
-IVb. References
-
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-http://www.digital.com  (search for current 21*4* datasheets and "21X4 SROM")
-http://www.national.com/pf/DP/DP83840A.html
-
-IVc. Errata
-
-*/
-
-/* A full-duplex map for media types. */
-enum MediaIs {
-	MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
-	MediaIs100=16};
-static const char media_cap[] =
-{0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };
-
-/* Offsets to the Command and Status Registers, "CSRs".  All accesses
-   must be longword instructions and quadword aligned. */
-enum xircom_offsets {
-	CSR0=0,    CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
-	CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
-	CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x04, };
-
-/* The bits in the CSR5 status registers, mostly interrupt sources. */
-enum status_bits {
-	LinkChange=0x08000000,
-	NormalIntr=0x10000, NormalIntrMask=0x00014045,
-	AbnormalIntr=0x8000, AbnormalIntrMask=0x0a00a5a2,
-	ReservedIntrMask=0xe0001a18,
-	EarlyRxIntr=0x4000, BusErrorIntr=0x2000,
-	EarlyTxIntr=0x400, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
-	TxFIFOUnderflow=0x20, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
-};
-
-enum csr0_control_bits {
-	EnableMWI=0x01000000, EnableMRL=0x00800000,
-	EnableMRM=0x00200000, EqualBusPrio=0x02,
-	SoftwareReset=0x01,
-};
-
-enum csr6_control_bits {
-	ReceiveAllBit=0x40000000, AllMultiBit=0x80, PromiscBit=0x40,
-	HashFilterBit=0x01, FullDuplexBit=0x0200,
-	TxThresh10=0x400000, TxStoreForw=0x200000,
-	TxThreshMask=0xc000, TxThreshShift=14,
-	EnableTx=0x2000, EnableRx=0x02,
-	ReservedZeroMask=0x8d930134, ReservedOneMask=0x320c0000,
-	EnableTxRx=(EnableTx | EnableRx),
-};
-
-
-enum tbl_flag {
-	HAS_MII=1, HAS_ACPI=2,
-};
-static struct xircom_chip_table {
-	char *chip_name;
-	int valid_intrs;			/* CSR7 interrupt enable settings */
-	int flags;
-} xircom_tbl[] = {
-  { "Xircom Cardbus Adapter",
-	LinkChange | NormalIntr | AbnormalIntr | BusErrorIntr |
-	RxDied | RxNoBuf | RxIntr | TxFIFOUnderflow | TxNoBuf | TxDied | TxIntr,
-	HAS_MII | HAS_ACPI, },
-  { NULL, },
-};
-/* This matches the table above. */
-enum chips {
-	X3201_3,
-};
-
-
-/* The Xircom Rx and Tx buffer descriptors. */
-struct xircom_rx_desc {
-	s32 status;
-	s32 length;
-	u32 buffer1, buffer2;
-};
-
-struct xircom_tx_desc {
-	s32 status;
-	s32 length;
-	u32 buffer1, buffer2;				/* We use only buffer 1.  */
-};
-
-enum tx_desc0_status_bits {
-	Tx0DescOwned=0x80000000, Tx0DescError=0x8000, Tx0NoCarrier=0x0800,
-	Tx0LateColl=0x0200, Tx0ManyColl=0x0100, Tx0Underflow=0x02,
-};
-enum tx_desc1_status_bits {
-	Tx1ComplIntr=0x80000000, Tx1LastSeg=0x40000000, Tx1FirstSeg=0x20000000,
-	Tx1SetupPkt=0x08000000, Tx1DisableCRC=0x04000000, Tx1RingWrap=0x02000000,
-	Tx1ChainDesc=0x01000000, Tx1NoPad=0x800000, Tx1HashSetup=0x400000,
-	Tx1WholePkt=(Tx1FirstSeg | Tx1LastSeg),
-};
-enum rx_desc0_status_bits {
-	Rx0DescOwned=0x80000000, Rx0DescError=0x8000, Rx0NoSpace=0x4000,
-	Rx0Runt=0x0800, Rx0McastPkt=0x0400, Rx0FirstSeg=0x0200, Rx0LastSeg=0x0100,
-	Rx0HugeFrame=0x80, Rx0CRCError=0x02,
-	Rx0WholePkt=(Rx0FirstSeg | Rx0LastSeg),
-};
-enum rx_desc1_status_bits {
-	Rx1RingWrap=0x02000000, Rx1ChainDesc=0x01000000,
-};
-
-struct xircom_private {
-	struct xircom_rx_desc rx_ring[RX_RING_SIZE];
-	struct xircom_tx_desc tx_ring[TX_RING_SIZE];
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct sk_buff* tx_skbuff[TX_RING_SIZE];
-#ifdef CARDBUS
-	/* The X3201-3 requires 4-byte aligned tx bufs */
-	struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
-#endif
-	/* The addresses of receive-in-place skbuffs. */
-	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	u16 setup_frame[PKT_SETUP_SZ / sizeof(u16)];	/* Pseudo-Tx frame to init address table. */
-	int chip_id;
-	struct net_device_stats stats;
-	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
-	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int speed100:1;
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int autoneg:1;
-	unsigned int default_port:4;		/* Last dev->if_port value. */
-	unsigned int open:1;
-	unsigned int csr0;					/* CSR0 setting. */
-	unsigned int csr6;					/* Current CSR6 control settings. */
-	u16 to_advertise;					/* NWay capabilities advertised.  */
-	u16 advertising[4];
-	signed char phys[4], mii_cnt;		/* MII device addresses. */
-	int saved_if_port;
-	struct pci_dev *pdev;
-	spinlock_t lock;
-};
-
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static void xircom_up(struct net_device *dev);
-static void xircom_down(struct net_device *dev);
-static int xircom_open(struct net_device *dev);
-static void xircom_tx_timeout(struct net_device *dev);
-static void xircom_init_ring(struct net_device *dev);
-static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int xircom_rx(struct net_device *dev);
-static void xircom_media_change(struct net_device *dev);
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int xircom_close(struct net_device *dev);
-static struct net_device_stats *xircom_get_stats(struct net_device *dev);
-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void set_rx_mode(struct net_device *dev);
-static void check_duplex(struct net_device *dev);
-static struct ethtool_ops ops;
-
-
-/* The Xircom cards are picky about when certain bits in CSR6 can be
-   manipulated.  Keith Owens <kaos@ocs.com.au>. */
-static void outl_CSR6(u32 newcsr6, long ioaddr)
-{
-	const int strict_bits =
-		TxThresh10 | TxStoreForw | TxThreshMask | EnableTxRx | FullDuplexBit;
-    int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200;
-    unsigned long flags;
-    save_flags(flags);
-    cli();
-	/* mask out the reserved bits that always read 0 on the Xircom cards */
-	newcsr6 &= ~ReservedZeroMask;
-	/* or in the reserved bits that always read 1 */
-	newcsr6 |= ReservedOneMask;
-    currcsr6 = inl(ioaddr + CSR6);
-    if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) ||
-	((currcsr6 & ~EnableTxRx) == 0)) {
-		outl(newcsr6, ioaddr + CSR6);	/* safe */
-		restore_flags(flags);
-		return;
-    }
-    /* make sure the transmitter and receiver are stopped first */
-    currcsr6 &= ~EnableTxRx;
-    while (1) {
-		csr5 = inl(ioaddr + CSR5);
-		if (csr5 == 0xffffffff)
-			break;  /* cannot read csr5, card removed? */
-		csr5_22_20 = csr5 & 0x700000;
-		csr5_19_17 = csr5 & 0x0e0000;
-		if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) &&
-			(csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000))
-			break;  /* both are stopped or suspended */
-		if (!--attempts) {
-			printk(KERN_INFO DRV_NAME ": outl_CSR6 too many attempts,"
-				   "csr5=0x%08x\n", csr5);
-			outl(newcsr6, ioaddr + CSR6);  /* unsafe but do it anyway */
-			restore_flags(flags);
-			return;
-		}
-		outl(currcsr6, ioaddr + CSR6);
-		udelay(1);
-    }
-    /* now it is safe to change csr6 */
-    outl(newcsr6, ioaddr + CSR6);
-    restore_flags(flags);
-}
-
-
-static void __devinit read_mac_address(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	int i, j;
-	unsigned char tuple, link, data_id, data_count;
-
-	/* Xircom has its address stored in the CIS;
-	 * we access it through the boot rom interface for now
-	 * this might not work, as the CIS is not parsed but I
-	 * (danilo) use the offset I found on my card's CIS !!!
-	 *
-	 * Doug Ledford: I changed this routine around so that it
-	 * walks the CIS memory space, parsing the config items, and
-	 * finds the proper lan_node_id tuple and uses the data
-	 * stored there.
-	 */
-	outl(1 << 12, ioaddr + CSR9); /* enable boot rom access */
-	for (i = 0x100; i < 0x1f7; i += link+2) {
-		outl(i, ioaddr + CSR10);
-		tuple = inl(ioaddr + CSR9) & 0xff;
-		outl(i + 1, ioaddr + CSR10);
-		link = inl(ioaddr + CSR9) & 0xff;
-		outl(i + 2, ioaddr + CSR10);
-		data_id = inl(ioaddr + CSR9) & 0xff;
-		outl(i + 3, ioaddr + CSR10);
-		data_count = inl(ioaddr + CSR9) & 0xff;
-		if ( (tuple == 0x22) &&
-			 (data_id == 0x04) && (data_count == 0x06) ) {
-			/*
-			 * This is it.  We have the data we want.
-			 */
-			for (j = 0; j < 6; j++) {
-				outl(i + j + 4, ioaddr + CSR10);
-				dev->dev_addr[j] = inl(ioaddr + CSR9) & 0xff;
-			}
-			break;
-		} else if (link == 0) {
-			break;
-		}
-	}
-}
-
-
-/*
- * locate the MII interfaces and initialize them.
- * we disable full-duplex modes here,
- * because we don't know how to handle them.
- */
-static void find_mii_transceivers(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int phy, phy_idx;
-
-	if (media_cap[tp->default_port] & MediaIsMII) {
-		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
-		tp->to_advertise = media2advert[tp->default_port - 9];
-	} else
-		tp->to_advertise =
-			/*ADVERTISE_100BASE4 | ADVERTISE_100FULL |*/ ADVERTISE_100HALF |
-			/*ADVERTISE_10FULL |*/ ADVERTISE_10HALF | ADVERTISE_CSMA;
-
-	/* Find the connected MII xcvrs.
-	   Doing this in open() would allow detecting external xcvrs later,
-	   but takes much time. */
-	for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) {
-		int mii_status = mdio_read(dev, phy, MII_BMSR);
-		if ((mii_status & (BMSR_100BASE4 | BMSR_100HALF | BMSR_10HALF)) == BMSR_100BASE4 ||
-			((mii_status & BMSR_100BASE4) == 0 &&
-			 (mii_status & (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF)) != 0)) {
-			int mii_reg0 = mdio_read(dev, phy, MII_BMCR);
-			int mii_advert = mdio_read(dev, phy, MII_ADVERTISE);
-			int reg4 = ((mii_status >> 6) & tp->to_advertise) | ADVERTISE_CSMA;
-			tp->phys[phy_idx] = phy;
-			tp->advertising[phy_idx++] = reg4;
-			printk(KERN_INFO "%s:  MII transceiver #%d "
-				   "config %4.4x status %4.4x advertising %4.4x.\n",
-				   dev->name, phy, mii_reg0, mii_status, mii_advert);
-		}
-	}
-	tp->mii_cnt = phy_idx;
-	if (phy_idx == 0) {
-		printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
-			   dev->name);
-		tp->phys[0] = 0;
-	}
-}
-
-
-/*
- * To quote Arjan van de Ven:
- *   transceiver_voodoo() enables the external UTP plug thingy.
- *   it's called voodoo as I stole this code and cannot cross-reference
- *   it with the specification.
- * Actually it seems to go like this:
- * - GPIO2 enables the MII itself so we can talk to it. The MII gets reset
- *   so any prior MII settings are lost.
- * - GPIO0 enables the TP port so the MII can talk to the network.
- * - a software reset will reset both GPIO pins.
- * I also moved the software reset here, because doing it in xircom_up()
- * required enabling the GPIO pins each time, which reset the MII each time.
- * Thus we couldn't control the MII -- which sucks because we don't know
- * how to handle full-duplex modes so we *must* disable them.
- */
-static void transceiver_voodoo(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
-	outl(SoftwareReset, ioaddr + CSR0);
-	udelay(2);
-
-	/* Deassert reset. */
-	outl(tp->csr0, ioaddr + CSR0);
-
-	/* Reset the xcvr interface and turn on heartbeat. */
-	outl(0x0008, ioaddr + CSR15);
-	udelay(5);  /* The delays are Xircom-recommended to give the
-				 * chipset time to reset the actual hardware
-				 * on the PCMCIA card
-				 */
-	outl(0xa8050000, ioaddr + CSR15);
-	udelay(5);
-	outl(0xa00f0000, ioaddr + CSR15);
-	udelay(5);
-
-	outl_CSR6(0, ioaddr);
-	//outl_CSR6(FullDuplexBit, ioaddr);
-}
-
-
-static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct net_device *dev;
-	struct xircom_private *tp;
-	static int board_idx = -1;
-	int chip_idx = id->driver_data;
-	long ioaddr;
-	int i;
-	u8 chip_rev;
-
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
-	static int printed_version;
-	if (!printed_version++)
-		printk(version);
-#endif
-
-	//printk(KERN_INFO "xircom_init_one(%s)\n", pci_name(pdev));
-
-	board_idx++;
-
-	if (pci_enable_device(pdev))
-		return -ENODEV;
-
-	pci_set_master(pdev);
-
-	ioaddr = pci_resource_start(pdev, 0);
-	dev = alloc_etherdev(sizeof(*tp));
-	if (!dev) {
-		printk (KERN_ERR DRV_NAME "%d: cannot alloc etherdev, aborting\n", board_idx);
-		return -ENOMEM;
-	}
-	SET_MODULE_OWNER(dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	dev->base_addr = ioaddr;
-	dev->irq = pdev->irq;
-
-	if (pci_request_regions(pdev, dev->name)) {
-		printk (KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", board_idx);
-		goto err_out_free_netdev;
-	}
-
-	/* Bring the chip out of sleep mode.
-	   Caution: Snooze mode does not work with some boards! */
-	if (xircom_tbl[chip_idx].flags & HAS_ACPI)
-		pci_write_config_dword(pdev, PCI_POWERMGMT, 0);
-
-	/* Stop the chip's Tx and Rx processes. */
-	outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
-	/* Clear the missed-packet counter. */
-	(volatile int)inl(ioaddr + CSR8);
-
-	tp = netdev_priv(dev);
-
-	spin_lock_init(&tp->lock);
-	tp->pdev = pdev;
-	tp->chip_id = chip_idx;
-	/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */
-	/* XXX: is this necessary for Xircom? */
-	tp->csr0 = csr0 & ~EnableMWI;
-
-	pci_set_drvdata(pdev, dev);
-
-	/* The lower four bits are the media type. */
-	if (board_idx >= 0 && board_idx < MAX_UNITS) {
-		tp->default_port = options[board_idx] & 15;
-		if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
-			tp->full_duplex = 1;
-		if (mtu[board_idx] > 0)
-			dev->mtu = mtu[board_idx];
-	}
-	if (dev->mem_start)
-		tp->default_port = dev->mem_start;
-	if (tp->default_port) {
-		if (media_cap[tp->default_port] & MediaAlwaysFD)
-			tp->full_duplex = 1;
-	}
-	if (tp->full_duplex)
-		tp->autoneg = 0;
-	else
-		tp->autoneg = 1;
-	tp->speed100 = 1;
-
-	/* The Xircom-specific entries in the device structure. */
-	dev->open = &xircom_open;
-	dev->hard_start_xmit = &xircom_start_xmit;
-	dev->stop = &xircom_close;
-	dev->get_stats = &xircom_get_stats;
-	dev->do_ioctl = &xircom_ioctl;
-#ifdef HAVE_MULTICAST
-	dev->set_multicast_list = &set_rx_mode;
-#endif
-	dev->tx_timeout = xircom_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &ops);
-
-	transceiver_voodoo(dev);
-
-	read_mac_address(dev);
-
-	if (register_netdev(dev))
-		goto err_out_cleardev;
-
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
-	printk(KERN_INFO "%s: %s rev %d at %#3lx,",
-	       dev->name, xircom_tbl[chip_idx].chip_name, chip_rev, ioaddr);
-	for (i = 0; i < 6; i++)
-		printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
-	printk(", IRQ %d.\n", dev->irq);
-
-	if (xircom_tbl[chip_idx].flags & HAS_MII) {
-		find_mii_transceivers(dev);
-		check_duplex(dev);
-	}
-
-	return 0;
-
-err_out_cleardev:
-	pci_set_drvdata(pdev, NULL);
-	pci_release_regions(pdev);
-err_out_free_netdev:
-	free_netdev(dev);
-	return -ENODEV;
-}
-
-
-/* MII transceiver control section.
-   Read and write the MII registers using software-generated serial
-   MDIO protocol.  See the MII specifications or DP83840A data sheet
-   for details. */
-
-/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
-   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
-   "overclocking" issues or future 66Mhz PCI. */
-#define mdio_delay() inl(mdio_addr)
-
-/* Read and write the MII registers using software-generated serial
-   MDIO protocol.  It is just different enough from the EEPROM protocol
-   to not share code.  The maxium data clock rate is 2.5 Mhz. */
-#define MDIO_SHIFT_CLK	0x10000
-#define MDIO_DATA_WRITE0 0x00000
-#define MDIO_DATA_WRITE1 0x20000
-#define MDIO_ENB		0x00000		/* Ignore the 0x02000 databook setting. */
-#define MDIO_ENB_IN		0x40000
-#define MDIO_DATA_READ	0x80000
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	int i;
-	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-	int retval = 0;
-	long ioaddr = dev->base_addr;
-	long mdio_addr = ioaddr + CSR9;
-
-	/* Establish sync by sending at least 32 logic ones. */
-	for (i = 32; i >= 0; i--) {
-		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Shift the read command bits out. */
-	for (i = 15; i >= 0; i--) {
-		int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
-
-		outl(MDIO_ENB | dataval, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Read the two transition, 16 data, and wire-idle bits. */
-	for (i = 19; i > 0; i--) {
-		outl(MDIO_ENB_IN, mdio_addr);
-		mdio_delay();
-		retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
-		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	return (retval>>1) & 0xffff;
-}
-
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	int i;
-	int cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
-	long ioaddr = dev->base_addr;
-	long mdio_addr = ioaddr + CSR9;
-
-	/* Establish sync by sending 32 logic ones. */
-	for (i = 32; i >= 0; i--) {
-		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Shift the command bits out. */
-	for (i = 31; i >= 0; i--) {
-		int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
-		outl(MDIO_ENB | dataval, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Clear out extra bits. */
-	for (i = 2; i > 0; i--) {
-		outl(MDIO_ENB_IN, mdio_addr);
-		mdio_delay();
-		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	return;
-}
-
-
-static void
-xircom_up(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int i;
-
-	xircom_init_ring(dev);
-	/* Clear the tx ring */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		tp->tx_skbuff[i] = NULL;
-		tp->tx_ring[i].status = 0;
-	}
-
-	if (xircom_debug > 1)
-		printk(KERN_DEBUG "%s: xircom_up() irq %d.\n", dev->name, dev->irq);
-
-	outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);
-	outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);
-
-	tp->saved_if_port = dev->if_port;
-	if (dev->if_port == 0)
-		dev->if_port = tp->default_port;
-
-	tp->csr6 = TxThresh10 /*| FullDuplexBit*/;						/* XXX: why 10 and not 100? */
-
-	set_rx_mode(dev);
-
-	/* Start the chip's Tx to process setup frame. */
-	outl_CSR6(tp->csr6, ioaddr);
-	outl_CSR6(tp->csr6 | EnableTx, ioaddr);
-
-	/* Acknowledge all outstanding interrupts sources */
-	outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
-	/* Enable interrupts by setting the interrupt mask. */
-	outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
-	/* Enable Rx */
-	outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-	/* Rx poll demand */
-	outl(0, ioaddr + CSR2);
-
-	/* Tell the net layer we're ready */
-	netif_start_queue (dev);
-
-	/* Check current media state */
-	xircom_media_change(dev);
-
-	if (xircom_debug > 2) {
-		printk(KERN_DEBUG "%s: Done xircom_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
-			   dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),
-			   inl(ioaddr + CSR6));
-	}
-}
-
-
-static int
-xircom_open(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-
-	if (request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev))
-		return -EAGAIN;
-
-	xircom_up(dev);
-	tp->open = 1;
-
-	return 0;
-}
-
-
-static void xircom_tx_timeout(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	if (media_cap[dev->if_port] & MediaIsMII) {
-		/* Do nothing -- the media monitor should handle this. */
-		if (xircom_debug > 1)
-			printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
-				   dev->name);
-	}
-
-#if defined(way_too_many_messages)
-	if (xircom_debug > 3) {
-		int i;
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			u8 *buf = (u8 *)(tp->rx_ring[i].buffer1);
-			int j;
-			printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x  "
-				   "%2.2x %2.2x %2.2x.\n",
-				   i, (unsigned int)tp->rx_ring[i].status,
-				   (unsigned int)tp->rx_ring[i].length,
-				   (unsigned int)tp->rx_ring[i].buffer1,
-				   (unsigned int)tp->rx_ring[i].buffer2,
-				   buf[0], buf[1], buf[2]);
-			for (j = 0; buf[j] != 0xee && j < 1600; j++)
-				if (j < 100) printk(" %2.2x", buf[j]);
-			printk(" j=%d.\n", j);
-		}
-		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)tp->rx_ring);
-		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
-		printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
-		printk("\n");
-	}
-#endif
-
-	/* Stop and restart the chip's Tx/Rx processes . */
-	outl_CSR6(tp->csr6 | EnableRx, ioaddr);
-	outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-	/* Trigger an immediate transmit demand. */
-	outl(0, ioaddr + CSR1);
-
-	dev->trans_start = jiffies;
-	netif_wake_queue (dev);
-	tp->stats.tx_errors++;
-}
-
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void xircom_init_ring(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int i;
-
-	tp->tx_full = 0;
-	tp->cur_rx = tp->cur_tx = 0;
-	tp->dirty_rx = tp->dirty_tx = 0;
-
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		tp->rx_ring[i].status = 0;
-		tp->rx_ring[i].length = PKT_BUF_SZ;
-		tp->rx_ring[i].buffer2 = virt_to_bus(&tp->rx_ring[i+1]);
-		tp->rx_skbuff[i] = NULL;
-	}
-	/* Mark the last entry as wrapping the ring. */
-	tp->rx_ring[i-1].length = PKT_BUF_SZ | Rx1RingWrap;
-	tp->rx_ring[i-1].buffer2 = virt_to_bus(&tp->rx_ring[0]);
-
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		/* Note the receive buffer must be longword aligned.
-		   dev_alloc_skb() provides 16 byte alignment.  But do *not*
-		   use skb_reserve() to align the IP header! */
-		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
-		tp->rx_skbuff[i] = skb;
-		if (skb == NULL)
-			break;
-		skb->dev = dev;			/* Mark as being used by this device. */
-		tp->rx_ring[i].status = Rx0DescOwned;	/* Owned by Xircom chip */
-		tp->rx_ring[i].buffer1 = virt_to_bus(skb->data);
-	}
-	tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-
-	/* The Tx buffer descriptor is filled in as needed, but we
-	   do need to clear the ownership bit. */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		tp->tx_skbuff[i] = NULL;
-		tp->tx_ring[i].status = 0;
-		tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
-#ifdef CARDBUS
-		if (tp->chip_id == X3201_3)
-			tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ);
-#endif /* CARDBUS */
-	}
-	tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
-}
-
-
-static int
-xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int entry;
-	u32 flag;
-
-	/* Caution: the write order is important here, set the base address
-	   with the "ownership" bits last. */
-
-	/* Calculate the next Tx descriptor entry. */
-	entry = tp->cur_tx % TX_RING_SIZE;
-
-	tp->tx_skbuff[entry] = skb;
-#ifdef CARDBUS
-	if (tp->chip_id == X3201_3) {
-		memcpy(tp->tx_aligned_skbuff[entry]->data,skb->data,skb->len);
-		tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
-	} else
-#endif
-		tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
-
-	if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
-		flag = Tx1WholePkt; /* No interrupt */
-	} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
-		flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
-	} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
-		flag = Tx1WholePkt; /* No Tx-done intr. */
-	} else {
-		/* Leave room for set_rx_mode() to fill entries. */
-		flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
-		tp->tx_full = 1;
-	}
-	if (entry == TX_RING_SIZE - 1)
-		flag |= Tx1WholePkt | Tx1ComplIntr | Tx1RingWrap;
-
-	tp->tx_ring[entry].length = skb->len | flag;
-	tp->tx_ring[entry].status = Tx0DescOwned;	/* Pass ownership to the chip. */
-	tp->cur_tx++;
-	if (tp->tx_full)
-		netif_stop_queue (dev);
-	else
-		netif_wake_queue (dev);
-
-	/* Trigger an immediate transmit demand. */
-	outl(0, dev->base_addr + CSR1);
-
-	dev->trans_start = jiffies;
-
-	return 0;
-}
-
-
-static void xircom_media_change(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	u16 reg0, reg1, reg4, reg5;
-	u32 csr6 = inl(ioaddr + CSR6), newcsr6;
-
-	/* reset status first */
-	mdio_read(dev, tp->phys[0], MII_BMCR);
-	mdio_read(dev, tp->phys[0], MII_BMSR);
-
-	reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
-	reg1 = mdio_read(dev, tp->phys[0], MII_BMSR);
-
-	if (reg1 & BMSR_LSTATUS) {
-		/* link is up */
-		if (reg0 & BMCR_ANENABLE) {
-			/* autonegotiation is enabled */
-			reg4 = mdio_read(dev, tp->phys[0], MII_ADVERTISE);
-			reg5 = mdio_read(dev, tp->phys[0], MII_LPA);
-			if (reg4 & ADVERTISE_100FULL && reg5 & LPA_100FULL) {
-				tp->speed100 = 1;
-				tp->full_duplex = 1;
-			} else if (reg4 & ADVERTISE_100HALF && reg5 & LPA_100HALF) {
-				tp->speed100 = 1;
-				tp->full_duplex = 0;
-			} else if (reg4 & ADVERTISE_10FULL && reg5 & LPA_10FULL) {
-				tp->speed100 = 0;
-				tp->full_duplex = 1;
-			} else {
-				tp->speed100 = 0;
-				tp->full_duplex = 0;
-			}
-		} else {
-			/* autonegotiation is disabled */
-			if (reg0 & BMCR_SPEED100)
-				tp->speed100 = 1;
-			else
-				tp->speed100 = 0;
-			if (reg0 & BMCR_FULLDPLX)
-				tp->full_duplex = 1;
-			else
-				tp->full_duplex = 0;
-		}
-		printk(KERN_DEBUG "%s: Link is up, running at %sMbit %s-duplex\n",
-		       dev->name,
-		       tp->speed100 ? "100" : "10",
-		       tp->full_duplex ? "full" : "half");
-		netif_carrier_on(dev);
-		newcsr6 = csr6 & ~FullDuplexBit;
-		if (tp->full_duplex)
-			newcsr6 |= FullDuplexBit;
-		if (newcsr6 != csr6)
-			outl_CSR6(newcsr6, ioaddr + CSR6);
-	} else {
-		printk(KERN_DEBUG "%s: Link is down\n", dev->name);
-		netif_carrier_off(dev);
-	}
-}
-
-
-static void check_duplex(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	u16 reg0;
-
-	mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET);
-	udelay(500);
-	while (mdio_read(dev, tp->phys[0], MII_BMCR) & BMCR_RESET);
-
-	reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
-	mdio_write(dev, tp->phys[0], MII_ADVERTISE, tp->advertising[0]);
-
-	if (tp->autoneg) {
-		reg0 &= ~(BMCR_SPEED100 | BMCR_FULLDPLX);
-		reg0 |= BMCR_ANENABLE | BMCR_ANRESTART;
-	} else {
-		reg0 &= ~(BMCR_ANENABLE | BMCR_ANRESTART);
-		if (tp->speed100)
-			reg0 |= BMCR_SPEED100;
-		if (tp->full_duplex)
-			reg0 |= BMCR_FULLDPLX;
-		printk(KERN_DEBUG "%s: Link forced to %sMbit %s-duplex\n",
-		       dev->name,
-		       tp->speed100 ? "100" : "10",
-		       tp->full_duplex ? "full" : "half");
-	}
-	mdio_write(dev, tp->phys[0], MII_BMCR, reg0);
-}
-
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{
-	struct net_device *dev = dev_instance;
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int csr5, work_budget = max_interrupt_work;
-	int handled = 0;
-
-	spin_lock (&tp->lock);
-
-	do {
-		csr5 = inl(ioaddr + CSR5);
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		outl(csr5 & 0x0001ffff, ioaddr + CSR5);
-
-		if (xircom_debug > 4)
-			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
-				   dev->name, csr5, inl(dev->base_addr + CSR5));
-
-		if (csr5 == 0xffffffff)
-			break;	/* all bits set, assume PCMCIA card removed */
-
-		if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
-			break;
-
-		handled = 1;
-
-		if (csr5 & (RxIntr | RxNoBuf))
-			work_budget -= xircom_rx(dev);
-
-		if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
-			unsigned int dirty_tx;
-
-			for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
-				 dirty_tx++) {
-				int entry = dirty_tx % TX_RING_SIZE;
-				int status = tp->tx_ring[entry].status;
-
-				if (status < 0)
-					break;			/* It still hasn't been Txed */
-				/* Check for Rx filter setup frames. */
-				if (tp->tx_skbuff[entry] == NULL)
-				  continue;
-
-				if (status & Tx0DescError) {
-					/* There was an major error, log it. */
-#ifndef final_version
-					if (xircom_debug > 1)
-						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
-							   dev->name, status);
-#endif
-					tp->stats.tx_errors++;
-					if (status & Tx0ManyColl) {
-						tp->stats.tx_aborted_errors++;
-					}
-					if (status & Tx0NoCarrier) tp->stats.tx_carrier_errors++;
-					if (status & Tx0LateColl) tp->stats.tx_window_errors++;
-					if (status & Tx0Underflow) tp->stats.tx_fifo_errors++;
-				} else {
-					tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
-					tp->stats.collisions += (status >> 3) & 15;
-					tp->stats.tx_packets++;
-				}
-
-				/* Free the original skb. */
-				dev_kfree_skb_irq(tp->tx_skbuff[entry]);
-				tp->tx_skbuff[entry] = NULL;
-			}
-
-#ifndef final_version
-			if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
-				printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-
-			if (tp->tx_full &&
-			    tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2)
-				/* The ring is no longer full */
-				tp->tx_full = 0;
-
-			if (tp->tx_full)
-				netif_stop_queue (dev);
-			else
-				netif_wake_queue (dev);
-
-			tp->dirty_tx = dirty_tx;
-			if (csr5 & TxDied) {
-				if (xircom_debug > 2)
-					printk(KERN_WARNING "%s: The transmitter stopped."
-						   "  CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
-						   dev->name, csr5, inl(ioaddr + CSR6), tp->csr6);
-				outl_CSR6(tp->csr6 | EnableRx, ioaddr);
-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-			}
-		}
-
-		/* Log errors. */
-		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
-			if (csr5 & LinkChange)
-				xircom_media_change(dev);
-			if (csr5 & TxFIFOUnderflow) {
-				if ((tp->csr6 & TxThreshMask) != TxThreshMask)
-					tp->csr6 += (1 << TxThreshShift);	/* Bump up the Tx threshold */
-				else
-					tp->csr6 |= TxStoreForw;  /* Store-n-forward. */
-				/* Restart the transmit process. */
-				outl_CSR6(tp->csr6 | EnableRx, ioaddr);
-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-			}
-			if (csr5 & RxDied) {		/* Missed a Rx frame. */
-				tp->stats.rx_errors++;
-				tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
-			}
-			/* Clear all error sources, included undocumented ones! */
-			outl(0x0800f7ba, ioaddr + CSR5);
-		}
-		if (--work_budget < 0) {
-			if (xircom_debug > 1)
-				printk(KERN_WARNING "%s: Too much work during an interrupt, "
-					   "csr5=0x%8.8x.\n", dev->name, csr5);
-			/* Acknowledge all interrupt sources. */
-			outl(0x8001ffff, ioaddr + CSR5);
-			break;
-		}
-	} while (1);
-
-	if (xircom_debug > 3)
-		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
-			   dev->name, inl(ioaddr + CSR5));
-
-	spin_unlock (&tp->lock);
-	return IRQ_RETVAL(handled);
-}
-
-
-static int
-xircom_rx(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	int entry = tp->cur_rx % RX_RING_SIZE;
-	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
-	int work_done = 0;
-
-	if (xircom_debug > 4)
-		printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
-			   tp->rx_ring[entry].status);
-	/* If we own the next entry, it's a new packet. Send it up. */
-	while (tp->rx_ring[entry].status >= 0) {
-		s32 status = tp->rx_ring[entry].status;
-
-		if (xircom_debug > 5)
-			printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
-				   tp->rx_ring[entry].status);
-		if (--rx_work_limit < 0)
-			break;
-		if ((status & 0x38008300) != 0x0300) {
-			if ((status & 0x38000300) != 0x0300) {
-				/* Ignore earlier buffers. */
-				if ((status & 0xffff) != 0x7fff) {
-					if (xircom_debug > 1)
-						printk(KERN_WARNING "%s: Oversized Ethernet frame "
-							   "spanned multiple buffers, status %8.8x!\n",
-							   dev->name, status);
-					tp->stats.rx_length_errors++;
-				}
-			} else if (status & Rx0DescError) {
-				/* There was a fatal error. */
-				if (xircom_debug > 2)
-					printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
-						   dev->name, status);
-				tp->stats.rx_errors++; /* end of a packet.*/
-				if (status & (Rx0Runt | Rx0HugeFrame)) tp->stats.rx_length_errors++;
-				if (status & Rx0CRCError) tp->stats.rx_crc_errors++;
-			}
-		} else {
-			/* Omit the four octet CRC from the length. */
-			short pkt_len = ((status >> 16) & 0x7ff) - 4;
-			struct sk_buff *skb;
-
-#ifndef final_version
-			if (pkt_len > 1518) {
-				printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
-					   dev->name, pkt_len, pkt_len);
-				pkt_len = 1518;
-				tp->stats.rx_length_errors++;
-			}
-#endif
-			/* Check if the packet is long enough to accept without copying
-			   to a minimally-sized skbuff. */
-			if (pkt_len < rx_copybreak
-				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-				skb->dev = dev;
-				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-#if ! defined(__alpha__)
-				eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
-								 pkt_len, 0);
-				skb_put(skb, pkt_len);
-#else
-				memcpy(skb_put(skb, pkt_len),
-					   bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
-#endif
-				work_done++;
-			} else { 	/* Pass up the skb already on the Rx ring. */
-				skb_put(skb = tp->rx_skbuff[entry], pkt_len);
-				tp->rx_skbuff[entry] = NULL;
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			tp->stats.rx_packets++;
-			tp->stats.rx_bytes += pkt_len;
-		}
-		entry = (++tp->cur_rx) % RX_RING_SIZE;
-	}
-
-	/* Refill the Rx ring buffers. */
-	for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
-		entry = tp->dirty_rx % RX_RING_SIZE;
-		if (tp->rx_skbuff[entry] == NULL) {
-			struct sk_buff *skb;
-			skb = tp->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
-			if (skb == NULL)
-				break;
-			skb->dev = dev;			/* Mark as being used by this device. */
-			tp->rx_ring[entry].buffer1 = virt_to_bus(skb->data);
-			work_done++;
-		}
-		tp->rx_ring[entry].status = Rx0DescOwned;
-	}
-
-	return work_done;
-}
-
-
-static void
-xircom_down(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct xircom_private *tp = netdev_priv(dev);
-
-	/* Disable interrupts by clearing the interrupt mask. */
-	outl(0, ioaddr + CSR7);
-	/* Stop the chip's Tx and Rx processes. */
-	outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
-
-	if (inl(ioaddr + CSR6) != 0xffffffff)
-		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-
-	dev->if_port = tp->saved_if_port;
-}
-
-
-static int
-xircom_close(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct xircom_private *tp = netdev_priv(dev);
-	int i;
-
-	if (xircom_debug > 1)
-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
-			   dev->name, inl(ioaddr + CSR5));
-
-	netif_stop_queue(dev);
-
-	if (netif_device_present(dev))
-		xircom_down(dev);
-
-	free_irq(dev->irq, dev);
-
-	/* Free all the skbuffs in the Rx queue. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = tp->rx_skbuff[i];
-		tp->rx_skbuff[i] = NULL;
-		tp->rx_ring[i].status = 0;		/* Not owned by Xircom chip. */
-		tp->rx_ring[i].length = 0;
-		tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
-		if (skb) {
-			dev_kfree_skb(skb);
-		}
-	}
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (tp->tx_skbuff[i])
-			dev_kfree_skb(tp->tx_skbuff[i]);
-		tp->tx_skbuff[i] = NULL;
-	}
-
-	tp->open = 0;
-	return 0;
-}
-
-
-static struct net_device_stats *xircom_get_stats(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	if (netif_device_present(dev))
-		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-
-	return &tp->stats;
-}
-
-static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	ecmd->supported =
-			SUPPORTED_10baseT_Half |
-			SUPPORTED_10baseT_Full |
-			SUPPORTED_100baseT_Half |
-			SUPPORTED_100baseT_Full |
-			SUPPORTED_Autoneg |
-			SUPPORTED_MII;
-
-	ecmd->advertising = ADVERTISED_MII;
-	if (tp->advertising[0] & ADVERTISE_10HALF)
-		ecmd->advertising |= ADVERTISED_10baseT_Half;
-	if (tp->advertising[0] & ADVERTISE_10FULL)
-		ecmd->advertising |= ADVERTISED_10baseT_Full;
-	if (tp->advertising[0] & ADVERTISE_100HALF)
-		ecmd->advertising |= ADVERTISED_100baseT_Half;
-	if (tp->advertising[0] & ADVERTISE_100FULL)
-		ecmd->advertising |= ADVERTISED_100baseT_Full;
-	if (tp->autoneg) {
-		ecmd->advertising |= ADVERTISED_Autoneg;
-		ecmd->autoneg = AUTONEG_ENABLE;
-	} else
-		ecmd->autoneg = AUTONEG_DISABLE;
-
-	ecmd->port = PORT_MII;
-	ecmd->transceiver = XCVR_INTERNAL;
-	ecmd->phy_address = tp->phys[0];
-	ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10;
-	ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	ecmd->maxtxpkt = TX_RING_SIZE / 2;
-	ecmd->maxrxpkt = 0;
-	return 0;
-}
-
-static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	u16 autoneg, speed100, full_duplex;
-
-	autoneg = (ecmd->autoneg == AUTONEG_ENABLE);
-	speed100 = (ecmd->speed == SPEED_100);
-	full_duplex = (ecmd->duplex == DUPLEX_FULL);
-
-	tp->autoneg = autoneg;
-	if (speed100 != tp->speed100 ||
-	    full_duplex != tp->full_duplex) {
-		tp->speed100 = speed100;
-		tp->full_duplex = full_duplex;
-		/* change advertising bits */
-		tp->advertising[0] &= ~(ADVERTISE_10HALF |
-				     ADVERTISE_10FULL |
-				     ADVERTISE_100HALF |
-				     ADVERTISE_100FULL |
-				     ADVERTISE_100BASE4);
-		if (speed100) {
-			if (full_duplex)
-				tp->advertising[0] |= ADVERTISE_100FULL;
-			else
-				tp->advertising[0] |= ADVERTISE_100HALF;
-		} else {
-			if (full_duplex)
-				tp->advertising[0] |= ADVERTISE_10FULL;
-			else
-				tp->advertising[0] |= ADVERTISE_10HALF;
-		}
-	}
-	check_duplex(dev);
-	return 0;
-}
-
-static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, pci_name(tp->pdev));
-}
-
-static struct ethtool_ops ops = {
-	.get_settings = xircom_get_settings,
-	.set_settings = xircom_set_settings,
-	.get_drvinfo = xircom_get_drvinfo,
-};
-
-/* Provide ioctl() calls to examine the MII xcvr state. */
-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	u16 *data = (u16 *)&rq->ifr_ifru;
-	int phy = tp->phys[0] & 0x1f;
-	unsigned long flags;
-
-	switch(cmd) {
-	/* Legacy mii-diag interface */
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-		if (tp->mii_cnt)
-			data[0] = phy;
-		else
-			return -ENODEV;
-		return 0;
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-		save_flags(flags);
-		cli();
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
-		restore_flags(flags);
-		return 0;
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		save_flags(flags);
-		cli();
-		if (data[0] == tp->phys[0]) {
-			u16 value = data[2];
-			switch (data[1]) {
-			case 0:
-				if (value & (BMCR_RESET | BMCR_ANENABLE))
-					/* Autonegotiation. */
-					tp->autoneg = 1;
-				else {
-					tp->full_duplex = (value & BMCR_FULLDPLX) ? 1 : 0;
-					tp->autoneg = 0;
-				}
-				break;
-			case 4:
-				tp->advertising[0] = value;
-				break;
-			}
-			check_duplex(dev);
-		}
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
-		restore_flags(flags);
-		return 0;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return -EOPNOTSUPP;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   Note that we only use exclusion around actually queueing the
-   new frame, not around filling tp->setup_frame.  This is non-deterministic
-   when re-entered but still correct. */
-static void set_rx_mode(struct net_device *dev)
-{
-	struct xircom_private *tp = netdev_priv(dev);
-	struct dev_mc_list *mclist;
-	long ioaddr = dev->base_addr;
-	int csr6 = inl(ioaddr + CSR6);
-	u16 *eaddrs, *setup_frm;
-	u32 tx_flags;
-	int i;
-
-	tp->csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
-	csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		tp->csr6 |= PromiscBit;
-		csr6 |= PromiscBit;
-		goto out;
-	}
-
-	if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
-		/* Too many to filter well -- accept all multicasts. */
-		tp->csr6 |= AllMultiBit;
-		csr6 |= AllMultiBit;
-		goto out;
-	}
-
-	tx_flags = Tx1WholePkt | Tx1SetupPkt | PKT_SETUP_SZ;
-
-	/* Note that only the low-address shortword of setup_frame is valid! */
-	setup_frm = tp->setup_frame;
-	mclist = dev->mc_list;
-
-	/* Fill the first entry with our physical address. */
-	eaddrs = (u16 *)dev->dev_addr;
-	*setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
-	*setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
-	*setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
-
-	if (dev->mc_count > 14) { /* Must use a multicast hash table. */
-		u32 *hash_table = (u32 *)(tp->setup_frame + 4 * 12);
-		u32 hash, hash2;
-
-		tx_flags |= Tx1HashSetup;
-		tp->csr6 |= HashFilterBit;
-		csr6 |= HashFilterBit;
-
-		/* Fill the unused 3 entries with the broadcast address.
-		   At least one entry *must* contain the broadcast address!!!*/
-		for (i = 0; i < 3; i++) {
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-		}
-
-		/* Truly brain-damaged hash filter layout */
-		/* XXX: not sure if I should take the last or the first 9 bits */
-		for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
-			u32 *hptr;
-			hash = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x1ff;
-			if (hash < 384) {
-				hash2 = hash + ((hash >> 4) << 4) +
-					((hash >> 5) << 5);
-			} else {
-				hash -= 384;
-				hash2 = 64 + hash + (hash >> 4) * 80;
-			}
-			hptr = &hash_table[hash2 & ~0x1f];
-			*hptr |= cpu_to_le32(1 << (hash2 & 0x1f));
-		}
-	} else {
-		/* We have <= 14 mcast addresses so we can use Xircom's
-		   wonderful 16-address perfect filter. */
-		for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
-			eaddrs = (u16 *)mclist->dmi_addr;
-			*setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
-			*setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
-			*setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
-		}
-		/* Fill the unused entries with the broadcast address.
-		   At least one entry *must* contain the broadcast address!!!*/
-		for (; i < 15; i++) {
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-			*setup_frm = 0xffff; setup_frm += 2;
-		}
-	}
-
-	/* Now add this frame to the Tx list. */
-	if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
-		/* Same setup recently queued, we need not add it. */
-		/* XXX: Huh? All it means is that the Tx list is full...*/
-	} else {
-		unsigned long flags;
-		unsigned int entry;
-		int dummy = -1;
-
-		save_flags(flags); cli();
-		entry = tp->cur_tx++ % TX_RING_SIZE;
-
-		if (entry != 0) {
-			/* Avoid a chip errata by prefixing a dummy entry. */
-			tp->tx_skbuff[entry] = NULL;
-			tp->tx_ring[entry].length =
-				(entry == TX_RING_SIZE - 1) ? Tx1RingWrap : 0;
-			tp->tx_ring[entry].buffer1 = 0;
-			/* race with chip, set Tx0DescOwned later */
-			dummy = entry;
-			entry = tp->cur_tx++ % TX_RING_SIZE;
-		}
-
-		tp->tx_skbuff[entry] = NULL;
-		/* Put the setup frame on the Tx list. */
-		if (entry == TX_RING_SIZE - 1)
-			tx_flags |= Tx1RingWrap;		/* Wrap ring. */
-		tp->tx_ring[entry].length = tx_flags;
-		tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
-		tp->tx_ring[entry].status = Tx0DescOwned;
-		if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
-			tp->tx_full = 1;
-			netif_stop_queue (dev);
-		}
-		if (dummy >= 0)
-			tp->tx_ring[dummy].status = Tx0DescOwned;
-		restore_flags(flags);
-		/* Trigger an immediate transmit demand. */
-		outl(0, ioaddr + CSR1);
-	}
-
-out:
-	outl_CSR6(csr6, ioaddr);
-}
-
-
-static struct pci_device_id xircom_pci_table[] = {
-  { 0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 },
-  {0},
-};
-MODULE_DEVICE_TABLE(pci, xircom_pci_table);
-
-
-#ifdef CONFIG_PM
-static int xircom_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct xircom_private *tp = netdev_priv(dev);
-	printk(KERN_INFO "xircom_suspend(%s)\n", dev->name);
-	if (tp->open)
-		xircom_down(dev);
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, 3);
-
-	return 0;
-}
-
-
-static int xircom_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct xircom_private *tp = netdev_priv(dev);
-	printk(KERN_INFO "xircom_resume(%s)\n", dev->name);
-
-	pci_set_power_state(pdev,0);
-	pci_enable_device(pdev);
-	pci_restore_state(pdev);
-
-	/* Bring the chip out of sleep mode.
-	   Caution: Snooze mode does not work with some boards! */
-	if (xircom_tbl[tp->chip_id].flags & HAS_ACPI)
-		pci_write_config_dword(tp->pdev, PCI_POWERMGMT, 0);
-
-	transceiver_voodoo(dev);
-	if (xircom_tbl[tp->chip_id].flags & HAS_MII)
-		check_duplex(dev);
-
-	if (tp->open)
-		xircom_up(dev);
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-
-static void __devexit xircom_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-
-	printk(KERN_INFO "xircom_remove_one(%s)\n", dev->name);
-	unregister_netdev(dev);
-	pci_release_regions(pdev);
-	free_netdev(dev);
-	pci_set_drvdata(pdev, NULL);
-}
-
-
-static struct pci_driver xircom_driver = {
-	.name		= DRV_NAME,
-	.id_table	= xircom_pci_table,
-	.probe		= xircom_init_one,
-	.remove		= __devexit_p(xircom_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= xircom_suspend,
-	.resume		= xircom_resume
-#endif /* CONFIG_PM */
-};
-
-
-static int __init xircom_init(void)
-{
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-	printk(version);
-#endif
-	return pci_module_init(&xircom_driver);
-}
-
-
-static void __exit xircom_exit(void)
-{
-	pci_unregister_driver(&xircom_driver);
-}
-
-module_init(xircom_init)
-module_exit(xircom_exit)
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */

^ permalink raw reply

* [2.6 patch] drivers/net/bonding/bonding.h: "extern inline" -> "static inline"
From: Adrian Bunk @ 2005-11-18  3:33 UTC (permalink / raw)
  To: ctindel, fubar; +Cc: bonding-devel, linux-kernel, netdev

"extern inline" doesn't make much sense.


Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

 drivers/net/bonding/bonding.h |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- linux-2.6.15-rc1-mm1-full/drivers/net/bonding/bonding.h.old	2005-11-18 02:36:37.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/drivers/net/bonding/bonding.h	2005-11-18 02:37:05.000000000 +0100
@@ -218,7 +218,7 @@
  *
  * Caller must hold bond lock for read
  */
-extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
 {
 	struct slave *slave = NULL;
 	int i;
@@ -232,7 +232,7 @@
 	return slave;
 }
 
-extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
+static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
 {
 	if (!slave || !slave->dev->master) {
 		return NULL;
@@ -241,13 +241,13 @@
 	return (struct bonding *)slave->dev->master->priv;
 }
 
-extern inline void bond_set_slave_inactive_flags(struct slave *slave)
+static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
 	slave->state = BOND_STATE_BACKUP;
 	slave->dev->flags |= IFF_NOARP;
 }
 
-extern inline void bond_set_slave_active_flags(struct slave *slave)
+static inline void bond_set_slave_active_flags(struct slave *slave)
 {
 	slave->state = BOND_STATE_ACTIVE;
 	slave->dev->flags &= ~IFF_NOARP;

^ permalink raw reply

* [2.6 patch] drivers/net/gianfar.h: "extern inline" -> "static inline"
From: Adrian Bunk @ 2005-11-18  3:33 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

"extern inline" doesn't make much sense.


Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

 drivers/net/gianfar.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- linux-2.6.15-rc1-mm1-full/drivers/net/gianfar.h.old	2005-11-18 02:38:02.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/drivers/net/gianfar.h	2005-11-18 02:38:10.000000000 +0100
@@ -711,14 +711,14 @@
 	uint32_t msg_enable;
 };
 
-extern inline u32 gfar_read(volatile unsigned *addr)
+static inline u32 gfar_read(volatile unsigned *addr)
 {
 	u32 val;
 	val = in_be32(addr);
 	return val;
 }
 
-extern inline void gfar_write(volatile unsigned *addr, u32 val)
+static inline void gfar_write(volatile unsigned *addr, u32 val)
 {
 	out_be32(addr, val);
 }

^ permalink raw reply

* [2.6 patch] drivers/net/wireless/orinoco.h: "extern inline" -> "static inline"
From: Adrian Bunk @ 2005-11-18  3:33 UTC (permalink / raw)
  To: proski, hermes; +Cc: orinoco-devel, linux-kernel, jgarzik, netdev

"extern inline" doesn't make much sense.


Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

 drivers/net/wireless/orinoco.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- linux-2.6.15-rc1-mm1-full/drivers/net/wireless/orinoco.h.old	2005-11-18 02:38:43.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/drivers/net/wireless/orinoco.h	2005-11-18 02:38:47.000000000 +0100
@@ -155,7 +155,7 @@
  * SPARC, due to its weird semantics for save/restore flags. extern
  * inline should prevent the kernel from linking or module from
  * loading if they are not inlined. */
-extern inline int orinoco_lock(struct orinoco_private *priv,
+static inline int orinoco_lock(struct orinoco_private *priv,
 			       unsigned long *flags)
 {
 	spin_lock_irqsave(&priv->lock, *flags);
@@ -168,7 +168,7 @@
 	return 0;
 }
 
-extern inline void orinoco_unlock(struct orinoco_private *priv,
+static inline void orinoco_unlock(struct orinoco_private *priv,
 				  unsigned long *flags)
 {
 	spin_unlock_irqrestore(&priv->lock, *flags);

^ permalink raw reply

* Re: [2.6 patch] drivers/net/wireless/orinoco.h: "extern inline" -> "static inline"
From: David Gibson @ 2005-11-18  3:52 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: proski-mXXj517/zsQ,
	orinoco-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	jgarzik-e+AXbWqSrlAAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20051118033329.GU11494-HeJ8Db2Gnd6zQB+pC5nmwQ@public.gmane.org>

On Fri, Nov 18, 2005 at 04:33:29AM +0100, Adrian Bunk wrote:
> "extern inline" doesn't make much sense.

Yes it does.  "extern inline" tells gcc not to fall back to out of
line version if it can't inline the function.  These functions *must*
by inlined, or they'll break horribly on Sparc, at least.

> --- linux-2.6.15-rc1-mm1-full/drivers/net/wireless/orinoco.h.old	2005-11-18 02:38:43.000000000 +0100
> +++ linux-2.6.15-rc1-mm1-full/drivers/net/wireless/orinoco.h	2005-11-18 02:38:47.000000000 +0100
> @@ -155,7 +155,7 @@
>   * SPARC, due to its weird semantics for save/restore flags. extern
>   * inline should prevent the kernel from linking or module from
>   * loading if they are not inlined. */
> -extern inline int orinoco_lock(struct orinoco_private *priv,
> +static inline int orinoco_lock(struct orinoco_private *priv,
>  			       unsigned long *flags)
>  {
>  	spin_lock_irqsave(&priv->lock, *flags);
> @@ -168,7 +168,7 @@
>  	return 0;
>  }
>  
> -extern inline void orinoco_unlock(struct orinoco_private *priv,
> +static inline void orinoco_unlock(struct orinoco_private *priv,
>  				  unsigned long *flags)
>  {
>  	spin_unlock_irqrestore(&priv->lock, *flags);
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson


-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click

^ permalink raw reply

* Re: [Orinoco-devel] [2.6 patch] drivers/net/wireless/orinoco.h: "extern inline" -> "static inline"
From: Adrian Bunk @ 2005-11-18  4:00 UTC (permalink / raw)
  To: proski, orinoco-devel, linux-kernel, jgarzik, netdev
In-Reply-To: <20051118035236.GB23760@localhost.localdomain>

On Fri, Nov 18, 2005 at 02:52:36PM +1100, David Gibson wrote:
> On Fri, Nov 18, 2005 at 04:33:29AM +0100, Adrian Bunk wrote:
> > "extern inline" doesn't make much sense.
> 
> Yes it does.  "extern inline" tells gcc not to fall back to out of
> line version if it can't inline the function.  These functions *must*
> by inlined, or they'll break horribly on Sparc, at least.
>...

For any non-ancient gcc and !alpha, we are already telling gcc via 
__attribute__((always_inline)) that it should abort compilation if it 
can't inline the function.

The problem is that "extern inline" gives warnings with 
-Wmissing-prototypes, and I want to add this flag to the CFLAGS since it 
helps us to avoid a class of nasty runtime errors.

> David Gibson

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

^ permalink raw reply

* [2.6 patch] move some code to net/ipx/af_ipx.c
From: Adrian Bunk @ 2005-11-18  5:22 UTC (permalink / raw)
  To: Matt Mackall, acme; +Cc: Andrew Morton, linux-kernel, netdev
In-Reply-To: <20051114015707.GB5735@stusta.de>

On Mon, Nov 14, 2005 at 02:57:07AM +0100, Adrian Bunk wrote:
> On Fri, Nov 11, 2005 at 02:35:51AM -0600, Matt Mackall wrote:
> > trivial: drop unused 802.3 code if we compile without IPX
> > 
> > (originally from http://wohnheim.fh-wedel.de/~joern/software/kernel/je/25/)
> > 
> > Signed-off-by: Matt Mackall <mpm@selenic.com>
> > 
> > Index: tiny/net/802/Makefile
> > ===================================================================
> > --- tiny.orig/net/802/Makefile	2005-03-15 00:24:59.000000000 -0600
> > +++ tiny/net/802/Makefile	2005-03-15 00:25:48.000000000 -0600
> > @@ -2,8 +2,6 @@
> >  # Makefile for the Linux 802.x protocol layers.
> >  #
> >  
> > -obj-y			:= p8023.o
> > -
> >  # Check the p8022 selections against net/core/Makefile.
> >  obj-$(CONFIG_SYSCTL)	+= sysctl_net_802.o
> >  obj-$(CONFIG_LLC)	+= p8022.o psnap.o
> > @@ -11,5 +9,5 @@ obj-$(CONFIG_TR)	+= p8022.o psnap.o tr.o
> >  obj-$(CONFIG_NET_FC)	+=                 fc.o
> >  obj-$(CONFIG_FDDI)	+=                 fddi.o
> >  obj-$(CONFIG_HIPPI)	+=                 hippi.o
> > -obj-$(CONFIG_IPX)	+= p8022.o psnap.o
> > +obj-$(CONFIG_IPX)	+= p8022.o psnap.o p8023.o
> >  obj-$(CONFIG_ATALK)	+= p8022.o psnap.o
> 
> This patch isn't bad, but looking closer we could move the contents of 
> p8023.c as well as the contents of at least p8022.c and pe2.c into 
> af_ipx.c.
> 
> Is the contents of any of these three files expected to be used
> outside IPX (closest candidate would be appletalk)?


Below is a patch implementing what I was thinking of.

cu
Adrian


<--  snip  -->


This patch moves some code only used in this file to net/ipx/af_ipx.c .


Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

 include/net/p8022.h   |   13 -----
 net/802/Makefile      |   17 ++-----
 net/802/p8022.c       |   66 ---------------------------
 net/802/p8023.c       |   61 -------------------------
 net/8021q/vlan.c      |    1 
 net/8021q/vlan_dev.c  |    1 
 net/ethernet/Makefile |    2 
 net/ethernet/pe2.c    |   39 ----------------
 net/ipx/af_ipx.c      |  102 ++++++++++++++++++++++++++++++++++++++++--
 9 files changed, 106 insertions(+), 196 deletions(-)

--- linux-2.6.15-rc1-mm1-full/net/802/Makefile.old	2005-11-18 02:14:35.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/net/802/Makefile	2005-11-18 02:15:06.000000000 +0100
@@ -2,14 +2,11 @@
 # Makefile for the Linux 802.x protocol layers.
 #
 
-obj-y			:= p8023.o
-
-# Check the p8022 selections against net/core/Makefile.
 obj-$(CONFIG_SYSCTL)	+= sysctl_net_802.o
-obj-$(CONFIG_LLC)	+= p8022.o psnap.o
-obj-$(CONFIG_TR)	+= p8022.o psnap.o tr.o sysctl_net_802.o
-obj-$(CONFIG_NET_FC)	+=                 fc.o
-obj-$(CONFIG_FDDI)	+=                 fddi.o
-obj-$(CONFIG_HIPPI)	+=                 hippi.o
-obj-$(CONFIG_IPX)	+= p8022.o psnap.o
-obj-$(CONFIG_ATALK)	+= p8022.o psnap.o
+obj-$(CONFIG_LLC)	+= psnap.o
+obj-$(CONFIG_TR)	+= psnap.o tr.o sysctl_net_802.o
+obj-$(CONFIG_NET_FC)	+=         fc.o
+obj-$(CONFIG_FDDI)	+=         fddi.o
+obj-$(CONFIG_HIPPI)	+=         hippi.o
+obj-$(CONFIG_IPX)	+= psnap.o
+obj-$(CONFIG_ATALK)	+= psnap.o
--- linux-2.6.15-rc1-mm1-full/net/ethernet/Makefile.old	2005-11-18 02:15:17.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/net/ethernet/Makefile	2005-11-18 02:15:22.000000000 +0100
@@ -4,5 +4,3 @@
 
 obj-y					+= eth.o
 obj-$(CONFIG_SYSCTL)			+= sysctl_net_ether.o
-obj-$(subst m,y,$(CONFIG_IPX))		+= pe2.o
-obj-$(subst m,y,$(CONFIG_ATALK))	+= pe2.o
--- linux-2.6.15-rc1-mm1-full/net/8021q/vlan.c.old	2005-11-18 02:19:40.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/net/8021q/vlan.c	2005-11-18 02:19:46.000000000 +0100
@@ -26,7 +26,6 @@
 #include <linux/mm.h>
 #include <linux/in.h>
 #include <linux/init.h>
-#include <net/p8022.h>
 #include <net/arp.h>
 #include <linux/rtnetlink.h>
 #include <linux/notifier.h>
--- linux-2.6.15-rc1-mm1-full/net/8021q/vlan_dev.c.old	2005-11-18 02:19:55.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/net/8021q/vlan_dev.c	2005-11-18 02:19:58.000000000 +0100
@@ -29,7 +29,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <net/datalink.h>
-#include <net/p8022.h>
 #include <net/arp.h>
 
 #include "vlan.h"
--- linux-2.6.15-rc1-mm1-full/net/ipx/af_ipx.c.old	2005-11-18 02:17:00.000000000 +0100
+++ linux-2.6.15-rc1-mm1-full/net/ipx/af_ipx.c	2005-11-18 02:26:01.000000000 +0100
@@ -48,10 +48,10 @@
 #include <linux/termios.h>
 
 #include <net/ipx.h>
-#include <net/p8022.h>
 #include <net/psnap.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
+#include <net/llc.h>
 
 #include <asm/uaccess.h>
 
@@ -1939,8 +1939,104 @@
 	.notifier_call	= ipxitf_device_event,
 };
 
-extern struct datalink_proto *make_EII_client(void);
-extern void destroy_EII_client(struct datalink_proto *);
+static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
+			 unsigned char *dest)
+{
+	llc_build_and_send_ui_pkt(dl->sap, skb, dest, dl->sap->laddr.lsap);
+	return 0;
+}
+
+static struct datalink_proto *register_8022_client(unsigned char type,
+					    int (*func)(struct sk_buff *skb,
+							struct net_device *dev,
+							struct packet_type *pt,
+							struct net_device *orig_dev))
+{
+	struct datalink_proto *proto;
+
+	proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
+	if (proto) {
+		proto->type[0]		= type;
+		proto->header_length	= 3;
+		proto->request		= p8022_request;
+		proto->sap = llc_sap_open(type, func);
+		if (!proto->sap) {
+			kfree(proto);
+			proto = NULL;
+		}
+	}
+	return proto;
+}
+
+static void unregister_8022_client(struct datalink_proto *proto)
+{
+	llc_sap_put(proto->sap);
+	kfree(proto);
+}
+
+/*
+ *	Place an 802.3 header on a packet. The driver will do the mac
+ *	addresses, we just need to give it the buffer length.
+ */
+static int p8023_request(struct datalink_proto *dl,
+			 struct sk_buff *skb, unsigned char *dest_node)
+{
+	struct net_device *dev = skb->dev;
+
+	dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
+	return dev_queue_xmit(skb);
+}
+
+/*
+ *	Create an 802.3 client. Note there can be only one 802.3 client
+ */
+static struct datalink_proto *make_8023_client(void)
+{
+	struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
+
+	if (proto) {
+		proto->header_length = 0;
+		proto->request	     = p8023_request;
+	}
+	return proto;
+}
+
+/*
+ *	Destroy the 802.3 client.
+ */
+static void destroy_8023_client(struct datalink_proto *dl)
+{
+	kfree(dl);
+}
+
+static int pEII_request(struct datalink_proto *dl,
+			struct sk_buff *skb, unsigned char *dest_node)
+{
+	struct net_device *dev = skb->dev;
+
+	skb->protocol = htons(ETH_P_IPX);
+	if (dev->hard_header)
+		dev->hard_header(skb, dev, ETH_P_IPX,
+				 dest_node, NULL, skb->len);
+	return dev_queue_xmit(skb);
+}
+
+static struct datalink_proto *make_EII_client(void)
+{
+	struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
+
+	if (proto) {
+		proto->header_length = 0;
+		proto->request = pEII_request;
+	}
+
+	return proto;
+}
+
+static void destroy_EII_client(struct datalink_proto *dl)
+{
+	kfree(dl);
+}
 
 static unsigned char ipx_8022_type = 0xE0;
 static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
--- linux-2.6.15-rc1-mm1-full/include/net/p8022.h	2005-10-28 02:02:08.000000000 +0200
+++ /dev/null	2005-11-08 19:07:57.000000000 +0100
@@ -1,13 +0,0 @@
-#ifndef _NET_P8022_H
-#define _NET_P8022_H
-extern struct datalink_proto *
-	register_8022_client(unsigned char type,
-			     int (*func)(struct sk_buff *skb,
-					 struct net_device *dev,
-					 struct packet_type *pt,
-					 struct net_device *orig_dev));
-extern void unregister_8022_client(struct datalink_proto *proto);
-
-extern struct datalink_proto *make_8023_client(void);
-extern void destroy_8023_client(struct datalink_proto *dl);
-#endif
--- linux-2.6.15-rc1-mm1-full/net/ethernet/pe2.c	2005-11-17 21:30:56.000000000 +0100
+++ /dev/null	2005-11-08 19:07:57.000000000 +0100
@@ -1,39 +0,0 @@
-#include <linux/in.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-
-#include <net/datalink.h>
-
-static int pEII_request(struct datalink_proto *dl,
-			struct sk_buff *skb, unsigned char *dest_node)
-{
-	struct net_device *dev = skb->dev;
-
-	skb->protocol = htons(ETH_P_IPX);
-	if (dev->hard_header)
-		dev->hard_header(skb, dev, ETH_P_IPX,
-				 dest_node, NULL, skb->len);
-	return dev_queue_xmit(skb);
-}
-
-struct datalink_proto *make_EII_client(void)
-{
-	struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
-
-	if (proto) {
-		proto->header_length = 0;
-		proto->request = pEII_request;
-	}
-
-	return proto;
-}
-
-void destroy_EII_client(struct datalink_proto *dl)
-{
-	kfree(dl);
-}
-
-EXPORT_SYMBOL(destroy_EII_client);
-EXPORT_SYMBOL(make_EII_client);
--- linux-2.6.15-rc1-mm1-full/net/802/p8022.c	2005-10-28 02:02:08.000000000 +0200
+++ /dev/null	2005-11-08 19:07:57.000000000 +0100
@@ -1,66 +0,0 @@
-/*
- *	NET3:	Support for 802.2 demultiplexing off Ethernet (Token ring
- *		is kept separate see p8022tr.c)
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- *
- *		Demultiplex 802.2 encoded protocols. We match the entry by the
- *		SSAP/DSAP pair and then deliver to the registered datalink that
- *		matches. The control byte is ignored and handling of such items
- *		is up to the routine passed the frame.
- *
- *		Unlike the 802.3 datalink we have a list of 802.2 entries as
- *		there are multiple protocols to demux. The list is currently
- *		short (3 or 4 entries at most). The current demux assumes this.
- */
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <net/datalink.h>
-#include <linux/mm.h>
-#include <linux/in.h>
-#include <linux/init.h>
-#include <net/llc.h>
-#include <net/p8022.h>
-
-static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
-			 unsigned char *dest)
-{
-	llc_build_and_send_ui_pkt(dl->sap, skb, dest, dl->sap->laddr.lsap);
-	return 0;
-}
-
-struct datalink_proto *register_8022_client(unsigned char type,
-					    int (*func)(struct sk_buff *skb,
-							struct net_device *dev,
-							struct packet_type *pt,
-							struct net_device *orig_dev))
-{
-	struct datalink_proto *proto;
-
-	proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
-	if (proto) {
-		proto->type[0]		= type;
-		proto->header_length	= 3;
-		proto->request		= p8022_request;
-		proto->sap = llc_sap_open(type, func);
-		if (!proto->sap) {
-			kfree(proto);
-			proto = NULL;
-		}
-	}
-	return proto;
-}
-
-void unregister_8022_client(struct datalink_proto *proto)
-{
-	llc_sap_put(proto->sap);
-	kfree(proto);
-}
-
-EXPORT_SYMBOL(register_8022_client);
-EXPORT_SYMBOL(unregister_8022_client);
-
-MODULE_LICENSE("GPL");
--- linux-2.6.15-rc1-mm1-full/net/802/p8023.c	2005-11-17 21:30:55.000000000 +0100
+++ /dev/null	2005-11-08 19:07:57.000000000 +0100
@@ -1,61 +0,0 @@
-/*
- *	NET3:	802.3 data link hooks used for IPX 802.3
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *
- *	802.3 isn't really a protocol data link layer. Some old IPX stuff
- *	uses it however. Note that there is only one 802.3 protocol layer
- *	in the system. We don't currently support different protocols
- *	running raw 802.3 on different devices. Thankfully nobody else
- *	has done anything like the old IPX.
- */
-
-#include <linux/in.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-
-#include <net/datalink.h>
-#include <net/p8022.h>
-
-/*
- *	Place an 802.3 header on a packet. The driver will do the mac
- *	addresses, we just need to give it the buffer length.
- */
-static int p8023_request(struct datalink_proto *dl,
-			 struct sk_buff *skb, unsigned char *dest_node)
-{
-	struct net_device *dev = skb->dev;
-
-	dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
-	return dev_queue_xmit(skb);
-}
-
-/*
- *	Create an 802.3 client. Note there can be only one 802.3 client
- */
-struct datalink_proto *make_8023_client(void)
-{
-	struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
-
-	if (proto) {
-		proto->header_length = 0;
-		proto->request	     = p8023_request;
-	}
-	return proto;
-}
-
-/*
- *	Destroy the 802.3 client.
- */
-void destroy_8023_client(struct datalink_proto *dl)
-{
-	kfree(dl);
-}
-
-EXPORT_SYMBOL(destroy_8023_client);
-EXPORT_SYMBOL(make_8023_client);

^ permalink raw reply

* Re: [RFC: 2.6 patch] remove drivers/net/eepro100.c
From: Russell King @ 2005-11-18  9:01 UTC (permalink / raw)
  To: Adrian Bunk; +Cc: saw, jgarzik, linux-kernel, netdev
In-Reply-To: <20051118033302.GO11494@stusta.de>

On Fri, Nov 18, 2005 at 04:33:02AM +0100, Adrian Bunk wrote:
> This patch removes the obsolete drivers/net/eepro100.c driver.
> 
> Is there any reason why it should be kept?

Tt's the only driver which works correctly on ARM CPUs.  e100 is
basically buggy.  This has been discussed here on lkml and more
recently on linux-netdev.  If anyone has any further questions
please read the archives of those two lists.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

^ permalink raw reply

* Re: [RFC: 2.6 patch] remove drivers/net/eepro100.c
From: David S. Miller @ 2005-11-18  9:08 UTC (permalink / raw)
  To: rmk+lkml; +Cc: bunk, saw, jgarzik, linux-kernel, netdev
In-Reply-To: <20051118090158.GA11621@flint.arm.linux.org.uk>

From: Russell King <rmk+lkml@arm.linux.org.uk>
Date: Fri, 18 Nov 2005 09:01:59 +0000

> On Fri, Nov 18, 2005 at 04:33:02AM +0100, Adrian Bunk wrote:
> > This patch removes the obsolete drivers/net/eepro100.c driver.
> > 
> > Is there any reason why it should be kept?
> 
> Tt's the only driver which works correctly on ARM CPUs.  e100 is
> basically buggy.  This has been discussed here on lkml and more
> recently on linux-netdev.  If anyone has any further questions
> please read the archives of those two lists.

Yes, sadly this is still true and therefore the eepro100 driver
needs to stick around.

^ permalink raw reply

* Re: [DEBUG INFO]IPv6: sleeping function called from invalid context.
From: Thomas Graf @ 2005-11-18 12:35 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki / ?$B5HF#1QL@; +Cc: yanzheng, netdev, linux-kernel
In-Reply-To: <20051118.094721.49574151.yoshfuji@linux-ipv6.org>

* YOSHIFUJI Hideaki / ?$B5HF#1QL@ <yoshfuji@linux-ipv6.org> 2005-11-18 09:47
> In article <437D23EB.4020204@21cn.com> (at Fri, 18 Nov 2005 08:44:27 +0800), Yan Zheng <yanzheng@21cn.com> says:
> 
> > I get follow message when switch to single user mode and the kernel version is 2.6.15-rc1-git5.
> :
> > Nov 18 08:26:23 localhost kernel: Debug: sleeping function called from invalid context at mm/slab.c:2472
> > Nov 18 08:26:23 localhost kernel: in_atomic():1, irqs_disabled():0
> > Nov 18 08:26:23 localhost kernel:  [<c0149d5a>] kmem_cache_alloc+0x5a/0x70
> > Nov 18 08:26:23 localhost kernel:  [<e0f47336>] inet6_dump_fib+0xb6/0x110 [ipv6]
> 
> I remember someone replaced GFP_ATOMIC with GFP_KERNEL...

I did. I think it was right, why would an allocation be necessary on
the second call to inet6_dump_fib()? The walker allocated in process
context on the first call should be reused from cb->args[0].

^ permalink raw reply

* Re: [RFC: 2.6 patch] remove drivers/net/eepro100.c
From: Jeff Garzik @ 2005-11-18 16:12 UTC (permalink / raw)
  To: Russell King; +Cc: Adrian Bunk, saw, linux-kernel, netdev, David S. Miller
In-Reply-To: <20051118090158.GA11621@flint.arm.linux.org.uk>

Russell King wrote:
> On Fri, Nov 18, 2005 at 04:33:02AM +0100, Adrian Bunk wrote:
> 
>>This patch removes the obsolete drivers/net/eepro100.c driver.
>>
>>Is there any reason why it should be kept?
> 
> 
> Tt's the only driver which works correctly on ARM CPUs.  e100 is
> basically buggy.  This has been discussed here on lkml and more
> recently on linux-netdev.  If anyone has any further questions
> please read the archives of those two lists.

After reading the archives, one discovers the current status is:

	waiting on ARM folks to test e100

Latest reference is public message-id <4371A373.6000308@pobox.com>, 
which was CC'd to you.

There is a patch in netdev-2.6.git#e100-sbit and in Andrew's -mm tree 
that should solve the ARM problems, and finally allow us to kill 
eepro100.  But it's waiting for feedback...

	Jeff

^ permalink raw reply

* Re: [RFC: 2.6 patch] remove drivers/net/eepro100.c
From: Russell King @ 2005-11-18 16:32 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Adrian Bunk, saw, linux-kernel, netdev, David S. Miller
In-Reply-To: <437DFD6C.1020106@pobox.com>

On Fri, Nov 18, 2005 at 11:12:28AM -0500, Jeff Garzik wrote:
> Russell King wrote:
> >On Fri, Nov 18, 2005 at 04:33:02AM +0100, Adrian Bunk wrote:
> >
> >>This patch removes the obsolete drivers/net/eepro100.c driver.
> >>
> >>Is there any reason why it should be kept?
> >
> >
> >Tt's the only driver which works correctly on ARM CPUs.  e100 is
> >basically buggy.  This has been discussed here on lkml and more
> >recently on linux-netdev.  If anyone has any further questions
> >please read the archives of those two lists.
> 
> After reading the archives, one discovers the current status is:
> 
> 	waiting on ARM folks to test e100
> 
> Latest reference is public message-id <4371A373.6000308@pobox.com>, 
> which was CC'd to you.
> 
> There is a patch in netdev-2.6.git#e100-sbit and in Andrew's -mm tree 
> that should solve the ARM problems, and finally allow us to kill 
> eepro100.  But it's waiting for feedback...

So what you're saying is that it's down to me to test the thing.

Ok.

I've been extremely patient waiting for e100 to get fixed (it's been
literally _years_), and I think it isn't surprising that the hardware
it was noticed on has been packed away.

Now I ask the same of others for when I'm (a) well enough to enter
the cold environment in which this machine is currently stored and
(b) can find the time to resurect the machine.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

^ permalink raw reply

* Re: [RFC: 2.6 patch] remove drivers/net/eepro100.c
From: Tim Schmielau @ 2005-11-18 17:04 UTC (permalink / raw)
  To: Adrian Bunk; +Cc: saw, jgarzik, linux-kernel, netdev
In-Reply-To: <20051118033302.GO11494@stusta.de>

On Fri, 18 Nov 2005, Adrian Bunk wrote:

> This patch removes the obsolete drivers/net/eepro100.c driver.
> 
> Is there any reason why it should be kept?
> 
> 
> Signed-off-by: Adrian Bunk <bunk@stusta.de>

Can you state a reason why it is obsolete and should be removed?
IMHO this would provide a much better commit message.

Tim

^ permalink raw reply

* Re: [2.6 patch] move some code to net/ipx/af_ipx.c
From: Matt Mackall @ 2005-11-18 17:27 UTC (permalink / raw)
  To: Adrian Bunk; +Cc: acme, Andrew Morton, linux-kernel, netdev
In-Reply-To: <20051118052252.GG11494@stusta.de>

On Fri, Nov 18, 2005 at 06:22:52AM +0100, Adrian Bunk wrote:
> > 
> > This patch isn't bad, but looking closer we could move the contents of 
> > p8023.c as well as the contents of at least p8022.c and pe2.c into 
> > af_ipx.c.
> > 
> > Is the contents of any of these three files expected to be used
> > outside IPX (closest candidate would be appletalk)?
> 
> Below is a patch implementing what I was thinking of.

Looks reasonable.

-- 
Mathematics is the supreme nostalgia of our time.

^ permalink raw reply

* Rejected posting to LANTRA-L@SEGATE.SUNET.SE
From: Sunet/KTH NOC LISTSERV Server (14.4) @ 2005-11-18 19:17 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 524 bytes --]

You  are  not  authorized  to  send   mail  to  the  LANTRA-L  list  from  your
netdev@OSS.SGI.COM account.  You might be authorized  to post to the  list from
another of your accounts, or perhaps when using another mail program configured
to use a  different e-mail address, but  LISTSERV has no way  to associate this
other account or address with yours. If  you need assistance or if you have any
questions regarding  the policy of the  LANTRA-L list, please contact  the list
owners at LANTRA-L-request@SEGATE.SUNET.SE.

[-- Attachment #2: Type: message/rfc822, Size: 1345 bytes --]

From: netdev@oss.sgi.com
To: lantra-l@segate.sunet.se
Subject: status
Date: Fri, 18 Nov 2005 14:31:21 -0500
Message-ID: <200511181917.jAIJH11g009100@segate.sunet.se>

This message was not delivered due to the following reason:

Your message was not delivered because the destination computer was
not reachable within the allowed queue period. The amount of time
a message is queued before it is returned depends on local configura-
tion parameters.

Most likely there is a network problem that prevented delivery, but
it is also possible that the computer is turned off, or does not
have a mail system running right now.

Your message was not delivered within 3 days:
Host 160.165.245.61 is not responding.

The following recipients could not receive this message:
<lantra-l@segate.sunet.se>

Please reply to postmaster@segate.sunet.se
if you feel this message to be in error.



^ permalink raw reply

* [git patches] 2.6.x net driver fixes
From: Jeff Garzik @ 2005-11-18 20:12 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: netdev, linux-kernel


Please pull from 'upstream-fixes' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git

to receive the following assorted fixes:

 drivers/net/au1000_eth.c                |    1 
 drivers/net/e100.c                      |  273 ++++++++++++++++++++++++++++++--
 drivers/net/fec_8xx/Kconfig             |    2 
 drivers/net/ioc3-eth.c                  |    2 
 drivers/net/r8169.c                     |    6 
 drivers/net/saa9730.h                   |   36 ++--
 drivers/net/smc91x.c                    |   17 +
 drivers/net/wan/hdlc_cisco.c            |    6 
 drivers/net/wan/hdlc_fr.c               |    4 
 drivers/net/wan/hdlc_generic.c          |    6 
 drivers/net/wireless/hermes.c           |    6 
 drivers/net/wireless/hermes.h           |    6 
 drivers/net/wireless/i82593.h           |   11 -
 drivers/net/wireless/ipw2100.c          |   29 ++-
 drivers/net/wireless/ipw2100.h          |    2 
 drivers/net/wireless/prism54/isl_38xx.c |    4 
 include/net/ieee80211.h                 |    2 
 17 files changed, 352 insertions(+), 61 deletions(-)

Andrew Morton:
      git-netdev-all-ieee80211_get_payload-warning-fix

Francois Romieu:
      r8169: fix printk_ratelimit in the interrupt handler
      r8169: do not abort when the power management capabilities are disabled

Gabriel A. Devenyi:
      drivers/net/wireless/hermes.c unsigned int comparision

James Ketrenos:
      ipw2100: Fix 'Driver using old /proc/net/wireless...' message

Jeff Garzik:
      [wireless hermes] build fix

Jesse Brandeburg:
      e100: re-enable microcode with more useful defaults

John W. Linville:
      i82593.h: make header comment GPL-compatible
      fec_8xx: make CONFIG_FEC_8XX depend on CONFIG_8xx

Krzysztof Halasa:
      Generic HDLC WAN drivers - disable netif_carrier_off()

Nicolas Pitre:
      smc91x: fix one source of spurious interrupts

Ralf Baechle:
      IOC3: Replace obsolete PCI API
      au1000_eth: Include <linux/config.h>
      SAA9730: Add missing header bits.

Roger While:
      prism54 : Remove extraneous udelay/register read

Russell King:
      smc91x: fix bank mismatch

diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 332e995..cd0b1dc 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -32,6 +32,7 @@
  * 
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 7a6aeae..22cd045 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -156,7 +156,7 @@
 
 #define DRV_NAME		"e100"
 #define DRV_EXT		"-NAPI"
-#define DRV_VERSION		"3.4.14-k2"DRV_EXT
+#define DRV_VERSION		"3.4.14-k4"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2005 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -903,8 +903,8 @@ static void mdio_write(struct net_device
 
 static void e100_get_defaults(struct nic *nic)
 {
-	struct param_range rfds = { .min = 16, .max = 256, .count = 64 };
-	struct param_range cbs  = { .min = 64, .max = 256, .count = 64 };
+	struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
+	struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };
 
 	pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
 	/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
@@ -1007,25 +1007,264 @@ static void e100_configure(struct nic *n
 		c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
 }
 
+/********************************************************/
+/*  Micro code for 8086:1229 Rev 8                      */
+/********************************************************/
+
+/*  Parameter values for the D101M B-step  */
+#define D101M_CPUSAVER_TIMER_DWORD		78
+#define D101M_CPUSAVER_BUNDLE_DWORD		65
+#define D101M_CPUSAVER_MIN_SIZE_DWORD		126
+
+#define D101M_B_RCVBUNDLE_UCODE \
+{\
+0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
+0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
+0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
+0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
+0x00380438, 0x00000000, 0x00140000, 0x00380555, \
+0x00308000, 0x00100662, 0x00100561, 0x000E0408, \
+0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
+0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
+0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
+0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
+0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
+0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
+0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
+0x00041000, 0x00010004, 0x00130826, 0x000C0006, \
+0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
+0x00101210, 0x00380C34, 0x00000000, 0x00000000, \
+0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
+0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
+0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
+0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
+0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
+0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
+0x00130826, 0x000C0001, 0x00220559, 0x00101313, \
+0x00380559, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00130831, 0x0010090B, 0x00124813, \
+0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
+0x003806A8, 0x00000000, 0x00000000, 0x00000000, \
+}
+
+/********************************************************/
+/*  Micro code for 8086:1229 Rev 9                      */
+/********************************************************/
+
+/*  Parameter values for the D101S  */
+#define D101S_CPUSAVER_TIMER_DWORD		78
+#define D101S_CPUSAVER_BUNDLE_DWORD		67
+#define D101S_CPUSAVER_MIN_SIZE_DWORD		128
+
+#define D101S_RCVBUNDLE_UCODE \
+{\
+0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
+0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
+0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
+0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
+0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
+0x00308000, 0x00100610, 0x00100561, 0x000E0408, \
+0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
+0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
+0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
+0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
+0x003A047E, 0x00044010, 0x00380819, 0x00000000, \
+0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
+0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
+0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
+0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
+0x00101313, 0x00380700, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
+0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
+0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
+0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
+0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
+0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
+0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
+0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
+0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
+0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00130831, \
+0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
+0x00041000, 0x00010004, 0x00380700  \
+}
+
+/********************************************************/
+/*  Micro code for the 8086:1229 Rev F/10               */
+/********************************************************/
+
+/*  Parameter values for the D102 E-step  */
+#define D102_E_CPUSAVER_TIMER_DWORD		42
+#define D102_E_CPUSAVER_BUNDLE_DWORD		54
+#define D102_E_CPUSAVER_MIN_SIZE_DWORD		46
+
+#define     D102_E_RCVBUNDLE_UCODE \
+{\
+0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \
+0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
+0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
+0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
+0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
+0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \
+0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+}
+
 static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 {
-	int i;
-	static const u32 ucode[UCODE_SIZE] = {
-		/* NFS packets are misinterpreted as TCO packets and
-		 * incorrectly routed to the BMC over SMBus.  This
-		 * microcode patch checks the fragmented IP bit in the
-		 * NFS/UDP header to distinguish between NFS and TCO. */
-		0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF,
-		0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000,
-		0x00906EFD, 0x00900EFD,	0x00E00EF8,
-	};
+/* *INDENT-OFF* */
+	static struct {
+		u32 ucode[UCODE_SIZE + 1];
+		u8 mac;
+		u8 timer_dword;
+		u8 bundle_dword;
+		u8 min_size_dword;
+	} ucode_opts[] = {
+		{ D101M_B_RCVBUNDLE_UCODE,
+		  mac_82559_D101M,
+		  D101M_CPUSAVER_TIMER_DWORD,
+		  D101M_CPUSAVER_BUNDLE_DWORD,
+		  D101M_CPUSAVER_MIN_SIZE_DWORD },
+		{ D101S_RCVBUNDLE_UCODE,
+		  mac_82559_D101S,
+		  D101S_CPUSAVER_TIMER_DWORD,
+		  D101S_CPUSAVER_BUNDLE_DWORD,
+		  D101S_CPUSAVER_MIN_SIZE_DWORD },
+		{ D102_E_RCVBUNDLE_UCODE,
+		  mac_82551_F,
+		  D102_E_CPUSAVER_TIMER_DWORD,
+		  D102_E_CPUSAVER_BUNDLE_DWORD,
+		  D102_E_CPUSAVER_MIN_SIZE_DWORD },
+		{ D102_E_RCVBUNDLE_UCODE,
+		  mac_82551_10,
+		  D102_E_CPUSAVER_TIMER_DWORD,
+		  D102_E_CPUSAVER_BUNDLE_DWORD,
+		  D102_E_CPUSAVER_MIN_SIZE_DWORD },
+		{ {0}, 0, 0, 0, 0}
+	}, *opts;
+/* *INDENT-ON* */
+
+/*************************************************************************
+*  CPUSaver parameters
+*
+*  All CPUSaver parameters are 16-bit literals that are part of a
+*  "move immediate value" instruction.  By changing the value of
+*  the literal in the instruction before the code is loaded, the
+*  driver can change the algorithm.
+*
+*  INTDELAY - This loads the dead-man timer with its inital value.
+*    When this timer expires the interrupt is asserted, and the 
+*    timer is reset each time a new packet is received.  (see
+*    BUNDLEMAX below to set the limit on number of chained packets)
+*    The current default is 0x600 or 1536.  Experiments show that
+*    the value should probably stay within the 0x200 - 0x1000.
+*
+*  BUNDLEMAX - 
+*    This sets the maximum number of frames that will be bundled.  In
+*    some situations, such as the TCP windowing algorithm, it may be
+*    better to limit the growth of the bundle size than let it go as
+*    high as it can, because that could cause too much added latency.
+*    The default is six, because this is the number of packets in the
+*    default TCP window size.  A value of 1 would make CPUSaver indicate
+*    an interrupt for every frame received.  If you do not want to put
+*    a limit on the bundle size, set this value to xFFFF.
+*
+*  BUNDLESMALL - 
+*    This contains a bit-mask describing the minimum size frame that
+*    will be bundled.  The default masks the lower 7 bits, which means
+*    that any frame less than 128 bytes in length will not be bundled,
+*    but will instead immediately generate an interrupt.  This does
+*    not affect the current bundle in any way.  Any frame that is 128
+*    bytes or large will be bundled normally.  This feature is meant
+*    to provide immediate indication of ACK frames in a TCP environment.
+*    Customers were seeing poor performance when a machine with CPUSaver
+*    enabled was sending but not receiving.  The delay introduced when
+*    the ACKs were received was enough to reduce total throughput, because
+*    the sender would sit idle until the ACK was finally seen.
+*
+*    The current default is 0xFF80, which masks out the lower 7 bits.
+*    This means that any frame which is x7F (127) bytes or smaller
+*    will cause an immediate interrupt.  Because this value must be a 
+*    bit mask, there are only a few valid values that can be used.  To
+*    turn this feature off, the driver can write the value xFFFF to the
+*    lower word of this instruction (in the same way that the other
+*    parameters are used).  Likewise, a value of 0xF800 (2047) would
+*    cause an interrupt to be generated for every frame, because all
+*    standard Ethernet frames are <= 2047 bytes in length.
+*************************************************************************/
+
+/* if you wish to disable the ucode functionality, while maintaining the 
+ * workarounds it provides, set the following defines to:
+ * BUNDLESMALL 0
+ * BUNDLEMAX 1
+ * INTDELAY 1
+ */
+#define BUNDLESMALL 1
+#define BUNDLEMAX (u16)6
+#define INTDELAY (u16)1536 /* 0x600 */
+
+	/* do not load u-code for ICH devices */
+	if (nic->flags & ich)
+		goto noloaducode;
+
+	/* Search for ucode match against h/w rev_id */
+	for (opts = ucode_opts; opts->mac; opts++) {
+		int i;
+		u32 *ucode = opts->ucode;
+		if (nic->mac != opts->mac)
+			continue;
+
+		/* Insert user-tunable settings */
+		ucode[opts->timer_dword] &= 0xFFFF0000;
+		ucode[opts->timer_dword] |= INTDELAY;
+		ucode[opts->bundle_dword] &= 0xFFFF0000;
+		ucode[opts->bundle_dword] |= BUNDLEMAX;
+		ucode[opts->min_size_dword] &= 0xFFFF0000;
+		ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80;
 
-	if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
-		for(i = 0; i < UCODE_SIZE; i++)
+		for (i = 0; i < UCODE_SIZE; i++)
 			cb->u.ucode[i] = cpu_to_le32(ucode[i]);
 		cb->command = cpu_to_le16(cb_ucode);
-	} else
-		cb->command = cpu_to_le16(cb_nop);
+		return;
+	}
+
+noloaducode:
+	cb->command = cpu_to_le16(cb_nop);
 }
 
 static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
index 94e7a9a..a84c232 100644
--- a/drivers/net/fec_8xx/Kconfig
+++ b/drivers/net/fec_8xx/Kconfig
@@ -1,6 +1,6 @@
 config FEC_8XX
 	tristate "Motorola 8xx FEC driver"
-	depends on NET_ETHERNET && FEC
+	depends on NET_ETHERNET && 8xx
 	select MII
 
 config FEC_8XX_GENERIC_PHY
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 6a3129b..9b8295e 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -1360,7 +1360,7 @@ static struct pci_driver ioc3_driver = {
 
 static int __init ioc3_init_module(void)
 {
-	return pci_module_init(&ioc3_driver);
+	return pci_register_driver(&ioc3_driver);
 }
 
 static void __exit ioc3_cleanup_module(void)
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 159b56a..14a76f7 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1346,10 +1346,8 @@ rtl8169_init_board(struct pci_dev *pdev,
 	} else {
 		if (netif_msg_probe(tp)) {
 			printk(KERN_ERR PFX
-			       "Cannot find PowerManagement capability. "
-			       "Aborting.\n");
+			       "PowerManagement capability not found.\n");
 		}
-		goto err_out_mwi;
 	}
 
 	/* make sure PCI base addr 1 is MMIO */
@@ -2516,7 +2514,7 @@ rtl8169_interrupt(int irq, void *dev_ins
 	} while (boguscnt > 0);
 
 	if (boguscnt <= 0) {
-		if (net_ratelimit() && netif_msg_intr(tp)) {
+		if (netif_msg_intr(tp) && net_ratelimit() ) {
 			printk(KERN_WARNING
 			       "%s: Too much work at interrupt!\n", dev->name);
 		}
diff --git a/drivers/net/saa9730.h b/drivers/net/saa9730.h
index 9e9da6b..a7e9d29 100644
--- a/drivers/net/saa9730.h
+++ b/drivers/net/saa9730.h
@@ -1,6 +1,7 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2000, 2005  MIPS Technologies, Inc.  All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
  *
  * ########################################################################
  *
@@ -265,6 +266,7 @@
 
 /* The SAA9730 (LAN) controller register map, as seen via the PCI-bus. */
 #define SAA9730_LAN_REGS_ADDR   0x20400
+#define SAA9730_LAN_REGS_SIZE   0x00400
 
 struct lan_saa9730_regmap {
 	volatile unsigned int TxBuffA;			/* 0x20400 */
@@ -309,6 +311,7 @@ typedef volatile struct lan_saa9730_regm
 
 /* The SAA9730 (EVM) controller register map, as seen via the PCI-bus. */
 #define SAA9730_EVM_REGS_ADDR   0x02000
+#define SAA9730_EVM_REGS_SIZE   0x00400
 
 struct evm_saa9730_regmap {
 	volatile unsigned int InterruptStatus1;		/* 0x2000 */
@@ -329,16 +332,32 @@ typedef volatile struct evm_saa9730_regm
 
 
 struct lan_saa9730_private {
+	/*
+	 * Rx/Tx packet buffers.
+	 * The Rx and Tx packets must be PACKET_SIZE aligned.
+	 */
+	void		*buffer_start;
+	unsigned int	buffer_size;
+
+	/*
+	 * DMA address of beginning of this object, returned
+	 * by pci_alloc_consistent().
+	 */
+	dma_addr_t	dma_addr;
+
+	/* Pointer to the associated pci device structure */
+	struct pci_dev	*pci_dev;
+
 	/* Pointer for the SAA9730 LAN controller register set. */
 	t_lan_saa9730_regmap *lan_saa9730_regs;
 
 	/* Pointer to the SAA9730 EVM register. */
 	t_evm_saa9730_regmap *evm_saa9730_regs;
 
-	/* TRUE if the next buffer to write is RxBuffA,  FALSE if RxBuffB. */
-	unsigned char NextRcvToUseIsA;
 	/* Rcv buffer Index. */
 	unsigned char NextRcvPacketIndex;
+	/* Next buffer index. */
+	unsigned char NextRcvBufferIndex;
 
 	/* Index of next packet to use in that buffer. */
 	unsigned char NextTxmPacketIndex;
@@ -353,13 +372,8 @@ struct lan_saa9730_private {
 	unsigned char DmaRcvPackets;
 	unsigned char DmaTxmPackets;
 
-	unsigned char RcvAIndex;	/* index into RcvBufferSpace[] for Blk A */
-	unsigned char RcvBIndex;	/* index into RcvBufferSpace[] for Blk B */
-
-	unsigned int
-	    TxmBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_TXM_Q_SIZE];
-	unsigned int
-	    RcvBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_RCV_Q_SIZE];
+	void	      *TxmBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_TXM_Q_SIZE];
+	void	      *RcvBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_RCV_Q_SIZE];
 	unsigned int TxBufferFree[LAN_SAA9730_BUFFERS];
 
 	unsigned char PhysicalAddress[LAN_SAA9730_CAM_ENTRIES][6];
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index c91e2e8..28bf2e6 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -155,6 +155,12 @@ MODULE_LICENSE("GPL");
 #define MEMORY_WAIT_TIME	16
 
 /*
+ * The maximum number of processing loops allowed for each call to the
+ * IRQ handler.  
+ */
+#define MAX_IRQ_LOOPS		8
+
+/*
  * This selects whether TX packets are sent one by one to the SMC91x internal
  * memory and throttled until transmission completes.  This may prevent
  * RX overruns a litle by keeping much of the memory free for RX packets
@@ -684,7 +690,6 @@ static void smc_hardware_send_pkt(unsign
 
 	/* queue the packet for TX */
 	SMC_SET_MMU_CMD(MC_ENQUEUE);
-	SMC_ACK_INT(IM_TX_EMPTY_INT);
 	smc_special_unlock(&lp->lock);
 
 	dev->trans_start = jiffies;
@@ -1207,6 +1212,7 @@ static void smc_phy_configure(void *data
 	smc_phy_check_media(dev, 1);
 
 smc_phy_configure_exit:
+	SMC_SELECT_BANK(2);
 	spin_unlock_irq(&lp->lock);
 	lp->work_pending = 0;
 }
@@ -1305,7 +1311,7 @@ static irqreturn_t smc_interrupt(int irq
 	SMC_SET_INT_MASK(0);
 
 	/* set a timeout value, so I don't stay here forever */
-	timeout = 8;
+	timeout = MAX_IRQ_LOOPS;
 
 	do {
 		status = SMC_GET_INT();
@@ -1372,10 +1378,13 @@ static irqreturn_t smc_interrupt(int irq
 	/* restore register states */
 	SMC_SET_PTR(saved_pointer);
 	SMC_SET_INT_MASK(mask);
-
 	spin_unlock(&lp->lock);
 
-	DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
+	if (timeout == MAX_IRQ_LOOPS)
+		PRINTK("%s: spurious interrupt (mask = 0x%02x)\n",
+		       dev->name, mask);
+	DBG(3, "%s: Interrupt done (%d loops)\n",
+	       dev->name, MAX_IRQ_LOOPS - timeout);
 
 	/*
 	 * We return IRQ_HANDLED unconditionally here even if there was
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index a01efa6..1fd0466 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -192,7 +192,9 @@ static int cisco_rx(struct sk_buff *skb)
 					       "uptime %ud%uh%um%us)\n",
 					       dev->name, days, hrs,
 					       min, sec);
+#if 0
 					netif_carrier_on(dev);
+#endif
 					hdlc->state.cisco.up = 1;
 				}
 			}
@@ -225,7 +227,9 @@ static void cisco_timer(unsigned long ar
 		       hdlc->state.cisco.settings.timeout * HZ)) {
 		hdlc->state.cisco.up = 0;
 		printk(KERN_INFO "%s: Link down\n", dev->name);
+#if 0
 		netif_carrier_off(dev);
+#endif
 	}
 
 	cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
@@ -261,8 +265,10 @@ static void cisco_stop(struct net_device
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	del_timer_sync(&hdlc->state.cisco.timer);
+#if 0
 	if (netif_carrier_ok(dev))
 		netif_carrier_off(dev);
+#endif
 	hdlc->state.cisco.up = 0;
 	hdlc->state.cisco.request_sent = 0;
 }
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index e1601d3..523afe1 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -545,8 +545,10 @@ static void fr_set_link_state(int reliab
 
 	hdlc->state.fr.reliable = reliable;
 	if (reliable) {
+#if 0
 		if (!netif_carrier_ok(dev))
 			netif_carrier_on(dev);
+#endif
 
 		hdlc->state.fr.n391cnt = 0; /* Request full status */
 		hdlc->state.fr.dce_changed = 1;
@@ -560,8 +562,10 @@ static void fr_set_link_state(int reliab
 			}
 		}
 	} else {
+#if 0
 		if (netif_carrier_ok(dev))
 			netif_carrier_off(dev);
+#endif
 
 		while (pvc) {		/* Deactivate all PVCs */
 			pvc_carrier(0, pvc);
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index cdd4c09..46cef8f 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -79,11 +79,13 @@ static void __hdlc_set_carrier_on(struct
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	if (hdlc->proto.start)
 		return hdlc->proto.start(dev);
+#if 0
 #ifdef DEBUG_LINK
 	if (netif_carrier_ok(dev))
 		printk(KERN_ERR "hdlc_set_carrier_on(): already on\n");
 #endif
 	netif_carrier_on(dev);
+#endif
 }
 
 
@@ -94,11 +96,13 @@ static void __hdlc_set_carrier_off(struc
 	if (hdlc->proto.stop)
 		return hdlc->proto.stop(dev);
 
+#if 0
 #ifdef DEBUG_LINK
 	if (!netif_carrier_ok(dev))
 		printk(KERN_ERR "hdlc_set_carrier_off(): already off\n");
 #endif
 	netif_carrier_off(dev);
+#endif
 }
 
 
@@ -294,8 +298,10 @@ int register_hdlc_device(struct net_devi
 	if (result != 0)
 		return -EIO;
 
+#if 0
 	if (netif_carrier_ok(dev))
 		netif_carrier_off(dev); /* no carrier until DCD goes up */
+#endif
 
 	return 0;
 }
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 579480d..346c6fe 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -398,7 +398,7 @@ static int hermes_bap_seek(hermes_t *hw,
  *
  * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
  */
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len,
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
 		     u16 id, u16 offset)
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -424,7 +424,7 @@ int hermes_bap_pread(hermes_t *hw, int b
  *
  * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
  */
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
 		      u16 id, u16 offset)
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -450,7 +450,7 @@ int hermes_bap_pwrite(hermes_t *hw, int 
  *
  * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
  */
-int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, unsigned len,
+int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, int len,
 		      u16 id, u16 offset)
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index a6bd472..7644f72 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -372,12 +372,12 @@ int hermes_docmd_wait(hermes_t *hw, u16 
 		      struct hermes_response *resp);
 int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
 
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len,
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
 		       u16 id, u16 offset);
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
 			u16 id, u16 offset);
 int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf,
-			unsigned data_len, unsigned len, u16 id, u16 offset);
+			unsigned data_len, int len, u16 id, u16 offset);
 int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
 		    u16 *length, void *buf);
 int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
diff --git a/drivers/net/wireless/i82593.h b/drivers/net/wireless/i82593.h
index 33acb8a..afac5c7 100644
--- a/drivers/net/wireless/i82593.h
+++ b/drivers/net/wireless/i82593.h
@@ -7,11 +7,16 @@
  *
  * Copyright 1994, Anders Klemets <klemets@it.kth.se>
  *
- * This software may be freely distributed for noncommercial purposes
- * as long as this notice is retained.
- * 
  * HISTORY
  * i82593.h,v
+ * Revision 1.4  2005/11/4  09:15:00  baroniunas
+ * Modified copyright with permission of author as follows:
+ *
+ *   "If I82539.H is the only file with my copyright statement
+ *    that is included in the Source Forge project, then you have
+ *    my approval to change the copyright statement to be a GPL
+ *    license, in the way you proposed on October 10."
+ *
  * Revision 1.1  1996/07/17 15:23:12  root
  * Initial revision
  *
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index a2e6214..77d2a21 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -6344,7 +6344,8 @@ static struct net_device *ipw2100_alloc_
 	dev->ethtool_ops = &ipw2100_ethtool_ops;
 	dev->tx_timeout = ipw2100_tx_timeout;
 	dev->wireless_handlers = &ipw2100_wx_handler_def;
-	dev->get_wireless_stats = ipw2100_wx_wireless_stats;
+	priv->wireless_data.ieee80211 = priv->ieee;
+	dev->wireless_data = &priv->wireless_data;
 	dev->set_mac_address = ipw2100_set_address;
 	dev->watchdog_timeo = 3 * HZ;
 	dev->irq = 0;
@@ -7178,6 +7179,11 @@ static int ipw2100_wx_get_range(struct n
 	}
 	range->num_frequency = val;
 
+	/* Event capability (kernel + driver) */
+	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+				IW_EVENT_CAPA_MASK(SIOCGIWAP));
+	range->event_capa[1] = IW_EVENT_CAPA_K_1;
+
 	IPW_DEBUG_WX("GET Range\n");
 
 	return 0;
@@ -8446,16 +8452,6 @@ static iw_handler ipw2100_private_handle
 #endif				/* CONFIG_IPW2100_MONITOR */
 };
 
-static struct iw_handler_def ipw2100_wx_handler_def = {
-	.standard = ipw2100_wx_handlers,
-	.num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler),
-	.num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler),
-	.num_private_args = sizeof(ipw2100_private_args) /
-	    sizeof(struct iw_priv_args),
-	.private = (iw_handler *) ipw2100_private_handler,
-	.private_args = (struct iw_priv_args *)ipw2100_private_args,
-};
-
 /*
  * Get wireless statistics.
  * Called by /proc/net/wireless
@@ -8597,6 +8593,17 @@ static struct iw_statistics *ipw2100_wx_
 	return (struct iw_statistics *)NULL;
 }
 
+static struct iw_handler_def ipw2100_wx_handler_def = {
+	.standard = ipw2100_wx_handlers,
+	.num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler),
+	.num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler),
+	.num_private_args = sizeof(ipw2100_private_args) /
+	    sizeof(struct iw_priv_args),
+	.private = (iw_handler *) ipw2100_private_handler,
+	.private_args = (struct iw_priv_args *)ipw2100_private_args,
+	.get_wireless_stats = ipw2100_wx_wireless_stats,
+};
+
 static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
 {
 	union iwreq_data wrqu;
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index 140fdf2..7c65b10 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -571,6 +571,8 @@ struct ipw2100_priv {
 	struct net_device *net_dev;
 	struct iw_statistics wstats;
 
+	struct iw_public_data wireless_data;
+
 	struct tasklet_struct irq_tasklet;
 
 	struct workqueue_struct *workqueue;
diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
index 109a96d..23deee6 100644
--- a/drivers/net/wireless/prism54/isl_38xx.c
+++ b/drivers/net/wireless/prism54/isl_38xx.c
@@ -164,12 +164,12 @@ isl38xx_trigger_device(int asleep, void 
 		/* assert the Wakeup interrupt in the Device Interrupt Register */
 		isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_WAKEUP,
 				  ISL38XX_DEV_INT_REG);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
 		udelay(ISL38XX_WRITEIO_DELAY);
 
 		/* perform another read on the Device Status Register */
 		reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
-
-#if VERBOSE > SHOW_ERROR_MESSAGES
 		do_gettimeofday(&current_time);
 		DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
 		      current_time.tv_sec, (long)current_time.tv_usec, reg);
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index b93fd8c..cde2f4f 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1042,7 +1042,7 @@ static inline u8 *ieee80211_get_payload(
 	case IEEE80211_4ADDR_LEN:
 		return ((struct ieee80211_hdr_4addr *)hdr)->payload;
 	}
-
+	return NULL;
 }
 
 static inline int ieee80211_is_ofdm_rate(u8 rate)

^ permalink raw reply related

* Re: [2.6 patch] move some code to net/ipx/af_ipx.c
From: Arnaldo Carvalho de Melo @ 2005-11-18 20:24 UTC (permalink / raw)
  To: Adrian Bunk; +Cc: Matt Mackall, acme, Andrew Morton, linux-kernel, netdev
In-Reply-To: <20051118052252.GG11494@stusta.de>

On 11/18/05, Adrian Bunk <bunk@stusta.de> wrote:
> On Mon, Nov 14, 2005 at 02:57:07AM +0100, Adrian Bunk wrote:
> > On Fri, Nov 11, 2005 at 02:35:51AM -0600, Matt Mackall wrote:
> > > trivial: drop unused 802.3 code if we compile without IPX
> > >
> > > (originally from http://wohnheim.fh-wedel.de/~joern/software/kernel/je/25/)

Thanks Adrian, from a quick glance looks OK, I'll review it later
today to see if everything is fine wrt appletalk, tr, etc.

- Arnaldo

^ permalink raw reply

* Re: [RFC: 2.6 patch] remove drivers/net/tulip/xircom_tulip_cb.c
From: Mark Lord @ 2005-11-18 22:34 UTC (permalink / raw)
  To: Adrian Bunk; +Cc: jgarzik, tulip-users, linux-kernel, netdev
In-Reply-To: <20051118033306.GP11494@stusta.de>

Adrian Bunk wrote:
> This patch removes the obsolete drivers/net/tulip/xircom_tulip_cb.c 
> driver.
> 
> Is there any reason why it should be kept?

Yes.  It is the only driver that works
without lockups on Xircom Cardbus cards.
Or so has been the case any time I've tried
the alternatives.

Is there any good reason to nuke it?

^ permalink raw reply

* Re: [PATCH]IPv6: Acquire addrconf_hash_lock for reading instead of writing in addrconf_verify(...)
From: David S. Miller @ 2005-11-18 23:51 UTC (permalink / raw)
  To: yanzheng; +Cc: netdev, linux-kernel, yoshfuji
In-Reply-To: <437BE773.6010007@21cn.com>

From: Yan Zheng <yanzheng@21cn.com>
Date: Thu, 17 Nov 2005 10:14:11 +0800

> addrconf_verify(...) only traverse address hash table when addrconf_hash_lock is held
> for writing, and it may hold addrconf_hash_lock for a long time. So I think it's better
> to acquire addrconf_hash_lock for reading instead of  writing
> 
> Signed-off-by: Yan Zheng <yanzheng@21cn.com>

Applied, thanks Yan.

^ permalink raw reply

* Re: [PATCH] [RFT] ip_tables NUMA optimization
From: David S. Miller @ 2005-11-19  0:00 UTC (permalink / raw)
  To: dada1; +Cc: laforge, netdev, netfilter-devel
In-Reply-To: <437CA009.4020006@cosmosbay.com>

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Thu, 17 Nov 2005 16:21:45 +0100

> It should probably use vfree() like :
> 
>  > +	for_each_cpu(cpu) {
>  > +		if (info->size <= PAGE_SIZE)
>  > +			kfree(info->entries[cpu]);
>  > +		else
>  > +			vfree(info->entries[cpu]);
>  > +	}

I've put the patch into the net-2.6.16 tree with the obvious
fix Eric points out.

Thanks.

^ permalink raw reply

* Re: [PATCH 02/10]: [NETFILTER]: Defer fragmentation in ip_output when connection tracking is used
From: Patrick McHardy @ 2005-11-19  7:02 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Kernel Netdev Mailing List, Rusty Russell,
	Netfilter Development Mailinglist, Harald Welte
In-Reply-To: <437BEAC8.40904@trash.net>

[-- Attachment #1: Type: text/plain, Size: 1633 bytes --]

Patrick McHardy wrote:
> Herbert Xu wrote:
> 
>> On Fri, Nov 11, 2005 at 03:19:17AM +0000, Patrick McHardy wrote:
>>
>>> [NETFILTER]: Defer fragmentation in ip_output when connection 
>>> tracking is used
>>>
>> I'm slightly uneasy about this change because for POST_ROUTING, the
>> defragmentation occurs in the middle of the hook, NF_IP_PRI_NAT_SRC.
>>
>> This means that things like the mangle table currently sees the
>> fragments as opposed to the whole packet.  This patch will change
>> that.
>>
>> Now I'm not saying that this is necessarily a bad thing.  In fact,
>> for all I know it might make more sense to do this.  But we should
>> consider the possible implications before embarking on it.
> 
> 
> Good point. I would also prefer to have fragmentation occur after
> POST_ROUTING in all cases. Looking at the in-tree targets, it means
> loosing the ability to do a couple of things:
> 
> - CLASSIFY fragments differently
> - MARK fragments differently
> - DSCP/ECN/TOS mark fragments differently
> - Change TTLs of fragments to differently values
> 
> None of them seems very important. The DSCP and ECN targets were
> broken until not long ago without anyone noticing, the TTL target is
> relatively new. So it comes down to loosing the ability to classify
> fragments of one packet differently using iptables, which doesn't
> make much sense too me. In fact I think it would make classification
> easier if mangle would see the whole packet.

How about this patch that moves the POST_ROUTING hook before
fragmentation instead of defering it? Can anyone think of a
reason why mangle/POSTROUTING should see fragments?


[-- Attachment #2: x --]
[-- Type: text/plain, Size: 7047 bytes --]

[NETFILTER]: Call POST_ROUTING hook before fragmentation

Call POST_ROUTING hook before fragmentation to get rid of the okfn use
in ip_refrag and save the useless fragmentation/defragmentation step
when NAT is used.

The patch introduces one user-visible change, the POSTROUTING chain
in the mangle table gets entire packets, not fragments, which should
simplify use of the MARK and CLASSIFY targets for queueing as a nice
side-effect.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 1bead31b7e969e00bc5c043d34f20f9edb12a961
tree 16b82a0bedbb29b6a709140a7047ce2d52bb776f
parent 6dafdbcbf8b78409e4767ae30766826f21300a9f
author Patrick McHardy <kaber@trash.net> Sat, 19 Nov 2005 07:58:46 +0100
committer Patrick McHardy <kaber@trash.net> Sat, 19 Nov 2005 07:58:46 +0100

 include/net/ip.h                               |    1 -
 net/ipv4/ip_output.c                           |   30 +++++++++++-------------
 net/ipv4/netfilter/ip_conntrack_standalone.c   |   26 +--------------------
 net/ipv4/netfilter/ip_nat_standalone.c         |   17 --------------
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |   26 +--------------------
 5 files changed, 16 insertions(+), 84 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index e4563bb..9f09882 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -310,7 +310,6 @@ enum ip_defrag_users
 	IP_DEFRAG_CALL_RA_CHAIN,
 	IP_DEFRAG_CONNTRACK_IN,
 	IP_DEFRAG_CONNTRACK_OUT,
-	IP_DEFRAG_NAT_OUT,
 	IP_DEFRAG_VS_IN,
 	IP_DEFRAG_VS_OUT,
 	IP_DEFRAG_VS_FWD
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 11c2f68..946e812 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -202,13 +202,11 @@ static inline int ip_finish_output2(stru
 
 static inline int ip_finish_output(struct sk_buff *skb)
 {
-	struct net_device *dev = skb->dst->dev;
-
-	skb->dev = dev;
-	skb->protocol = htons(ETH_P_IP);
-
-	return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
-		       ip_finish_output2);
+	if (skb->len > dst_mtu(skb->dst) &&
+	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+		return ip_fragment(skb, ip_finish_output2);
+	else
+		return ip_finish_output2(skb);
 }
 
 int ip_mc_output(struct sk_buff *skb)
@@ -265,21 +263,21 @@ int ip_mc_output(struct sk_buff *skb)
 				newskb->dev, ip_dev_loopback_xmit);
 	}
 
-	if (skb->len > dst_mtu(&rt->u.dst))
-		return ip_fragment(skb, ip_finish_output);
-	else
-		return ip_finish_output(skb);
+	return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev,
+		       ip_finish_output);
 }
 
 int ip_output(struct sk_buff *skb)
 {
+	struct net_device *dev = skb->dst->dev;
+
 	IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 
-	if (skb->len > dst_mtu(skb->dst) &&
-		!(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
-		return ip_fragment(skb, ip_finish_output);
-	else
-		return ip_finish_output(skb);
+	skb->dev = dev;
+	skb->protocol = htons(ETH_P_IP);
+
+	return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
+		       ip_finish_output);
 }
 
 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index dd476b1..13ed18a 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -450,30 +450,6 @@ static unsigned int ip_conntrack_defrag(
 	return NF_ACCEPT;
 }
 
-static unsigned int ip_refrag(unsigned int hooknum,
-			      struct sk_buff **pskb,
-			      const struct net_device *in,
-			      const struct net_device *out,
-			      int (*okfn)(struct sk_buff *))
-{
-	struct rtable *rt = (struct rtable *)(*pskb)->dst;
-
-	/* We've seen it coming out the other side: confirm */
-	if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
-		return NF_DROP;
-
-	/* Local packets are never produced too large for their
-	   interface.  We degfragment them at LOCAL_OUT, however,
-	   so we have to refragment them here. */
-	if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
-	    !skb_shinfo(*pskb)->tso_size) {
-		/* No hook can be after us, so this should be OK. */
-		ip_fragment(*pskb, okfn);
-		return NF_STOLEN;
-	}
-	return NF_ACCEPT;
-}
-
 static unsigned int ip_conntrack_local(unsigned int hooknum,
 				       struct sk_buff **pskb,
 				       const struct net_device *in,
@@ -543,7 +519,7 @@ static struct nf_hook_ops ip_conntrack_h
 
 /* Refragmenter; last chance. */
 static struct nf_hook_ops ip_conntrack_out_ops = {
-	.hook		= ip_refrag,
+	.hook		= ip_confirm,
 	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_POST_ROUTING,
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 30cd4e1..f04111f 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -190,23 +190,6 @@ ip_nat_out(unsigned int hooknum,
 	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
 		return NF_ACCEPT;
 
-	/* We can hit fragment here; forwarded packets get
-	   defragmented by connection tracking coming in, then
-	   fragmented (grr) by the forward code.
-
-	   In future: If we have nfct != NULL, AND we have NAT
-	   initialized, AND there is no helper, then we can do full
-	   NAPT on the head, and IP-address-only NAT on the rest.
-
-	   I'm starting to have nightmares about fragments.  */
-
-	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-		*pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
-
-		if (!*pskb)
-			return NF_STOLEN;
-	}
-
 	return ip_nat_fn(hooknum, pskb, in, out, okfn);
 }
 
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 8202c1c..818ba72 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -180,30 +180,6 @@ static unsigned int ipv4_conntrack_defra
 	return NF_ACCEPT;
 }
 
-static unsigned int ipv4_refrag(unsigned int hooknum,
-				struct sk_buff **pskb,
-				const struct net_device *in,
-				const struct net_device *out,
-				int (*okfn)(struct sk_buff *))
-{
-	struct rtable *rt = (struct rtable *)(*pskb)->dst;
-
-	/* We've seen it coming out the other side: confirm */
-	if (ipv4_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
-		return NF_DROP;
-
-	/* Local packets are never produced too large for their
-	   interface.  We degfragment them at LOCAL_OUT, however,
-	   so we have to refragment them here. */
-	if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
-	    !skb_shinfo(*pskb)->tso_size) {
-		/* No hook can be after us, so this should be OK. */
-		ip_fragment(*pskb, okfn);
-		return NF_STOLEN;
-	}
-	return NF_ACCEPT;
-}
-
 static unsigned int ipv4_conntrack_in(unsigned int hooknum,
 				      struct sk_buff **pskb,
 				      const struct net_device *in,
@@ -283,7 +259,7 @@ static struct nf_hook_ops ipv4_conntrack
 
 /* Refragmenter; last chance. */
 static struct nf_hook_ops ipv4_conntrack_out_ops = {
-	.hook		= ipv4_refrag,
+	.hook		= ipv4_confirm,
 	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_POST_ROUTING,

^ permalink raw reply related

* [2.6 patch] drivers/net/Kconfig: indentation fix
From: Adrian Bunk @ 2005-11-19  8:03 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel

This patch fixes a wrong indentation.


Signed-off-by: Adrian Bunk <bunk@stusta.de>

--- linux-2.6.15-rc1-mm2-full/drivers/net/Kconfig.old	2005-11-19 04:03:27.000000000 +0100
+++ linux-2.6.15-rc1-mm2-full/drivers/net/Kconfig	2005-11-19 04:03:38.000000000 +0100
@@ -129,7 +129,7 @@
 
 	  If you don't have this card, of course say N.
 
-	source "drivers/net/arcnet/Kconfig"
+source "drivers/net/arcnet/Kconfig"
 
 source "drivers/net/phy/Kconfig"
 

^ permalink raw reply

* Re: [PATCH] [RFT] ip_tables NUMA optimization
From: Harald Welte @ 2005-11-19  8:45 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, netfilter-devel, dada1
In-Reply-To: <20051118.160043.119281166.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 770 bytes --]

On Fri, Nov 18, 2005 at 04:00:43PM -0800, David S. Miller wrote:
 
> > It should probably use vfree() like :
> > 
> >  > +	for_each_cpu(cpu) {
> >  > +		if (info->size <= PAGE_SIZE)
> >  > +			kfree(info->entries[cpu]);
> >  > +		else
> >  > +			vfree(info->entries[cpu]);
> >  > +	}
> 
> I've put the patch into the net-2.6.16 tree with the obvious
> fix Eric points out.

thanks!

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox