diff options
Diffstat (limited to 'drivers/net')
62 files changed, 1938 insertions, 461 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 5d11a06ecb2..d339308539f 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1096,14 +1096,18 @@ static int __init vortex_eisa_init (void) int orig_cards_found = vortex_cards_found; #ifdef CONFIG_EISA - if (eisa_driver_register (&vortex_eisa_driver) >= 0) { - /* Because of the way EISA bus is probed, we cannot assume - * any device have been found when we exit from - * eisa_driver_register (the bus root driver may not be - * initialized yet). So we blindly assume something was - * found, and let the sysfs magic happend... */ - - eisa_found = 1; + int err; + + err = eisa_driver_register (&vortex_eisa_driver); + if (!err) { + /* + * Because of the way EISA bus is probed, we cannot assume + * any device have been found when we exit from + * eisa_driver_register (the bus root driver may not be + * initialized yet). So we blindly assume something was + * found, and let the sysfs magic happend... + */ + eisa_found = 1; } #endif diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index f5ee064ab6b..feae7832fc8 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -1131,7 +1131,7 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev) No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. */ -#define eeprom_delay() RTL_R32(Cfg9346) +#define eeprom_delay() (void)RTL_R32(Cfg9346) /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 00993e8ba58..e20b849a22e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2172,6 +2172,7 @@ config BNX2 config SPIDER_NET tristate "Spider Gigabit Ethernet driver" depends on PCI && PPC_CELL + select FW_LOADER help This driver supports the Gigabit Ethernet chips present on the Cell Processor-Based Blades from IBM. diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 00e72b12fb9..b90468aea07 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -58,8 +58,8 @@ obj-$(CONFIG_STNIC) += stnic.o 8390.o obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BNX2) += bnx2.o -spidernet-y += spider_net.o spider_net_ethtool.o sungem_phy.o -obj-$(CONFIG_SPIDER_NET) += spidernet.o +spidernet-y += spider_net.o spider_net_ethtool.o +obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 8e538a6d7d9..79bb56b8dce 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -829,7 +829,7 @@ static void __devexit a2065_remove_one(struct zorro_dev *z) static int __init a2065_init_module(void) { - return zorro_module_init(&a2065_driver); + return zorro_register_driver(&a2065_driver); } static void __exit a2065_cleanup_module(void) diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 9fe93acfc8e..d1b6b1f794e 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -864,7 +864,7 @@ static void __devexit ariadne_remove_one(struct zorro_dev *z) static int __init ariadne_init_module(void) { - return zorro_module_init(&ariadne_driver); + return zorro_register_driver(&ariadne_driver); } static void __exit ariadne_cleanup_module(void) diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index 625184b65e3..77fe20dbea3 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig @@ -31,3 +31,11 @@ config ARM_ETHERH help If you have an Acorn system with one of these network cards, you should say Y to this option if you wish to use it with Linux. + +config ARM_AT91_ETHER + tristate "AT91RM9200 Ethernet support" + depends on NET_ETHERNET && ARM && ARCH_AT91RM9200 + select MII + help + If you wish to compile a kernel for the AT91RM9200 and enable + ethernet support, then you should always answer Y to this. diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index bc263edf06a..42c95b79c26 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o obj-$(CONFIG_ARM_ETHERH) += etherh.o obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHER1) += ether1.o +obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c new file mode 100644 index 00000000000..5503dc8a66e --- /dev/null +++ b/drivers/net/arm/at91_ether.c @@ -0,0 +1,1110 @@ +/* + * Ethernet driver for the Atmel AT91RM9200 (Thunder) + * + * Copyright (C) 2003 SAN People (Pty) Ltd + * + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. + * Initial version by Rick Bronson 01/11/2003 + * + * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker + * (Polaroid Corporation) + * + * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/config.h> +#include <linux/mii.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/dma-mapping.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/clk.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/mach-types.h> + +#include <asm/arch/at91rm9200_emac.h> +#include <asm/arch/gpio.h> +#include <asm/arch/board.h> + +#include "at91_ether.h" + +#define DRV_NAME "at91_ether" +#define DRV_VERSION "1.0" + +static struct net_device *at91_dev; +static struct clk *ether_clk; + +/* ..................................................................... */ + +/* + * Read from a EMAC register. + */ +static inline unsigned long at91_emac_read(unsigned int reg) +{ + void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC; + + return __raw_readl(emac_base + reg); +} + +/* + * Write to a EMAC register. + */ +static inline void at91_emac_write(unsigned int reg, unsigned long value) +{ + void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC; + + __raw_writel(value, emac_base + reg); +} + +/* ........................... PHY INTERFACE ........................... */ + +/* + * Enable the MDIO bit in MAC control register + * When not called from an interrupt-handler, access to the PHY must be + * protected by a spinlock. + */ +static void enable_mdi(void) +{ + unsigned long ctl; + + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */ +} + +/* + * Disable the MDIO bit in the MAC control register + */ +static void disable_mdi(void) +{ + unsigned long ctl; + + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */ +} + +/* + * Wait until the PHY operation is complete. + */ +static inline void at91_phy_wait(void) { + unsigned long timeout = jiffies + 2; + + while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) { + if (time_after(jiffies, timeout)) { + printk("at91_ether: MIO timeout\n"); + break; + } + cpu_relax(); + } +} + +/* + * Write value to the a PHY register + * Note: MDI interface is assumed to already have been enabled. + */ +static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value) +{ + at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W + | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA)); + + /* Wait until IDLE bit in Network Status register is cleared */ + at91_phy_wait(); +} + +/* + * Read value stored in a PHY register. + * Note: MDI interface is assumed to already have been enabled. + */ +static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value) +{ + at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R + | ((phy_addr & 0x1f) << 23) | (address << 18)); + + /* Wait until IDLE bit in Network Status register is cleared */ + at91_phy_wait(); + + *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA; +} + +/* ........................... PHY MANAGEMENT .......................... */ + +/* + * Access the PHY to determine the current link speed and mode, and update the + * MAC accordingly. + * If no link or auto-negotiation is busy, then no changes are made. + */ +static void update_linkspeed(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int bmsr, bmcr, lpa, mac_cfg; + unsigned int speed, duplex; + + if (!mii_link_ok(&lp->mii)) { /* no link */ + netif_carrier_off(dev); + printk(KERN_INFO "%s: Link down.\n", dev->name); + return; + } + + /* Link up, or auto-negotiation still in progress */ + read_phy(lp->phy_address, MII_BMSR, &bmsr); + read_phy(lp->phy_address, MII_BMCR, &bmcr); + if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ + if (!(bmsr & BMSR_ANEGCOMPLETE)) + return; /* Do nothing - another interrupt generated when negotiation complete */ + + read_phy(lp->phy_address, MII_LPA, &lpa); + if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; + else speed = SPEED_10; + if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; + else duplex = DUPLEX_HALF; + } else { + speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; + duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; + } + + /* Update the MAC */ + mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); + if (speed == SPEED_100) { + if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ + mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; + else /* 100 Half Duplex */ + mac_cfg |= AT91_EMAC_SPD; + } else { + if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ + mac_cfg |= AT91_EMAC_FD; + else {} /* 10 Half Duplex */ + } + at91_emac_write(AT91_EMAC_CFG, mac_cfg); + + printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); + netif_carrier_on(dev); +} + +/* + * Handle interrupts from the PHY + */ +static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int phy; + + /* + * This hander is triggered on both edges, but the PHY chips expect + * level-triggering. We therefore have to check if the PHY actually has + * an IRQ pending. + */ + enable_mdi(); + if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { + read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */ + if (!(phy & (1 << 0))) + goto done; + } + else if (lp->phy_type == MII_LXT971A_ID) { + read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */ + if (!(phy & (1 << 2))) + goto done; + } + else if (lp->phy_type == MII_BCM5221_ID) { + read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */ + if (!(phy & (1 << 0))) + goto done; + } + else if (lp->phy_type == MII_KS8721_ID) { + read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */ + if (!(phy & ((1 << 2) | 1))) + goto done; + } + + update_linkspeed(dev); + +done: + disable_mdi(); + + return IRQ_HANDLED; +} + +/* + * Initialize and enable the PHY interrupt for link-state changes + */ +static void enable_phyirq(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int dsintr, irq_number; + int status; + + if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ + return; + if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ + return; + if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ + return; + + irq_number = lp->board_data.phy_irq_pin; + status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); + if (status) { + printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); + return; + } + + spin_lock_irq(&lp->lock); + enable_mdi(); + + if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ + read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); + dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ + write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); + } + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ + read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); + dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */ + write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); + } + else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ + dsintr = (1 << 15) | ( 1 << 14); + write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); + } + else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ + dsintr = (1 << 10) | ( 1 << 8); + write_phy(lp->phy_address, MII_TPISTATUS, dsintr); + } + + disable_mdi(); + spin_unlock_irq(&lp->lock); +} + +/* + * Disable the PHY interrupt + */ +static void disable_phyirq(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int dsintr; + unsigned int irq_number; + + if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ + return; + if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ + return; + if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ + return; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ + read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); + dsintr = dsintr | 0xf00; /* set bits 8..11 */ + write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); + } + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ + read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); + dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */ + write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); + } + else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ + read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr); + dsintr = ~(1 << 14); + write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); + } + else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ + read_phy(lp->phy_address, MII_TPISTATUS, &dsintr); + dsintr = ~((1 << 10) | (1 << 8)); + write_phy(lp->phy_address, MII_TPISTATUS, dsintr); + } + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + irq_number = lp->board_data.phy_irq_pin; + free_irq(irq_number, dev); /* Free interrupt handler */ +} + +/* + * Perform a software reset of the PHY. + */ +#if 0 +static void reset_phy(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int bmcr; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + /* Perform PHY reset */ + write_phy(lp->phy_address, MII_BMCR, BMCR_RESET); + + /* Wait until PHY reset is complete */ + do { + read_phy(lp->phy_address, MII_BMCR, &bmcr); + } while (!(bmcr && BMCR_RESET)); + + disable_mdi(); + spin_unlock_irq(&lp->lock); +} +#endif + +/* ......................... ADDRESS MANAGEMENT ........................ */ + +/* + * NOTE: Your bootloader must always set the MAC address correctly before + * booting into Linux. + * + * - It must always set the MAC address after reset, even if it doesn't + * happen to access the Ethernet while it's booting. Some versions of + * U-Boot on the AT91RM9200-DK do not do this. + * + * - Likewise it must store the addresses in the correct byte order. + * MicroMonitor (uMon) on the CSB337 does this incorrectly (and + * continues to do so, for bug-compatibility). + */ + +static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo) +{ + char addr[6]; + + if (machine_is_csb337()) { + addr[5] = (lo & 0xff); /* The CSB337 bootloader stores the MAC the wrong-way around */ + addr[4] = (lo & 0xff00) >> 8; + addr[3] = (lo & 0xff0000) >> 16; + addr[2] = (lo & 0xff000000) >> 24; + addr[1] = (hi & 0xff); + addr[0] = (hi & 0xff00) >> 8; + } + else { + addr[0] = (lo & 0xff); + addr[1] = (lo & 0xff00) >> 8; + addr[2] = (lo & 0xff0000) >> 16; + addr[3] = (lo & 0xff000000) >> 24; + addr[4] = (hi & 0xff); + addr[5] = (hi & 0xff00) >> 8; + } + + if (is_valid_ether_addr(addr)) { + memcpy(dev->dev_addr, &addr, 6); + return 1; + } + return 0; +} + +/* + * Set the ethernet MAC address in dev->dev_addr + */ +static void __init get_mac_address(struct net_device *dev) +{ + /* Check Specific-Address 1 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L))) + return; + /* Check Specific-Address 2 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L))) + return; + /* Check Specific-Address 3 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L))) + return; + /* Check Specific-Address 4 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L))) + return; + + printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n"); +} + +/* + * Program the hardware MAC address from dev->dev_addr. + */ +static void update_mac_address(struct net_device *dev) +{ + at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0])); + at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4])); + + at91_emac_write(AT91_EMAC_SA2L, 0); + at91_emac_write(AT91_EMAC_SA2H, 0); +} + +/* + * Store the new hardware address in dev->dev_addr, and update the MAC. + */ +static int set_mac_address(struct net_device *dev, void* addr) +{ + struct sockaddr *address = addr; + + if (!is_valid_ether_addr(address->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, address->sa_data, dev->addr_len); + update_mac_address(dev); + + printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\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 0; +} + +static int inline hash_bit_value(int bitnr, __u8 *addr) +{ + if (addr[bitnr / 8] & (1 << (bitnr % 8))) + return 1; + return 0; +} + +/* + * The hash address register is 64 bits long and takes up two locations in the memory map. + * The least significant bits are stored in EMAC_HSL and the most significant + * bits in EMAC_HSH. + * + * The unicast hash enable and the multicast hash enable bits in the network configuration + * register enable the reception of hash matched frames. The destination address is + * reduced to a 6 bit index into the 64 bit hash register using the following hash function. + * The hash function is an exclusive or of every sixth bit of the destination address. + * hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47] + * hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46] + * hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45] + * hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44] + * hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43] + * hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42] + * da[0] represents the least significant bit of the first byte received, that is, the multicast/ + * unicast indicator, and da[47] represents the most significant bit of the last byte + * received. + * If the hash index points to a bit that is set in the hash register then the frame will be + * matched according to whether the frame is multicast or unicast. + * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and + * the hash index points to a bit set in the hash register. + * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the + * hash index points to a bit set in the hash register. + * To receive all multicast frames, the hash register should be set with all ones and the + * multicast hash enable bit should be set in the network configuration register. + */ + +/* + * Return the hash index value for the specified address. + */ +static int hash_get_index(__u8 *addr) +{ + int i, j, bitval; + int hash_index = 0; + + for (j = 0; j < 6; j++) { + for (i = 0, bitval = 0; i < 8; i++) + bitval ^= hash_bit_value(i*6 + j, addr); + + hash_index |= (bitval << j); + } + + return hash_index; +} + +/* + * Add multicast addresses to the internal multicast-hash table. + */ +static void at91ether_sethashtable(struct net_device *dev) +{ + struct dev_mc_list *curr; + unsigned long mc_filter[2]; + unsigned int i, bitnr; + + mc_filter[0] = mc_filter[1] = 0; + + curr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, curr = curr->next) { + if (!curr) break; /* unexpected end of list */ + + bitnr = hash_get_index(curr->dmi_addr); + mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); + } + + at91_emac_write(AT91_EMAC_HSH, mc_filter[0]); + at91_emac_write(AT91_EMAC_HSL, mc_filter[1]); +} + +/* + * Enable/Disable promiscuous and multicast modes. + */ +static void at91ether_set_rx_mode(struct net_device *dev) +{ + unsigned long cfg; + + cfg = at91_emac_read(AT91_EMAC_CFG); + + if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */ + cfg |= AT91_EMAC_CAF; + else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */ + cfg &= ~AT91_EMAC_CAF; + + if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */ + at91_emac_write(AT91_EMAC_HSH, -1); + at91_emac_write(AT91_EMAC_HSL, -1); + cfg |= AT91_EMAC_MTI; + } else if (dev->mc_count > 0) { /* Enable specific multicasts */ + at91ether_sethashtable(dev); + cfg |= AT91_EMAC_MTI; + } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ + at91_emac_write(AT91_EMAC_HSH, 0); + at91_emac_write(AT91_EMAC_HSL, 0); + cfg &= ~AT91_EMAC_MTI; + } + + at91_emac_write(AT91_EMAC_CFG, cfg); +} + + +/* ......................... ETHTOOL SUPPORT ........................... */ + + +static int mdio_read(struct net_device *dev, int phy_id, int location) +{ + unsigned int value; + + read_phy(phy_id, location, &value); + return value; +} + +static void mdio_write(struct net_device *dev, int phy_id, int location, int value) +{ + write_phy(phy_id, location, value); +} + +static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ret; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + ret = mii_ethtool_gset(&lp->mii, cmd); + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */ + cmd->supported = SUPPORTED_FIBRE; + cmd->port = PORT_FIBRE; + } + + return ret; +} + +static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ret; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + ret = mii_ethtool_sset(&lp->mii, cmd); + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + return ret; +} + +static int at91ether_nwayreset(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ret; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + ret = mii_nway_restart(&lp->mii); + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + return ret; +} + +static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); +} + +static struct ethtool_ops at91ether_ethtool_ops = { + .get_settings = at91ether_get_settings, + .set_settings = at91ether_set_settings, + .get_drvinfo = at91ether_get_drvinfo, + .nway_reset = at91ether_nwayreset, + .get_link = ethtool_op_get_link, +}; + + +/* ................................ MAC ................................ */ + +/* + * Initialize and start the Receiver and Transmit subsystems + */ +static void at91ether_start(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + struct recv_desc_bufs *dlist, *dlist_phys; + int i; + unsigned long ctl; + + dlist = lp->dlist; + dlist_phys = lp->dlist_phys; + + for (i = 0; i < MAX_RX_DESCR; i++) { + dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0]; + dlist->descriptors[i].size = 0; + } + + /* Set the Wrap bit on the last descriptor */ + dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP; + + /* Reset buffer index */ + lp->rxBuffIndex = 0; + + /* Program address of descriptor list in Rx Buffer Queue register */ + at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys); + + /* Enable Receive and Transmit */ + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE); +} + +/* + * Open the ethernet interface + */ +static int at91ether_open(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned long ctl; + + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + clk_enable(ether_clk); /* Re-enable Peripheral clock */ + + /* Clear internal statistics */ + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR); + + /* Update the MAC address (incase user has changed it) */ + update_mac_address(dev); + + /* Enable PHY interrupt */ + enable_phyirq(dev); + + /* Enable MAC interrupts */ + at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA + | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM + | AT91_EMAC_ROVR | AT91_EMAC_ABT); + + /* Determine current link speed */ + spin_lock_irq(&lp->lock); + enable_mdi(); + update_linkspeed(dev); + disable_mdi(); + spin_unlock_irq(&lp->lock); + + at91ether_start(dev); + netif_start_queue(dev); + return 0; +} + +/* + * Close the interface + */ +static int at91ether_close(struct net_device *dev) +{ + unsigned long ctl; + + /* Disable Receiver and Transmitter */ + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE)); + + /* Disable PHY interrupt */ + disable_phyirq(dev); + + /* Disable MAC interrupts */ + at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA + | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM + | AT91_EMAC_ROVR | AT91_EMAC_ABT); + + netif_stop_queue(dev); + + clk_disable(ether_clk); /* Disable Peripheral clock */ + + return 0; +} + +/* + * Transmit packet. + */ +static int at91ether_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + + if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) { + netif_stop_queue(dev); + + /* Store packet information (to free when Tx completed) */ + lp->skb = skb; + lp->skb_length = skb->len; + lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); + lp->stats.tx_bytes += skb->len; + + /* Set address of the data in the Transmit Address register */ + at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr); + /* Set length of the packet in the Transmit Control register */ + at91_emac_write(AT91_EMAC_TCR, skb->len); + + dev->trans_start = jiffies; + } else { + printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n"); + return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) + on this skb, he also reports -ENETDOWN and printk's, so either + we free and return(0) or don't free and return 1 */ + } + + return 0; +} + +/* + * Update the current statistics from the internal statistics registers. + */ +static struct net_device_stats *at91ether_stats(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ale, lenerr, seqe, lcol, ecol; + + if (netif_running(dev)) { + lp->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */ + ale = at91_emac_read(AT91_EMAC_ALE); + lp->stats.rx_frame_errors += ale; /* Alignment errors */ + lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF); + lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */ + seqe = at91_emac_read(AT91_EMAC_SEQE); + lp->stats.rx_crc_errors += seqe; /* CRC error */ + lp->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */ + lp->stats.rx_errors += (ale + lenerr + seqe + + at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB)); + + lp->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */ + lp->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */ + lp->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */ + lp->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */ + + lcol = at91_emac_read(AT91_EMAC_LCOL); + ecol = at91_emac_read(AT91_EMAC_ECOL); + lp->stats.tx_window_errors += lcol; /* Late collisions */ + lp->stats.tx_aborted_errors += ecol; /* 16 collisions */ + + lp->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol); + } + return &lp->stats; +} + +/* + * Extract received frame from buffer descriptors and sent to upper layers. + * (Called from interrupt context) + */ +static void at91ether_rx(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + struct recv_desc_bufs *dlist; + unsigned char *p_recv; + struct sk_buff *skb; + unsigned int pktlen; + + dlist = lp->dlist; + while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) { + p_recv = dlist->recv_buf[lp->rxBuffIndex]; + pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */ + skb = alloc_skb(pktlen + 2, GFP_ATOMIC); + if (skb != NULL) { + skb_reserve(skb, 2); + memcpy(skb_put(skb, pktlen), p_recv, pktlen); + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->len = pktlen; + dev->last_rx = jiffies; + lp->stats.rx_bytes += pktlen; + netif_rx(skb); + } + else { + lp->stats.rx_dropped += 1; + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); + } + + if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST) + lp->stats.multicast++; + + dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */ + if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */ + lp->rxBuffIndex = 0; + else + lp->rxBuffIndex++; + } +} + +/* + * MAC interrupt handler + */ +static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned long intstatus, ctl; + + /* MAC Interrupt Status register indicates what interrupts are pending. + It is automatically cleared once read. */ + intstatus = at91_emac_read(AT91_EMAC_ISR); + + if (intstatus & AT91_EMAC_RCOM) /* Receive complete */ + at91ether_rx(dev); + + if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */ + /* The TCOM bit is set even if the transmission failed. */ + if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY)) + lp->stats.tx_errors += 1; + + if (lp->skb) { + dev_kfree_skb_irq(lp->skb); + lp->skb = NULL; + dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); + } + netif_wake_queue(dev); + } + + /* Work-around for Errata #11 */ + if (intstatus & AT91_EMAC_RBNA) { + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE); + } + + if (intstatus & AT91_EMAC_ROVR) + printk("%s: ROVR error\n", dev->name); + + return IRQ_HANDLED; +} + +/* + * Initialize the ethernet interface + */ +static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev) +{ + struct at91_eth_data *board_data = pdev->dev.platform_data; + struct net_device *dev; + struct at91_private *lp; + unsigned int val; + int res; + + if (at91_dev) /* already initialized */ + return 0; + + dev = alloc_etherdev(sizeof(struct at91_private)); + if (!dev) + return -ENOMEM; + + dev->base_addr = AT91_VA_BASE_EMAC; + dev->irq = AT91_ID_EMAC; + SET_MODULE_OWNER(dev); + + /* Install the interrupt handler */ + if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) { + free_netdev(dev); + return -EBUSY; + } + + /* Allocate memory for DMA Receive descriptors */ + lp = (struct at91_private *)dev->priv; + lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL); + if (lp->dlist == NULL) { + free_irq(dev->irq, dev); + free_netdev(dev); + return -ENOMEM; + } + lp->board_data = *board_data; + platform_set_drvdata(pdev, dev); + + spin_lock_init(&lp->lock); + + ether_setup(dev); + dev->open = at91ether_open; + dev->stop = at91ether_close; + dev->hard_start_xmit = at91ether_tx; + dev->get_stats = at91ether_stats; + dev->set_multicast_list = at91ether_set_rx_mode; + dev->set_mac_address = set_mac_address; + dev->ethtool_ops = &at91ether_ethtool_ops; + + SET_NETDEV_DEV(dev, &pdev->dev); + + get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */ + update_mac_address(dev); /* Program ethernet address into MAC */ + + at91_emac_write(AT91_EMAC_CTL, 0); + + if (lp->board_data.is_rmii) + at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII); + else + at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG); + + /* Perform PHY-specific initialization */ + spin_lock_irq(&lp->lock); + enable_mdi(); + if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { + read_phy(phy_address, MII_DSCR_REG, &val); + if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */ + lp->phy_media = PORT_FIBRE; + } else if (machine_is_csb337()) { + /* mix link activity status into LED2 link state */ + write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22); + } + disable_mdi(); + spin_unlock_irq(&lp->lock); + + lp->mii.dev = dev; /* Support for ethtool */ + lp->mii.mdio_read = mdio_read; + lp->mii.mdio_write = mdio_write; + + lp->phy_type = phy_type; /* Type of PHY connected */ + lp->phy_address = phy_address; /* MDI address of PHY */ + + /* Register the network interface */ + res = register_netdev(dev); + if (res) { + free_irq(dev->irq, dev); + free_netdev(dev); + dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); + return res; + } + at91_dev = dev; + + /* Determine current link speed */ + spin_lock_irq(&lp->lock); + enable_mdi(); + update_linkspeed(dev); + disable_mdi(); + spin_unlock_irq(&lp->lock); + netif_carrier_off(dev); /* will be enabled in open() */ + + /* Display ethernet banner */ + printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n", + dev->name, (uint) dev->base_addr, dev->irq, + at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-", + at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex", + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) + printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); + else if (phy_type == MII_LXT971A_ID) + printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name); + else if (phy_type == MII_RTL8201_ID) + printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name); + else if (phy_type == MII_BCM5221_ID) + printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name); + else if (phy_type == MII_DP83847_ID) + printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name); + else if (phy_type == MII_AC101L_ID) + printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name); + else if (phy_type == MII_KS8721_ID) + printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name); + + return 0; +} + +/* + * Detect MAC and PHY and perform initialization + */ +static int __init at91ether_probe(struct platform_device *pdev) +{ + unsigned int phyid1, phyid2; + int detected = -1; + unsigned long phy_id; + unsigned short phy_address = 0; + + ether_clk = clk_get(&pdev->dev, "ether_clk"); + if (!ether_clk) { + printk(KERN_ERR "at91_ether: no clock defined\n"); + return -ENODEV; + } + clk_enable(ether_clk); /* Enable Peripheral clock */ + + while ((detected != 0) && (phy_address < 32)) { + /* Read the PHY ID registers */ + enable_mdi(); + read_phy(phy_address, MII_PHYSID1, &phyid1); + read_phy(phy_address, MII_PHYSID2, &phyid2); + disable_mdi(); + + phy_id = (phyid1 << 16) | (phyid2 & 0xfff0); + switch (phy_id) { + case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */ + case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */ + case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */ + case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */ + case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */ + case MII_DP83847_ID: /* National Semiconductor DP83847: */ + case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */ + case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */ + detected = at91ether_setup(phy_id, phy_address, pdev); + break; + } + + phy_address++; + } + + clk_disable(ether_clk); /* Disable Peripheral clock */ + + return detected; +} + +static int __devexit at91ether_remove(struct platform_device *pdev) +{ + struct at91_private *lp = (struct at91_private *) at91_dev->priv; + + unregister_netdev(at91_dev); + free_irq(at91_dev->irq, at91_dev); + dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); + clk_put(ether_clk); + + free_netdev(at91_dev); + at91_dev = NULL; + return 0; +} + +static struct platform_driver at91ether_driver = { + .probe = at91ether_probe, + .remove = __devexit_p(at91ether_remove), + /* FIXME: support suspend and resume */ + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init at91ether_init(void) +{ + return platform_driver_register(&at91ether_driver); +} + +static void __exit at91ether_exit(void) +{ + platform_driver_unregister(&at91ether_driver); +} + +module_init(at91ether_init) +module_exit(at91ether_exit) + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); +MODULE_AUTHOR("Andrew Victor"); diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h new file mode 100644 index 00000000000..9885735c9c8 --- /dev/null +++ b/drivers/net/arm/at91_ether.h @@ -0,0 +1,101 @@ +/* + * Ethernet driver for the Atmel AT91RM9200 (Thunder) + * + * Copyright (C) SAN People (Pty) Ltd + * + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. + * Initial version by Rick Bronson. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef AT91_ETHERNET +#define AT91_ETHERNET + + +/* Davicom 9161 PHY */ +#define MII_DM9161_ID 0x0181b880 +#define MII_DM9161A_ID 0x0181b8a0 + +/* Davicom specific registers */ +#define MII_DSCR_REG 16 +#define MII_DSCSR_REG 17 +#define MII_DSINTR_REG 21 + +/* Intel LXT971A PHY */ +#define MII_LXT971A_ID 0x001378E0 + +/* Intel specific registers */ +#define MII_ISINTE_REG 18 +#define MII_ISINTS_REG 19 +#define MII_LEDCTRL_REG 20 + +/* Realtek RTL8201 PHY */ +#define MII_RTL8201_ID 0x00008200 + +/* Broadcom BCM5221 PHY */ +#define MII_BCM5221_ID 0x004061e0 + +/* Broadcom specific registers */ +#define MII_BCMINTR_REG 26 + +/* National Semiconductor DP83847 */ +#define MII_DP83847_ID 0x20005c30 + +/* Altima AC101L PHY */ +#define MII_AC101L_ID 0x00225520 + +/* Micrel KS8721 PHY */ +#define MII_KS8721_ID 0x00221610 + +/* ........................................................................ */ + +#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */ +#define MAX_RX_DESCR 9 /* max number of receive buffers */ + +#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */ +#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */ + +#define EMAC_BROADCAST 0x80000000 /* broadcast address */ +#define EMAC_MULTICAST 0x40000000 /* multicast address */ +#define EMAC_UNICAST 0x20000000 /* unicast address */ + +struct rbf_t +{ + unsigned int addr; + unsigned long size; +}; + +struct recv_desc_bufs +{ + struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */ + char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */ +}; + +struct at91_private +{ + struct net_device_stats stats; + struct mii_if_info mii; /* ethtool support */ + struct at91_eth_data board_data; /* board-specific configuration */ + + /* PHY */ + unsigned long phy_type; /* type of PHY (PHY_ID) */ + spinlock_t lock; /* lock for MDI interface */ + short phy_media; /* media interface type */ + unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */ + + /* Transmit */ + struct sk_buff *skb; /* holds skb until xmit interrupt completes */ + dma_addr_t skb_physaddr; /* phys addr from pci_map_single */ + int skb_length; /* saved skb length for pci_unmap_single */ + + /* Receive */ + int rxBuffIndex; /* index into receive descriptor list */ + struct recv_desc_bufs *dlist; /* descriptor list address */ + struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */ +}; + +#endif diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c index 0095384ff45..5e5f80b99b9 100644 --- a/drivers/net/atari_bionet.c +++ b/drivers/net/atari_bionet.c @@ -123,7 +123,7 @@ static char version[] = * Global variable 'bionet_debug'. Can be set at load time by 'insmod' */ unsigned int bionet_debug = NET_DEBUG; -MODULE_PARM(bionet_debug, "i"); +module_param(bionet_debug, int, 0); MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c index 8b997809f9d..d6039e62d83 100644 --- a/drivers/net/atari_pamsnet.c +++ b/drivers/net/atari_pamsnet.c @@ -119,7 +119,7 @@ static char *version = * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod' */ unsigned int pamsnet_debug = NET_DEBUG; -MODULE_PARM(pamsnet_debug, "i"); +module_param(pamsnet_debug, int, 0); MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index e01b6a78ec6..442b2cbeb58 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -78,7 +78,7 @@ static int lance_debug = LANCE_DEBUG; #else static int lance_debug = 1; #endif -MODULE_PARM(lance_debug, "i"); +module_param(lance_debug, int, 0); MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index cd0b1dccfb6..1363083b4d8 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -90,8 +90,6 @@ static void au1000_tx_timeout(struct net_device *); static int au1000_set_config(struct net_device *dev, struct ifmap *map); static void set_rx_mode(struct net_device *); static struct net_device_stats *au1000_get_stats(struct net_device *); -static inline void update_tx_stats(struct net_device *, u32, u32); -static inline void update_rx_stats(struct net_device *, u32); static void au1000_timer(unsigned long); static int au1000_ioctl(struct net_device *, struct ifreq *, int); static int mdio_read(struct net_device *, int, int); @@ -1825,16 +1823,11 @@ static void __exit au1000_cleanup_module(void) } } - -static inline void -update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len) +static void update_tx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; struct net_device_stats *ps = &aup->stats; - ps->tx_packets++; - ps->tx_bytes += pkt_len; - if (status & TX_FRAME_ABORTED) { if (dev->if_port == IF_PORT_100BASEFX) { if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { @@ -1867,7 +1860,7 @@ static void au1000_tx_ack(struct net_device *dev) ptxd = aup->tx_dma_ring[aup->tx_tail]; while (ptxd->buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->buff_stat &= ~TX_T_DONE; ptxd->len = 0; au_sync(); @@ -1889,6 +1882,7 @@ static void au1000_tx_ack(struct net_device *dev) static int au1000_tx(struct sk_buff *skb, struct net_device *dev) { struct au1000_private *aup = (struct au1000_private *) dev->priv; + struct net_device_stats *ps = &aup->stats; volatile tx_dma_t *ptxd; u32 buff_stat; db_dest_t *pDB; @@ -1908,7 +1902,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) return 1; } else if (buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->len = 0; } @@ -1928,6 +1922,9 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) else ptxd->len = skb->len; + ps->tx_packets++; + ps->tx_bytes += ptxd->len; + ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; au_sync(); dev_kfree_skb(skb); @@ -1936,7 +1933,6 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) return 0; } - static inline void update_rx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 7d213707008..2671da20a49 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -9,13 +9,54 @@ * Written by: Michael Chan (mchan@broadcom.com) */ +#include <linux/config.h> + +#include <linux/module.h> +#include <linux/moduleparam.h> + +#include <linux/kernel.h> +#include <linux/timer.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/dma-mapping.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <linux/delay.h> +#include <asm/byteorder.h> +#include <linux/time.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#ifdef NETIF_F_HW_VLAN_TX +#include <linux/if_vlan.h> +#define BCM_VLAN 1 +#endif +#ifdef NETIF_F_TSO +#include <net/ip.h> +#include <net/tcp.h> +#include <net/checksum.h> +#define BCM_TSO 1 +#endif +#include <linux/workqueue.h> +#include <linux/crc32.h> +#include <linux/prefetch.h> +#include <linux/cache.h> + #include "bnx2.h" #include "bnx2_fw.h" #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.38" -#define DRV_MODULE_RELDATE "February 10, 2006" +#define DRV_MODULE_VERSION "1.4.39" +#define DRV_MODULE_RELDATE "March 22, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -313,8 +354,6 @@ bnx2_disable_int(struct bnx2 *bp) static void bnx2_enable_int(struct bnx2 *bp) { - u32 val; - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx); @@ -322,8 +361,7 @@ bnx2_enable_int(struct bnx2 *bp) REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); + REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); } static void @@ -362,15 +400,11 @@ bnx2_free_mem(struct bnx2 *bp) { int i; - if (bp->stats_blk) { - pci_free_consistent(bp->pdev, sizeof(struct statistics_block), - bp->stats_blk, bp->stats_blk_mapping); - bp->stats_blk = NULL; - } if (bp->status_blk) { - pci_free_consistent(bp->pdev, sizeof(struct status_block), + pci_free_consistent(bp->pdev, bp->status_stats_size, bp->status_blk, bp->status_blk_mapping); bp->status_blk = NULL; + bp->stats_blk = NULL; } if (bp->tx_desc_ring) { pci_free_consistent(bp->pdev, @@ -395,14 +429,13 @@ bnx2_free_mem(struct bnx2 *bp) static int bnx2_alloc_mem(struct bnx2 *bp) { - int i; + int i, status_blk_size; - bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, - GFP_KERNEL); + bp->tx_buf_ring = kzalloc(sizeof(struct sw_bd) * TX_DESC_CNT, + GFP_KERNEL); if (bp->tx_buf_ring == NULL) return -ENOMEM; - memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT); bp->tx_desc_ring = pci_alloc_consistent(bp->pdev, sizeof(struct tx_bd) * TX_DESC_CNT, @@ -428,21 +461,22 @@ bnx2_alloc_mem(struct bnx2 *bp) } - bp->status_blk = pci_alloc_consistent(bp->pdev, - sizeof(struct status_block), + /* Combine status and statistics blocks into one allocation. */ + status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); + bp->status_stats_size = status_blk_size + + sizeof(struct statistics_block); + + bp->status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size, &bp->status_blk_mapping); if (bp->status_blk == NULL) goto alloc_mem_err; - memset(bp->status_blk, 0, sizeof(struct status_block)); + memset(bp->status_blk, 0, bp->status_stats_size); - bp->stats_blk = pci_alloc_consistent(bp->pdev, - sizeof(struct statistics_block), - &bp->stats_blk_mapping); - if (bp->stats_blk == NULL) - goto alloc_mem_err; + bp->stats_blk = (void *) ((unsigned long) bp->status_blk + + status_blk_size); - memset(bp->stats_blk, 0, sizeof(struct statistics_block)); + bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; return 0; @@ -1926,6 +1960,13 @@ bnx2_poll(struct net_device *dev, int *budget) spin_lock(&bp->phy_lock); bnx2_phy_int(bp); spin_unlock(&bp->phy_lock); + + /* This is needed to take care of transient status + * during link changes. + */ + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); } if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) @@ -3307,6 +3348,8 @@ bnx2_init_chip(struct bnx2 *bp) udelay(20); + bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND); + return rc; } @@ -3746,7 +3789,6 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) struct sk_buff *skb, *rx_skb; unsigned char *packet; u16 rx_start_idx, rx_idx; - u32 val; dma_addr_t map; struct tx_bd *txbd; struct sw_bd *rx_buf; @@ -3777,8 +3819,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) map = pci_map_single(bp->pdev, skb->data, pkt_size, PCI_DMA_TODEVICE); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); udelay(5); @@ -3802,8 +3845,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) udelay(100); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); udelay(5); @@ -3939,7 +3983,6 @@ static int bnx2_test_intr(struct bnx2 *bp) { int i; - u32 val; u16 status_idx; if (!netif_running(bp->dev)) @@ -3948,8 +3991,7 @@ bnx2_test_intr(struct bnx2 *bp) status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; /* This register is not touched during run-time. */ - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); + REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); REG_RD(bp, BNX2_HC_COMMAND); for (i = 0; i < 10; i++) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index fd4b7f2eb47..b87925f6a22 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -13,46 +13,6 @@ #ifndef BNX2_H #define BNX2_H -#include <linux/config.h> - -#include <linux/module.h> -#include <linux/moduleparam.h> - -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/dma-mapping.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <linux/delay.h> -#include <asm/byteorder.h> -#include <linux/time.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#ifdef NETIF_F_HW_VLAN_TX -#include <linux/if_vlan.h> -#define BCM_VLAN 1 -#endif -#ifdef NETIF_F_TSO -#include <net/ip.h> -#include <net/tcp.h> -#include <net/checksum.h> -#define BCM_TSO 1 -#endif -#include <linux/workqueue.h> -#include <linux/crc32.h> -#include <linux/prefetch.h> - /* Hardware data structures and register definitions automatically * generated from RTL code. Do not modify. */ @@ -3917,15 +3877,17 @@ struct bnx2 { #define USING_MSI_FLAG 0x20 #define ASF_ENABLE_FLAG 0x40 - struct tx_bd *tx_desc_ring; - struct sw_bd *tx_buf_ring; - u32 tx_prod_bseq; - u16 tx_prod; - u16 tx_cons; - int tx_ring_size; + /* Put tx producer and consumer fields in separate cache lines. */ - u16 hw_tx_cons; - u16 hw_rx_cons; + u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES))); + u16 tx_prod; + + struct tx_bd *tx_desc_ring; + struct sw_bd *tx_buf_ring; + int tx_ring_size; + + u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES))); + u16 hw_tx_cons; #ifdef BCM_VLAN struct vlan_group *vlgrp; @@ -3939,6 +3901,7 @@ struct bnx2 { u32 rx_prod_bseq; u16 rx_prod; u16 rx_cons; + u16 hw_rx_cons; u32 rx_csum; @@ -4038,6 +4001,7 @@ struct bnx2 { struct statistics_block *stats_blk; dma_addr_t stats_blk_mapping; + u32 hc_cmd; u32 rx_mode; u16 req_line_speed; @@ -4082,6 +4046,8 @@ struct bnx2 { struct flash_spec *flash_info; u32 flash_size; + + int status_stats_size; }; static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 8f1573e658a..ac48f754350 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -192,12 +192,15 @@ static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; +static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */ +static int link_mode; + MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)"); MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(cassini_debug, "i"); +module_param(cassini_debug, int, 0); MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value"); -MODULE_PARM(link_mode, "i"); +module_param(link_mode, int, 0); MODULE_PARM_DESC(link_mode, "default link mode"); /* @@ -209,7 +212,7 @@ MODULE_PARM_DESC(link_mode, "default link mode"); * Value in seconds, for user input. */ static int linkdown_timeout = DEFAULT_LINKDOWN_TIMEOUT; -MODULE_PARM(linkdown_timeout, "i"); +module_param(linkdown_timeout, int, 0); MODULE_PARM_DESC(linkdown_timeout, "min reset interval in sec. for PCS linkdown issue; disabled if not positive"); @@ -221,8 +224,6 @@ MODULE_PARM_DESC(linkdown_timeout, static int link_transition_timeout; -static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */ -static int link_mode; static u16 link_modes[] __devinitdata = { BMCR_ANENABLE, /* 0 : autoneg */ diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 349ebe783ed..7fe2638ae06 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -124,7 +124,7 @@ MODULE_LICENSE("GPL"); static int dflt_msg_enable = DFLT_MSG_ENABLE; -MODULE_PARM(dflt_msg_enable, "i"); +module_param(dflt_msg_enable, int, 0); MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap"); diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 03804cc38be..0941d40f046 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1412,7 +1412,7 @@ static int __init depca_mca_probe(struct device *device) irq = 11; break; default: - printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + printk("%s: mca_probe IRQ error. You should never get here (%d).\n", mdev->name, where); return -EINVAL; } diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 32d13166c6e..e175d487668 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -1551,7 +1551,7 @@ MODULE_PARM_DESC(nicmode, "Digi RightSwitch operating mode (1: switch, 2: multi- static int __init dgrs_init_module (void) { int i; - int cardcount = 0; + int err; /* * Command line variable overrides @@ -1593,13 +1593,13 @@ static int __init dgrs_init_module (void) * Find and configure all the cards */ #ifdef CONFIG_EISA - cardcount = eisa_driver_register(&dgrs_eisa_driver); - if (cardcount < 0) - return cardcount; + err = eisa_driver_register(&dgrs_eisa_driver); + if (err) + return err; #endif - cardcount = pci_register_driver(&dgrs_pci_driver); - if (cardcount) - return cardcount; + err = pci_register_driver(&dgrs_pci_driver); + if (err) + return err; return 0; } diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index b4f3a9f8a53..7e433809713 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -55,11 +55,11 @@ MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>"); MODULE_DESCRIPTION("Motorola 8xx FEC ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(fec_8xx_debug, "i"); +int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */ +module_param(fec_8xx_debug, int, 0); MODULE_PARM_DESC(fec_8xx_debug, "FEC 8xx bitmapped debugging message enable value"); -int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */ /*************************************************/ diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index f5d49a11065..196298f33db 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -58,11 +58,11 @@ MODULE_DESCRIPTION("Freescale Ethernet Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -MODULE_PARM(fs_enet_debug, "i"); +int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */ +module_param(fs_enet_debug, int, 0); MODULE_PARM_DESC(fs_enet_debug, "Freescale bitmapped debugging message enable value"); -int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */ static void fs_set_multicast_list(struct net_device *dev) { diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c index 5958a631472..2d243540461 100644 --- a/drivers/net/gt96100eth.c +++ b/drivers/net/gt96100eth.c @@ -114,8 +114,8 @@ static int max_interrupt_work = 32; static char mac0[18] = "00.02.03.04.05.06"; static char mac1[18] = "00.01.02.03.04.05"; -MODULE_PARM(mac0, "c18"); -MODULE_PARM(mac1, "c18"); +module_param_string(mac0, mac0, 18, 0); +module_param_string(mac1, mac0, 18, 0); MODULE_PARM_DESC(mac0, "MAC address for GT96100 ethernet port 0"); MODULE_PARM_DESC(mac1, "MAC address for GT96100 ethernet port 1"); diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index c8dc40214a0..79a8fbcf5f9 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -280,7 +280,7 @@ static unsigned long rand; MODULE_AUTHOR("Klaus Kudielka"); MODULE_DESCRIPTION("Driver for high-speed SCC boards"); -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i"); +module_param_array(io, int, NULL, 0); MODULE_LICENSE("GPL"); static void __exit dmascc_exit(void) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index dc5e9d59dee..d81a8e1eeb8 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -1012,7 +1012,7 @@ static void __exit mkiss_exit_driver(void) MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>"); MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs"); -MODULE_PARM(crc_force, "i"); +module_param(crc_force, int, 0); MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]"); MODULE_LICENSE("GPL"); MODULE_ALIAS_LDISC(N_AX25); diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 74e167e7dea..0d7a6250e34 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -250,6 +250,12 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr) ei_status.block_output = &hpp_mem_block_output; ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr; dev->mem_start = mem_start; + ei_status.mem = ioremap(mem_start, + (HP_STOP_PG - HP_START_PG)*256); + if (!ei_status.mem) { + retval = -ENOMEM; + goto out; + } ei_status.rmem_start = dev->mem_start + TX_PAGES/2*256; dev->mem_end = ei_status.rmem_end = dev->mem_start + (HP_STOP_PG - HP_START_PG)*256; @@ -262,8 +268,10 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr) retval = register_netdev(dev); if (retval) - goto out; + goto out1; return 0; +out1: + iounmap(ei_status.mem); out: release_region(ioaddr, HP_IO_EXTENT); return retval; @@ -372,7 +380,7 @@ hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring outw((ring_page<<8), ioaddr + HPP_IN_ADDR); outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); - isa_memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr)); + memcpy_fromio(hdr, ei_status.mem, sizeof(struct e8390_pkt_hdr)); outw(option_reg, ioaddr + HPP_OPTION); hdr->count = (le16_to_cpu(hdr->count) + 3) & ~3; /* Round up allocation. */ } @@ -391,7 +399,7 @@ hpp_mem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int Also note that we *can't* use eth_io_copy_and_sum() because it will not always copy "count" bytes (e.g. padded IP). */ - isa_memcpy_fromio(skb->data, dev->mem_start, count); + memcpy_fromio(skb->data, ei_status.mem, count); outw(option_reg, ioaddr + HPP_OPTION); } @@ -416,7 +424,7 @@ hpp_mem_block_output(struct net_device *dev, int count, outw(start_page << 8, ioaddr + HPP_OUT_ADDR); outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); - isa_memcpy_toio(dev->mem_start, buf, (count + 3) & ~3); + memcpy_toio(ei_status.mem, buf, (count + 3) & ~3); outw(option_reg, ioaddr + HPP_OPTION); return; @@ -470,6 +478,7 @@ init_module(void) static void cleanup_card(struct net_device *dev) { /* NB: hpp_close() handles free_irq */ + iounmap(ei_status.mem); release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index d8410634bca..68569346460 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -217,7 +217,7 @@ static int hplance_close(struct net_device *dev) int __init hplance_init_module(void) { - return dio_module_init(&hplance_driver); + return dio_register_driver(&hplance_driver); } void __exit hplance_cleanup_module(void) diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 6e0ca7340a8..d9fb8e74e63 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -242,7 +242,7 @@ static void __devexit hydra_remove_one(struct zorro_dev *z) static int __init hydra_init_module(void) { - return zorro_module_init(&hydra_driver); + return zorro_register_driver(&hydra_driver); } static void __exit hydra_cleanup_module(void) diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 6070195b87b..98fa5319e5c 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -1118,9 +1118,9 @@ static void __exit irport_cleanup(void) } } -MODULE_PARM(io, "1-4i"); +module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io, "Base I/O addresses"); -MODULE_PARM(irq, "1-4i"); +module_param_array(irq, int, NULL, 0); MODULE_PARM_DESC(irq, "IRQ lines"); MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c index d82651a97ba..6f7dce8eba5 100644 --- a/drivers/net/ixp2000/enp2611.c +++ b/drivers/net/ixp2000/enp2611.c @@ -16,7 +16,7 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/moduleparam.h> -#include <asm/arch/uengine.h> +#include <asm/hardware/uengine.h> #include <asm/mach-types.h> #include <asm/io.h> #include "ixpdev.h" diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 09f03f493be..77f104a005f 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -16,7 +16,7 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/moduleparam.h> -#include <asm/arch/uengine.h> +#include <asm/hardware/uengine.h> #include <asm/mach-types.h> #include <asm/io.h> #include "ixp2400_rx.ucode" diff --git a/drivers/net/lance.c b/drivers/net/lance.c index d1d714faa6c..bb5ad479210 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -464,20 +464,25 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int static int did_version; /* Already printed version info. */ unsigned long flags; int err = -ENOMEM; + void __iomem *bios; /* First we look for special cases. Check for HP's on-board ethernet by looking for 'HP' in the BIOS. There are two HP versions, check the BIOS for the configuration port. This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com. */ - if (isa_readw(0x000f0102) == 0x5048) { + bios = ioremap(0xf00f0, 0x14); + if (!bios) + return -ENOMEM; + if (readw(bios + 0x12) == 0x5048) { static const short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360}; - int hp_port = (isa_readl(0x000f00f1) & 1) ? 0x499 : 0x99; + int hp_port = (readl(bios + 1) & 1) ? 0x499 : 0x99; /* We can have boards other than the built-in! Verify this is on-board. */ if ((inb(hp_port) & 0xc0) == 0x80 && ioaddr_table[inb(hp_port) & 3] == ioaddr) hp_builtin = hp_port; } + iounmap(bios); /* We also recognize the HP Vectra on-board here, but check below. */ hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 && inb(ioaddr+2) == 0x09); diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index f7b7238d835..957888de3d7 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -177,7 +177,7 @@ static int i596_debug = (DEB_SERIOUS|DEB_PROBE); MODULE_AUTHOR("Richard Hirst"); MODULE_DESCRIPTION("i82596 driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(i596_debug, "i"); +module_param(i596_debug, int, 0); MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask"); /* Copy frames shorter than rx_copybreak, otherwise pass on up in @@ -1520,9 +1520,9 @@ static void set_multicast_list(struct net_device *dev) } } -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); static int num_drivers; static struct net_device *netdevs[MAX_DRIVERS]; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 690a1aae0b3..0c13795dca3 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -172,11 +172,9 @@ static struct net_device_stats *get_stats(struct net_device *dev) memset(stats, 0, sizeof(struct net_device_stats)); - for (i=0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct net_device_stats *lb_stats; - if (!cpu_possible(i)) - continue; lb_stats = &per_cpu(loopback_stats, i); stats->rx_bytes += lb_stats->rx_bytes; stats->tx_bytes += lb_stats->tx_bytes; diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index f65b0db111b..cd3c9a5a98b 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c @@ -629,7 +629,7 @@ static int set_mac_address(struct net_device *dev, void *addr) static struct net_device *dev_cs89x0; static int debug; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0); MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 2a5add257b8..77792b28602 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -1042,7 +1042,7 @@ static void __exit mace_cleanup(void) MODULE_AUTHOR("Paul Mackerras"); MODULE_DESCRIPTION("PowerMac MACE driver."); -MODULE_PARM(port_aaui, "i"); +module_param(port_aaui, int, 0); MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/meth.c b/drivers/net/meth.c index e23655f5049..d644bf3a933 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -62,7 +62,7 @@ MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver"); #ifdef HAVE_TX_TIMEOUT static int timeout = TX_TIMEOUT; -MODULE_PARM(timeout, "i"); +module_param(timeout, int, 0); #endif /* diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index aaebd28a192..7ea3d596ac3 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -601,9 +601,9 @@ static int io[MAX_NE_CARDS]; static int irq[MAX_NE_CARDS]; static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */ -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +module_param_array(io, int, NULL, 0); +module_param_array(irq, int, NULL, 0); +module_param_array(bad, int, NULL, 0); MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s)"); MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver"); diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index e3ebb5803b0..d11821dd86e 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -117,7 +117,7 @@ enum ne2k_pci_chipsets { }; -static const struct { +static struct { char *name; int flags; } pci_clone_list[] __devinitdata = { diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 2ab01a5d1d2..a68bf474f6e 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -766,8 +766,8 @@ static void ni5010_show_registers(struct net_device *dev) #ifdef MODULE static struct net_device *dev_ni5010; -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); +module_param(io, int, 0); +module_param(irq, int, 0); MODULE_PARM_DESC(io, "ni5010 I/O base address"); MODULE_PARM_DESC(irq, "ni5010 IRQ number"); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index f608c12e3e8..b2073fce821 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -46,6 +46,7 @@ #include <linux/rwsem.h> #include <linux/stddef.h> #include <linux/device.h> +#include <linux/mutex.h> #include <net/slhc_vj.h> #include <asm/atomic.h> @@ -198,11 +199,11 @@ static unsigned int cardmap_find_first_free(struct cardmap *map); static void cardmap_destroy(struct cardmap **map); /* - * all_ppp_sem protects the all_ppp_units mapping. + * all_ppp_mutex protects the all_ppp_units mapping. * It also ensures that finding a ppp unit in the all_ppp_units map * and updating its file.refcnt field is atomic. */ -static DECLARE_MUTEX(all_ppp_sem); +static DEFINE_MUTEX(all_ppp_mutex); static struct cardmap *all_ppp_units; static atomic_t ppp_unit_count = ATOMIC_INIT(0); @@ -804,7 +805,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, /* Attach to an existing ppp unit */ if (get_user(unit, p)) break; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); err = -ENXIO; ppp = ppp_find_unit(unit); if (ppp != 0) { @@ -812,7 +813,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, file->private_data = &ppp->file; err = 0; } - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); break; case PPPIOCATTCHAN: @@ -2446,7 +2447,7 @@ ppp_create_interface(int unit, int *retp) dev->do_ioctl = ppp_net_ioctl; ret = -EEXIST; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); if (unit < 0) unit = cardmap_find_first_free(all_ppp_units); else if (cardmap_get(all_ppp_units, unit) != NULL) @@ -2465,12 +2466,12 @@ ppp_create_interface(int unit, int *retp) atomic_inc(&ppp_unit_count); cardmap_set(&all_ppp_units, unit, ppp); - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); *retp = 0; return ppp; out2: - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); free_netdev(dev); out1: kfree(ppp); @@ -2500,7 +2501,7 @@ static void ppp_shutdown_interface(struct ppp *ppp) { struct net_device *dev; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); ppp_lock(ppp); dev = ppp->dev; ppp->dev = NULL; @@ -2514,7 +2515,7 @@ static void ppp_shutdown_interface(struct ppp *ppp) ppp->file.dead = 1; ppp->owner = NULL; wake_up_interruptible(&ppp->file.rwait); - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); } /* @@ -2556,7 +2557,7 @@ static void ppp_destroy_interface(struct ppp *ppp) /* * Locate an existing ppp unit. - * The caller should have locked the all_ppp_sem. + * The caller should have locked the all_ppp_mutex. */ static struct ppp * ppp_find_unit(int unit) @@ -2601,7 +2602,7 @@ ppp_connect_channel(struct channel *pch, int unit) int ret = -ENXIO; int hdrlen; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); ppp = ppp_find_unit(unit); if (ppp == 0) goto out; @@ -2626,7 +2627,7 @@ ppp_connect_channel(struct channel *pch, int unit) outl: write_unlock_bh(&pch->upl); out: - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); return ret; } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index a1cb07cdb60..253440a9802 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -128,6 +128,7 @@ static const struct mii_chip_info { { "SiS 900 Internal MII PHY", 0x001d, 0x8000, LAN }, { "SiS 7014 Physical Layer Solution", 0x0016, 0xf830, LAN }, { "Altimata AC101LF PHY", 0x0022, 0x5520, LAN }, + { "ADM 7001 LAN PHY", 0x002e, 0xcc60, LAN }, { "AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, LAN }, { "AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, HOME}, { "ICS LAN PHY", 0x0015, 0xF440, LAN }, diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index a5f2b1ee075..38a26df4095 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1727,7 +1727,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pTxd->pMBuf = pMessage; - pTxd->TBControl = Control | BMU_OWN | sk_frag->size;; + pTxd->TBControl = Control | BMU_OWN | sk_frag->size; /* ** Do we have the last fragment? diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 4eda81d41b1..35dbf05c7f0 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,7 +44,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.4" +#define DRV_VERSION "1.5" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -357,7 +357,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev) skge->net_stats.rx_bytes = data[1]; skge->net_stats.tx_packets = data[2] + data[4] + data[6]; skge->net_stats.rx_packets = data[3] + data[5] + data[7]; - skge->net_stats.multicast = data[5] + data[7]; + skge->net_stats.multicast = data[3] + data[5]; skge->net_stats.collisions = data[10]; skge->net_stats.tx_aborted_errors = data[12]; @@ -781,7 +781,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, * Note: DMA address is not changed by chip. * MTU not changed while receiver active. */ -static void skge_rx_reuse(struct skge_element *e, unsigned int size) +static inline void skge_rx_reuse(struct skge_element *e, unsigned int size) { struct skge_rx_desc *rd = e->desc; @@ -829,7 +829,7 @@ static int skge_rx_fill(struct skge_port *skge) do { struct sk_buff *skb; - skb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); + skb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_KERNEL); if (!skb) return -ENOMEM; @@ -847,8 +847,7 @@ static void skge_link_up(struct skge_port *skge) LED_BLK_OFF|LED_SYNC_OFF|LED_ON); netif_carrier_on(skge->netdev); - if (skge->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(skge->netdev); + netif_wake_queue(skge->netdev); if (netif_msg_link(skge)) printk(KERN_INFO PFX @@ -2155,7 +2154,7 @@ static int skge_up(struct net_device *dev) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); if (dev->mtu > RX_BUF_SIZE) - skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN; + skge->rx_buf_size = dev->mtu + ETH_HLEN; else skge->rx_buf_size = RX_BUF_SIZE; @@ -2190,8 +2189,6 @@ static int skge_up(struct net_device *dev) if (err) goto free_rx_ring; - skge->tx_avail = skge->tx_ring.count - 1; - /* Initialize MAC */ spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) @@ -2294,6 +2291,12 @@ static int skge_down(struct net_device *dev) return 0; } +static inline int skge_avail(const struct skge_ring *ring) +{ + return ((ring->to_clean > ring->to_use) ? 0 : ring->count) + + (ring->to_clean - ring->to_use) - 1; +} + static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); @@ -2314,7 +2317,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_LOCKED; } - if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { + if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -2390,8 +2393,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) dev->name, e - ring->start, skb->len); ring->to_use = e->next; - skge->tx_avail -= skb_shinfo(skb)->nr_frags + 1; - if (skge->tx_avail <= MAX_SKB_FRAGS + 1) { + if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) { pr_debug("%s: transmit queue full\n", dev->name); netif_stop_queue(dev); } @@ -2404,35 +2406,37 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e) +static void skge_tx_complete(struct skge_port *skge, struct skge_element *last) { - /* This ring element can be skb or fragment */ - if (e->skb) { - pci_unmap_single(hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_TODEVICE); - dev_kfree_skb(e->skb); + struct pci_dev *pdev = skge->hw->pdev; + struct skge_element *e; + + for (e = skge->tx_ring.to_clean; e != last; e = e->next) { + struct sk_buff *skb = e->skb; + int i; + e->skb = NULL; - } else { - pci_unmap_page(hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_TODEVICE); + pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr), + skb_headlen(skb), PCI_DMA_TODEVICE); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + e = e->next; + pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), + skb_shinfo(skb)->frags[i].size, + PCI_DMA_TODEVICE); + } + + dev_kfree_skb(skb); } + skge->tx_ring.to_clean = e; } static void skge_tx_clean(struct skge_port *skge) { - struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; spin_lock_bh(&skge->tx_lock); - for (e = ring->to_clean; e != ring->to_use; e = e->next) { - ++skge->tx_avail; - skge_tx_free(skge->hw, e); - } - ring->to_clean = e; + skge_tx_complete(skge, skge->tx_ring.to_use); + netif_wake_queue(skge->netdev); spin_unlock_bh(&skge->tx_lock); } @@ -2592,7 +2596,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, goto error; if (len < RX_COPY_THRESHOLD) { - skb = dev_alloc_skb(len + 2); + skb = alloc_skb(len + 2, GFP_ATOMIC); if (!skb) goto resubmit; @@ -2607,10 +2611,11 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, skge_rx_reuse(e, skge->rx_buf_size); } else { struct sk_buff *nskb; - nskb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); + nskb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_ATOMIC); if (!nskb) goto resubmit; + skb_reserve(nskb, NET_IP_ALIGN); pci_unmap_single(skge->hw->pdev, pci_unmap_addr(e, mapaddr), pci_unmap_len(e, maplen), @@ -2661,30 +2666,29 @@ resubmit: static void skge_tx_done(struct skge_port *skge) { struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; + struct skge_element *e, *last; spin_lock(&skge->tx_lock); - for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) { + last = ring->to_clean; + for (e = ring->to_clean; e != ring->to_use; e = e->next) { struct skge_tx_desc *td = e->desc; - u32 control; - rmb(); - control = td->control; - if (control & BMU_OWN) + if (td->control & BMU_OWN) break; - if (unlikely(netif_msg_tx_done(skge))) - printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n", - skge->netdev->name, e - ring->start, td->status); - - skge_tx_free(skge->hw, e); - e->skb = NULL; - ++skge->tx_avail; + if (td->control & BMU_EOF) { + last = e->next; + if (unlikely(netif_msg_tx_done(skge))) + printk(KERN_DEBUG PFX "%s: tx done slot %td\n", + skge->netdev->name, e - ring->start); + } } - ring->to_clean = e; + + skge_tx_complete(skge, last); + skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - if (skge->tx_avail > MAX_SKB_FRAGS + 1) + if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1) netif_wake_queue(skge->netdev); spin_unlock(&skge->tx_lock); @@ -2718,8 +2722,7 @@ static int skge_poll(struct net_device *dev, int *budget) netif_receive_skb(skb); ++work_done; - } else - skge_rx_reuse(e, skge->rx_buf_size); + } } ring->to_clean = e; diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 2efdacc290e..1f1ce88c818 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2418,7 +2418,6 @@ struct skge_port { int port; spinlock_t tx_lock; - u32 tx_avail; struct skge_ring tx_ring; struct skge_ring rx_ring; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f08fe6c884b..68f9c206a62 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1175,7 +1175,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* just drop the packet if non-linear expansion fails */ if (skb_header_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); goto out_unlock; } @@ -1324,7 +1324,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) PCI_DMA_TODEVICE); } - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); } sky2->tx_cons = put; @@ -2478,17 +2478,34 @@ static const struct sky2_stat { { "rx_unicast", GM_RXF_UC_OK }, { "tx_mac_pause", GM_TXF_MPAUSE }, { "rx_mac_pause", GM_RXF_MPAUSE }, - { "collisions", GM_TXF_SNG_COL }, + { "collisions", GM_TXF_COL }, { "late_collision",GM_TXF_LAT_COL }, { "aborted", GM_TXF_ABO_COL }, + { "single_collisions", GM_TXF_SNG_COL }, { "multi_collisions", GM_TXF_MUL_COL }, - { "fifo_underrun", GM_TXE_FIFO_UR }, - { "fifo_overflow", GM_RXE_FIFO_OV }, - { "rx_toolong", GM_RXF_LNG_ERR }, - { "rx_jabber", GM_RXF_JAB_PKT }, + + { "rx_short", GM_RXF_SHT }, { "rx_runt", GM_RXE_FRAG }, + { "rx_64_byte_packets", GM_RXF_64B }, + { "rx_65_to_127_byte_packets", GM_RXF_127B }, + { "rx_128_to_255_byte_packets", GM_RXF_255B }, + { "rx_256_to_511_byte_packets", GM_RXF_511B }, + { "rx_512_to_1023_byte_packets", GM_RXF_1023B }, + { "rx_1024_to_1518_byte_packets", GM_RXF_1518B }, + { "rx_1518_to_max_byte_packets", GM_RXF_MAX_SZ }, { "rx_too_long", GM_RXF_LNG_ERR }, + { "rx_fifo_overflow", GM_RXE_FIFO_OV }, + { "rx_jabber", GM_RXF_JAB_PKT }, { "rx_fcs_error", GM_RXF_FCS_ERR }, + + { "tx_64_byte_packets", GM_TXF_64B }, + { "tx_65_to_127_byte_packets", GM_TXF_127B }, + { "tx_128_to_255_byte_packets", GM_TXF_255B }, + { "tx_256_to_511_byte_packets", GM_TXF_511B }, + { "tx_512_to_1023_byte_packets", GM_TXF_1023B }, + { "tx_1024_to_1518_byte_packets", GM_TXF_1518B }, + { "tx_1519_to_max_byte_packets", GM_TXF_MAX_SZ }, + { "tx_fifo_underrun", GM_TXE_FIFO_UR }, }; static u32 sky2_get_rx_csum(struct net_device *dev) @@ -2590,7 +2607,7 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev) sky2->net_stats.rx_bytes = data[1]; sky2->net_stats.tx_packets = data[2] + data[4] + data[6]; sky2->net_stats.rx_packets = data[3] + data[5] + data[7]; - sky2->net_stats.multicast = data[5] + data[7]; + sky2->net_stats.multicast = data[3] + data[5]; sky2->net_stats.collisions = data[10]; sky2->net_stats.tx_aborted_errors = data[12]; diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index d63cd5a1b71..62532b4e45c 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1373,23 +1373,23 @@ enum { GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */ GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */ GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ +/* MIB Counters */ + GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */ + GM_MIB_CNT_SIZE = 256, }; -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ /* * MIB Counters base address definitions (low word) - * use offset 4 for access to high word (32 bit r/o) */ enum { - GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ + GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */ GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */ GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */ GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ + GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */ GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */ GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */ @@ -1397,37 +1397,36 @@ enum { GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */ GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */ GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */ - GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */ - GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */ - GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */ - GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */ - GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */ - GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */ - GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */ - GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ - GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ - GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */ - GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */ - GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */ - GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */ - GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */ - GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */ - GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */ - GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */ - GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */ - GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */ - GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */ - GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */ - GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */ - - GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */ - GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */ - GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */ - GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */ - GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */ - GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */ + GM_RXF_127B = GM_MIB_CNT_BASE + 104,/* 65-127 Byte Rx Frame */ + GM_RXF_255B = GM_MIB_CNT_BASE + 112,/* 128-255 Byte Rx Frame */ + GM_RXF_511B = GM_MIB_CNT_BASE + 120,/* 256-511 Byte Rx Frame */ + GM_RXF_1023B = GM_MIB_CNT_BASE + 128,/* 512-1023 Byte Rx Frame */ + GM_RXF_1518B = GM_MIB_CNT_BASE + 136,/* 1024-1518 Byte Rx Frame */ + GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144,/* 1519-MaxSize Byte Rx Frame */ + GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152,/* Rx Frame too Long Error */ + GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160,/* Rx Jabber Packet Frame */ + + GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176,/* Rx FIFO overflow Event */ + GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192,/* Unicast Frames Xmitted OK */ + GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200,/* Broadcast Frames Xmitted OK */ + GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208,/* Pause MAC Ctrl Frames Xmitted */ + GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216,/* Multicast Frames Xmitted OK */ + GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224,/* Octets Transmitted OK Low */ + GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232,/* Octets Transmitted OK High */ + GM_TXF_64B = GM_MIB_CNT_BASE + 240,/* 64 Byte Tx Frame */ + GM_TXF_127B = GM_MIB_CNT_BASE + 248,/* 65-127 Byte Tx Frame */ + GM_TXF_255B = GM_MIB_CNT_BASE + 256,/* 128-255 Byte Tx Frame */ + GM_TXF_511B = GM_MIB_CNT_BASE + 264,/* 256-511 Byte Tx Frame */ + GM_TXF_1023B = GM_MIB_CNT_BASE + 272,/* 512-1023 Byte Tx Frame */ + GM_TXF_1518B = GM_MIB_CNT_BASE + 280,/* 1024-1518 Byte Tx Frame */ + GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288,/* 1519-MaxSize Byte Tx Frame */ + + GM_TXF_COL = GM_MIB_CNT_BASE + 304,/* Tx Collision */ + GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312,/* Tx Late Collision */ + GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320,/* Tx aborted due to Exces. Col. */ + GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328,/* Tx Multiple Collision */ + GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336,/* Tx Single Collision */ + GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344,/* Tx FIFO Underrun Event */ }; /* GMAC Bit Definitions */ @@ -1805,7 +1804,7 @@ struct sky2_rx_le { __le16 length; u8 ctrl; u8 opcode; -} __attribute((packed));; +} __attribute((packed)); struct sky2_status_le { __le32 status; /* also checksum */ diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 01bdb233405..d4c0002b43d 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -71,7 +71,7 @@ static int lance_debug = LANCE_DEBUG; #else static int lance_debug = 1; #endif -MODULE_PARM(lance_debug, "i"); +module_param(lance_debug, int, 0); MODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 88829eb9568..b5473325bff 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.53" -#define DRV_MODULE_RELDATE "Mar 22, 2006" +#define DRV_MODULE_VERSION "3.54" +#define DRV_MODULE_RELDATE "Mar 23, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -225,6 +225,10 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, @@ -4557,6 +4561,7 @@ static int tg3_chip_reset(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tw32(GRC_FASTBOOT_PC, 0); @@ -6152,6 +6157,9 @@ static int tg3_reset_hw(struct tg3 *tp) gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | GRC_LCLCTRL_GPIO_OUTPUT3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL; + tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ @@ -6191,7 +6199,8 @@ static int tg3_reset_hw(struct tg3 *tp) } /* Enable host coalescing bug fix */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) val |= (1 << 29); tw32_f(WDMAC_MODE, val); @@ -6249,6 +6258,9 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(100); tp->rx_mode = RX_MODE_ENABLE; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); @@ -7907,7 +7919,8 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) return 0; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ethtool_op_set_tx_hw_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8332,7 +8345,8 @@ static int tg3_test_memory(struct tg3 *tp) int i; if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) mem_tbl = mem_tbl_5755; else mem_tbl = mem_tbl_5705; @@ -8924,6 +8938,47 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1; + + nvcfg1 = tr32(NVRAM_CFG1); + + /* NVRAM protection for TPM */ + if (nvcfg1 & (1 << 27)) + tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ: + case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + break; + case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + case FLASH_5755VENDOR_ATMEL_FLASH_1: + case FLASH_5755VENDOR_ATMEL_FLASH_2: + case FLASH_5755VENDOR_ATMEL_FLASH_3: + case FLASH_5755VENDOR_ATMEL_FLASH_4: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 264; + break; + case FLASH_5752VENDOR_ST_M45PE10: + case FLASH_5752VENDOR_ST_M45PE20: + case FLASH_5752VENDOR_ST_M45PE40: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 256; + break; + } +} + static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -8997,6 +9052,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tg3_get_5752_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tg3_get_5755_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tg3_get_5787_nvram_info(tp); else @@ -9310,6 +9367,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, nvram_cmd |= NVRAM_CMD_LAST; if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -10044,6 +10102,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -10053,7 +10112,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; } else @@ -10063,6 +10123,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; @@ -10219,6 +10280,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { @@ -10274,6 +10338,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; @@ -10413,7 +10478,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* All chips before 5787 can get confused if TX buffers * straddle the 4GB address boundary in some cases. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tp->dev->hard_start_xmit = tg3_start_xmit; else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; @@ -11002,6 +11068,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; + case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; @@ -11350,7 +11417,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) dev->features |= NETIF_F_HW_CSUM; else dev->features |= NETIF_F_IP_CSUM; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index baa34c4721d..c43cc326420 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -138,6 +138,7 @@ #define ASIC_REV_5752 0x06 #define ASIC_REV_5780 0x08 #define ASIC_REV_5714 0x09 +#define ASIC_REV_5755 0x0a #define ASIC_REV_5787 0x0b #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 @@ -456,6 +457,7 @@ #define RX_MODE_PROMISC 0x00000100 #define RX_MODE_NO_CRC_CHECK 0x00000200 #define RX_MODE_KEEP_VLAN_TAG 0x00000400 +#define RX_MODE_IPV6_CSUM_ENABLE 0x01000000 #define MAC_RX_STATUS 0x0000046c #define RX_STATUS_REMOTE_TX_XOFFED 0x00000001 #define RX_STATUS_XOFF_RCVD 0x00000002 @@ -1340,6 +1342,7 @@ #define GRC_LCLCTRL_CLEARINT 0x00000002 #define GRC_LCLCTRL_SETINT 0x00000004 #define GRC_LCLCTRL_INT_ON_ATTN 0x00000008 +#define GRC_LCLCTRL_GPIO_UART_SEL 0x00000010 /* 5755 only */ #define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */ #define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */ #define GRC_LCLCTRL_GPIO_INPUT3 0x00000020 @@ -1441,6 +1444,9 @@ #define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001 #define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002 #define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000 +#define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003 +#define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003 +#define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002 #define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003 #define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002 #define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000 @@ -2259,6 +2265,7 @@ struct tg3 { #define PHY_ID_BCM5752 0x60008100 #define PHY_ID_BCM5714 0x60008340 #define PHY_ID_BCM5780 0x60008350 +#define PHY_ID_BCM5755 0xbc050cc0 #define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff @@ -2286,7 +2293,7 @@ struct tg3 { (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ - (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 6299e186c73..e3dd144d326 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1327,11 +1327,11 @@ static void de_clean_rings (struct de_private *de) struct sk_buff *skb = de->tx_skb[i].skb; if ((skb) && (skb != DE_DUMMY_SKB)) { if (skb != DE_SETUP_SKB) { - dev_kfree_skb(skb); de->net_stats.tx_dropped++; pci_unmap_single(de->pdev, de->tx_skb[i].mapping, skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb(skb); } else { pci_unmap_single(de->pdev, de->tx_skb[i].mapping, diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5b0a19a5058..fd17aa8491b 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -25,6 +25,16 @@ config NET_RADIO the tools from <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. +config NET_WIRELESS_RTNETLINK + bool "Wireless Extension API over RtNetlink" + depends on NET_RADIO + ---help--- + Support the Wireless Extension API over the RtNetlink socket + in addition to the traditional ioctl interface (selected above). + + For now, few tools use this facility, but it might grow in the + future. The only downside is that it adds 4.5 kB to your kernel. + # Note : the cards are obsolete (can't buy them anymore), but the drivers # are not, as people are still using them... comment "Obsolete Wireless cards support (pre-802.11)" diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 864937a409e..108d9fed8f0 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -770,6 +770,11 @@ typedef struct { } BSSListRid; typedef struct { + BSSListRid bss; + struct list_head list; +} BSSListElement; + +typedef struct { u8 rssipct; u8 rssidBm; } tdsRssiEntry; @@ -902,6 +907,7 @@ static char swversion[] = "2.1"; #define NUM_MODULES 2 #define MIC_MSGLEN_MAX 2400 #define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX +#define AIRO_DEF_MTU 2312 typedef struct { u32 size; // size @@ -1119,6 +1125,8 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi); static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); +static void airo_networks_free(struct airo_info *ai); + struct airo_info { struct net_device_stats stats; struct net_device *dev; @@ -1150,7 +1158,7 @@ struct airo_info { #define FLAG_COMMIT 13 #define FLAG_RESET 14 #define FLAG_FLASHING 15 -#define JOB_MASK 0x1ff0000 +#define JOB_MASK 0x2ff0000 #define JOB_DIE 16 #define JOB_XMIT 17 #define JOB_XMIT11 18 @@ -1160,6 +1168,7 @@ struct airo_info { #define JOB_EVENT 22 #define JOB_AUTOWEP 23 #define JOB_WSTATS 24 +#define JOB_SCAN_RESULTS 25 int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap); unsigned short *flash; @@ -1176,7 +1185,7 @@ struct airo_info { } xmit, xmit11; struct net_device *wifidev; struct iw_statistics wstats; // wireless stats - unsigned long scan_timestamp; /* Time started to scan */ + unsigned long scan_timeout; /* Time scan should be read */ struct iw_spy_data spy_data; struct iw_public_data wireless_data; /* MIC stuff */ @@ -1198,6 +1207,10 @@ struct airo_info { APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; + + struct list_head network_list; + struct list_head network_free_list; + BSSListElement *networks; }; static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, @@ -1216,6 +1229,22 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime); static int flashputbuf(struct airo_info *ai); static int flashrestart(struct airo_info *ai,struct net_device *dev); +#define airo_print(type, name, fmt, args...) \ + { printk(type "airo(%s): " fmt "\n", name, ##args); } + +#define airo_print_info(name, fmt, args...) \ + airo_print(KERN_INFO, name, fmt, ##args) + +#define airo_print_dbg(name, fmt, args...) \ + airo_print(KERN_DEBUG, name, fmt, ##args) + +#define airo_print_warn(name, fmt, args...) \ + airo_print(KERN_WARNING, name, fmt, ##args) + +#define airo_print_err(name, fmt, args...) \ + airo_print(KERN_ERR, name, fmt, ##args) + + /*********************************************************************** * MIC ROUTINES * *********************************************************************** @@ -1294,7 +1323,7 @@ static int micsetup(struct airo_info *ai) { ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP); if (ai->tfm == NULL) { - printk(KERN_ERR "airo: failed to load transform for AES\n"); + airo_print_err(ai->dev->name, "failed to load transform for AES"); return ERROR; } @@ -1726,11 +1755,11 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo wkr.kindex = cpu_to_le16(wkr.kindex); wkr.klen = cpu_to_le16(wkr.klen); rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock); - if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc); + if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc); if (perm) { rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock); if (rc!=SUCCESS) { - printk(KERN_ERR "airo: WEP_PERM set %x\n", rc); + airo_print_err(ai->dev->name, "WEP_PERM set %x", rc); } } return rc; @@ -1909,7 +1938,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct airo_info *ai = dev->priv; if (!skb) { - printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__); + airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__); return 0; } npacks = skb_queue_len (&ai->txq); @@ -1955,8 +1984,8 @@ static int mpi_send_packet (struct net_device *dev) /* get a packet to send */ if ((skb = skb_dequeue(&ai->txq)) == 0) { - printk (KERN_ERR - "airo: %s: Dequeue'd zero in send_packet()\n", + airo_print_err(dev->name, + "%s: Dequeue'd zero in send_packet()", __FUNCTION__); return 0; } @@ -2108,7 +2137,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { u32 *fids = priv->fids; if ( skb == NULL ) { - printk( KERN_ERR "airo: skb == NULL!!!\n" ); + airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); return 0; } @@ -2179,7 +2208,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { } if ( skb == NULL ) { - printk( KERN_ERR "airo: skb == NULL!!!\n" ); + airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); return 0; } @@ -2364,6 +2393,8 @@ void stop_airo_card( struct net_device *dev, int freeres ) dev_kfree_skb(skb); } + airo_networks_free (ai); + kfree(ai->flash); kfree(ai->rssi); kfree(ai->APList); @@ -2434,7 +2465,7 @@ static int mpi_init_descriptors (struct airo_info *ai) cmd.parm2 = MPI_MAX_FIDS; rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate RX FID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate RX FID"); return rc; } @@ -2462,7 +2493,7 @@ static int mpi_init_descriptors (struct airo_info *ai) rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate TX FID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate TX FID"); return rc; } @@ -2476,7 +2507,7 @@ static int mpi_init_descriptors (struct airo_info *ai) cmd.parm2 = 1; /* Magic number... */ rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate RID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate RID"); return rc; } @@ -2508,25 +2539,25 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, aux_len = AUXMEMSIZE; if (!request_mem_region(mem_start, mem_len, name)) { - printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", (int)mem_start, (int)mem_len, name); goto out; } if (!request_mem_region(aux_start, aux_len, name)) { - printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", (int)aux_start, (int)aux_len, name); goto free_region1; } ai->pcimem = ioremap(mem_start, mem_len); if (!ai->pcimem) { - printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", (int)mem_start, (int)mem_len, name); goto free_region2; } ai->pciaux = ioremap(aux_start, aux_len); if (!ai->pciaux) { - printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", (int)aux_start, (int)aux_len, name); goto free_memmap; } @@ -2534,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, /* Reserve PKTSIZE for each fid and 2K for the Rids */ ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma); if (!ai->shared) { - printk(KERN_ERR "airo: Couldn't alloc_consistent %d\n", + airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d", PCI_SHARED_LEN); goto free_auxmap; } @@ -2626,7 +2657,7 @@ static void wifi_setup(struct net_device *dev) dev->type = ARPHRD_IEEE80211; dev->hard_header_len = ETH_HLEN; - dev->mtu = 2312; + dev->mtu = AIRO_DEF_MTU; dev->addr_len = ETH_ALEN; dev->tx_queue_len = 100; @@ -2670,6 +2701,42 @@ static int reset_card( struct net_device *dev , int lock) { return 0; } +#define MAX_NETWORK_COUNT 64 +static int airo_networks_allocate(struct airo_info *ai) +{ + if (ai->networks) + return 0; + + ai->networks = + kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement), + GFP_KERNEL); + if (!ai->networks) { + airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); + return -ENOMEM; + } + + return 0; +} + +static void airo_networks_free(struct airo_info *ai) +{ + if (!ai->networks) + return; + kfree(ai->networks); + ai->networks = NULL; +} + +static void airo_networks_initialize(struct airo_info *ai) +{ + int i; + + INIT_LIST_HEAD(&ai->network_free_list); + INIT_LIST_HEAD(&ai->network_list); + for (i = 0; i < MAX_NETWORK_COUNT; i++) + list_add_tail(&ai->networks[i].list, + &ai->network_free_list); +} + static struct net_device *_init_airo_card( unsigned short irq, int port, int is_pcmcia, struct pci_dev *pci, struct device *dmdev ) @@ -2681,22 +2748,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, /* Create the network device object. */ dev = alloc_etherdev(sizeof(*ai)); if (!dev) { - printk(KERN_ERR "airo: Couldn't alloc_etherdev\n"); + airo_print_err("", "Couldn't alloc_etherdev"); return NULL; } if (dev_alloc_name(dev, dev->name) < 0) { - printk(KERN_ERR "airo: Couldn't get name!\n"); + airo_print_err("", "Couldn't get name!"); goto err_out_free; } ai = dev->priv; ai->wifidev = NULL; ai->flags = 0; + ai->dev = dev; if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { - printk(KERN_DEBUG "airo: Found an MPI350 card\n"); + airo_print_dbg(dev->name, "Found an MPI350 card"); set_bit(FLAG_MPI, &ai->flags); } - ai->dev = dev; spin_lock_init(&ai->aux_lock); sema_init(&ai->sem, 1); ai->config.len = 0; @@ -2711,6 +2778,10 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, if (rc) goto err_out_thr; + if (airo_networks_allocate (ai)) + goto err_out_unlink; + airo_networks_initialize (ai); + /* The Airo-specific entries in the device structure. */ if (test_bit(FLAG_MPI,&ai->flags)) { skb_queue_head_init (&ai->txq); @@ -2732,33 +2803,33 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, SET_NETDEV_DEV(dev, dmdev); - reset_card (dev, 1); msleep(400); rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev ); if (rc) { - printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc ); + airo_print_err(dev->name, "register interrupt %d failed, rc %d", + irq, rc); goto err_out_unlink; } if (!is_pcmcia) { if (!request_region( dev->base_addr, 64, dev->name )) { rc = -EBUSY; - printk(KERN_ERR "airo: Couldn't request region\n"); + airo_print_err(dev->name, "Couldn't request region"); goto err_out_irq; } } if (test_bit(FLAG_MPI,&ai->flags)) { if (mpi_map_card(ai, pci, dev->name)) { - printk(KERN_ERR "airo: Could not map memory\n"); + airo_print_err(dev->name, "Could not map memory"); goto err_out_res; } } if (probe) { if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) { - printk( KERN_ERR "airo: MAC could not be enabled\n" ); + airo_print_err(dev->name, "MAC could not be enabled" ); rc = -EIO; goto err_out_map; } @@ -2769,21 +2840,20 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, rc = register_netdev(dev); if (rc) { - printk(KERN_ERR "airo: Couldn't register_netdev\n"); + airo_print_err(dev->name, "Couldn't register_netdev"); goto err_out_map; } ai->wifidev = init_wifidev(ai, dev); set_bit(FLAG_REGISTERED,&ai->flags); - printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", - dev->name, + airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] ); /* Allocate the transmit buffers */ if (probe && !test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2); + ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); setup_proc_entry( dev, dev->priv ); /* XXX check for failure */ netif_start_queue(dev); @@ -2840,16 +2910,16 @@ int reset_airo_card( struct net_device *dev ) return -1; if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) { - printk( KERN_ERR "airo: MAC could not be enabled\n" ); + airo_print_err(dev->name, "MAC could not be enabled"); return -1; } - printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", dev->name, + airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); /* Allocate the transmit buffers if needed */ if (!test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate (ai,2312,i>=MAX_FIDS/2); + ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); enable_interrupts( ai ); netif_wake_queue(dev); @@ -2875,6 +2945,65 @@ static void airo_send_event(struct net_device *dev) { wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); } +static void airo_process_scan_results (struct airo_info *ai) { + union iwreq_data wrqu; + BSSListRid BSSList; + int rc; + BSSListElement * loop_net; + BSSListElement * tmp_net; + + /* Blow away current list of scan results */ + list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) { + list_move_tail (&loop_net->list, &ai->network_free_list); + /* Don't blow away ->list, just BSS data */ + memset (loop_net, 0, sizeof (loop_net->bss)); + } + + /* Try to read the first entry of the scan result */ + rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0); + if((rc) || (BSSList.index == 0xffff)) { + /* No scan results */ + goto out; + } + + /* Read and parse all entries */ + tmp_net = NULL; + while((!rc) && (BSSList.index != 0xffff)) { + /* Grab a network off the free list */ + if (!list_empty(&ai->network_free_list)) { + tmp_net = list_entry(ai->network_free_list.next, + BSSListElement, list); + list_del(ai->network_free_list.next); + } + + if (tmp_net != NULL) { + memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss)); + list_add_tail(&tmp_net->list, &ai->network_list); + tmp_net = NULL; + } + + /* Read next entry */ + rc = PC4500_readrid(ai, RID_BSSLISTNEXT, + &BSSList, sizeof(BSSList), 0); + } + +out: + ai->scan_timeout = 0; + clear_bit(JOB_SCAN_RESULTS, &ai->flags); + up(&ai->sem); + + /* Send an empty event to user space. + * We don't send the received data on + * the event because it would require + * us to do complex transcoding, and + * we want to minimise the work done in + * the irq handler. Use a request to + * extract the data - Jean II */ + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL); +} + static int airo_thread(void *data) { struct net_device *dev = data; struct airo_info *ai = dev->priv; @@ -2904,13 +3033,26 @@ static int airo_thread(void *data) { set_current_state(TASK_INTERRUPTIBLE); if (ai->flags & JOB_MASK) break; - if (ai->expires) { - if (time_after_eq(jiffies,ai->expires)){ + if (ai->expires || ai->scan_timeout) { + if (ai->scan_timeout && + time_after_eq(jiffies,ai->scan_timeout)){ + set_bit(JOB_SCAN_RESULTS,&ai->flags); + break; + } else if (ai->expires && + time_after_eq(jiffies,ai->expires)){ set_bit(JOB_AUTOWEP,&ai->flags); break; } if (!signal_pending(current)) { - schedule_timeout(ai->expires - jiffies); + unsigned long wake_at; + if (!ai->expires || !ai->scan_timeout) { + wake_at = max(ai->expires, + ai->scan_timeout); + } else { + wake_at = min(ai->expires, + ai->scan_timeout); + } + schedule_timeout(wake_at - jiffies); continue; } } else if (!signal_pending(current)) { @@ -2953,6 +3095,10 @@ static int airo_thread(void *data) { airo_send_event(dev); else if (test_bit(JOB_AUTOWEP, &ai->flags)) timer_func(dev); + else if (test_bit(JOB_SCAN_RESULTS, &ai->flags)) + airo_process_scan_results(ai); + else /* Shouldn't get here, but we make sure to unlock */ + up(&ai->sem); } complete_and_exit (&ai->thr_exited, 0); } @@ -3047,19 +3193,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) * and reassociations as valid status * Jean II */ if(newStatus == ASSOCIATED) { - if (apriv->scan_timestamp) { - /* Send an empty event to user space. - * We don't send the received data on - * the event because it would require - * us to do complex transcoding, and - * we want to minimise the work done in - * the irq handler. Use a request to - * extract the data - Jean II */ - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); - apriv->scan_timestamp = 0; +#if 0 + /* FIXME: Grabbing scan results here + * seems to be too early??? Just wait for + * timeout instead. */ + if (apriv->scan_timeout > 0) { + set_bit(JOB_SCAN_RESULTS, &apriv->flags); + wake_up_interruptible(&apriv->thr_wait); } +#endif if (down_trylock(&apriv->sem) != 0) { set_bit(JOB_EVENT, &apriv->flags); wake_up_interruptible(&apriv->thr_wait); @@ -3117,8 +3259,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) } len = le16_to_cpu(hdr.len); - if (len > 2312) { - printk( KERN_ERR "airo: Bad size %d\n", len ); + if (len > AIRO_DEF_MTU) { + airo_print_err(apriv->dev->name, "Bad size %d", len); goto badrx; } if (len == 0) @@ -3161,10 +3303,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) bap_read (apriv, &gap, sizeof(gap), BAP0); gap = le16_to_cpu(gap); if (gap) { - if (gap <= 8) + if (gap <= 8) { bap_read (apriv, tmpbuf, gap, BAP0); - else - printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n"); + } else { + airo_print_err(apriv->dev->name, "gaplen too " + "big. Problems will follow..."); + } } bap_read (apriv, buffer + hdrlen/2, len, BAP0); } else { @@ -3281,12 +3425,13 @@ exitrx: } } else { OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); - printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" ); + airo_print_err(apriv->dev->name, "Unallocated FID was " + "used to xmit" ); } } exittx: if ( status & ~STATUS_INTS & ~IGNORE_INTS ) - printk( KERN_WARNING "airo: Got weird status %x\n", + airo_print_warn(apriv->dev->name, "Got weird status %x", status & ~STATUS_INTS & ~IGNORE_INTS ); } @@ -3359,8 +3504,8 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { up(&ai->sem); if (rc) - printk(KERN_ERR "%s: Cannot enable MAC, err=%d\n", - __FUNCTION__,rc); + airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d", + __FUNCTION__, rc); return rc; } @@ -3489,8 +3634,8 @@ void mpi_receive_802_11 (struct airo_info *ai) if (ai->wifidev == NULL) hdr.len = 0; len = le16_to_cpu(hdr.len); - if (len > 2312) { - printk( KERN_ERR "airo: Bad size %d\n", len ); + if (len > AIRO_DEF_MTU) { + airo_print_err(ai->dev->name, "Bad size %d", len); goto badrx; } if (len == 0) @@ -3531,8 +3676,8 @@ void mpi_receive_802_11 (struct airo_info *ai) if (gap <= 8) ptr += gap; else - printk(KERN_ERR - "airo: gaplen too big. Problems will follow...\n"); + airo_print_err(ai->dev->name, + "gaplen too big. Problems will follow..."); } memcpy ((char *)buffer + hdrlen, ptr, len); ptr += len; @@ -3604,15 +3749,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { if (lock) up(&ai->sem); - printk(KERN_ERR "airo: Error checking for AUX port\n"); + airo_print_err(ai->dev->name, "Error checking for AUX port"); return ERROR; } if (!aux_bap || rsp.status & 0xff00) { ai->bap_read = fast_bap_read; - printk(KERN_DEBUG "airo: Doing fast bap_reads\n"); + airo_print_dbg(ai->dev->name, "Doing fast bap_reads"); } else { ai->bap_read = aux_bap_read; - printk(KERN_DEBUG "airo: Doing AUX bap_reads\n"); + airo_print_dbg(ai->dev->name, "Doing AUX bap_reads"); } } if (lock) @@ -3643,7 +3788,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (cap_rid.softCap & 8) ai->config.rmode |= RXMODE_NORMALIZED_RSSI; else - printk(KERN_WARNING "airo: unknown received signal level scale\n"); + airo_print_warn(ai->dev->name, "unknown received signal " + "level scale"); } ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; ai->config.authType = AUTH_OPEN; @@ -3706,7 +3852,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) status = enable_MAC(ai, &rsp, lock); if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) { - printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); + airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x," + " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); return ERROR; } @@ -3749,8 +3896,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { } if ( max_tries == -1 ) { - printk( KERN_ERR - "airo: Max tries exceeded when issueing command\n" ); + airo_print_err(ai->dev->name, + "Max tries exceeded when issueing command"); if (IN4500(ai, COMMAND) & COMMAND_BUSY) OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); return ERROR; @@ -3762,11 +3909,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { pRsp->rsp1 = IN4500(ai, RESP1); pRsp->rsp2 = IN4500(ai, RESP2); if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) { - printk (KERN_ERR "airo: cmd= %x\n", pCmd->cmd); - printk (KERN_ERR "airo: status= %x\n", pRsp->status); - printk (KERN_ERR "airo: Rsp0= %x\n", pRsp->rsp0); - printk (KERN_ERR "airo: Rsp1= %x\n", pRsp->rsp1); - printk (KERN_ERR "airo: Rsp2= %x\n", pRsp->rsp2); + airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd); + airo_print_err(ai->dev->name, "status= %x\n", pRsp->status); + airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0); + airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1); + airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2); } // clear stuck command busy if necessary @@ -3799,15 +3946,15 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ) } } else if ( status & BAP_ERR ) { /* invalid rid or offset */ - printk( KERN_ERR "airo: BAP error %x %d\n", + airo_print_err(ai->dev->name, "BAP error %x %d", status, whichbap ); return ERROR; } else if (status & BAP_DONE) { // success return SUCCESS; } if ( !(max_tries--) ) { - printk( KERN_ERR - "airo: BAP setup error too many retries\n" ); + airo_print_err(ai->dev->name, + "airo: BAP setup error too many retries\n"); return ERROR; } // -- PC4500 missed it, try again @@ -3962,8 +4109,8 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2; if ( len <= 2 ) { - printk( KERN_ERR - "airo: Rid %x has a length of %d which is too short\n", + airo_print_err(ai->dev->name, + "Rid %x has a length of %d which is too short", (int)rid, (int)len ); rc = ERROR; goto done; @@ -3996,8 +4143,8 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, Resp rsp; if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid)) - printk(KERN_ERR - "%s: MAC should be disabled (rid=%04x)\n", + airo_print_err(ai->dev->name, + "%s: MAC should be disabled (rid=%04x)", __FUNCTION__, rid); memset(&cmd, 0, sizeof(cmd)); memset(&rsp, 0, sizeof(rsp)); @@ -4013,7 +4160,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, &ai->config_desc.rid_desc, sizeof(Rid)); if (len < 4 || len > 2047) { - printk(KERN_ERR "%s: len=%d\n",__FUNCTION__,len); + airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len); rc = -1; } else { memcpy((char *)ai->config_desc.virtual_host_addr, @@ -4021,10 +4168,10 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, rc = issuecommand(ai, &cmd, &rsp); if ((rc & 0xff00) != 0) { - printk(KERN_ERR "%s: Write rid Error %d\n", - __FUNCTION__,rc); - printk(KERN_ERR "%s: Cmd=%04x\n", - __FUNCTION__,cmd.cmd); + airo_print_err(ai->dev->name, "%s: Write rid Error %d", + __FUNCTION__, rc); + airo_print_err(ai->dev->name, "%s: Cmd=%04x", + __FUNCTION__, cmd.cmd); } if ((rsp.status & 0x7f00)) @@ -4123,7 +4270,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) len >>= 16; if (len <= ETH_ALEN * 2) { - printk( KERN_WARNING "Short packet %d\n", len ); + airo_print_warn(ai->dev->name, "Short packet %d", len); return ERROR; } len -= ETH_ALEN * 2; @@ -4187,7 +4334,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket) } if (len < hdrlen) { - printk( KERN_WARNING "Short packet %d\n", len ); + airo_print_warn(ai->dev->name, "Short packet %d", len); return ERROR; } @@ -4584,15 +4731,14 @@ static int proc_stats_rid_open( struct inode *inode, i*4<stats.len; i++){ if (!statsLabels[i]) continue; if (j+strlen(statsLabels[i])+16>4096) { - printk(KERN_WARNING - "airo: Potentially disasterous buffer overflow averted!\n"); + airo_print_warn(apriv->dev->name, + "Potentially disasterous buffer overflow averted!"); break; } j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]); } if (i*4>=stats.len){ - printk(KERN_WARNING - "airo: Got a short rid\n"); + airo_print_warn(apriv->dev->name, "Got a short rid"); } data->readlen = j; return 0; @@ -4754,7 +4900,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 14; v = get_dec_u16(line, &i, 4); - v = (v<0) ? 0 : ((v>2312) ? 2312 : v); + v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); ai->config.rtsThres = (u16)v; set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) { @@ -4788,7 +4934,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 15; v = get_dec_u16(line, &i, 4); - v = (v<256) ? 256 : ((v>2312) ? 2312 : v); + v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); v = v & 0xfffe; /* Make sure its even */ ai->config.fragThresh = (u16)v; set_bit (FLAG_COMMIT, &ai->flags); @@ -4798,8 +4944,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { case 'd': ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break; case 'c': ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break; case 'm': ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break; - default: - printk( KERN_WARNING "airo: Unknown modulation\n" ); + default: airo_print_warn(ai->dev->name, "Unknown modulation"); } } else if (!strncmp(line, "Preamble: ", 10)) { line += 10; @@ -4807,10 +4952,10 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break; case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break; case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break; - default: printk(KERN_WARNING "airo: Unknown preamble\n"); + default: airo_print_warn(ai->dev->name, "Unknown preamble"); } } else { - printk( KERN_WARNING "Couldn't figure out %s\n", line ); + airo_print_warn(ai->dev->name, "Couldn't figure out %s", line); } while( line[0] && line[0] != '\n' ) line++; if ( line[0] ) line++; @@ -5076,7 +5221,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { } j = 2; } else { - printk(KERN_ERR "airo: WepKey passed invalid key index\n"); + airo_print_err(ai->dev->name, "WepKey passed invalid key index"); return; } @@ -5489,17 +5634,16 @@ static int __init airo_init_module( void ) airo_entry->gid = proc_gid; for( i = 0; i < 4 && io[i] && irq[i]; i++ ) { - printk( KERN_INFO - "airo: Trying to configure ISA adapter at irq=%d io=0x%x\n", - irq[i], io[i] ); + airo_print_info("", "Trying to configure ISA adapter at irq=%d " + "io=0x%x", irq[i], io[i] ); if (init_airo_card( irq[i], io[i], 0, NULL )) have_isa_dev = 1; } #ifdef CONFIG_PCI - printk( KERN_INFO "airo: Probing for PCI adapters\n" ); + airo_print_info("", "Probing for PCI adapters"); pci_register_driver(&airo_driver); - printk( KERN_INFO "airo: Finished probing for PCI adapters\n" ); + airo_print_info("", "Finished probing for PCI adapters"); #endif /* Always exit with success, as we are a library module @@ -5511,7 +5655,7 @@ static int __init airo_init_module( void ) static void __exit airo_cleanup_module( void ) { while( airo_devices ) { - printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name ); + airo_print_info(airo_devices->dev->name, "Unregistering...\n"); stop_airo_card( airo_devices->dev, 1 ); } #ifdef CONFIG_PCI @@ -5622,7 +5766,8 @@ static int airo_set_freq(struct net_device *dev, /* We should do a better check than that, * based on the card capability !!! */ if((channel < 1) || (channel > 14)) { - printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m); + airo_print_dbg(dev->name, "New channel value of %d is invalid!", + fwrq->m); rc = -EINVAL; } else { readConfigRid(local, 1); @@ -5946,8 +6091,8 @@ static int airo_set_rts(struct net_device *dev, int rthr = vwrq->value; if(vwrq->disabled) - rthr = 2312; - if((rthr < 0) || (rthr > 2312)) { + rthr = AIRO_DEF_MTU; + if((rthr < 0) || (rthr > AIRO_DEF_MTU)) { return -EINVAL; } readConfigRid(local, 1); @@ -5970,7 +6115,7 @@ static int airo_get_rts(struct net_device *dev, readConfigRid(local, 1); vwrq->value = local->config.rtsThres; - vwrq->disabled = (vwrq->value >= 2312); + vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; return 0; @@ -5989,8 +6134,8 @@ static int airo_set_frag(struct net_device *dev, int fthr = vwrq->value; if(vwrq->disabled) - fthr = 2312; - if((fthr < 256) || (fthr > 2312)) { + fthr = AIRO_DEF_MTU; + if((fthr < 256) || (fthr > AIRO_DEF_MTU)) { return -EINVAL; } fthr &= ~0x1; /* Get an even value - is it really needed ??? */ @@ -6014,7 +6159,7 @@ static int airo_get_frag(struct net_device *dev, readConfigRid(local, 1); vwrq->value = local->config.fragThresh; - vwrq->disabled = (vwrq->value >= 2312); + vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; return 0; @@ -6709,9 +6854,9 @@ static int airo_get_range(struct net_device *dev, range->throughput = 1500 * 1000; range->min_rts = 0; - range->max_rts = 2312; + range->max_rts = AIRO_DEF_MTU; range->min_frag = 256; - range->max_frag = 2312; + range->max_frag = AIRO_DEF_MTU; if(cap_rid.softCap & 2) { // WEP: RC4 40 bits @@ -6972,6 +7117,7 @@ static int airo_set_scan(struct net_device *dev, struct airo_info *ai = dev->priv; Cmd cmd; Resp rsp; + int wake = 0; /* Note : you may have realised that, as this is a SET operation, * this is privileged and therefore a normal user can't @@ -6981,17 +7127,25 @@ static int airo_set_scan(struct net_device *dev, * Jean II */ if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + + /* If there's already a scan in progress, don't + * trigger another one. */ + if (ai->scan_timeout > 0) + goto out; + /* Initiate a scan command */ memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_LISTBSS; - if (down_interruptible(&ai->sem)) - return -ERESTARTSYS; issuecommand(ai, &cmd, &rsp); - ai->scan_timestamp = jiffies; - up(&ai->sem); - - /* At this point, just return to the user. */ + ai->scan_timeout = RUN_AT(3*HZ); + wake = 1; +out: + up(&ai->sem); + if (wake) + wake_up_interruptible(&ai->thr_wait); return 0; } @@ -7111,59 +7265,38 @@ static int airo_get_scan(struct net_device *dev, char *extra) { struct airo_info *ai = dev->priv; - BSSListRid BSSList; - int rc; + BSSListElement *net; + int err = 0; char *current_ev = extra; - /* When we are associated again, the scan has surely finished. - * Just in case, let's make sure enough time has elapsed since - * we started the scan. - Javier */ - if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) { - /* Important note : we don't want to block the caller - * until results are ready for various reasons. - * First, managing wait queues is complex and racy - * (there may be multiple simultaneous callers). - * Second, we grab some rtnetlink lock before comming - * here (in dev_ioctl()). - * Third, the caller can wait on the Wireless Event - * - Jean II */ + /* If a scan is in-progress, return -EAGAIN */ + if (ai->scan_timeout > 0) return -EAGAIN; - } - ai->scan_timestamp = 0; - /* There's only a race with proc_BSSList_open(), but its - * consequences are begnign. So I don't bother fixing it - Javier */ - - /* Try to read the first entry of the scan result */ - rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1); - if((rc) || (BSSList.index == 0xffff)) { - /* Client error, no scan results... - * The caller need to restart the scan. */ - return -ENODATA; - } + if (down_interruptible(&ai->sem)) + return -EAGAIN; - /* Read and parse all entries */ - while((!rc) && (BSSList.index != 0xffff)) { + list_for_each_entry (net, &ai->network_list, list) { /* Translate to WE format this entry */ current_ev = airo_translate_scan(dev, current_ev, extra + dwrq->length, - &BSSList); + &net->bss); /* Check if there is space for one more entry */ if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { /* Ask user space to try again with a bigger buffer */ - return -E2BIG; + err = -E2BIG; + goto out; } - - /* Read next entry */ - rc = PC4500_readrid(ai, RID_BSSLISTNEXT, - &BSSList, sizeof(BSSList), 1); } + /* Length of data */ dwrq->length = (current_ev - extra); dwrq->flags = 0; /* todo */ - return 0; +out: + up(&ai->sem); + return err; } /*------------------------------------------------------------------*/ @@ -7711,7 +7844,7 @@ static int cmdreset(struct airo_info *ai) { disable_MAC(ai, 1); if(!waitbusy (ai)){ - printk(KERN_INFO "Waitbusy hang before RESET\n"); + airo_print_info(ai->dev->name, "Waitbusy hang before RESET"); return -EBUSY; } @@ -7720,7 +7853,7 @@ static int cmdreset(struct airo_info *ai) { ssleep(1); /* WAS 600 12/7/00 */ if(!waitbusy (ai)){ - printk(KERN_INFO "Waitbusy hang AFTER RESET\n"); + airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET"); return -EBUSY; } return 0; @@ -7748,7 +7881,7 @@ static int setflashmode (struct airo_info *ai) { if(!waitbusy(ai)) { clear_bit (FLAG_FLASHING, &ai->flags); - printk(KERN_INFO "Waitbusy hang after setflash mode\n"); + airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode"); return -EIO; } return 0; @@ -7777,7 +7910,7 @@ static int flashpchar(struct airo_info *ai,int byte,int dwelltime) { /* timeout for busy clear wait */ if(waittime <= 0 ){ - printk(KERN_INFO "flash putchar busywait timeout! \n"); + airo_print_info(ai->dev->name, "flash putchar busywait timeout!"); return -EBUSY; } @@ -7866,7 +7999,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev){ if (!test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) { ai->fids[i] = transmit_allocate - ( ai, 2312, i >= MAX_FIDS / 2 ); + ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 ); } ssleep(1); /* Added 12/7/00 */ diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 753a1de6664..06c3fa32b31 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr) if (ret == 1) { sta = ap_add_sta(ap, sta_addr); if (!sta) - ret = -1; + return -1; sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; sta->ap = 1; memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index f8f4503475f..d335b250923 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link) parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL); if (parse == NULL || hw_priv == NULL) { - kfree(parse); - kfree(hw_priv); ret = -ENOMEM; goto failed; } diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index b1f142d9e23..328e9a1d13b 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len) res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL); up(&local->rid_bap_sem); + if (res) { printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE " "failed (res=%d, rid=%04x, len=%d)\n", dev->name, res, rid, len); - return res; - } - if (res == -ETIMEDOUT) - prism2_hw_reset(dev); + if (res == -ETIMEDOUT) + prism2_hw_reset(dev); + } return res; } diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index f3e0ce1ee03..8b37e824dfc 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { if (!sta_ptr) local->tx_keyidx = i; - else if (i) { - ret = -EINVAL; - goto done; - } } diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 2e85bdced2d..194f0709758 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev, memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) - return -EIO; + goto err_out_free; phymem = pci_resource_start(pdev, 0); @@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev, err_out_disable: pci_disable_device(pdev); prism2_free_local_data(dev); + + err_out_free: kfree(hw_priv); return -ENODEV; diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 94fe2449f09..edaaa943eb8 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, switch (cis[pos]) { case CISTPL_CONFIG: - if (cis[pos + 1] < 1) + if (cis[pos + 1] < 2) goto cis_error; rmsz = (cis[pos + 2] & 0x3c) >> 2; rasz = cis[pos + 2] & 0x03; @@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, break; case CISTPL_MANFID: - if (cis[pos + 1] < 4) + if (cis[pos + 1] < 5) goto cis_error; manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); @@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev, memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) - return -EIO; + goto err_out_free; /* National Datacomm NCP130 based on TMD7160, not PLX9052. */ tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131); @@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev, return hostap_hw_ready(dev); fail: - prism2_free_local_data(dev); - kfree(hw_priv); - if (irq_registered && dev) free_irq(dev->irq, dev); @@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev, iounmap(attr_mem); pci_disable_device(pdev); + prism2_free_local_data(dev); + + err_out_free: + kfree(hw_priv); return -ENODEV; } diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index eea2f04c8c6..ebb23878583 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -332,7 +332,7 @@ mgt_le_to_cpu(int type, void *data) case OID_TYPE_ATTACH:{ struct obj_attachment *attach = data; attach->id = le16_to_cpu(attach->id); - attach->size = le16_to_cpu(attach->size);; + attach->size = le16_to_cpu(attach->size); break; } case OID_TYPE_SSID: @@ -401,7 +401,7 @@ mgt_cpu_to_le(int type, void *data) case OID_TYPE_ATTACH:{ struct obj_attachment *attach = data; attach->id = cpu_to_le16(attach->id); - attach->size = cpu_to_le16(attach->size);; + attach->size = cpu_to_le16(attach->size); break; } case OID_TYPE_SSID: diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index fee4be1ce81..5fa6fbe35bb 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -147,7 +147,7 @@ struct pdi { __le16 _len; /* length of ID and data, in words */ __le16 _id; /* record ID */ char data[0]; /* plug data */ -} __attribute__ ((packed));; +} __attribute__ ((packed)); /* Functions for access to little-endian data */ diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 76102160359..8037e5806d0 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -426,7 +426,7 @@ static void __devexit zorro8390_remove_one(struct zorro_dev *z) static int __init zorro8390_init_module(void) { - return zorro_module_init(&zorro8390_driver); + return zorro_register_driver(&zorro8390_driver); } static void __exit zorro8390_cleanup_module(void) |