diff options
-rw-r--r-- | drivers/net/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/forcedeth.c | 231 | ||||
-rw-r--r-- | drivers/net/gianfar_mii.c | 2 | ||||
-rw-r--r-- | drivers/net/gt96100eth.c | 10 | ||||
-rw-r--r-- | drivers/net/ibmveth.c | 2 | ||||
-rw-r--r-- | drivers/net/saa9730.c | 613 | ||||
-rw-r--r-- | drivers/net/smc91x.h | 32 | ||||
-rw-r--r-- | drivers/net/wireless/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/wireless/atmel.c | 88 | ||||
-rw-r--r-- | drivers/net/wireless/atmel.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/atmel_cs.c | 176 | ||||
-rw-r--r-- | drivers/net/wireless/atmel_pci.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/lcs.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth.h | 77 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 261 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.h | 13 | ||||
-rw-r--r-- | drivers/s390/net/qeth_sys.c | 8 | ||||
-rw-r--r-- | drivers/s390/net/qeth_tso.h | 2 |
19 files changed, 850 insertions, 681 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5c69d57f854..ebd7313d7fc 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -812,7 +812,7 @@ config SMC91X 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 22aec6ed80f..525624fc03b 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 @@ enum { #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 @@ enum { * 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 @@ struct fe_priv { */ 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 @@ static void nv_rx_process(struct net_device *dev) 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 @@ static void nv_set_multicast(struct net_device *dev) 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 @@ set_speed: 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 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) 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 @@ static int nv_open(struct net_device *dev) 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 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } 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 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } /* 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 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i 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)); - } - - if (i != 32) { - /* reset it */ - phy_init(dev); + pci_name(pci_dev)); + goto out_freering; } + + /* reset it */ + phy_init(dev); /* set default link speed settings */ np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; @@ -2689,6 +2730,10 @@ static void __exit exit_nic(void) 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 7263395d78b..9544279e8bc 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -133,7 +133,7 @@ int gfar_mdio_probe(struct device *dev) 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 666cfbbcf6d..5958a631472 100644 --- a/drivers/net/gt96100eth.c +++ b/drivers/net/gt96100eth.c @@ -72,8 +72,6 @@ static void dump_tx_desc(int dbg_lvl, struct net_device *dev, int i); 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 @@ dump_MII(int dbg_lvl, struct net_device *dev) 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 @@ static int __init gt96100_probe1(struct pci_dev *pci, int port_num) 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_set_rx_mode(struct net_device *dev) 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 be191d80ef9..ceb98fd398a 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 110e777f206..b2acedbefa8 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 @@ int lan_saa9730_debug; #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 @@ MODULE_DEVICE_TABLE(pci, saa9730_pci_tbl); /* 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 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp) } } 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 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp) 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 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp) 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 void lan_saa9730_buffer_init(struct lan_saa9730_private *lp) } } -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; - void *Pa; - unsigned int i, j, RcvBufferSize, TxmBufferSize; - unsigned int buffer_start; + pci_free_consistent(pdev, lp->buffer_size, lp->buffer_start, + lp->dma_addr); +} - /* - * 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); +static int lan_saa9730_allocate_buffers(struct pci_dev *pdev, + struct lan_saa9730_private *lp) +{ + void *Pa; + 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 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp) 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_load(struct lan_saa9730_private *lp) 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 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) /* 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 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) } /* 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 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) 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 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) /* 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 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) 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 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) 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 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) 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_mii_init(struct lan_saa9730_private *lp) 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 @@ static int lan_saa9730_control_init(struct lan_saa9730_private *lp) &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 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp) 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 @@ static int lan_saa9730_dma_init(struct lan_saa9730_private *lp) /* 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 @@ static int lan_saa9730_start(struct lan_saa9730_private *lp) /* 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_restart(struct lan_saa9730_private *lp) 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 @@ static int lan_saa9730_tx(struct net_device *dev) 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 @@ static int lan_saa9730_tx(struct net_device *dev) 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 @@ static int lan_saa9730_tx(struct net_device *dev) } } - /* 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 @@ static int lan_saa9730_rx(struct net_device *dev) 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 @@ static int lan_saa9730_rx(struct net_device *dev) 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 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id, 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 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id, 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 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id, 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 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp, 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 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp, 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)); - - /* Set hardware tx buffer. */ - OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use); + *(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)); + + /* 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 @@ static void lan_saa9730_tx_timeout(struct net_device *dev) 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 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb, 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 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb, 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_start_xmit(struct sk_buff *skb, 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 int lan_saa9730_close(struct net_device *dev) 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 lan_saa9730_set_multicast(struct net_device *dev) static void __devexit saa9730_remove_one(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - unregister_netdev(dev); - kfree(dev->priv); - free_netdev(dev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } + struct net_device *dev = pci_get_drvdata(pdev); + struct lan_saa9730_private *lp = netdev_priv(dev); + + 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 @@ static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq) 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 @@ static int __devinit saa9730_init_one(struct pci_dev *pdev, const struct pci_dev 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 817f200742c..a10cd184d59 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -289,6 +289,38 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) #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 7187958e40c..00e55165b76 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -330,7 +330,7 @@ config PCI_HERMES 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 a3e23527fe7..5e53c5258a3 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 @@ static int atmel_read_proc(char *page, char **start, off_t off, 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 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT 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 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT 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 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT 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 @@ void stop_atmel_card(struct net_device *dev, int freeres) 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 @@ static int atmel_set_encode(struct net_device *dev, } 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 @@ static int atmel_get_encode(struct net_device *dev, 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 handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c } } - -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 @@ static void send_authentication_request(struct atmel_private *priv, u8 *challeng 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 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) 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 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) 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 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) } } - 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 @@ static void atmel_management_timer(u_long a) 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 @@ static void atmel_command_irq(struct atmel_private *priv) 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 @@ static int probe_atmel_card(struct net_device *dev) 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 825000edfc2..b9b3e5b7654 100644 --- a/drivers/net/wireless/atmel.h +++ b/drivers/net/wireless/atmel.h @@ -35,9 +35,9 @@ typedef enum { 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 1bd13146c64..17d1fd90f83 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 @@ static int card_present(void *arg) 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 @@ static void atmel_config(dev_link_t *link) 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 @@ static void atmel_config(dev_link_t *link) 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 @@ static void atmel_config(dev_link_t *link) ((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 @@ static void atmel_config(dev_link_t *link) 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 @@ static void atmel_release(dev_link_t *link) 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 @@ static int atmel_event(event_t event, int priority, } /* 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 2eb00a957bb..a61b3bc6ccc 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c @@ -72,7 +72,7 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev, 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 1c8ad2fcad8..da8c515743e 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 @@ __exit lcs_cleanup_module(void) 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 38a2441564d..d238c7ed103 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 @@ struct qeth_reply { 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 @@ struct qeth_card_blkt { 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 @@ struct qeth_card_info { __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 @@ struct qeth_card_info { 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 @@ struct qeth_card_options { 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 @@ qeth_get_qdio_q_format(struct qeth_card *card) } } +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 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr) 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 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr) 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 692003c9f89..99cceb242ec 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 @@ static void 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 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, 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 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, (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 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, 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 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) 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 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) (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 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) 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 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) 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 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) 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 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) { 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 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) if (!rc) { list_del(&addr->entry); kfree(addr); + goto again; } } } @@ -851,6 +879,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) 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 @@ qeth_register_ip_addresses(void *ptr) 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 @@ qeth_start_kernel_thread(struct qeth_card *card) 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 @@ qeth_open(struct net_device *dev) 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 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, 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 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *, 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 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) 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 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) 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 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) } 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 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, 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_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) 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_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) 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_set_multicast_list(struct net_device *dev) 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 @@ qeth_add_multicast_ipv4(struct qeth_card *card) 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 @@ qeth_layer2_send_setmac_cb(struct qeth_card *card, 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 @@ qeth_layer2_send_delmac_cb(struct qeth_card *card, 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 @@ static int 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 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p) 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 @@ qeth_default_setadapterparms_cb(struct qeth_card *card, return 0; } + + static int qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) @@ -6481,8 +6637,13 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, 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_layer2_initialize(struct qeth_card *card) 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_deregister); 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 30e053d3cac..f0a080a9e51 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 7edc5f1fc0d..5f71486e708 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 @@ enum qeth_ipa_setadp_cmd { 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 @@ enum qeth_ipa_addr_ops { 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 f91a02db574..ddd6019ba09 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 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, 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 ad33e6f466f..e245af3c4cb 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 $ * |