Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5c69d57..ebd7313 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -812,7 +812,7 @@
 	tristate "SMC 91C9x/91C1xxx support"
 	select CRC32
 	select MII
-	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH)
+	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00)
 	help
 	  This is a driver for SMC's 91x series of Ethernet chipsets,
 	  including the SMC91C94 and the SMC91C111. Say Y if you want it
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 22aec6e..525624f 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -80,7 +80,7 @@
  *			   into nv_close, otherwise reenabling for wol can
  *			   cause DMA to kfree'd memory.
  *	0.31: 14 Nov 2004: ethtool support for getting/setting link
- *	                   capabilities.
+ *			   capabilities.
  *	0.32: 16 Apr 2005: RX_ERROR4 handling added.
  *	0.33: 16 May 2005: Support for MCP51 added.
  *	0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics.
@@ -89,14 +89,17 @@
  *	0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list
  *	0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of
  *			   per-packet flags.
- *      0.39: 18 Jul 2005: Add 64bit descriptor support.
- *      0.40: 19 Jul 2005: Add support for mac address change.
- *      0.41: 30 Jul 2005: Write back original MAC in nv_close instead
+ *	0.39: 18 Jul 2005: Add 64bit descriptor support.
+ *	0.40: 19 Jul 2005: Add support for mac address change.
+ *	0.41: 30 Jul 2005: Write back original MAC in nv_close instead
  *			   of nv_remove
- *      0.42: 06 Aug 2005: Fix lack of link speed initialization
+ *	0.42: 06 Aug 2005: Fix lack of link speed initialization
  *			   in the second (and later) nv_open call
- *      0.43: 10 Aug 2005: Add support for tx checksum.
- *      0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
+ *	0.43: 10 Aug 2005: Add support for tx checksum.
+ *	0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
+ *	0.45: 18 Sep 2005: Remove nv_stop/start_rx from every link check
+ *	0.46: 20 Oct 2005: Add irq optimization modes.
+ *	0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -108,7 +111,7 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.44"
+#define FORCEDETH_VERSION		"0.47"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -163,7 +166,8 @@
 #define NVREG_IRQ_LINK			0x0040
 #define NVREG_IRQ_TX_ERROR		0x0080
 #define NVREG_IRQ_TX1			0x0100
-#define NVREG_IRQMASK_WANTED		0x00df
+#define NVREG_IRQMASK_THROUGHPUT	0x00df
+#define NVREG_IRQMASK_CPU		0x0040
 
 #define NVREG_IRQ_UNKNOWN	(~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
 					NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \
@@ -177,7 +181,8 @@
  * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
  */
 	NvRegPollingInterval = 0x00c,
-#define NVREG_POLL_DEFAULT	970
+#define NVREG_POLL_DEFAULT_THROUGHPUT	970
+#define NVREG_POLL_DEFAULT_CPU	13
 	NvRegMisc1 = 0x080,
 #define NVREG_MISC1_HD		0x02
 #define NVREG_MISC1_FORCE	0x3b0f3c
@@ -538,6 +543,25 @@
  */
 static int max_interrupt_work = 5;
 
+/*
+ * Optimization can be either throuput mode or cpu mode
+ * 
+ * Throughput Mode: Every tx and rx packet will generate an interrupt.
+ * CPU Mode: Interrupts are controlled by a timer.
+ */
+#define NV_OPTIMIZATION_MODE_THROUGHPUT 0
+#define NV_OPTIMIZATION_MODE_CPU        1
+static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT;
+
+/*
+ * Poll interval for timer irq
+ *
+ * This interval determines how frequent an interrupt is generated.
+ * The is value is determined by [(time_in_micro_secs * 100) / (2^10)]
+ * Min = 0, and Max = 65535
+ */
+static int poll_interval = -1;
+
 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
 {
 	return netdev_priv(dev);
@@ -1328,67 +1352,71 @@
 			if (!(Flags & NV_RX_DESCRIPTORVALID))
 				goto next_pkt;
 
-			if (Flags & NV_RX_MISSEDFRAME) {
-				np->stats.rx_missed_errors++;
-				np->stats.rx_errors++;
-				goto next_pkt;
-			}
-			if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
-				np->stats.rx_errors++;
-				goto next_pkt;
-			}
-			if (Flags & NV_RX_CRCERR) {
-				np->stats.rx_crc_errors++;
-				np->stats.rx_errors++;
-				goto next_pkt;
-			}
-			if (Flags & NV_RX_OVERFLOW) {
-				np->stats.rx_over_errors++;
-				np->stats.rx_errors++;
-				goto next_pkt;
-			}
-			if (Flags & NV_RX_ERROR4) {
-				len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
-				if (len < 0) {
+			if (Flags & NV_RX_ERROR) {
+				if (Flags & NV_RX_MISSEDFRAME) {
+					np->stats.rx_missed_errors++;
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-			}
-			/* framing errors are soft errors. */
-			if (Flags & NV_RX_FRAMINGERR) {
-				if (Flags & NV_RX_SUBSTRACT1) {
-					len--;
+				if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
+					np->stats.rx_errors++;
+					goto next_pkt;
+				}
+				if (Flags & NV_RX_CRCERR) {
+					np->stats.rx_crc_errors++;
+					np->stats.rx_errors++;
+					goto next_pkt;
+				}
+				if (Flags & NV_RX_OVERFLOW) {
+					np->stats.rx_over_errors++;
+					np->stats.rx_errors++;
+					goto next_pkt;
+				}
+				if (Flags & NV_RX_ERROR4) {
+					len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
+					if (len < 0) {
+						np->stats.rx_errors++;
+						goto next_pkt;
+					}
+				}
+				/* framing errors are soft errors. */
+				if (Flags & NV_RX_FRAMINGERR) {
+					if (Flags & NV_RX_SUBSTRACT1) {
+						len--;
+					}
 				}
 			}
 		} else {
 			if (!(Flags & NV_RX2_DESCRIPTORVALID))
 				goto next_pkt;
 
-			if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
-				np->stats.rx_errors++;
-				goto next_pkt;
-			}
-			if (Flags & NV_RX2_CRCERR) {
-				np->stats.rx_crc_errors++;
-				np->stats.rx_errors++;
-				goto next_pkt;
-			}
-			if (Flags & NV_RX2_OVERFLOW) {
-				np->stats.rx_over_errors++;
-				np->stats.rx_errors++;
-				goto next_pkt;
-			}
-			if (Flags & NV_RX2_ERROR4) {
-				len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
-				if (len < 0) {
+			if (Flags & NV_RX2_ERROR) {
+				if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-			}
-			/* framing errors are soft errors */
-			if (Flags & NV_RX2_FRAMINGERR) {
-				if (Flags & NV_RX2_SUBSTRACT1) {
-					len--;
+				if (Flags & NV_RX2_CRCERR) {
+					np->stats.rx_crc_errors++;
+					np->stats.rx_errors++;
+					goto next_pkt;
+				}
+				if (Flags & NV_RX2_OVERFLOW) {
+					np->stats.rx_over_errors++;
+					np->stats.rx_errors++;
+					goto next_pkt;
+				}
+				if (Flags & NV_RX2_ERROR4) {
+					len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
+					if (len < 0) {
+						np->stats.rx_errors++;
+						goto next_pkt;
+					}
+				}
+				/* framing errors are soft errors */
+				if (Flags & NV_RX2_FRAMINGERR) {
+					if (Flags & NV_RX2_SUBSTRACT1) {
+						len--;
+					}
 				}
 			}
 			Flags &= NV_RX2_CHECKSUMMASK;
@@ -1612,6 +1640,17 @@
 	spin_unlock_irq(&np->lock);
 }
 
+/**
+ * nv_update_linkspeed: Setup the MAC according to the link partner
+ * @dev: Network device to be configured
+ *
+ * The function queries the PHY and checks if there is a link partner.
+ * If yes, then it sets up the MAC accordingly. Otherwise, the MAC is
+ * set to 10 MBit HD.
+ *
+ * The function returns 0 if there is no link partner and 1 if there is
+ * a good link partner.
+ */
 static int nv_update_linkspeed(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
@@ -1751,13 +1790,11 @@
 static void nv_linkchange(struct net_device *dev)
 {
 	if (nv_update_linkspeed(dev)) {
-		if (netif_carrier_ok(dev)) {
-			nv_stop_rx(dev);
-		} else {
+		if (!netif_carrier_ok(dev)) {
 			netif_carrier_on(dev);
 			printk(KERN_INFO "%s: link up.\n", dev->name);
+			nv_start_rx(dev);
 		}
-		nv_start_rx(dev);
 	} else {
 		if (netif_carrier_ok(dev)) {
 			netif_carrier_off(dev);
@@ -1799,22 +1836,18 @@
 		if (!(events & np->irqmask))
 			break;
 
-		if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_ERR)) {
+		spin_lock(&np->lock);
+		nv_tx_done(dev);
+		spin_unlock(&np->lock);
+		
+		nv_rx_process(dev);
+		if (nv_alloc_rx(dev)) {
 			spin_lock(&np->lock);
-			nv_tx_done(dev);
+			if (!np->in_shutdown)
+				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
 			spin_unlock(&np->lock);
 		}
-
-		if (events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)) {
-			nv_rx_process(dev);
-			if (nv_alloc_rx(dev)) {
-				spin_lock(&np->lock);
-				if (!np->in_shutdown)
-					mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
-				spin_unlock(&np->lock);
-			}
-		}
-
+		
 		if (events & NVREG_IRQ_LINK) {
 			spin_lock(&np->lock);
 			nv_link_irq(dev);
@@ -2216,7 +2249,14 @@
 	writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
 	writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
 	writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);
-	writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval);
+	if (poll_interval == -1) {
+		if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT)
+			writel(NVREG_POLL_DEFAULT_THROUGHPUT, base + NvRegPollingInterval);
+		else
+			writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval);
+	}
+	else
+		writel(poll_interval & 0xFFFF, base + NvRegPollingInterval);
 	writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
 	writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING,
 			base + NvRegAdapterControl);
@@ -2501,7 +2541,11 @@
 	} else {
 		np->tx_flags = NV_TX2_VALID;
 	}
-	np->irqmask = NVREG_IRQMASK_WANTED;
+	if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT)
+		np->irqmask = NVREG_IRQMASK_THROUGHPUT;
+	else
+		np->irqmask = NVREG_IRQMASK_CPU;
+
 	if (id->driver_data & DEV_NEED_TIMERIRQ)
 		np->irqmask |= NVREG_IRQ_TIMER;
 	if (id->driver_data & DEV_NEED_LINKTIMER) {
@@ -2514,16 +2558,17 @@
 	}
 
 	/* find a suitable phy */
-	for (i = 1; i < 32; i++) {
+	for (i = 1; i <= 32; i++) {
 		int id1, id2;
+		int phyaddr = i & 0x1F;
 
 		spin_lock_irq(&np->lock);
-		id1 = mii_rw(dev, i, MII_PHYSID1, MII_READ);
+		id1 = mii_rw(dev, phyaddr, MII_PHYSID1, MII_READ);
 		spin_unlock_irq(&np->lock);
 		if (id1 < 0 || id1 == 0xffff)
 			continue;
 		spin_lock_irq(&np->lock);
-		id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ);
+		id2 = mii_rw(dev, phyaddr, MII_PHYSID2, MII_READ);
 		spin_unlock_irq(&np->lock);
 		if (id2 < 0 || id2 == 0xffff)
 			continue;
@@ -2531,23 +2576,19 @@
 		id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
 		id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
 		dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n",
-				pci_name(pci_dev), id1, id2, i);
-		np->phyaddr = i;
+			pci_name(pci_dev), id1, id2, phyaddr);
+		np->phyaddr = phyaddr;
 		np->phy_oui = id1 | id2;
 		break;
 	}
-	if (i == 32) {
-		/* PHY in isolate mode? No phy attached and user wants to
-		 * test loopback? Very odd, but can be correct.
-		 */
+	if (i == 33) {
 		printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",
-				pci_name(pci_dev));
+		       pci_name(pci_dev));
+		goto out_freering;
 	}
-
-	if (i != 32) {
-		/* reset it */
-		phy_init(dev);
-	}
+	
+	/* reset it */
+	phy_init(dev);
 
 	/* set default link speed settings */
 	np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
@@ -2689,6 +2730,10 @@
 
 module_param(max_interrupt_work, int, 0);
 MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt");
+module_param(optimization_mode, int, 0);
+MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer.");
+module_param(poll_interval, int, 0);
+MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535.");
 
 MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
 MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 7263395..9544279 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -133,7 +133,7 @@
 	if (NULL == dev)
 		return -EINVAL;
 
-	new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
+	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
 
 	if (NULL == new_bus)
 		return -ENOMEM;
diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c
index 666cfbb..5958a63 100644
--- a/drivers/net/gt96100eth.c
+++ b/drivers/net/gt96100eth.c
@@ -72,8 +72,6 @@
 static void dump_rx_desc(int dbg_lvl, struct net_device *dev, int i);
 static void dump_skb(int dbg_lvl, struct net_device *dev,
 		     struct sk_buff *skb);
-static void dump_hw_addr(int dbg_lvl, struct net_device *dev,
-			 const char* pfx, unsigned char* addr_str);
 static void update_stats(struct gt96100_private *gp);
 static void abort(struct net_device *dev, u32 abort_bits);
 static void hard_stop(struct net_device *dev);
@@ -334,13 +332,13 @@
 
 static void
 dump_hw_addr(int dbg_lvl, struct net_device *dev, const char* pfx,
-	     unsigned char* addr_str)
+	     const char* func, unsigned char* addr_str)
 {
 	int i;
 	char buf[100], octet[5];
     
 	if (dbg_lvl <= GT96100_DEBUG) {
-		strcpy(buf, pfx);
+		sprintf(buf, pfx, func);
 		for (i = 0; i < 6; i++) {
 			sprintf(octet, "%2.2x%s",
 				addr_str[i], i<5 ? ":" : "\n");
@@ -708,7 +706,7 @@
 
 	info("%s found at 0x%x, irq %d\n",
 	     chip_name(gp->chip_rev), gtif->iobase, gtif->irq);
-	dump_hw_addr(0, dev, "HW Address ", dev->dev_addr);
+	dump_hw_addr(0, dev, "%s: HW Address ", __FUNCTION__, dev->dev_addr);
 	info("%s chip revision=%d\n", chip_name(gp->chip_rev), gp->chip_rev);
 	info("%s ethernet port %d\n", chip_name(gp->chip_rev), gp->port_num);
 	info("external PHY ID1=0x%04x, ID2=0x%04x\n", phy_id1, phy_id2);
@@ -1488,7 +1486,7 @@
 		gt96100_add_hash_entry(dev, dev->dev_addr);
 
 		for (mcptr = dev->mc_list; mcptr; mcptr = mcptr->next) {
-			dump_hw_addr(2, dev, __FUNCTION__ ": addr=",
+			dump_hw_addr(2, dev, "%s: addr=", __FUNCTION__,
 				     mcptr->dmi_addr);
 			gt96100_add_hash_entry(dev, mcptr->dmi_addr);
 		}
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index be191d8..ceb98fd 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -58,7 +58,7 @@
 
 #include "ibmveth.h"
 
-#define DEBUG 1
+#undef DEBUG
 
 #define ibmveth_printk(fmt, args...) \
   printk(KERN_INFO "%s: " fmt, __FILE__, ## args)
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index 110e777..b2acedb 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -1,8 +1,8 @@
 /*
- * 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>
+ * Copyright (C) 2004 Ralf Baechle <ralf@linux-mips.org>
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -17,15 +17,13 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- *
  * SAA9730 ethernet driver.
  *
  * Changes:
- * Angelo Dell'Aera <buffer@antifork.org> : Conversion to the new PCI API (pci_driver).
- *                                          Conversion to spinlocks.
- *                                          Error handling fixes.
- *                                           
+ * Angelo Dell'Aera <buffer@antifork.org> :	Conversion to the new PCI API
+ *						(pci_driver).
+ *						Conversion to spinlocks.
+ *						Error handling fixes.
  */
 
 #include <linux/init.h>
@@ -36,8 +34,11 @@
 #include <linux/skbuff.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
+#include <linux/types.h>
 
 #include <asm/addrspace.h>
+#include <asm/io.h>
+
 #include <asm/mips-boards/prom.h>
 
 #include "saa9730.h"
@@ -51,8 +52,8 @@
 #define DRV_MODULE_NAME "saa9730"
 
 static struct pci_device_id saa9730_pci_tbl[] = {
-	{ PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9370,
-          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ 0, }
 };
 
@@ -61,50 +62,48 @@
 /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
 static unsigned int pci_irq_line;
 
-#define INL(a)     inl((unsigned long)a)
-#define OUTL(x,a)  outl(x,(unsigned long)a)
-
 static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp)
 {
-	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+	outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
 	     &lp->evm_saa9730_regs->InterruptBlock1);
-	OUTL(INL(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
+	outl(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
 	     &lp->evm_saa9730_regs->InterruptStatus1);
-	OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
+	outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
 	     EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1);
 }
+
 static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp)
 {
-	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+	outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
 	     &lp->evm_saa9730_regs->InterruptBlock1);
-	OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
+	outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
 	     &lp->evm_saa9730_regs->InterruptEnable1);
 }
 
 static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp)
 {
-	OUTL(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
+	outl(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
 }
 
 static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp)
 {
-	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+	outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
 	     &lp->evm_saa9730_regs->InterruptBlock1);
 }
 
 static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
 {
-	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+	outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
 	     &lp->evm_saa9730_regs->InterruptBlock1);
 }
 
-static void show_saa9730_regs(struct lan_saa9730_private *lp)
+static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp)
 {
 	int i, j;
-	printk("TxmBufferA = %x\n", lp->TxmBuffer[0][0]);
-	printk("TxmBufferB = %x\n", lp->TxmBuffer[1][0]);
-	printk("RcvBufferA = %x\n", lp->RcvBuffer[0][0]);
-	printk("RcvBufferB = %x\n", lp->RcvBuffer[1][0]);
+	printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]);
+	printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]);
+	printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]);
+	printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]);
 	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
 		for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
 			printk("TxmBuffer[%d][%d] = %x\n", i, j,
@@ -120,13 +119,13 @@
 		}
 	}
 	printk("lp->evm_saa9730_regs->InterruptBlock1 = %x\n",
-	       INL(&lp->evm_saa9730_regs->InterruptBlock1));
+	       readl(&lp->evm_saa9730_regs->InterruptBlock1));
 	printk("lp->evm_saa9730_regs->InterruptStatus1 = %x\n",
-	       INL(&lp->evm_saa9730_regs->InterruptStatus1));
+	       readl(&lp->evm_saa9730_regs->InterruptStatus1));
 	printk("lp->evm_saa9730_regs->InterruptEnable1 = %x\n",
-	       INL(&lp->evm_saa9730_regs->InterruptEnable1));
+	       readl(&lp->evm_saa9730_regs->InterruptEnable1));
 	printk("lp->lan_saa9730_regs->Ok2Use = %x\n",
-	       INL(&lp->lan_saa9730_regs->Ok2Use));
+	       readl(&lp->lan_saa9730_regs->Ok2Use));
 	printk("lp->NextTxmBufferIndex = %x\n", lp->NextTxmBufferIndex);
 	printk("lp->NextTxmPacketIndex = %x\n", lp->NextTxmPacketIndex);
 	printk("lp->PendingTxmBufferIndex = %x\n",
@@ -134,23 +133,23 @@
 	printk("lp->PendingTxmPacketIndex = %x\n",
 	       lp->PendingTxmPacketIndex);
 	printk("lp->lan_saa9730_regs->LanDmaCtl = %x\n",
-	       INL(&lp->lan_saa9730_regs->LanDmaCtl));
+	       readl(&lp->lan_saa9730_regs->LanDmaCtl));
 	printk("lp->lan_saa9730_regs->DmaStatus = %x\n",
-	       INL(&lp->lan_saa9730_regs->DmaStatus));
+	       readl(&lp->lan_saa9730_regs->DmaStatus));
 	printk("lp->lan_saa9730_regs->CamCtl = %x\n",
-	       INL(&lp->lan_saa9730_regs->CamCtl));
+	       readl(&lp->lan_saa9730_regs->CamCtl));
 	printk("lp->lan_saa9730_regs->TxCtl = %x\n",
-	       INL(&lp->lan_saa9730_regs->TxCtl));
+	       readl(&lp->lan_saa9730_regs->TxCtl));
 	printk("lp->lan_saa9730_regs->TxStatus = %x\n",
-	       INL(&lp->lan_saa9730_regs->TxStatus));
+	       readl(&lp->lan_saa9730_regs->TxStatus));
 	printk("lp->lan_saa9730_regs->RxCtl = %x\n",
-	       INL(&lp->lan_saa9730_regs->RxCtl));
+	       readl(&lp->lan_saa9730_regs->RxCtl));
 	printk("lp->lan_saa9730_regs->RxStatus = %x\n",
-	       INL(&lp->lan_saa9730_regs->RxStatus));
+	       readl(&lp->lan_saa9730_regs->RxStatus));
 	for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
-		OUTL(i, &lp->lan_saa9730_regs->CamAddress);
+		outl(i, &lp->lan_saa9730_regs->CamAddress);
 		printk("lp->lan_saa9730_regs->CamData = %x\n",
-		       INL(&lp->lan_saa9730_regs->CamData));
+		       readl(&lp->lan_saa9730_regs->CamData));
 	}
 	printk("lp->stats.tx_packets = %lx\n", lp->stats.tx_packets);
 	printk("lp->stats.tx_errors = %lx\n", lp->stats.tx_errors);
@@ -178,17 +177,17 @@
 	       lp->stats.rx_length_errors);
 
 	printk("lp->lan_saa9730_regs->DebugPCIMasterAddr = %x\n",
-	       INL(&lp->lan_saa9730_regs->DebugPCIMasterAddr));
+	       readl(&lp->lan_saa9730_regs->DebugPCIMasterAddr));
 	printk("lp->lan_saa9730_regs->DebugLanTxStateMachine = %x\n",
-	       INL(&lp->lan_saa9730_regs->DebugLanTxStateMachine));
+	       readl(&lp->lan_saa9730_regs->DebugLanTxStateMachine));
 	printk("lp->lan_saa9730_regs->DebugLanRxStateMachine = %x\n",
-	       INL(&lp->lan_saa9730_regs->DebugLanRxStateMachine));
+	       readl(&lp->lan_saa9730_regs->DebugLanRxStateMachine));
 	printk("lp->lan_saa9730_regs->DebugLanTxFifoPointers = %x\n",
-	       INL(&lp->lan_saa9730_regs->DebugLanTxFifoPointers));
+	       readl(&lp->lan_saa9730_regs->DebugLanTxFifoPointers));
 	printk("lp->lan_saa9730_regs->DebugLanRxFifoPointers = %x\n",
-	       INL(&lp->lan_saa9730_regs->DebugLanRxFifoPointers));
+	       readl(&lp->lan_saa9730_regs->DebugLanRxFifoPointers));
 	printk("lp->lan_saa9730_regs->DebugLanCtlStateMachine = %x\n",
-	       INL(&lp->lan_saa9730_regs->DebugLanCtlStateMachine));
+	       readl(&lp->lan_saa9730_regs->DebugLanCtlStateMachine));
 }
 
 static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp)
@@ -214,98 +213,108 @@
 	}
 }
 
-static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp)
+static void lan_saa9730_free_buffers(struct pci_dev *pdev,
+				     struct lan_saa9730_private *lp)
 {
-	unsigned int mem_size;
+	pci_free_consistent(pdev, lp->buffer_size, lp->buffer_start,
+			    lp->dma_addr);
+}
+
+static int lan_saa9730_allocate_buffers(struct pci_dev *pdev,
+					struct lan_saa9730_private *lp)
+{
 	void *Pa;
-	unsigned int i, j, RcvBufferSize, TxmBufferSize;
-	unsigned int buffer_start;
-
-	/* 
-	 * Allocate all RX and TX packets in one chunk. 
-	 * The Rx and Tx packets must be PACKET_SIZE aligned.
-	 */
-	mem_size = ((LAN_SAA9730_RCV_Q_SIZE + LAN_SAA9730_TXM_Q_SIZE) *
-		    LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_BUFFERS) +
-	    LAN_SAA9730_PACKET_SIZE;
-	buffer_start =
-	    (unsigned int) kmalloc(mem_size, GFP_DMA | GFP_KERNEL);
-
-	if (!buffer_start)
-		return -ENOMEM;
-
-	/* 
-	 * Set DMA buffer to kseg1 (uncached).
-	 * Make sure to flush before using it uncached.
-	 */
-	Pa = (void *) KSEG1ADDR((buffer_start + LAN_SAA9730_PACKET_SIZE) &
-				~(LAN_SAA9730_PACKET_SIZE - 1));
-	dma_cache_wback_inv((unsigned long) Pa, mem_size);
+	unsigned int i, j, rxoffset, txoffset;
+	int ret;
 
 	/* Initialize buffer space */
-	RcvBufferSize = LAN_SAA9730_PACKET_SIZE;
-	TxmBufferSize = LAN_SAA9730_PACKET_SIZE;
 	lp->DmaRcvPackets = LAN_SAA9730_RCV_Q_SIZE;
 	lp->DmaTxmPackets = LAN_SAA9730_TXM_Q_SIZE;
 
+	/* Initialize Rx Buffer Index */
+	lp->NextRcvPacketIndex = 0;
+	lp->NextRcvBufferIndex = 0;
+
+	/* Set current buffer index & next available packet index */
+	lp->NextTxmPacketIndex = 0;
+	lp->NextTxmBufferIndex = 0;
+	lp->PendingTxmPacketIndex = 0;
+	lp->PendingTxmBufferIndex = 0;
+
+	/*
+	 * Allocate all RX and TX packets in one chunk.
+	 * The Rx and Tx packets must be PACKET_SIZE aligned.
+	 */
+	lp->buffer_size = ((LAN_SAA9730_RCV_Q_SIZE + LAN_SAA9730_TXM_Q_SIZE) *
+			   LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_BUFFERS) +
+			  LAN_SAA9730_PACKET_SIZE;
+	lp->buffer_start = pci_alloc_consistent(pdev, lp->buffer_size,
+						&lp->dma_addr);
+	if (!lp->buffer_start) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	Pa = (void *)ALIGN((unsigned long)lp->buffer_start,
+			   LAN_SAA9730_PACKET_SIZE);
+
+	rxoffset = Pa - lp->buffer_start;
+
 	/* Init RX buffers */
 	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
 		for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) {
 			*(unsigned int *) Pa =
 			    cpu_to_le32(RXSF_READY <<
 					RX_STAT_CTL_OWNER_SHF);
-			lp->RcvBuffer[i][j] = (unsigned int) Pa;
-			Pa += RcvBufferSize;
+			lp->RcvBuffer[i][j] = Pa;
+			Pa += LAN_SAA9730_PACKET_SIZE;
 		}
 	}
 
+	txoffset = Pa - lp->buffer_start;
+
 	/* Init TX buffers */
 	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
 		for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
 			*(unsigned int *) Pa =
 			    cpu_to_le32(TXSF_EMPTY <<
 					TX_STAT_CTL_OWNER_SHF);
-			lp->TxmBuffer[i][j] = (unsigned int) Pa;
-			Pa += TxmBufferSize;
+			lp->TxmBuffer[i][j] = Pa;
+			Pa += LAN_SAA9730_PACKET_SIZE;
 		}
 	}
 
-	/* 
-	 * Set rx buffer A and rx buffer B to point to the first two buffer 
+	/*
+	 * Set rx buffer A and rx buffer B to point to the first two buffer
 	 * spaces.
 	 */
-	OUTL(PHYSADDR(lp->RcvBuffer[0][0]),
+	outl(lp->dma_addr + rxoffset,
 	     &lp->lan_saa9730_regs->RxBuffA);
-	OUTL(PHYSADDR(lp->RcvBuffer[1][0]),
+	outl(lp->dma_addr + rxoffset +
+	     LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE,
 	     &lp->lan_saa9730_regs->RxBuffB);
 
-	/* Initialize Buffer Index */
-	lp->NextRcvPacketIndex = 0;
-	lp->NextRcvToUseIsA = 1;
-
-	/* Set current buffer index & next availble packet index */
-	lp->NextTxmPacketIndex = 0;
-	lp->NextTxmBufferIndex = 0;
-	lp->PendingTxmPacketIndex = 0;
-	lp->PendingTxmBufferIndex = 0;
-
-	/* 
+	/*
 	 * Set txm_buf_a and txm_buf_b to point to the first two buffer
-	 * space 
+	 * space
 	 */
-	OUTL(PHYSADDR(lp->TxmBuffer[0][0]),
+	outl(lp->dma_addr + txoffset,
 	     &lp->lan_saa9730_regs->TxBuffA);
-	OUTL(PHYSADDR(lp->TxmBuffer[1][0]),
+	outl(lp->dma_addr + txoffset +
+	     LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE,
 	     &lp->lan_saa9730_regs->TxBuffB);
 
 	/* Set packet number */
-	OUTL((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) |
+	outl((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) |
 	     (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) |
 	     (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) |
 	     (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF),
 	     &lp->lan_saa9730_regs->PacketCount);
 
 	return 0;
+
+out:
+	return ret;
 }
 
 static int lan_saa9730_cam_load(struct lan_saa9730_private *lp)
@@ -317,8 +326,8 @@
 
 	for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
 		/* First set address to where data is written */
-		OUTL(i, &lp->lan_saa9730_regs->CamAddress);
-		OUTL((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16)
+		outl(i, &lp->lan_saa9730_regs->CamAddress);
+		outl((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16)
 		     | (NetworkAddress[2] << 8) | NetworkAddress[3],
 		     &lp->lan_saa9730_regs->CamData);
 		NetworkAddress += 4;
@@ -328,8 +337,7 @@
 
 static int lan_saa9730_cam_init(struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 	unsigned int i;
 
 	/* Copy MAC-address into all entries. */
@@ -347,7 +355,7 @@
 
 	/* Check link status, spin here till station is not busy. */
 	i = 0;
-	while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
+	while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
 		i++;
 		if (i > 100) {
 			printk("Error: lan_saa9730_mii_init: timeout\n");
@@ -357,12 +365,12 @@
 	}
 
 	/* Now set the control and address register. */
-	OUTL(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF,
+	outl(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF,
 	     &lp->lan_saa9730_regs->StationMgmtCtl);
 
 	/* check link status, spin here till station is not busy */
 	i = 0;
-	while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
+	while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
 		i++;
 		if (i > 100) {
 			printk("Error: lan_saa9730_mii_init: timeout\n");
@@ -375,7 +383,7 @@
 	mdelay(1);
 
 	/* Check the link status. */
-	if (INL(&lp->lan_saa9730_regs->StationMgmtData) &
+	if (readl(&lp->lan_saa9730_regs->StationMgmtData) &
 	    PHY_STATUS_LINK_UP) {
 		/* Link is up. */
 		return 0;
@@ -383,14 +391,14 @@
 		/* Link is down, reset the PHY first. */
 
 		/* set PHY address = 'CONTROL' */
-		OUTL(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,
+		outl(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,
 		     &lp->lan_saa9730_regs->StationMgmtCtl);
 
 		/* Wait for 1 ms. */
 		mdelay(1);
 
 		/* set 'CONTROL' = force reset and renegotiate */
-		OUTL(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |
+		outl(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |
 		     PHY_CONTROL_RESTART_AUTO_NEG,
 		     &lp->lan_saa9730_regs->StationMgmtData);
 
@@ -398,12 +406,12 @@
 		mdelay(50);
 
 		/* set 'BUSY' to start operation */
-		OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |
+		outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |
 		     PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl);
 
 		/* await completion */
 		i = 0;
-		while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) &
+		while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) &
 		       MD_CA_BUSY) {
 			i++;
 			if (i > 100) {
@@ -419,13 +427,13 @@
 
 		for (l = 0; l < 2; l++) {
 			/* set PHY address = 'STATUS' */
-			OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |
+			outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |
 			     PHY_STATUS,
 			     &lp->lan_saa9730_regs->StationMgmtCtl);
 
 			/* await completion */
 			i = 0;
-			while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) &
+			while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) &
 			       MD_CA_BUSY) {
 				i++;
 				if (i > 100) {
@@ -440,7 +448,7 @@
 			mdelay(3000);
 
 			/* check the link status */
-			if (INL(&lp->lan_saa9730_regs->StationMgmtData) &
+			if (readl(&lp->lan_saa9730_regs->StationMgmtData) &
 			    PHY_STATUS_LINK_UP) {
 				/* link is up */
 				break;
@@ -454,7 +462,7 @@
 static int lan_saa9730_control_init(struct lan_saa9730_private *lp)
 {
 	/* Initialize DMA control register. */
-	OUTL((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |
+	outl((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |
 	     (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) |
 	     (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF)
 	     | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN |
@@ -462,27 +470,27 @@
 	     &lp->lan_saa9730_regs->LanDmaCtl);
 
 	/* Initial MAC control register. */
-	OUTL((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,
+	outl((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,
 	     &lp->lan_saa9730_regs->MacCtl);
 
 	/* Initialize CAM control register. */
-	OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,
+	outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,
 	     &lp->lan_saa9730_regs->CamCtl);
 
-	/* 
+	/*
 	 * Initialize CAM enable register, only turn on first entry, should
-	 * contain own addr. 
+	 * contain own addr.
 	 */
-	OUTL(0x0001, &lp->lan_saa9730_regs->CamEnable);
+	outl(0x0001, &lp->lan_saa9730_regs->CamEnable);
 
 	/* Initialize Tx control register */
-	OUTL(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);
+	outl(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);
 
 	/* Initialize Rcv control register */
-	OUTL(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);
+	outl(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);
 
 	/* Reset DMA engine */
-	OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+	outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
 
 	return 0;
 }
@@ -492,21 +500,21 @@
 	int i;
 
 	/* Stop DMA first */
-	OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) &
+	outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) &
 	     ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA),
 	     &lp->lan_saa9730_regs->LanDmaCtl);
 
 	/* Set the SW Reset bits in DMA and MAC control registers */
-	OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
-	OUTL(INL(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,
+	outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+	outl(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,
 	     &lp->lan_saa9730_regs->MacCtl);
 
-	/* 
+	/*
 	 * Wait for MAC reset to have finished. The reset bit is auto cleared
 	 * when the reset is done.
 	 */
 	i = 0;
-	while (INL(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) {
+	while (readl(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) {
 		i++;
 		if (i > 100) {
 			printk
@@ -524,7 +532,7 @@
 	/* Stop lan controller. */
 	lan_saa9730_stop(lp);
 
-	OUTL(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,
+	outl(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,
 	     &lp->lan_saa9730_regs->Timeout);
 
 	return 0;
@@ -536,28 +544,27 @@
 
 	/* Initialize Rx Buffer Index */
 	lp->NextRcvPacketIndex = 0;
-	lp->NextRcvToUseIsA = 1;
+	lp->NextRcvBufferIndex = 0;
 
-	/* Set current buffer index & next availble packet index */
+	/* Set current buffer index & next available packet index */
 	lp->NextTxmPacketIndex = 0;
 	lp->NextTxmBufferIndex = 0;
 	lp->PendingTxmPacketIndex = 0;
 	lp->PendingTxmBufferIndex = 0;
 
-	OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |
+	outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |
 	     DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl);
 
 	/* For Tx, turn on MAC then DMA */
-	OUTL(INL(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,
+	outl(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,
 	     &lp->lan_saa9730_regs->TxCtl);
 
 	/* For Rx, turn on DMA then MAC */
-	OUTL(INL(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,
+	outl(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,
 	     &lp->lan_saa9730_regs->RxCtl);
 
-	/* Set Ok2Use to let hardware owns the buffers */
-	OUTL(OK2USE_RX_A | OK2USE_RX_B | OK2USE_TX_A | OK2USE_TX_B,
-	     &lp->lan_saa9730_regs->Ok2Use);
+	/* Set Ok2Use to let hardware own the buffers.	*/
+	outl(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
 
 	return 0;
 }
@@ -572,8 +579,7 @@
 
 static int lan_saa9730_tx(struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 	unsigned int *pPacket;
 	unsigned int tx_status;
 
@@ -581,13 +587,11 @@
 		printk("lan_saa9730_tx interrupt\n");
 
 	/* Clear interrupt. */
-	OUTL(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);
+	outl(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);
 
 	while (1) {
-		pPacket =
-		    (unsigned int *) lp->TxmBuffer[lp->
-						   PendingTxmBufferIndex]
-		    [lp->PendingTxmPacketIndex];
+		pPacket = lp->TxmBuffer[lp->PendingTxmBufferIndex]
+				       [lp->PendingTxmPacketIndex];
 
 		/* Get status of first packet transmitted. */
 		tx_status = le32_to_cpu(*pPacket);
@@ -605,23 +609,22 @@
 			lp->stats.tx_errors++;
 			if (tx_status &
 			    (TX_STATUS_EX_COLL << TX_STAT_CTL_STATUS_SHF))
-				    lp->stats.tx_aborted_errors++;
+				lp->stats.tx_aborted_errors++;
 			if (tx_status &
-			    (TX_STATUS_LATE_COLL <<
-			     TX_STAT_CTL_STATUS_SHF)) lp->stats.
-	     tx_window_errors++;
+			    (TX_STATUS_LATE_COLL << TX_STAT_CTL_STATUS_SHF))
+				lp->stats.tx_window_errors++;
 			if (tx_status &
 			    (TX_STATUS_L_CARR << TX_STAT_CTL_STATUS_SHF))
-				    lp->stats.tx_carrier_errors++;
+				lp->stats.tx_carrier_errors++;
 			if (tx_status &
 			    (TX_STATUS_UNDER << TX_STAT_CTL_STATUS_SHF))
-				    lp->stats.tx_fifo_errors++;
+				lp->stats.tx_fifo_errors++;
 			if (tx_status &
 			    (TX_STATUS_SQ_ERR << TX_STAT_CTL_STATUS_SHF))
-				    lp->stats.tx_heartbeat_errors++;
+				lp->stats.tx_heartbeat_errors++;
 
 			lp->stats.collisions +=
-			    tx_status & TX_STATUS_TX_COLL_MSK;
+				tx_status & TX_STATUS_TX_COLL_MSK;
 		}
 
 		/* Free buffer. */
@@ -636,21 +639,15 @@
 		}
 	}
 
-	/* Make sure A and B are available to hardware. */
-	OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use);
-
-	if (netif_queue_stopped(dev)) {
-		/* The tx buffer is no longer full. */
-		netif_wake_queue(dev);
-	}
+	/* The tx buffer is no longer full. */
+	netif_wake_queue(dev);
 
 	return 0;
 }
 
 static int lan_saa9730_rx(struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 	int len = 0;
 	struct sk_buff *skb = 0;
 	unsigned int rx_status;
@@ -663,16 +660,13 @@
 		printk("lan_saa9730_rx interrupt\n");
 
 	/* Clear receive interrupts. */
-	OUTL(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
+	outl(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
 	     DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus);
 
 	/* Address next packet */
-	if (lp->NextRcvToUseIsA)
-		BufferIndex = 0;
-	else
-		BufferIndex = 1;
+	BufferIndex = lp->NextRcvBufferIndex;
 	PacketIndex = lp->NextRcvPacketIndex;
-	pPacket = (unsigned int *) lp->RcvBuffer[BufferIndex][PacketIndex];
+	pPacket = lp->RcvBuffer[BufferIndex][PacketIndex];
 	rx_status = le32_to_cpu(*pPacket);
 
 	/* Process each packet. */
@@ -715,51 +709,39 @@
 			lp->stats.rx_errors++;
 			if (rx_status &
 			    (RX_STATUS_CRC_ERR << RX_STAT_CTL_STATUS_SHF))
-				    lp->stats.rx_crc_errors++;
+				lp->stats.rx_crc_errors++;
 			if (rx_status &
-			    (RX_STATUS_ALIGN_ERR <<
-			     RX_STAT_CTL_STATUS_SHF)) lp->stats.
-	     rx_frame_errors++;
+			    (RX_STATUS_ALIGN_ERR << RX_STAT_CTL_STATUS_SHF))
+				lp->stats.rx_frame_errors++;
 			if (rx_status &
 			    (RX_STATUS_OVERFLOW << RX_STAT_CTL_STATUS_SHF))
-				    lp->stats.rx_fifo_errors++;
+				lp->stats.rx_fifo_errors++;
 			if (rx_status &
 			    (RX_STATUS_LONG_ERR << RX_STAT_CTL_STATUS_SHF))
-				    lp->stats.rx_length_errors++;
+				lp->stats.rx_length_errors++;
 		}
 
 		/* Indicate we have processed the buffer. */
-		*pPacket =
-		    cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);
+		*pPacket = cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);
+
+		/* Make sure A or B is available to hardware as appropriate. */
+		outl(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A,
+		     &lp->lan_saa9730_regs->Ok2Use);
 
 		/* Go to next packet in sequence. */
 		lp->NextRcvPacketIndex++;
 		if (lp->NextRcvPacketIndex >= LAN_SAA9730_RCV_Q_SIZE) {
 			lp->NextRcvPacketIndex = 0;
-			if (BufferIndex) {
-				lp->NextRcvToUseIsA = 1;
-			} else {
-				lp->NextRcvToUseIsA = 0;
-			}
+			lp->NextRcvBufferIndex ^= 1;
 		}
-		OUTL(OK2USE_RX_A | OK2USE_RX_B,
-		     &lp->lan_saa9730_regs->Ok2Use);
 
 		/* Address next packet */
-		if (lp->NextRcvToUseIsA)
-			BufferIndex = 0;
-		else
-			BufferIndex = 1;
+		BufferIndex = lp->NextRcvBufferIndex;
 		PacketIndex = lp->NextRcvPacketIndex;
-		pPacket =
-		    (unsigned int *) lp->
-		    RcvBuffer[BufferIndex][PacketIndex];
+		pPacket = lp->RcvBuffer[BufferIndex][PacketIndex];
 		rx_status = le32_to_cpu(*pPacket);
 	}
 
-	/* Make sure A and B are available to hardware. */
-	OUTL(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
-
 	return 0;
 }
 
@@ -767,8 +749,7 @@
 				  struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 
 	if (lan_saa9730_debug > 5)
 		printk("lan_saa9730_interrupt\n");
@@ -780,11 +761,11 @@
 	evm_saa9730_clear_lan_int(lp);
 
 	/* Service pending transmit interrupts. */
-	if (INL(&lp->lan_saa9730_regs->DmaStatus) & DMA_STATUS_MAC_TX_INT)
+	if (readl(&lp->lan_saa9730_regs->DmaStatus) & DMA_STATUS_MAC_TX_INT)
 		lan_saa9730_tx(dev);
 
 	/* Service pending receive interrupts. */
-	if (INL(&lp->lan_saa9730_regs->DmaStatus) &
+	if (readl(&lp->lan_saa9730_regs->DmaStatus) &
 	    (DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
 	     DMA_STATUS_RX_TO_INT)) lan_saa9730_rx(dev);
 
@@ -794,15 +775,9 @@
 	return IRQ_HANDLED;
 }
 
-static int lan_saa9730_open_fail(struct net_device *dev)
-{
-	return -ENODEV;
-}
-
 static int lan_saa9730_open(struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 
 	/* Associate IRQ with lan_saa9730_interrupt */
 	if (request_irq(dev->irq, &lan_saa9730_interrupt, 0, "SAA9730 Eth",
@@ -834,15 +809,13 @@
 	int PacketIndex;
 
 	if (lan_saa9730_debug > 5)
-		printk("lan_saa9730_write: skb=%08x\n",
-		       (unsigned int) skb);
+		printk("lan_saa9730_write: skb=%p\n", skb);
 
 	BufferIndex = lp->NextTxmBufferIndex;
 	PacketIndex = lp->NextTxmPacketIndex;
 
-	tx_status =
-	    le32_to_cpu(*(unsigned int *) lp->
-			TxmBuffer[BufferIndex][PacketIndex]);
+	tx_status = le32_to_cpu(*(unsigned int *)lp->TxmBuffer[BufferIndex]
+							      [PacketIndex]);
 	if ((tx_status & TX_STAT_CTL_OWNER_MSK) !=
 	    (TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF)) {
 		if (lan_saa9730_debug > 4)
@@ -858,29 +831,29 @@
 		lp->NextTxmBufferIndex ^= 1;
 	}
 
-	pbPacketData =
-	    (unsigned char *) lp->TxmBuffer[BufferIndex][PacketIndex];
+	pbPacketData = lp->TxmBuffer[BufferIndex][PacketIndex];
 	pbPacketData += 4;
 
 	/* copy the bits */
 	memcpy(pbPacketData, pbData, len);
 
 	/* Set transmit status for hardware */
-	*(unsigned int *) lp->TxmBuffer[BufferIndex][PacketIndex] =
-	    cpu_to_le32((TXSF_READY << TX_STAT_CTL_OWNER_SHF) |
-			(TX_STAT_CTL_INT_AFTER_TX << TX_STAT_CTL_FRAME_SHF)
-			| (len << TX_STAT_CTL_LENGTH_SHF));
+	*(unsigned int *)lp->TxmBuffer[BufferIndex][PacketIndex] =
+		cpu_to_le32((TXSF_READY << TX_STAT_CTL_OWNER_SHF) |
+			    (TX_STAT_CTL_INT_AFTER_TX <<
+			     TX_STAT_CTL_FRAME_SHF) |
+			    (len << TX_STAT_CTL_LENGTH_SHF));
 
-	/* Set hardware tx buffer. */
-	OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use);
+	/* Make sure A or B is available to hardware as appropriate. */
+	outl(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A,
+	     &lp->lan_saa9730_regs->Ok2Use);
 
 	return 0;
 }
 
 static void lan_saa9730_tx_timeout(struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 
 	/* Transmitter timeout, serious problems */
 	lp->stats.tx_errors++;
@@ -889,20 +862,19 @@
 	lan_saa9730_restart(lp);
 
 	dev->trans_start = jiffies;
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 }
 
 static int lan_saa9730_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 	unsigned long flags;
 	int skblen;
 	int len;
 
 	if (lan_saa9730_debug > 4)
-		printk("Send packet: skb=%08x\n", (unsigned int) skb);
+		printk("Send packet: skb=%p\n", skb);
 
 	skblen = skb->len;
 
@@ -912,8 +884,7 @@
 
 	if (lan_saa9730_write(lp, skb, skblen)) {
 		spin_unlock_irqrestore(&lp->lock, flags);
-		printk("Error when writing packet to controller: skb=%08x\n",
-		     (unsigned int) skb);
+		printk("Error when writing packet to controller: skb=%p\n", skb);
 		netif_stop_queue(dev);
 		return -1;
 	}
@@ -922,7 +893,7 @@
 	lp->stats.tx_packets++;
 
 	dev->trans_start = jiffies;
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 	dev_kfree_skb(skb);
 
 	spin_unlock_irqrestore(&lp->lock, flags);
@@ -932,8 +903,7 @@
 
 static int lan_saa9730_close(struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 
 	if (lan_saa9730_debug > 1)
 		printk("lan_saa9730_close:\n");
@@ -955,33 +925,31 @@
 static struct net_device_stats *lan_saa9730_get_stats(struct net_device
 						      *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 
 	return &lp->stats;
 }
 
 static void lan_saa9730_set_multicast(struct net_device *dev)
 {
-	struct lan_saa9730_private *lp =
-	    (struct lan_saa9730_private *) dev->priv;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 
 	/* Stop the controller */
 	lan_saa9730_stop(lp);
 
 	if (dev->flags & IFF_PROMISC) {
 		/* accept all packets */
-		OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC |
+		outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC |
 		     CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC,
 		     &lp->lan_saa9730_regs->CamCtl);
 	} else {
 		if (dev->flags & IFF_ALLMULTI) {
 			/* accept all multicast packets */
-			OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC |
+			outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC |
 			     CAM_CONTROL_BROAD_ACC,
 			     &lp->lan_saa9730_regs->CamCtl);
 		} else {
-			/* 
+			/*
 			 * Will handle the multicast stuff later. -carstenl
 			 */
 		}
@@ -993,91 +961,86 @@
 
 static void __devexit saa9730_remove_one(struct pci_dev *pdev)
 {
-        struct net_device *dev = pci_get_drvdata(pdev);
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 
-        if (dev) {
-                unregister_netdev(dev);
-		kfree(dev->priv);
-                free_netdev(dev);
-                pci_release_regions(pdev);
-                pci_disable_device(pdev);
-                pci_set_drvdata(pdev, NULL);
-        }
+	if (dev) {
+		unregister_netdev(dev);
+		lan_saa9730_free_buffers(pdev, lp);
+		iounmap(lp->lan_saa9730_regs);
+		iounmap(lp->evm_saa9730_regs);
+		free_netdev(dev);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		pci_set_drvdata(pdev, NULL);
+	}
 }
 
 
-static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq)
+static int lan_saa9730_init(struct net_device *dev, struct pci_dev *pdev,
+	unsigned long ioaddr, int irq)
 {
-	struct lan_saa9730_private *lp;
+	struct lan_saa9730_private *lp = netdev_priv(dev);
 	unsigned char ethernet_addr[6];
-	int ret = 0;
+	int ret;
 
-	dev->open = lan_saa9730_open_fail;
+	if (get_ethernet_addr(ethernet_addr)) {
+		ret = -ENODEV;
+		goto out;
+	}
 
-	if (get_ethernet_addr(ethernet_addr))
-		return -ENODEV;
-	
 	memcpy(dev->dev_addr, ethernet_addr, 6);
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
-	
-	/* 
-	 * Make certain the data structures used by the controller are aligned 
-	 * and DMAble. 
-	 */
-	/*
-	 *  XXX: that is obviously broken - kfree() won't be happy with us.
-	 */
-	lp = (struct lan_saa9730_private *) (((unsigned long)
-					      kmalloc(sizeof(*lp) + 7,
-						      GFP_DMA | GFP_KERNEL)
-					      + 7) & ~7);
 
-	if (!lp)
-		return -ENOMEM;
-
-	dev->priv = lp;
-	memset(lp, 0, sizeof(*lp));
+	lp->pci_dev = pdev;
 
 	/* Set SAA9730 LAN base address. */
-	lp->lan_saa9730_regs = (t_lan_saa9730_regmap *) (ioaddr +
-							 SAA9730_LAN_REGS_ADDR);
+	lp->lan_saa9730_regs = ioremap(ioaddr + SAA9730_LAN_REGS_ADDR,
+				       SAA9730_LAN_REGS_SIZE);
+	if (!lp->lan_saa9730_regs) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 	/* Set SAA9730 EVM base address. */
-	lp->evm_saa9730_regs = (t_evm_saa9730_regmap *) (ioaddr +
-							 SAA9730_EVM_REGS_ADDR);
+	lp->evm_saa9730_regs = ioremap(ioaddr + SAA9730_EVM_REGS_ADDR,
+				       SAA9730_EVM_REGS_SIZE);
+	if (!lp->evm_saa9730_regs) {
+		ret = -ENOMEM;
+		goto out_iounmap_lan;
+	}
 
 	/* Allocate LAN RX/TX frame buffer space. */
-	/* FIXME: a leak */
-	if ((ret = lan_saa9730_allocate_buffers(lp)))
-		goto out;
+	if ((ret = lan_saa9730_allocate_buffers(pdev, lp)))
+		goto out_iounmap;
 
 	/* Stop LAN controller. */
-	if ((ret = lan_saa9730_stop(lp))) 
-		goto out;
-	
+	if ((ret = lan_saa9730_stop(lp)))
+		goto out_free_consistent;
+
 	/* Initialize CAM registers. */
 	if ((ret = lan_saa9730_cam_init(dev)))
-		goto out;
+		goto out_free_consistent;
 
 	/* Initialize MII registers. */
 	if ((ret = lan_saa9730_mii_init(lp)))
-		goto out;
+		goto out_free_consistent;
 
 	/* Initialize control registers. */
-	if ((ret = lan_saa9730_control_init(lp))) 
-		goto out;
-        
+	if ((ret = lan_saa9730_control_init(lp)))
+		goto out_free_consistent;
+
 	/* Load CAM registers. */
-	if ((ret = lan_saa9730_cam_load(lp))) 
-		goto out;
-	
+	if ((ret = lan_saa9730_cam_load(lp)))
+		goto out_free_consistent;
+
 	/* Initialize DMA context registers. */
 	if ((ret = lan_saa9730_dma_init(lp)))
-		goto out;
-	
+		goto out_free_consistent;
+
 	spin_lock_init(&lp->lock);
-		
+
 	dev->open = lan_saa9730_open;
 	dev->hard_start_xmit = lan_saa9730_start_xmit;
 	dev->stop = lan_saa9730_close;
@@ -1086,44 +1049,43 @@
 	dev->tx_timeout = lan_saa9730_tx_timeout;
 	dev->watchdog_timeo = (HZ >> 1);
 	dev->dma = 0;
-	
-	ret = register_netdev(dev);
+
+	ret = register_netdev (dev);
 	if (ret)
-		goto out;
+		goto out_free_consistent;
+
 	return 0;
 
- out:
-	kfree(dev->priv);
+out_free_consistent:
+	lan_saa9730_free_buffers(pdev, lp);
+out_iounmap:
+	iounmap(lp->evm_saa9730_regs);
+out_iounmap_lan:
+	iounmap(lp->lan_saa9730_regs);
+out:
 	return ret;
 }
 
 
 static int __devinit saa9730_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	struct net_device *dev;
-	unsigned int pci_ioaddr;
+	struct net_device *dev = NULL;
+	unsigned long pci_ioaddr;
 	int err;
 
 	if (lan_saa9730_debug > 1)
 		printk("saa9730.c: PCI bios is present, checking for devices...\n");
 
-	err = -ENOMEM;
-	dev = alloc_etherdev(0);
-	if (!dev)
-		goto out;
-
-	SET_MODULE_OWNER(dev);
-
 	err = pci_enable_device(pdev);
-        if (err) {
-                printk(KERN_ERR "Cannot enable PCI device, aborting.\n");
-                goto out1;
-        }
+	if (err) {
+		printk(KERN_ERR "Cannot enable PCI device, aborting.\n");
+		goto out;
+	}
 
 	err = pci_request_regions(pdev, DRV_MODULE_NAME);
 	if (err) {
 		printk(KERN_ERR "Cannot obtain PCI resources, aborting.\n");
-		goto out2;
+		goto out_disable_pdev;
 	}
 
 	pci_irq_line = pdev->irq;
@@ -1132,49 +1094,54 @@
 	pci_ioaddr = pci_resource_start(pdev, 1);
 	pci_set_master(pdev);
 
-	printk("Found SAA9730 (PCI) at %#x, irq %d.\n",
+	printk("Found SAA9730 (PCI) at %lx, irq %d.\n",
 	       pci_ioaddr, pci_irq_line);
 
-	err = lan_saa9730_init(dev, pci_ioaddr, pci_irq_line);
+	dev = alloc_etherdev(sizeof(struct lan_saa9730_private));
+	if (!dev)
+		goto out_disable_pdev;
+
+	err = lan_saa9730_init(dev, pdev, pci_ioaddr, pci_irq_line);
 	if (err) {
-		printk("Lan init failed");
-		goto out2;
+		printk("LAN init failed");
+		goto out_free_netdev;
 	}
 
 	pci_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	return 0;
-	
-out2:
-	pci_disable_device(pdev);
-out1:
+
+out_free_netdev:
 	free_netdev(dev);
+out_disable_pdev:
+	pci_disable_device(pdev);
 out:
+	pci_set_drvdata(pdev, NULL);
 	return err;
 }
 
 
 static struct pci_driver saa9730_driver = {
-	.name           = DRV_MODULE_NAME,
-	.id_table       = saa9730_pci_tbl,
-	.probe          = saa9730_init_one,
-	.remove         = __devexit_p(saa9730_remove_one),
+	.name		= DRV_MODULE_NAME,
+	.id_table	= saa9730_pci_tbl,
+	.probe		= saa9730_init_one,
+	.remove		= __devexit_p(saa9730_remove_one),
 };
 
 
 static int __init saa9730_init(void)
 {
-        return pci_module_init(&saa9730_driver);
+	return pci_module_init(&saa9730_driver);
 }
 
 static void __exit saa9730_cleanup(void)
 {
-        pci_unregister_driver(&saa9730_driver);
+	pci_unregister_driver(&saa9730_driver);
 }
 
 module_init(saa9730_init);
 module_exit(saa9730_cleanup);
 
-
-
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_DESCRIPTION("Philips SAA9730 ethernet driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 817f200..a10cd18 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -289,6 +289,38 @@
 #define RPC_LSA_DEFAULT		RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT		RPC_LED_100_10
 
+#elif defined(CONFIG_SOC_AU1X00)
+
+#include <au1xxx.h>
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+#define SMC_IO_SHIFT		0
+#define SMC_NOWAIT		1
+
+#define SMC_inw(a, r)		au_readw((unsigned long)((a) + (r)))
+#define SMC_insw(a, r, p, l)	\
+	do {	\
+		unsigned long _a = (unsigned long)((a) + (r)); \
+		int _l = (l); \
+		u16 *_p = (u16 *)(p); \
+		while (_l-- > 0) \
+			*_p++ = au_readw(_a); \
+	} while(0)
+#define SMC_outw(v, a, r)	au_writew(v, (unsigned long)((a) + (r)))
+#define SMC_outsw(a, r, p, l)	\
+	do {	\
+		unsigned long _a = (unsigned long)((a) + (r)); \
+		int _l = (l); \
+		const u16 *_p = (const u16 *)(p); \
+		while (_l-- > 0) \
+			au_writew(*_p++ , _a); \
+	} while(0)
+
+#define set_irq_type(irq, type) do {} while (0)
+
 #else
 
 #define SMC_CAN_USE_8BIT	1
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 7187958..00e5516 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -330,7 +330,7 @@
 
 config ATMEL
       tristate "Atmel at76c50x chipset  802.11b support"
-      depends on NET_RADIO && EXPERIMENTAL
+      depends on NET_RADIO
       select FW_LOADER
       select CRC32
        ---help---
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index a3e2352..5e53c52 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -72,7 +72,7 @@
 #include "atmel.h"
 
 #define DRIVER_MAJOR 0
-#define DRIVER_MINOR 96
+#define DRIVER_MINOR 98
 
 MODULE_AUTHOR("Simon Kelley");
 MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
@@ -1504,7 +1504,7 @@
         return len;
 }
 
-struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWType fw_type,  
+struct net_device *init_atmel_card( unsigned short irq, unsigned long port, const AtmelFWType fw_type,  
 				    struct device *sys_dev, int (*card_present)(void *), void *card)
 {
 	struct net_device *dev;
@@ -1605,8 +1605,8 @@
 		goto err_out_free;
 	}
 
-	if (priv->bus_type == BUS_TYPE_PCI &&
-	    !request_region( dev->base_addr, 64, dev->name )) {
+	if (!request_region(dev->base_addr, 32, 
+			    priv->bus_type == BUS_TYPE_PCCARD ?  "atmel_cs" : "atmel_pci")) {
 		goto err_out_irq;
 	}
 	
@@ -1622,15 +1622,16 @@
 	
 	create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);	
 	
-	printk(KERN_INFO "%s: Atmel at76c50x wireless. Version %d.%d simon@thekelleys.org.uk\n",
-	       dev->name, DRIVER_MAJOR, DRIVER_MINOR);
+	printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+	       dev->name, DRIVER_MAJOR, DRIVER_MINOR,
+	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
 	
 	SET_MODULE_OWNER(dev);
 	return dev;
 	
  err_out_res:
-	if (priv->bus_type == BUS_TYPE_PCI)
-	        release_region( dev->base_addr, 64 );
+	release_region( dev->base_addr, 32);
  err_out_irq:
 	free_irq(dev->irq, dev);
  err_out_free:
@@ -1640,7 +1641,7 @@
 
 EXPORT_SYMBOL(init_atmel_card);
 
-void stop_atmel_card(struct net_device *dev, int freeres)
+void stop_atmel_card(struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
 		
@@ -1654,10 +1655,7 @@
 	remove_proc_entry("driver/atmel", NULL);
 	free_irq(dev->irq, dev);
 	kfree(priv->firmware);
-	if (freeres) {
-		/* PCMCIA frees this stuff, so only for PCI */
-	        release_region(dev->base_addr, 64);
-        }
+	release_region(dev->base_addr, 32);
 	free_netdev(dev);
 }
 
@@ -1810,9 +1808,9 @@
 	}
 	if(dwrq->flags & IW_ENCODE_RESTRICTED)
 		priv->exclude_unencrypted = 1;
-	if(dwrq->flags & IW_ENCODE_OPEN)
+       	if(dwrq->flags & IW_ENCODE_OPEN) 
 		priv->exclude_unencrypted = 0;
-	
+       
 	return -EINPROGRESS;		/* Call commit handler */
 }
 
@@ -1827,11 +1825,12 @@
 	
 	if (!priv->wep_is_on)
 		dwrq->flags = IW_ENCODE_DISABLED;
-	else if (priv->exclude_unencrypted)
-		dwrq->flags = IW_ENCODE_RESTRICTED;
-	else
-		dwrq->flags = IW_ENCODE_OPEN;
-		
+	else {
+		if (priv->exclude_unencrypted)
+			dwrq->flags = IW_ENCODE_RESTRICTED;
+		else
+			dwrq->flags = IW_ENCODE_OPEN;
+	}
 		/* Which key do we want ? -1 -> tx index */
 	if (index < 0 || index >= 4)
 		index = priv->default_key;
@@ -2645,8 +2644,8 @@
 	} 
 }
 
- 
-static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
+
+static void send_authentication_request(struct atmel_private *priv, u16 system, u8 *challenge, int challenge_len)
 {
 	struct ieee80211_hdr_4addr header;
 	struct auth_body auth;
@@ -2658,14 +2657,11 @@
 	memcpy(header.addr2, priv->dev->dev_addr, 6);
 	memcpy(header.addr3, priv->CurrentBSSID, 6);
 	
-	if (priv->wep_is_on) {
-		auth.alg = cpu_to_le16(C80211_MGMT_AAN_SHAREDKEY); 
+	if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) 
 		/* no WEP for authentication frames with TrSeqNo 1 */
-		if (priv->CurrentAuthentTransactionSeqNum != 1)
-			header.frame_ctl |=  cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-	} else {
-		auth.alg = cpu_to_le16(C80211_MGMT_AAN_OPENSYSTEM);
-	}
+                header.frame_ctl |=  cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+	
+	auth.alg = cpu_to_le16(system); 
 
 	auth.status = 0;
 	auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
@@ -2834,6 +2830,7 @@
 	struct auth_body *auth = (struct auth_body *)priv->rx_buf;
 	u16 status = le16_to_cpu(auth->status);
 	u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
+	u16 system = le16_to_cpu(auth->alg);
 	
 	if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) { 
 		/* no WEP */
@@ -2855,7 +2852,7 @@
 				
 		if (trans_seq_no == 0x0002 &&
 		    auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
-			send_authentication_request(priv, auth->chall_text, auth->chall_text_len);
+			send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
 			return;
 		}
 		
@@ -2872,14 +2869,20 @@
 		}
 	}			
 	
-	if (status == C80211_MGMT_SC_AuthAlgNotSupported && priv->connect_to_any_BSS) {
-		int bss_index;
-		
-		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
-		
-		if ((bss_index  = retrieve_bss(priv)) != -1) {
-			atmel_join_bss(priv, bss_index);
-			return;
+	if (status == C80211_MGMT_SC_AuthAlgNotSupported) {
+		/* Do opensystem first, then try sharedkey */
+		if (system ==  C80211_MGMT_AAN_OPENSYSTEM) {
+			priv->CurrentAuthentTransactionSeqNum = 0x001;
+			send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
+		} else if (priv->connect_to_any_BSS) {
+			int bss_index;
+			
+			priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
+			
+			if ((bss_index  = retrieve_bss(priv)) != -1) {
+				atmel_join_bss(priv, bss_index);
+				return;
+			}
 		}
 	}
 	
@@ -3205,7 +3208,7 @@
 		  priv->AuthenticationRequestRetryCnt++;
 		  priv->CurrentAuthentTransactionSeqNum = 0x0001;
 		  mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
-		  send_authentication_request(priv, NULL, 0);
+		  send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
 	  }
 	  
 	  break;
@@ -3312,7 +3315,7 @@
 				
 				mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
 				priv->CurrentAuthentTransactionSeqNum = 0x0001;
-				send_authentication_request(priv, NULL, 0);
+				send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
 			}
 			return;
 		}
@@ -3482,11 +3485,6 @@
 			printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
 			memcpy(dev->dev_addr, default_mac, 6);
 		}
-		printk(KERN_INFO "%s: MAC address %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-		       dev->name,
-		       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-		       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
-		
 	}
 	
 	return rc;
diff --git a/drivers/net/wireless/atmel.h b/drivers/net/wireless/atmel.h
index 825000e..b9b3e5b 100644
--- a/drivers/net/wireless/atmel.h
+++ b/drivers/net/wireless/atmel.h
@@ -35,9 +35,9 @@
 	ATMEL_FW_TYPE_506
 } AtmelFWType;
 
-struct net_device *init_atmel_card(unsigned short, int, const AtmelFWType, struct device *, 
+struct net_device *init_atmel_card(unsigned short, unsigned long, const AtmelFWType, struct device *, 
 				    int (*present_func)(void *), void * );
-void stop_atmel_card( struct net_device *, int );
+void stop_atmel_card( struct net_device *);
 int atmel_open( struct net_device * );
 
 #endif
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 1bd1314..17d1fd9 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -63,6 +63,7 @@
    be present but disabled -- but it can then be enabled for specific
    modules at load time with a 'pc_debug=#' option to insmod.
 */
+
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
 module_param(pc_debug, int, 0);
@@ -285,41 +286,6 @@
 	return 0;
 }
 
-/* list of cards we know about and their firmware requirements.
-   Go either by Manfid or version strings.
-   Cards not in this list will need a firmware parameter to the module
-   in all probability. Note that the SMC 2632 V2 and V3 have the same
-   manfids, so we ignore those and use the version1 strings. */
-
-static struct { 
-	int manf, card;
-	char *ver1;
-	AtmelFWType firmware;
-	char *name;
-} card_table[] = {
-	{ 0, 0, "WLAN/802.11b PC CARD", ATMEL_FW_TYPE_502D, "Actiontec 802CAT1" },  
-	{ 0, 0, "ATMEL/AT76C502AR", ATMEL_FW_TYPE_502, "NoName-RFMD" }, 
-	{ 0, 0, "ATMEL/AT76C502AR_D", ATMEL_FW_TYPE_502D, "NoName-revD" }, 
-	{ 0, 0, "ATMEL/AT76C502AR_E", ATMEL_FW_TYPE_502E, "NoName-revE" },
-	{ 0, 0, "ATMEL/AT76C504", ATMEL_FW_TYPE_504, "NoName-504" },
-	{ 0, 0, "ATMEL/AT76C504A", ATMEL_FW_TYPE_504A_2958, "NoName-504a-2958" },
-	{ 0, 0, "ATMEL/AT76C504_R", ATMEL_FW_TYPE_504_2958, "NoName-504-2958" },
-	{ MANFID_3COM, 0x0620, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRWE62092B" }, 
-	{ MANFID_3COM, 0x0696, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRSHPW196" }, 
-	{ 0, 0, "SMC/2632W-V2", ATMEL_FW_TYPE_502, "SMC 2632W-V2" },
-	{ 0, 0, "SMC/2632W", ATMEL_FW_TYPE_502D, "SMC 2632W-V3" },
-	{ 0xd601, 0x0007, NULL, ATMEL_FW_TYPE_502, "Sitecom WLAN-011" }, 
-	{ 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" }, 
-	{ 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" },
-	{ 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" },
-	{ 0, 0, "IEEE 802.11b/Wireless LAN Card S", ATMEL_FW_TYPE_504_2958, "Siemens Gigaset PC Card II" },
-	{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" },
-	{ 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" },
-	{ 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" },
-	{ 0, 0, "11WAVE/11WP611AL-E", ATMEL_FW_TYPE_502E, "11WAVE WaveBuddy" },
-	{ 0, 0, "LG/LW2100N", ATMEL_FW_TYPE_502E, "LG LW2100N 11Mbps WLAN PCMCIA Card" },
-};
-
 static void atmel_config(dev_link_t *link)
 {
 	client_handle_t handle;
@@ -328,10 +294,11 @@
 	local_info_t *dev;
 	int last_fn, last_ret;
 	u_char buf[64];
-	int card_index = -1, done = 0;
-	
+	struct pcmcia_device_id *did;
+
 	handle = link->handle;
 	dev = link->priv;
+	did = handle_to_dev(handle).driver_data;
 
 	DEBUG(0, "atmel_config(0x%p)\n", link);
 	
@@ -340,59 +307,6 @@
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
 	
-	tuple.DesiredTuple = CISTPL_MANFID;
-	if (pcmcia_get_first_tuple(handle, &tuple) == 0) {
-		int i;
-		cistpl_manfid_t *manfid;
-		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-		CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
-		manfid = &(parse.manfid);
-		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
-			if (!card_table[i].ver1 &&
-			    manfid->manf == card_table[i].manf &&
-			    manfid->card == card_table[i].card) {
-				card_index = i;
-				done = 1;
-			}
-		}
-	}
-
-	tuple.DesiredTuple = CISTPL_VERS_1;
-	if (!done && (pcmcia_get_first_tuple(handle, &tuple) == 0)) {
-		int i, j, k;
-		cistpl_vers_1_t *ver1;
-		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-		CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
-		ver1 = &(parse.version_1);
-		
-		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
-			for (j = 0; j < ver1->ns; j++) {
-				char *p = card_table[i].ver1;
-				char *q = &ver1->str[ver1->ofs[j]];
-				if (!p)
-					goto mismatch;
-				for (k = 0; k < j; k++) {
-					while ((*p != '\0') && (*p != '/')) p++;
-					if (*p == '\0') {
-						if (*q != '\0')
-							goto mismatch;
-					} else {
-						p++;
-					}
-				}
-				while((*q != '\0') && (*p != '\0') && 
-				      (*p != '/') && (*p == *q)) p++, q++;
-				if (((*p != '\0') && *p != '/') || *q != '\0')
-					goto mismatch;
-			}
-			card_index = i;
-			break;	/* done */
-			
-		mismatch:
-			j = 0; /* dummy stmt to shut up compiler */
-		}
-	}		
-
 	/*
 	  This reads the card's CONFIG tuple to find its configuration
 	  registers.
@@ -509,12 +423,13 @@
 	((local_info_t*)link->priv)->eth_dev = 
 		init_atmel_card(link->irq.AssignedIRQ,
 				link->io.BasePort1,
-				card_index == -1 ? ATMEL_FW_TYPE_NONE :  card_table[card_index].firmware,
+				did ? did->driver_info : ATMEL_FW_TYPE_NONE,
 				&handle_to_dev(handle),
 				card_present, 
 				link);
 	if (!((local_info_t*)link->priv)->eth_dev) 
-		goto cs_failed;
+			goto cs_failed;
+	
 	
 	/*
 	  At this point, the dev_node_t structure(s) need to be
@@ -523,26 +438,7 @@
 	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
 	dev->node.major = dev->node.minor = 0;
 	link->dev = &dev->node;
-	
-	/* Finally, report what we've done */
-	printk(KERN_INFO "%s: %s%sindex 0x%02x: Vcc %d.%d",
-	       dev->node.dev_name,
-	       card_index == -1 ? "" :  card_table[card_index].name,
-	       card_index == -1 ? "" : " ",
-	       link->conf.ConfigIndex,
-	       link->conf.Vcc/10, link->conf.Vcc%10);
-	if (link->conf.Vpp1)
-		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq.AssignedIRQ);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1+link->io.NumPorts1-1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2+link->io.NumPorts2-1);
-	printk("\n");
-	
+			
 	link->state &= ~DEV_CONFIG_PENDING;
 	return;
 	
@@ -569,7 +465,7 @@
 	link->dev = NULL;
 	
 	if (dev) 
-		stop_atmel_card(dev, 0);
+		stop_atmel_card(dev);
 	((local_info_t*)link->priv)->eth_dev = NULL; 
 	
 	/* Don't bother checking to see if these succeed or not */
@@ -637,25 +533,47 @@
 } /* atmel_event */
 
 /*====================================================================*/
+/* We use the driver_info field to store the correct firmware type for a card. */
+
+#define PCMCIA_DEVICE_MANF_CARD_INFO(manf, card, info) { \
+	.match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \
+			PCMCIA_DEV_ID_MATCH_CARD_ID, \
+	.manf_id = (manf), \
+	.card_id = (card), \
+        .driver_info = (kernel_ulong_t)(info), }
+
+#define PCMCIA_DEVICE_PROD_ID12_INFO(v1, v2, vh1, vh2, info) { \
+	.match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
+			PCMCIA_DEV_ID_MATCH_PROD_ID2, \
+	.prod_id = { (v1), (v2), NULL, NULL }, \
+	.prod_id_hash = { (vh1), (vh2), 0, 0 }, \
+        .driver_info = (kernel_ulong_t)(info), }
+
 static struct pcmcia_device_id atmel_ids[] = {
-	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0620),
-	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0696),
-	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3302),
-	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0007),
-	PCMCIA_DEVICE_PROD_ID12("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9),
-	PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f),
-	PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504", 0xabda4164, 0x5040670a),
-	PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f),
-	PCMCIA_DEVICE_PROD_ID12("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5),
-	PCMCIA_DEVICE_PROD_ID12("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b),
-	PCMCIA_DEVICE_PROD_ID12("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6),
-	PCMCIA_DEVICE_PROD_ID12("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68),
-	PCMCIA_DEVICE_PROD_ID12("SMC", "2632W", 0xc4f8b18b, 0x30f38774),
-	PCMCIA_DEVICE_PROD_ID12("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377),
-	PCMCIA_DEVICE_PROD_ID12("Wireless", "PC", 0xa407ecdd, 0x556e4d7e),
-	PCMCIA_DEVICE_PROD_ID12("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4),
+	PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM),
+	PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM),
+	PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E),
+	PCMCIA_DEVICE_MANF_CARD_INFO(0xd601, 0x0007, ATMEL_FW_TYPE_502),
+	PCMCIA_DEVICE_PROD_ID12_INFO("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9, ATMEL_FW_TYPE_502E),
+	PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f, ATMEL_FW_TYPE_502),
+	PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_D", 0xabda4164, 0x3675d704, ATMEL_FW_TYPE_502D),
+	PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_E", 0xabda4164, 0x4172e792, ATMEL_FW_TYPE_502E),
+	PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504_R", 0xabda4164, 0x917f3d72, ATMEL_FW_TYPE_504_2958),
+	PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504", 0xabda4164, 0x5040670a, ATMEL_FW_TYPE_504),
+	PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f, ATMEL_FW_TYPE_504A_2958),
+	PCMCIA_DEVICE_PROD_ID12_INFO("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5, ATMEL_FW_TYPE_502),
+	PCMCIA_DEVICE_PROD_ID12_INFO("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b, ATMEL_FW_TYPE_502E),
+	PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6, ATMEL_FW_TYPE_502),
+	PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN Card S", 0x5b878724, 0x5fba533a, ATMEL_FW_TYPE_504_2958),
+	PCMCIA_DEVICE_PROD_ID12_INFO("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68, ATMEL_FW_TYPE_502),
+	PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W", 0xc4f8b18b, 0x30f38774, ATMEL_FW_TYPE_502D),
+	PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377, ATMEL_FW_TYPE_502),
+	PCMCIA_DEVICE_PROD_ID12_INFO("Wireless", "PC_CARD", 0xa407ecdd, 0x119f6314, ATMEL_FW_TYPE_502D),
+	PCMCIA_DEVICE_PROD_ID12_INFO("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4, ATMEL_FW_TYPE_502D),
+	PCMCIA_DEVICE_PROD_ID12_INFO("LG", "LW2100N", 0xb474d43a, 0x6b1fec94, ATMEL_FW_TYPE_502E),
 	PCMCIA_DEVICE_NULL
 };
+
 MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
 
 static struct pcmcia_driver atmel_driver = {
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
index 2eb00a9..a61b3bc 100644
--- a/drivers/net/wireless/atmel_pci.c
+++ b/drivers/net/wireless/atmel_pci.c
@@ -72,7 +72,7 @@
 
 static void __devexit atmel_pci_remove(struct pci_dev *pdev)
 {
-	stop_atmel_card(pci_get_drvdata(pdev), 1);
+	stop_atmel_card(pci_get_drvdata(pdev));
 }
 
 static int __init atmel_init_module(void)
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 1c8ad2f..da8c515 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -8,7 +8,7 @@
  *    Author(s): Original Code written by
  *			  DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *		 Rewritten by
- *			  Frank Pavlic (pavlic@de.ibm.com) and
+ *			  Frank Pavlic (fpavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
  *    $Revision: 1.99 $	 $Date: 2005/05/11 08:10:17 $
@@ -2342,6 +2342,6 @@
 module_init(lcs_init_module);
 module_exit(lcs_cleanup_module);
 
-MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
+MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 38a2441..d238c7e 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -8,6 +8,7 @@
 #include <linux/trdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/ctype.h>
 
 #include <net/ipv6.h>
 #include <linux/in6.h>
@@ -24,7 +25,7 @@
 
 #include "qeth_mpc.h"
 
-#define VERSION_QETH_H 		"$Revision: 1.142 $"
+#define VERSION_QETH_H 		"$Revision: 1.152 $"
 
 #ifdef CONFIG_QETH_IPV6
 #define QETH_VERSION_IPV6 	":IPv6"
@@ -718,8 +719,6 @@
 	atomic_t refcnt;
 };
 
-#define QETH_BROADCAST_WITH_ECHO    1
-#define QETH_BROADCAST_WITHOUT_ECHO 2
 
 struct qeth_card_blkt {
 	int time_total;
@@ -727,8 +726,10 @@
 	int inter_packet_jumbo;
 };
 
-
-
+#define QETH_BROADCAST_WITH_ECHO    0x01
+#define QETH_BROADCAST_WITHOUT_ECHO 0x02
+#define QETH_LAYER2_MAC_READ	    0x01
+#define QETH_LAYER2_MAC_REGISTERED  0x02
 struct qeth_card_info {
 	unsigned short unit_addr2;
 	unsigned short cula;
@@ -736,7 +737,7 @@
 	__u16 func_level;
 	char mcl_level[QETH_MCL_LENGTH + 1];
 	int guestlan;
-	int layer2_mac_registered;
+	int mac_bits;
 	int portname_required;
 	int portno;
 	char portname[9];
@@ -749,6 +750,7 @@
 	int unique_id;
 	struct qeth_card_blkt blkt;
 	__u32 csum_mask;
+	enum qeth_ipa_promisc_modes promisc_mode;
 };
 
 struct qeth_card_options {
@@ -775,6 +777,7 @@
 enum qeth_threads {
 	QETH_SET_IP_THREAD  = 1,
 	QETH_RECOVER_THREAD = 2,
+	QETH_SET_PROMISC_MODE_THREAD = 4,
 };
 
 struct qeth_osn_info {
@@ -1074,6 +1077,26 @@
 	}
 }
 
+static inline int
+qeth_isdigit(char * buf)
+{
+	while (*buf) {
+		if (!isdigit(*buf++))
+			return 0;
+	}
+	return 1;
+}
+
+static inline int
+qeth_isxdigit(char * buf)
+{
+	while (*buf) {
+		if (!isxdigit(*buf++))
+			return 0;
+	}
+	return 1;
+}
+
 static inline void
 qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
 {
@@ -1090,18 +1113,27 @@
 	int i;
 
 	start = buf;
-	for (i = 0; i < 3; i++) {
-		if (!(end = strchr(start, '.')))
+	for (i = 0; i < 4; i++) {
+		if (i == 3) {
+			end = strchr(start,0xa);
+			if (end)
+				len = end - start;
+			else		
+				len = strlen(start);
+		}
+		else {
+			end = strchr(start, '.');
+			len = end - start;
+		}
+		if ((len <= 0) || (len > 3))
 			return -EINVAL;
-		len = end - start;
 		memset(abuf, 0, 4);
 		strncpy(abuf, start, len);
+		if (!qeth_isdigit(abuf))
+			return -EINVAL;
 		addr[i] = simple_strtoul(abuf, &tmp, 10);
 		start = end + 1;
 	}
-	memset(abuf, 0, 4);
-	strcpy(abuf, start);
-	addr[3] = simple_strtoul(abuf, &tmp, 10);
 	return 0;
 }
 
@@ -1128,18 +1160,27 @@
 
 	tmp_addr = (u16 *)addr;
 	start = buf;
-	for (i = 0; i < 7; i++) {
-		if (!(end = strchr(start, ':')))
+	for (i = 0; i < 8; i++) {
+		if (i == 7) {
+			end = strchr(start,0xa);
+			if (end)
+				len = end - start;
+			else
+				len = strlen(start);
+		}
+		else {
+			end = strchr(start, ':');
+			len = end - start;
+		}
+		if ((len <= 0) || (len > 4))
 			return -EINVAL;
-		len = end - start;
 		memset(abuf, 0, 5);
 		strncpy(abuf, start, len);
+		if (!qeth_isxdigit(abuf))
+			return -EINVAL;
 		tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
 		start = end + 1;
 	}
-	memset(abuf, 0, 5);
-	strcpy(abuf, start);
-	tmp_addr[7] = simple_strtoul(abuf, &tmp, 16);
 	return 0;
 }
 
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 692003c..99cceb2 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.242 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -9,10 +9,10 @@
  *    Author(s): Original Code written by
  *			  Utz Bacher (utz.bacher@de.ibm.com)
  *		 Rewritten by
- *			  Frank Pavlic (pavlic@de.ibm.com) and
+ *			  Frank Pavlic (fpavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.224 $	 $Date: 2005/05/04 20:19:18 $
+ *    $Revision: 1.242 $	 $Date: 2005/05/04 20:19:18 $
  *
  * 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
@@ -72,7 +72,7 @@
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.224 $"
+#define VERSION_QETH_C "$Revision: 1.242 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -160,6 +160,9 @@
 qeth_set_multicast_list(struct net_device *);
 
 static void
+qeth_setadp_promisc_mode(struct qeth_card *);
+
+static void
 qeth_notify_processes(void)
 {
 	/*notify all  registered processes */
@@ -602,11 +605,20 @@
 	int found = 0;
 
 	list_for_each_entry(addr, &card->ip_list, entry) {
+		if (card->options.layer2) {
+			if ((addr->type == todo->type) &&
+			    (memcmp(&addr->mac, &todo->mac, 
+				    OSA_ADDR_LEN) == 0)) {
+				found = 1;
+				break;
+			}
+			continue;
+		} 
 		if ((addr->proto     == QETH_PROT_IPV4)  &&
 		    (todo->proto     == QETH_PROT_IPV4)  &&
 		    (addr->type      == todo->type)      &&
 		    (addr->u.a4.addr == todo->u.a4.addr) &&
-		    (addr->u.a4.mask == todo->u.a4.mask)   ){
+		    (addr->u.a4.mask == todo->u.a4.mask)) {
 			found = 1;
 			break;
 		}
@@ -615,12 +627,12 @@
 		    (addr->type        == todo->type)         &&
 		    (addr->u.a6.pfxlen == todo->u.a6.pfxlen)  &&
 		    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
-			    sizeof(struct in6_addr)) == 0))     {
+			    sizeof(struct in6_addr)) == 0)) {
 			found = 1;
 			break;
 		}
 	}
-	if (found){
+	if (found) {
 		addr->users += todo->users;
 		if (addr->users <= 0){
 			*__addr = addr;
@@ -632,7 +644,7 @@
 			return 0;
 		}
 	}
-	if (todo->users > 0){
+	if (todo->users > 0) {
 		/* for VIPA and RXIP limit refcount to 1 */
 		if (todo->type != QETH_IP_TYPE_NORMAL)
 			todo->users = 1;
@@ -682,12 +694,22 @@
 		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
 		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
 			return 0;
+		if (card->options.layer2) {
+			if ((tmp->type	== addr->type)	&&
+			    (tmp->is_multicast == addr->is_multicast) &&
+			    (memcmp(&tmp->mac, &addr->mac, 
+				    OSA_ADDR_LEN) == 0)) {
+				found = 1;
+				break;
+			}
+			continue;
+		} 	 
 		if ((tmp->proto        == QETH_PROT_IPV4)     &&
 		    (addr->proto       == QETH_PROT_IPV4)     &&
 		    (tmp->type         == addr->type)         &&
 		    (tmp->is_multicast == addr->is_multicast) &&
 		    (tmp->u.a4.addr    == addr->u.a4.addr)    &&
-		    (tmp->u.a4.mask    == addr->u.a4.mask)      ){
+		    (tmp->u.a4.mask    == addr->u.a4.mask)) {
 			found = 1;
 			break;
 		}
@@ -697,7 +719,7 @@
 		    (tmp->is_multicast == addr->is_multicast)  &&
 		    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&
 		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
-			    sizeof(struct in6_addr)) == 0)        ){
+			    sizeof(struct in6_addr)) == 0)) {
 			found = 1;
 			break;
 		}
@@ -707,7 +729,7 @@
 			tmp->users += addr->users;
 		else
 			tmp->users += add? 1:-1;
-		if (tmp->users == 0){
+		if (tmp->users == 0) {
 			list_del(&tmp->entry);
 			kfree(tmp);
 		}
@@ -738,12 +760,15 @@
 	unsigned long flags;
 	int rc = 0;
 
-	QETH_DBF_TEXT(trace,4,"delip");
-	if (addr->proto == QETH_PROT_IPV4)
-		QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4);
+	QETH_DBF_TEXT(trace, 4, "delip");
+
+	if (card->options.layer2)
+		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+	else if (addr->proto == QETH_PROT_IPV4)
+		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
 	else {
-		QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8);
-		QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8);
+		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
 	}
 	spin_lock_irqsave(&card->ip_lock, flags);
 	rc = __qeth_insert_ip_todo(card, addr, 0);
@@ -757,12 +782,14 @@
 	unsigned long flags;
 	int rc = 0;
 
-	QETH_DBF_TEXT(trace,4,"addip");
-	if (addr->proto == QETH_PROT_IPV4)
-		QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4);
+	QETH_DBF_TEXT(trace, 4, "addip");
+	if (card->options.layer2)
+		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+	else if (addr->proto == QETH_PROT_IPV4)
+		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
 	else {
-		QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8);
-		QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8);
+		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
 	}
 	spin_lock_irqsave(&card->ip_lock, flags);
 	rc = __qeth_insert_ip_todo(card, addr, 1);
@@ -775,7 +802,7 @@
 {
 	struct qeth_ipaddr *addr, *tmp;
 	int rc;
-
+again:
 	list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
 		if (addr->is_multicast) {
 			spin_unlock_irqrestore(&card->ip_lock, *flags);
@@ -784,6 +811,7 @@
 			if (!rc) {
 				list_del(&addr->entry);
 				kfree(addr);
+				goto again;
 			}
 		}
 	}
@@ -851,6 +879,7 @@
 
 static void qeth_delete_mc_addresses(struct qeth_card *);
 static void qeth_add_multicast_ipv4(struct qeth_card *);
+static void qeth_layer2_add_multicast(struct qeth_card *);
 #ifdef CONFIG_QETH_IPV6
 static void qeth_add_multicast_ipv6(struct qeth_card *);
 #endif
@@ -939,6 +968,24 @@
 	return 0;
 }
 
+/*
+ * Drive the SET_PROMISC_MODE thread
+ */
+static int
+qeth_set_promisc_mode(void *ptr)
+{
+	struct qeth_card *card = (struct qeth_card *) ptr;
+
+	daemonize("qeth_setprm");
+	QETH_DBF_TEXT(trace,4,"setprm1");
+	if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
+		return 0;
+	QETH_DBF_TEXT(trace,4,"setprm2");
+	qeth_setadp_promisc_mode(card);
+	qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
+	return 0;
+}
+
 static int
 qeth_recover(void *ptr)
 {
@@ -1005,6 +1052,8 @@
 
 	if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
 		kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
+	if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
+		kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
 	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
 		kernel_thread(qeth_recover, (void *) card, SIGCHLD);
 }
@@ -3749,7 +3798,7 @@
 
 	if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
 	     (card->options.layer2) &&
-	     (!card->info.layer2_mac_registered)) {
+	     (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
 		QETH_DBF_TEXT(trace,4,"nomacadr");
 		return -EPERM;
 	}
@@ -4311,6 +4360,8 @@
 out:
 	if (flush_count)
 		qeth_flush_buffers(queue, 0, start_index, flush_count);
+	else if (!atomic_read(&queue->set_pci_flags_count))
+		atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
 	/*
 	 * queue->state will go from LOCKED -> UNLOCKED or from
 	 * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
@@ -4975,6 +5026,10 @@
 			    unsigned long);
 
 static int
+qeth_default_setadapterparms_cb(struct qeth_card *card,
+                                struct qeth_reply *reply,
+                                unsigned long data);
+static int
 qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
 		      __u16, long,
 		      int (*reply_cb)
@@ -5301,8 +5356,7 @@
 	struct qeth_ipaddr *addr;
 
 	QETH_DBF_TEXT(trace, 4, "frvaddr4");
-	if (!card->vlangrp)
-		return;
+
 	rcu_read_lock();
 	in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
 	if (!in_dev)
@@ -5330,8 +5384,7 @@
 	struct qeth_ipaddr *addr;
 
 	QETH_DBF_TEXT(trace, 4, "frvaddr6");
-	if (!card->vlangrp)
-		return;
+
 	in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
 	if (!in6_dev)
 		return;
@@ -5351,10 +5404,38 @@
 }
 
 static void
+qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
+{
+	if (card->options.layer2 || !card->vlangrp)
+		return;
+	qeth_free_vlan_addresses4(card, vid);
+	qeth_free_vlan_addresses6(card, vid);
+}
+
+static int
+qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
+                               struct qeth_reply *reply,
+                               unsigned long data)
+{
+        struct qeth_ipa_cmd *cmd;
+
+        QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+        cmd = (struct qeth_ipa_cmd *) data;
+        if (cmd->hdr.return_code) {
+		PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+			  "Continuing\n",cmd->data.setdelvlan.vlan_id, 
+			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
+		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+	}
+        return 0;
+}
+
+static int
 qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
 			    enum qeth_ipa_cmds ipacmd)
 {
- 	int rc;
 	struct qeth_ipa_cmd *cmd;
 	struct qeth_cmd_buffer *iob;
 
@@ -5362,15 +5443,8 @@
 	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
 	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
         cmd->data.setdelvlan.vlan_id = i;
-
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-        if (rc) {
-                PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
-			  "Continuing\n",i, QETH_CARD_IFNAME(card), rc);
-		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd);
-		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
-		QETH_DBF_TEXT_(trace, 2, "err%d", rc);
-        }
+	return qeth_send_ipa_cmd(card, iob, 
+				 qeth_layer2_send_setdelvlan_cb, NULL);
 }
 
 static void
@@ -5420,8 +5494,7 @@
 	qeth_free_vlan_skbs(card, vid);
 	spin_lock_irqsave(&card->vlanlock, flags);
 	/* unregister IP addresses of vlan device */
-	qeth_free_vlan_addresses4(card, vid);
-	qeth_free_vlan_addresses6(card, vid);
+	qeth_free_vlan_addresses(card, vid);
 	if (card->vlangrp)
 		card->vlangrp->vlan_devices[vid] = NULL;
 	spin_unlock_irqrestore(&card->vlanlock, flags);
@@ -5430,6 +5503,59 @@
 	qeth_set_multicast_list(card->dev);
 }
 #endif
+/**
+ * Examine hardware response to SET_PROMISC_MODE
+ */
+static int
+qeth_setadp_promisc_mode_cb(struct qeth_card *card, 
+			    struct qeth_reply *reply,
+			    unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_ipacmd_setadpparms *setparms;
+
+	QETH_DBF_TEXT(trace,4,"prmadpcb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	setparms = &(cmd->data.setadapterparms);
+	
+        qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+	if (cmd->hdr.return_code) { 
+		QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);	
+		setparms->data.mode = SET_PROMISC_MODE_OFF;
+	}
+	card->info.promisc_mode = setparms->data.mode;
+	return 0;
+}
+/*
+ * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
+ */
+static void
+qeth_setadp_promisc_mode(struct qeth_card *card)
+{
+	enum qeth_ipa_promisc_modes mode;
+	struct net_device *dev = card->dev;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "setprom");
+
+	if (((dev->flags & IFF_PROMISC) &&
+	     (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
+	    (!(dev->flags & IFF_PROMISC) &&
+	     (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
+		return;
+	mode = SET_PROMISC_MODE_OFF;
+	if (dev->flags & IFF_PROMISC)
+		mode = SET_PROMISC_MODE_ON;
+	QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
+
+	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
+			sizeof(struct qeth_ipacmd_setadpparms));
+	cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+	cmd->data.setadapterparms.data.mode = mode;
+	qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
+}
 
 /**
  * set multicast address on card
@@ -5444,12 +5570,22 @@
 	 
 	QETH_DBF_TEXT(trace,3,"setmulti");
 	qeth_delete_mc_addresses(card);
+	if (card->options.layer2) {
+		qeth_layer2_add_multicast(card);
+		goto out;
+	}
 	qeth_add_multicast_ipv4(card);
 #ifdef CONFIG_QETH_IPV6
 	qeth_add_multicast_ipv6(card);
 #endif
+out:
  	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
 		schedule_work(&card->kernel_thread_starter);
+	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+		return;
+	if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
+		schedule_work(&card->kernel_thread_starter);
+
 }
 
 static int
@@ -5657,6 +5793,24 @@
 	in_dev_put(in4_dev);
 }
 
+static void
+qeth_layer2_add_multicast(struct qeth_card *card)
+{
+	struct qeth_ipaddr *ipm;
+	struct dev_mc_list *dm;
+
+	QETH_DBF_TEXT(trace,4,"L2addmc");
+	for (dm = card->dev->mc_list; dm; dm = dm->next) {
+		ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
+		if (!ipm)
+			continue;
+		memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
+		ipm->is_multicast = 1;
+		if (!qeth_add_ip(card, ipm))
+			kfree(ipm);
+	}
+}
+
 #ifdef CONFIG_QETH_IPV6
 static inline void
 qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
@@ -5825,10 +5979,10 @@
 		PRINT_WARN("Error in registering MAC address on " \
 			   "device %s: x%x\n", CARD_BUS_ID(card),
 			   cmd->hdr.return_code);
-		card->info.layer2_mac_registered = 0;
+		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
 		cmd->hdr.return_code = -EIO;
 	} else {
-		card->info.layer2_mac_registered = 1;
+		card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
 		memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac,
 		       OSA_ADDR_LEN);
 		PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
@@ -5866,7 +6020,7 @@
 		cmd->hdr.return_code = -EIO;
 		return 0;
 	}
-	card->info.layer2_mac_registered = 0;
+	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
 
 	return 0;
 }
@@ -5874,7 +6028,7 @@
 qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac)
 {
 	QETH_DBF_TEXT(trace, 2, "L2Delmac");
-	if (!card->info.layer2_mac_registered)
+	if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
 		return 0;
 	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
 					  qeth_layer2_send_delmac_cb);
@@ -5896,7 +6050,7 @@
 	card = (struct qeth_card *) dev->priv;
 
 	if (!card->options.layer2) {
-		PRINT_WARN("Setting MAC address on %s is not supported"
+		PRINT_WARN("Setting MAC address on %s is not supported "
 			   "in Layer 3 mode.\n", dev->name);
 		QETH_DBF_TEXT(trace, 3, "setmcLY3");
 		return -EOPNOTSUPP;
@@ -6441,6 +6595,8 @@
 	return 0;
 }
 
+
+
 static int
 qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
 			      unsigned long data)
@@ -6481,8 +6637,13 @@
 	QETH_DBF_TEXT(trace,4,"chgmaccb");
 
 	cmd = (struct qeth_ipa_cmd *) data;
-	memcpy(card->dev->dev_addr,
-	       &cmd->data.setadapterparms.data.change_addr.addr,OSA_ADDR_LEN);
+	if (!card->options.layer2 || card->info.guestlan ||
+	    !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {	
+		memcpy(card->dev->dev_addr,
+		       &cmd->data.setadapterparms.data.change_addr.addr,
+		       OSA_ADDR_LEN);
+		card->info.mac_bits |= QETH_LAYER2_MAC_READ;
+	}
 	qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
 	return 0;
 }
@@ -6602,6 +6763,12 @@
         QETH_DBF_TEXT(setup, 2, "doL2init");
         QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
 
+	rc = qeth_query_setadapterparms(card);
+	if (rc) {
+		PRINT_WARN("could not query adapter parameters on device %s: "
+			   "x%x\n", CARD_BUS_ID(card), rc);
+	}
+
 	rc = qeth_setadpparms_change_macaddr(card);
 	if (rc) {
 		PRINT_WARN("couldn't get MAC address on "
@@ -8548,7 +8715,7 @@
 EXPORT_SYMBOL(qeth_osn_assist);
 module_init(qeth_init);
 module_exit(qeth_exit);
-MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
+MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
 MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
 		                      "Copyright 2000,2003 IBM Corporation\n");
 
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index 30e053d..f0a080a 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -4,7 +4,7 @@
  * Linux on zSeries OSA Express and HiperSockets support
  *
  * Copyright 2000,2003 IBM Corporation
- * Author(s): Frank Pavlic <pavlic@de.ibm.com>
+ * Author(s): Frank Pavlic <fpavlic@de.ibm.com>
  * 	      Thomas Spatzier <tspat@de.ibm.com>
  *
  */
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 7edc5f1..5f71486 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -6,7 +6,7 @@
  * Copyright 2000,2003 IBM Corporation
  * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  *            Thomas Spatzier <tspat@de.ibm.com>
- *            Frank Pavlic <pavlic@de.ibm.com>
+ *            Frank Pavlic <fpavlic@de.ibm.com>
  *
  */
 #ifndef __QETH_MPC_H__
@@ -14,7 +14,7 @@
 
 #include <asm/qeth.h>
 
-#define VERSION_QETH_MPC_H "$Revision: 1.43 $"
+#define VERSION_QETH_MPC_H "$Revision: 1.44 $"
 
 extern const char *VERSION_QETH_MPC_C;
 
@@ -217,7 +217,7 @@
 	IPA_SETADP_SEND_OSA_MESSAGE 		= 0x0100,
 	IPA_SETADP_SET_SNMP_CONTROL 		= 0x0200,
 	IPA_SETADP_READ_SNMP_PARMS 		= 0x0400,
-	IPA_SETADP_WRITE_SNMP_PARMS 		= 0x0800,
+	IPA_SETADP_SET_PROMISC_MODE		= 0x0800,
 	IPA_SETADP_QUERY_CARD_INFO 		= 0x1000,
 };
 enum qeth_ipa_mac_ops {
@@ -232,9 +232,12 @@
 	CHANGE_ADDR_ADD_ADDR 		= 1,
 	CHANGE_ADDR_DEL_ADDR 		= 2,
 	CHANGE_ADDR_FLUSH_ADDR_TABLE 	= 4,
-
-
 };
+enum qeth_ipa_promisc_modes {
+	SET_PROMISC_MODE_OFF		= 0,
+	SET_PROMISC_MODE_ON		= 1,
+};
+
 /* (SET)DELIP(M) IPA stuff ***************************************************/
 struct qeth_ipacmd_setdelip4 {
 	__u8   ip_addr[4];
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index f91a02d..ddd6019 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.58 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  * This file contains code related to sysfs.
@@ -8,7 +8,7 @@
  * Copyright 2000,2003 IBM Corporation
  *
  * Author(s): Thomas Spatzier <tspat@de.ibm.com>
- * 	      Frank Pavlic <pavlic@de.ibm.com>
+ * 	      Frank Pavlic <fpavlic@de.ibm.com>
  *
  */
 #include <linux/list.h>
@@ -20,7 +20,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.58 $";
 
 /*****************************************************************************/
 /*                                                                           */
@@ -1117,7 +1117,7 @@
 	start = buf;
 	/* get address string */
 	end = strchr(start, '/');
-	if (!end){
+	if (!end || (end-start >= 49)){
 		PRINT_WARN("Invalid format for ipato_addx/delx. "
 			   "Use <ip addr>/<mask bits>\n");
 		return -EINVAL;
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index ad33e6f..e245af3 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -5,7 +5,7 @@
  *
  * Copyright 2004 IBM Corporation
  *
- *    Author(s): Frank Pavlic <pavlic@de.ibm.com>
+ *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>
  *
  *    $Revision: 1.7 $	 $Date: 2005/05/04 20:19:18 $
  *