diff options
Diffstat (limited to 'drivers/net')
263 files changed, 7852 insertions, 8281 deletions
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index da1a22c13865..ab18343e58ef 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -990,7 +990,7 @@ static void elmc_rcv_int(struct net_device *dev) if (skb != NULL) { skb_reserve(skb, 2); /* 16 byte alignment */ skb_put(skb,totlen); - eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0); + skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index f26ca331615e..a8c0f436cdd2 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -324,7 +324,7 @@ static struct vortex_chip_info { {"3c980C Python-T", PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, {"3cSOHO100-TX Hurricane", - PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, + PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, }, {"3c555 Laptop Hurricane", PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, }, {"3c556 Laptop Tornado", @@ -1555,6 +1555,7 @@ vortex_up(struct net_device *dev) mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR); mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); + vp->mii.full_duplex = vp->full_duplex; vortex_check_media(dev, 1); } @@ -2886,7 +2887,6 @@ static const struct ethtool_ops vortex_ethtool_ops = { .set_settings = vortex_set_settings, .get_link = ethtool_op_get_link, .nway_reset = vortex_nway_reset, - .get_perm_addr = ethtool_op_get_perm_addr, }; #ifdef CONFIG_PCI diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 0877fc372f4b..e89ace109a5d 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -333,9 +333,9 @@ static int lance_rx (struct net_device *dev) skb_reserve (skb, 2); /* 16 byte align */ skb_put (skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)&(ib->rx_buf [lp->rx_new][0]), - len, 0); + len); skb->protocol = eth_type_trans (skb, dev); netif_rx (skb); dev->last_rx = jiffies; diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index a804965e6542..a79f28c7a100 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -26,7 +26,6 @@ TODO: * Test Tx checksumming thoroughly - * Implement dev->tx_timeout Low priority TODO: * Complete reset on PciErr @@ -107,11 +106,6 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu #define PFX DRV_NAME ": " -#ifndef TRUE -#define FALSE 0 -#define TRUE (!FALSE) -#endif - #define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK) @@ -661,7 +655,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) if (status & (TxOK | TxErr | TxEmpty | SWInt)) cp_tx(cp); if (status & LinkChg) - mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE); + mii_check_media(&cp->mii_if, netif_msg_link(cp), false); spin_unlock(&cp->lock); @@ -1188,7 +1182,7 @@ static int cp_open (struct net_device *dev) goto err_out_hw; netif_carrier_off(dev); - mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE); + mii_check_media(&cp->mii_if, netif_msg_link(cp), true); netif_start_queue(dev); return 0; @@ -1223,6 +1217,30 @@ static int cp_close (struct net_device *dev) return 0; } +static void cp_tx_timeout(struct net_device *dev) +{ + struct cp_private *cp = netdev_priv(dev); + unsigned long flags; + int rc; + + printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n", + dev->name, cpr8(Cmd), cpr16(CpCmd), + cpr16(IntrStatus), cpr16(IntrMask)); + + spin_lock_irqsave(&cp->lock, flags); + + cp_stop_hw(cp); + cp_clean_rings(cp); + rc = cp_init_rings(cp); + cp_start_hw(cp); + + netif_wake_queue(dev); + + spin_unlock_irqrestore(&cp->lock, flags); + + return; +} + #ifdef BROKEN static int cp_change_mtu(struct net_device *dev, int new_mtu) { @@ -1560,7 +1578,6 @@ static const struct ethtool_ops cp_ethtool_ops = { .set_wol = cp_set_wol, .get_strings = cp_get_strings, .get_ethtool_stats = cp_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, .get_eeprom_len = cp_get_eeprom_len, .get_eeprom = cp_get_eeprom, .set_eeprom = cp_set_eeprom, @@ -1804,7 +1821,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *regs; resource_size_t pciaddr; unsigned int addr_len, i, pci_using_dac; - u8 pci_rev; #ifndef MODULE static int version_printed; @@ -1812,13 +1828,11 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) printk("%s", version); #endif - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) { + pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) { dev_err(&pdev->dev, "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n", - pdev->vendor, pdev->device, pci_rev); + pdev->vendor, pdev->device, pdev->revision); dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n"); return -ENODEV; } @@ -1928,10 +1942,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev->change_mtu = cp_change_mtu; #endif dev->ethtool_ops = &cp_ethtool_ops; -#if 0 dev->tx_timeout = cp_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif #if CP_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; @@ -2050,7 +2062,7 @@ static int cp_resume (struct pci_dev *pdev) spin_lock_irqsave (&cp->lock, flags); - mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE); + mii_check_media(&cp->mii_if, netif_msg_link(cp), false); spin_unlock_irqrestore (&cp->lock, flags); diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index a844b1fe2dc4..f4e4298d24b9 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -931,7 +931,6 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, int i, addr_len, option; void __iomem *ioaddr; static int board_idx = -1; - u8 pci_rev; assert (pdev != NULL); assert (ent != NULL); @@ -949,13 +948,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, } #endif - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { + pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { dev_info(&pdev->dev, "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); + pdev->vendor, pdev->device, pdev->revision); dev_info(&pdev->dev, "Use the \"8139cp\" driver for improved performance and stability.\n"); } @@ -2017,7 +2014,7 @@ no_early_rx: #if RX_BUF_IDX == 3 wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); #else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); + skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); #endif skb_put (skb, pkt_size); @@ -2455,7 +2452,6 @@ static const struct ethtool_ops rtl8139_ethtool_ops = { .get_strings = rtl8139_get_strings, .get_stats_count = rtl8139_get_stats_count, .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 3ff1155459a3..d915837193cc 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -57,6 +57,7 @@ #include <asm/io.h> #include <asm/dma.h> #include <asm/pgtable.h> +#include <asm/cacheflush.h> static char version[] __initdata = "82596.c $Revision: 1.5 $\n"; diff --git a/drivers/net/8390.h b/drivers/net/8390.h index 414de5bd228f..04ddec0f4c61 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -73,6 +73,9 @@ struct ei_device { u32 *reg_offset; /* Register mapping table */ spinlock_t page_lock; /* Page register locks */ unsigned long priv; /* Private field to store bus IDs etc. */ +#ifdef AX88796_PLATFORM + unsigned char rxcr_base; /* default value for RXCR */ +#endif }; /* The maximum number of 8390 interrupt service routines called per IRQ. */ @@ -86,11 +89,19 @@ struct ei_device { /* Some generic ethernet register configurations. */ #define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ #define E8390_RX_IRQ_MASK 0x5 + +#ifdef AX88796_PLATFORM +#define E8390_RXCONFIG (ei_status.rxcr_base | 0x04) +#define E8390_RXOFF (ei_status.rxcr_base | 0x20) +#else #define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ #define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ +#endif + #define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ #define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ + /* Register accessed at EN_CMD, the 8390 base addr. */ #define E8390_STOP 0x01 /* Stop and reset the chip */ #define E8390_START 0x02 /* Start the chip, clear reset */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 3b1889804495..1d719b60b374 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -3,11 +3,9 @@ # Network device configuration # -menu "Network device support" - depends on NET - -config NETDEVICES +menuconfig NETDEVICES default y if UML + depends on NET bool "Network device support" ---help--- You can say N here if you don't intend to connect your Linux box to @@ -28,6 +26,14 @@ config NETDEVICES # that for each of the symbols. if NETDEVICES +config NETDEVICES_MULTIQUEUE + bool "Netdevice multiple hardware queue support" + ---help--- + Say Y here if you want to allow the network stack to use multiple + hardware TX queues on an ethernet device. + + Most people will say N here. + config IFB tristate "Intermediate Functional Block support" depends on NET_CLS_ACT @@ -77,6 +83,16 @@ config BONDING To compile this driver as a module, choose M here: the module will be called bonding. +config MACVLAN + tristate "MAC-VLAN support (EXPERIMENTAL)" + depends on EXPERIMENTAL + ---help--- + This allows one to create virtual interfaces that map packets to + or from specific MAC addresses to a particular interface. + + To compile this driver as a module, choose M here: the module + will be called macvlan. + config EQUALIZER tristate "EQL (serial line load balancing) support" ---help--- @@ -151,11 +167,9 @@ source "drivers/net/phy/Kconfig" # Ethernet # -menu "Ethernet (10 or 100Mbit)" - depends on !UML - -config NET_ETHERNET +menuconfig NET_ETHERNET bool "Ethernet (10 or 100Mbit)" + depends on !UML ---help--- Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common type of Local Area Network (LAN) in universities and companies. @@ -180,9 +194,10 @@ config NET_ETHERNET kernel: saying N will just cause the configurator to skip all the questions about Ethernet network cards. If unsure, say N. +if NET_ETHERNET + config MII tristate "Generic Media Independent Interface device support" - depends on NET_ETHERNET help Most ethernet controllers have MII transceiver either as an external or internal device. It is safe to say Y or M here even if your @@ -190,8 +205,8 @@ config MII config MACB tristate "Atmel MACB support" - depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263) - select MII + depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 + select PHYLIB help The Atmel MACB ethernet interface is found on many AT32 and AT91 parts. Say Y to include support for the MACB chip. @@ -201,9 +216,18 @@ config MACB source "drivers/net/arm/Kconfig" +config AX88796 + tristate "ASIX AX88796 NE2000 clone support" + depends on ARM || MIPS + select CRC32 + select MII + help + AX88796 driver, using platform bus to provide + chip detection and resources + config MACE tristate "MACE (Power Mac ethernet) support" - depends on NET_ETHERNET && PPC_PMAC && PPC32 + depends on PPC_PMAC && PPC32 select CRC32 help Power Macintoshes and clones with Ethernet built-in on the @@ -226,7 +250,7 @@ config MACE_AAUI_PORT config BMAC tristate "BMAC (G3 ethernet) support" - depends on NET_ETHERNET && PPC_PMAC && PPC32 + depends on PPC_PMAC && PPC32 select CRC32 help Say Y for support of BMAC Ethernet interfaces. These are used on G3 @@ -237,7 +261,7 @@ config BMAC config ARIADNE tristate "Ariadne support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO help If you have a Village Tronic Ariadne Ethernet adapter, say Y. Otherwise, say N. @@ -247,7 +271,7 @@ config ARIADNE config A2065 tristate "A2065 support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO select CRC32 help If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise, @@ -258,7 +282,7 @@ config A2065 config HYDRA tristate "Hydra support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO select CRC32 help If you have a Hydra Ethernet adapter, say Y. Otherwise, say N. @@ -268,7 +292,7 @@ config HYDRA config ZORRO8390 tristate "Zorro NS8390-based Ethernet support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO select CRC32 help This driver is for Zorro Ethernet cards using an NS8390-compatible @@ -281,7 +305,7 @@ config ZORRO8390 config APNE tristate "PCMCIA NE2000 support" - depends on NET_ETHERNET && AMIGA_PCMCIA + depends on AMIGA_PCMCIA select CRC32 help If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, @@ -292,7 +316,7 @@ config APNE config APOLLO_ELPLUS tristate "Apollo 3c505 support" - depends on NET_ETHERNET && APOLLO + depends on APOLLO help Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card. If you don't have one made for Apollos, you can use one from a PC, @@ -301,7 +325,7 @@ config APOLLO_ELPLUS config MAC8390 bool "Macintosh NS 8390 based ethernet cards" - depends on NET_ETHERNET && MAC + depends on MAC select CRC32 help If you want to include a driver to support Nubus or LC-PDS @@ -311,7 +335,7 @@ config MAC8390 config MAC89x0 tristate "Macintosh CS89x0 based ethernet cards" - depends on NET_ETHERNET && MAC + depends on MAC ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a Nubus or LC-PDS network (Ethernet) card of this type, say Y and @@ -324,7 +348,7 @@ config MAC89x0 config MACSONIC tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)" - depends on NET_ETHERNET && MAC + depends on MAC ---help--- Support for NatSemi SONIC based Ethernet devices. This includes the onboard Ethernet in many Quadras as well as some LC-PDS, @@ -338,7 +362,7 @@ config MACSONIC config MACMACE bool "Macintosh (AV) onboard MACE ethernet" - depends on NET_ETHERNET && MAC + depends on MAC select CRC32 help Support for the onboard AMD 79C940 MACE Ethernet controller used in @@ -348,7 +372,7 @@ config MACMACE config MVME147_NET tristate "MVME147 (Lance) Ethernet support" - depends on NET_ETHERNET && MVME147 + depends on MVME147 select CRC32 help Support for the on-board Ethernet interface on the Motorola MVME147 @@ -358,7 +382,7 @@ config MVME147_NET config MVME16x_NET tristate "MVME16x Ethernet support" - depends on NET_ETHERNET && MVME16x + depends on MVME16x help This is the driver for the Ethernet interface on the Motorola MVME162, 166, 167, 172 and 177 boards. Say Y here to include the @@ -367,7 +391,7 @@ config MVME16x_NET config BVME6000_NET tristate "BVME6000 Ethernet support" - depends on NET_ETHERNET && BVME6000 + depends on BVME6000 help This is the driver for the Ethernet interface on BVME4000 and BVME6000 VME boards. Say Y here to include the driver for this chip @@ -376,31 +400,15 @@ config BVME6000_NET config ATARILANCE tristate "Atari Lance support" - depends on NET_ETHERNET && ATARI + depends on ATARI help Say Y to include support for several Atari Ethernet adapters based on the AMD Lance chipset: RieblCard (with or without battery), or PAMCard VME (also the version by Rhotron, with different addresses). -config ATARI_BIONET - tristate "BioNet-100 support" - depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN - help - Say Y to include support for BioData's BioNet-100 Ethernet adapter - for the ACSI port. The driver works (has to work...) with a polled - I/O scheme, so it's rather slow :-( - -config ATARI_PAMSNET - tristate "PAMsNet support" - depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN - help - Say Y to include support for the PAMsNet Ethernet adapter for the - ACSI port ("ACSI node"). The driver works (has to work...) with a - polled I/O scheme, so it's rather slow :-( - config SUN3LANCE tristate "Sun3/Sun3x on-board LANCE support" - depends on NET_ETHERNET && (SUN3 || SUN3X) + depends on SUN3 || SUN3X help Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80) featured an AMD Lance 10Mbit Ethernet controller on board; say Y @@ -413,7 +421,7 @@ config SUN3LANCE config SUN3_82586 bool "Sun3 on-board Intel 82586 support" - depends on NET_ETHERNET && SUN3 + depends on SUN3 help This driver enables support for the on-board Intel 82586 based Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note @@ -422,7 +430,7 @@ config SUN3_82586 config HPLANCE bool "HP on-board LANCE support" - depends on NET_ETHERNET && DIO + depends on DIO select CRC32 help If you want to use the builtin "LANCE" Ethernet controller on an @@ -430,21 +438,28 @@ config HPLANCE config LASI_82596 tristate "Lasi ethernet" - depends on NET_ETHERNET && GSC + depends on GSC help Say Y here to support the builtin Intel 82596 ethernet controller found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet. +config SNI_82596 + tristate "SNI RM ethernet" + depends on NET_ETHERNET && SNI_RM + help + Say Y here to support the on-board Intel 82596 ethernet controller + built into SNI RM machines. + config MIPS_JAZZ_SONIC tristate "MIPS JAZZ onboard SONIC Ethernet support" - depends on NET_ETHERNET && MACH_JAZZ + depends on MACH_JAZZ help This is the driver for the onboard card of MIPS Magnum 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM systems. config MIPS_AU1X00_ENET bool "MIPS AU1000 Ethernet support" - depends on NET_ETHERNET && SOC_AU1X00 + depends on SOC_AU1X00 select PHYLIB select CRC32 help @@ -453,11 +468,11 @@ config MIPS_AU1X00_ENET config NET_SB1250_MAC tristate "SB1250 Ethernet support" - depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC + depends on SIBYTE_SB1xxx_SOC config SGI_IOC3_ETH bool "SGI IOC3 Ethernet" - depends on NET_ETHERNET && PCI && SGI_IP27 + depends on PCI && SGI_IP27 select CRC32 select MII help @@ -487,7 +502,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM config MIPS_SIM_NET tristate "MIPS simulator Network device" - depends on NET_ETHERNET && MIPS_SIM + depends on MIPS_SIM help The MIPSNET device is a simple Ethernet network device which is emulated by the MIPS Simulator. @@ -495,11 +510,11 @@ config MIPS_SIM_NET config SGI_O2MACE_ETH tristate "SGI O2 MACE Fast Ethernet support" - depends on NET_ETHERNET && SGI_IP32=y + depends on SGI_IP32=y config STNIC tristate "National DP83902AV support" - depends on NET_ETHERNET && SUPERH + depends on SUPERH select CRC32 help Support for cards based on the National Semiconductor DP83902AV @@ -511,7 +526,7 @@ config STNIC config SUNLANCE tristate "Sun LANCE support" - depends on NET_ETHERNET && SBUS + depends on SBUS select CRC32 help This driver supports the "le" interface present on all 32-bit Sparc @@ -524,7 +539,7 @@ config SUNLANCE config HAPPYMEAL tristate "Sun Happy Meal 10/100baseT support" - depends on NET_ETHERNET && (SBUS || PCI) + depends on SBUS || PCI select CRC32 help This driver supports the "hme" interface present on most Ultra @@ -537,7 +552,7 @@ config HAPPYMEAL config SUNBMAC tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)" - depends on NET_ETHERNET && SBUS && EXPERIMENTAL + depends on SBUS && EXPERIMENTAL select CRC32 help This driver supports the "be" interface available as an Sbus option. @@ -548,7 +563,7 @@ config SUNBMAC config SUNQE tristate "Sun QuadEthernet support" - depends on NET_ETHERNET && SBUS + depends on SBUS select CRC32 help This driver supports the "qe" 10baseT Ethernet device, available as @@ -560,7 +575,7 @@ config SUNQE config SUNGEM tristate "Sun GEM support" - depends on NET_ETHERNET && PCI + depends on PCI select CRC32 help Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also @@ -568,15 +583,21 @@ config SUNGEM config CASSINI tristate "Sun Cassini support" - depends on NET_ETHERNET && PCI + depends on PCI select CRC32 help Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf> +config SUNVNET + tristate "Sun Virtual Network support" + depends on SUN_LDOMS + help + Support for virtual network devices under Sun Logical Domains. + config NET_VENDOR_3COM bool "3COM cards" - depends on NET_ETHERNET && (ISA || EISA || MCA || PCI) + depends on ISA || EISA || MCA || PCI help If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from @@ -736,7 +757,7 @@ config TYPHOON config LANCE tristate "AMD LANCE and PCnet (AT1500 and NE2100) support" - depends on NET_ETHERNET && ISA && ISA_DMA_API + depends on ISA && ISA_DMA_API help If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from @@ -748,7 +769,7 @@ config LANCE config NET_VENDOR_SMC bool "Western Digital/SMC cards" - depends on NET_ETHERNET && (ISA || MCA || EISA || MAC) + depends on ISA || MCA || EISA || MAC help If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from @@ -818,23 +839,49 @@ config ULTRA32 <file:Documentation/networking/net-modules.txt>. The module will be called smc-ultra32. -config SMC91X - tristate "SMC 91C9x/91C1xxx support" +config BFIN_MAC + tristate "Blackfin 536/537 on-chip mac support" + depends on NET_ETHERNET && (BF537 || BF536) && (!BF537_PORT_H) select CRC32 - select MII - depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN) + select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE help - This is a driver for SMC's 91x series of Ethernet chipsets, - including the SMC91C94 and the SMC91C111. Say Y if you want it - compiled into the kernel, and read the file - <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO, - available from <http://www.linuxdoc.org/docs.html#howto>. + This is the driver for blackfin on-chip mac device. Say Y if you want it + compiled into the kernel. This driver is also available as a module + ( = code which can be inserted in and removed from the running kernel + whenever you want). The module will be called bfin_mac. - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called smc91x. If you want to compile it as a - module, say M here and read <file:Documentation/kbuild/modules.txt> - as well as <file:Documentation/networking/net-modules.txt>. +config BFIN_MAC_USE_L1 + bool "Use L1 memory for rx/tx packets" + depends on BFIN_MAC && BF537 + default y + help + To get maximum network performace, you should use L1 memory as rx/tx buffers. + Say N here if you want to reserve L1 memory for other uses. + +config BFIN_TX_DESC_NUM + int "Number of transmit buffer packets" + depends on BFIN_MAC + range 6 10 if BFIN_MAC_USE_L1 + range 10 100 + default "10" + help + Set the number of buffer packets used in driver. + +config BFIN_RX_DESC_NUM + int "Number of receive buffer packets" + depends on BFIN_MAC + range 20 100 if BFIN_MAC_USE_L1 + range 20 800 + default "20" + help + Set the number of buffer packets used in driver. + +config BFIN_MAC_RMII + bool "RMII PHY Interface (EXPERIMENTAL)" + depends on BFIN_MAC && EXPERIMENTAL + default n + help + Use Reduced PHY MII Interface config SMC9194 tristate "SMC 9194 support" @@ -852,10 +899,28 @@ config SMC9194 <file:Documentation/networking/net-modules.txt>. The module will be called smc9194. +config SMC91X + tristate "SMC 91C9x/91C1xxx support" + select CRC32 + select MII + depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN + help + This is a driver for SMC's 91x series of Ethernet chipsets, + including the SMC91C94 and the SMC91C111. Say Y if you want it + compiled into the kernel, and read the file + <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO, + available from <http://www.linuxdoc.org/docs.html#howto>. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called smc91x. If you want to compile it as a + module, say M here and read <file:Documentation/kbuild/modules.txt> + as well as <file:Documentation/networking/net-modules.txt>. + config NET_NETX tristate "NetX Ethernet support" select MII - depends on NET_ETHERNET && ARCH_NETX + depends on ARCH_NETX help This is support for the Hilscher netX builtin Ethernet ports @@ -865,7 +930,7 @@ config NET_NETX config DM9000 tristate "DM9000 support" - depends on (ARM || MIPS) && NET_ETHERNET + depends on ARM || BLACKFIN || MIPS select CRC32 select MII ---help--- @@ -879,7 +944,7 @@ config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 select MII - depends on NET_ETHERNET && ARCH_PXA + depends on ARCH_PXA help This is a driver for SMSC's LAN911x series of Ethernet chipsets including the new LAN9115, LAN9116, LAN9117, and LAN9118. @@ -893,7 +958,7 @@ config SMC911X config NET_VENDOR_RACAL bool "Racal-Interlan (Micom) NI cards" - depends on NET_ETHERNET && ISA + depends on ISA help If you have a network (Ethernet) card belonging to this class, such as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO, @@ -945,7 +1010,7 @@ source "drivers/net/tulip/Kconfig" config AT1700 tristate "AT1700/1720 support (EXPERIMENTAL)" - depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL + depends on (ISA || MCA_LEGACY) && EXPERIMENTAL select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y and read @@ -958,7 +1023,7 @@ config AT1700 config DEPCA tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support" - depends on NET_ETHERNET && (ISA || EISA || MCA) + depends on ISA || EISA || MCA select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y and read @@ -972,7 +1037,7 @@ config DEPCA config HP100 tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support" - depends on NET_ETHERNET && (ISA || EISA || PCI) + depends on ISA || EISA || PCI help If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from @@ -984,7 +1049,7 @@ config HP100 config NET_ISA bool "Other ISA cards" - depends on NET_ETHERNET && ISA + depends on ISA ---help--- If your network (Ethernet) card hasn't been mentioned yet and its bus system (that's the way the cards talks to the other components @@ -1147,7 +1212,7 @@ config SEEQ8005 config NE2_MCA tristate "NE/2 (ne2000 MCA version) support" - depends on NET_ETHERNET && MCA_LEGACY + depends on MCA_LEGACY select CRC32 help If you have a network (Ethernet) card of this type, say Y and read @@ -1160,7 +1225,7 @@ config NE2_MCA config IBMLANA tristate "IBM LAN Adapter/A support" - depends on NET_ETHERNET && MCA && MCA_LEGACY + depends on MCA && MCA_LEGACY ---help--- This is a Micro Channel Ethernet adapter. You need to set CONFIG_MCA to use this driver. It is both available as an in-kernel @@ -1176,7 +1241,7 @@ config IBMLANA config IBMVETH tristate "IBM LAN Virtual Ethernet support" - depends on NET_ETHERNET && PPC_PSERIES + depends on PPC_PSERIES ---help--- This driver supports virtual ethernet adapters on newer IBM iSeries and pSeries systems. @@ -1257,7 +1322,7 @@ config IBM_EMAC_TAH config NET_PCI bool "EISA, VLB, PCI and on board controllers" - depends on NET_ETHERNET && (ISA || EISA || PCI) + depends on ISA || EISA || PCI help This is another class of network cards which attach directly to the bus. If you have one of those, say Y and read the Ethernet-HOWTO, @@ -1313,6 +1378,7 @@ config AMD8111_ETH To compile this driver as a module, choose M here and read <file:Documentation/networking/net-modules.txt>. The module will be called amd8111e. + config AMD8111E_NAPI bool "Enable NAPI support" depends on AMD8111_ETH @@ -1778,7 +1844,7 @@ config SC92031 config NET_POCKET bool "Pocket and portable adapters" - depends on NET_ETHERNET && PARPORT + depends on PARPORT ---help--- Cute little network (Ethernet) devices which attach to the parallel port ("pocket adapters"), commonly used with laptops. If you have @@ -1847,14 +1913,14 @@ config DE620 config SGISEEQ tristate "SGI Seeq ethernet controller support" - depends on NET_ETHERNET && SGI_IP22 + depends on SGI_IP22 help Say Y here if you have an Seeq based Ethernet network card. This is used in many Silicon Graphics machines. config DECLANCE tristate "DEC LANCE ethernet controller support" - depends on NET_ETHERNET && MACH_DECSTATION + depends on MACH_DECSTATION select CRC32 help This driver is for the series of Ethernet controllers produced by @@ -1884,7 +1950,7 @@ config FEC2 config NE_H8300 tristate "NE2000 compatible support for H8/300" - depends on H8300 && NET_ETHERNET + depends on H8300 help Say Y here if you want to use the NE2000 compatible controller on the Renesas H8/300 processor. @@ -1892,7 +1958,7 @@ config NE_H8300 source "drivers/net/fec_8xx/Kconfig" source "drivers/net/fs_enet/Kconfig" -endmenu +endif # NET_ETHERNET # # Gigabit Ethernet @@ -1902,6 +1968,16 @@ menuconfig NETDEV_1000 bool "Ethernet (1000 Mbit)" depends on !UML default y + ---help--- + Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common + type of Local Area Network (LAN) in universities and companies. + + Say Y here to get to see options for Gigabit Ethernet drivers. + This option alone does not add any kernel code. + Note that drivers supporting both 100 and 1000 MBit may be listed + under "Ethernet (10 or 100MBit)" instead. + + If you say N, all options in this submenu will be skipped and disabled. if NETDEV_1000 @@ -2114,7 +2190,7 @@ config SKGE will be called skge. This is recommended. config SKY2 - tristate "SysKonnect Yukon2 support (EXPERIMENTAL)" + tristate "SysKonnect Yukon2 support" depends on PCI select CRC32 ---help--- @@ -2129,6 +2205,16 @@ config SKY2 To compile this driver as a module, choose M here: the module will be called sky2. This is recommended. +config SKY2_DEBUG + bool "Debugging interface" + depends on SKY2 && DEBUG_FS + help + This option adds the ability to dump driver state for debugging. + The file debugfs/sky2/ethX displays the state of the internal + transmit and receive rings. + + If unsure, say N. + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)" depends on PCI @@ -2264,6 +2350,16 @@ config TSI108_ETH To compile this driver as a module, choose M here: the module will be called tsi108_eth. +config GELIC_NET + tristate "PS3 Gigabit Ethernet driver" + depends on PPC_PS3 + help + This driver supports the network device on the PS3 game + console. This driver has built-in support for Ethernet. + + To compile this driver as a module, choose M here: the + module will be called ps3_gelic. + config GIANFAR tristate "Gianfar Ethernet" depends on 85xx || 83xx || PPC_86xx @@ -2303,7 +2399,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "MV-643XX Ethernet support" - depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32) + depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) select MII help This driver supports the gigabit Ethernet on the Marvell MV643XX @@ -2340,6 +2436,11 @@ menuconfig NETDEV_10000 bool "Ethernet (10000 Mbit)" depends on !UML default y + ---help--- + Say Y here to get to see options for 10 Gigabit Ethernet drivers. + This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and disabled. if NETDEV_10000 @@ -2532,6 +2633,18 @@ source "drivers/atm/Kconfig" source "drivers/s390/net/Kconfig" +config XEN_NETDEV_FRONTEND + tristate "Xen network device frontend driver" + depends on XEN + default y + help + The network device frontend driver allows the kernel to + access network devices exported exported by a virtual + machine containing a physical network device driver. The + frontend driver is intended for unprivileged guest domains; + if you are compiling a kernel for a Xen guest, you almost + certainly want to enable this. + config ISERIES_VETH tristate "iSeries Virtual Ethernet driver support" depends on PPC_ISERIES @@ -2838,6 +2951,19 @@ config PPPOATM which can lead to bad results if the ATM peer loses state and changes its encapsulation unilaterally. +config PPPOL2TP + tristate "PPP over L2TP (EXPERIMENTAL)" + depends on EXPERIMENTAL && PPP && INET + help + Support for PPP-over-L2TP socket family. L2TP is a protocol + used by ISPs and enterprises to tunnel PPP traffic over UDP + tunnels. L2TP is replacing PPTP for VPN uses. + + This kernel component handles only L2TP data packets: a + userland daemon handles L2TP the control protocol (tunnel + and session setup). One such daemon is OpenL2TP + (http://openl2tp.sourceforge.net/). + config SLIP tristate "SLIP (serial line) support" ---help--- @@ -2948,8 +3074,6 @@ config NETCONSOLE If you want to log kernel messages over the network, enable this. See <file:Documentation/networking/netconsole.txt> for details. -endif #NETDEVICES - config NETPOLL def_bool NETCONSOLE @@ -2961,4 +3085,4 @@ config NETPOLL_TRAP config NET_POLL_CONTROLLER def_bool NETPOLL -endmenu +endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index a77affa4f6e6..9c928a845841 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -18,7 +18,7 @@ gianfar_driver-objs := gianfar.o \ gianfar_sysfs.o obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o -ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o +ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o ucc_geth_ethtool.o # # link order important here @@ -34,6 +34,7 @@ obj-$(CONFIG_SUNBMAC) += sunbmac.o obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o obj-$(CONFIG_CASSINI) += cassini.o +obj-$(CONFIG_SUNVNET) += sunvnet.o obj-$(CONFIG_MACE) += mace.o obj-$(CONFIG_BMAC) += bmac.o @@ -60,6 +61,8 @@ obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BNX2) += bnx2.o spidernet-y += spider_net.o spider_net_ethtool.o obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o +obj-$(CONFIG_GELIC_NET) += ps3_gelic.o +ps3_gelic-objs += ps3_gelic_net.o obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o @@ -107,6 +110,7 @@ obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_FORCEDETH) += forcedeth.o obj-$(CONFIG_NE_H8300) += ne-h8300.o +obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o @@ -119,12 +123,16 @@ obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o obj-$(CONFIG_PPPOE) += pppox.o pppoe.o +obj-$(CONFIG_PPPOL2TP) += pppox.o pppol2tp.o obj-$(CONFIG_SLIP) += slip.o obj-$(CONFIG_SLHC) += slhc.o +obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o + obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_IFB) += ifb.o +obj-$(CONFIG_MACVLAN) += macvlan.o obj-$(CONFIG_DE600) += de600.o obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_LANCE) += lance.o @@ -157,6 +165,7 @@ obj-$(CONFIG_ELPLUS) += 3c505.o obj-$(CONFIG_AC3200) += ac3200.o 8390.o obj-$(CONFIG_APRICOT) += 82596.o obj-$(CONFIG_LASI_82596) += lasi_82596.o +obj-$(CONFIG_SNI_82596) += sni_82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o obj-$(CONFIG_BVME6000_NET) += 82596.o obj-$(CONFIG_SC92031) += sc92031.o @@ -169,14 +178,13 @@ obj-$(CONFIG_ZORRO8390) += zorro8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o obj-$(CONFIG_EQUALIZER) += eql.o +obj-$(CONFIG_LGUEST_NET) += lguest_net.o obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o obj-$(CONFIG_DECLANCE) += declance.o obj-$(CONFIG_ATARILANCE) += atarilance.o -obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o -obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o obj-$(CONFIG_A2065) += a2065.o obj-$(CONFIG_HYDRA) += hydra.o obj-$(CONFIG_ARIADNE) += ariadne.o @@ -194,6 +202,7 @@ obj-$(CONFIG_S2IO) += s2io.o obj-$(CONFIG_MYRI10GE) += myri10ge/ obj-$(CONFIG_SMC91X) += smc91x.o obj-$(CONFIG_SMC911X) += smc911x.o +obj-$(CONFIG_BFIN_MAC) += bfin_mac.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_FEC_8XX) += fec_8xx/ obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 1c3e293fbaf7..3b79c6cf21a3 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -75,8 +75,6 @@ extern struct net_device *atarilance_probe(int unit); extern struct net_device *sun3lance_probe(int unit); extern struct net_device *sun3_82586_probe(int unit); extern struct net_device *apne_probe(int unit); -extern struct net_device *bionet_probe(int unit); -extern struct net_device *pamsnet_probe(int unit); extern struct net_device *cs89x0_probe(int unit); extern struct net_device *hplance_probe(int unit); extern struct net_device *bagetlance_probe(int unit); @@ -264,12 +262,6 @@ static struct devprobe2 m68k_probes[] __initdata = { #ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */ {apne_probe, 0}, #endif -#ifdef CONFIG_ATARI_BIONET /* Atari Bionet Ethernet board */ - {bionet_probe, 0}, -#endif -#ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */ - {pamsnet_probe, 0}, -#endif #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ {mvme147lance_probe, 0}, #endif diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 81d5a374042a..a45de6975bfe 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -322,9 +322,9 @@ static int lance_rx (struct net_device *dev) skb_reserve (skb, 2); /* 16 byte align */ skb_put (skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)&(ib->rx_buf [lp->rx_new][0]), - len, 0); + len); skb->protocol = eth_type_trans (skb, dev); netif_rx (skb); dev->last_rx = jiffies; diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 04382f979c99..62e660a79387 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -159,10 +159,6 @@ static struct pci_device_id acenic_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) do{} while(0) -#endif - #define ace_sync_irq(irq) synchronize_irq(irq) #ifndef offset_in_page @@ -3132,12 +3128,6 @@ static int __devinit read_eeprom_byte(struct net_device *dev, int result = 0; short i; - if (!dev) { - printk(KERN_ERR "No device!\n"); - result = -ENODEV; - goto out; - } - /* * Don't take interrupts on this CPU will bit banging * the %#%#@$ I2C device diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index a241ae7855a3..bc5a38a6705f 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -746,7 +746,7 @@ static int ariadne_rx(struct net_device *dev) skb_reserve(skb,2); /* 16 byte align */ skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0); + skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len); skb->protocol=eth_type_trans(skb,dev); #if 0 printk(KERN_DEBUG "RX pkt type 0x%04x from ", diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index 678e4f48d36b..f9cc2b621fe2 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig @@ -4,7 +4,7 @@ # config ARM_AM79C961A bool "ARM EBSA110 AM79C961A support" - depends on NET_ETHERNET && ARM && ARCH_EBSA110 + depends on ARM && ARCH_EBSA110 select CRC32 help If you wish to compile a kernel for the EBSA-110, then you should @@ -12,21 +12,21 @@ config ARM_AM79C961A config ARM_ETHER1 tristate "Acorn Ether1 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN + depends on ARM && ARCH_ACORN help If you have an Acorn system with one of these (AKA25) network cards, you should say Y to this option if you wish to use it with Linux. config ARM_ETHER3 tristate "Acorn/ANT Ether3 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN + depends on ARM && ARCH_ACORN 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_ETHERH tristate "I-cubed EtherH/ANT EtherM support" - depends on NET_ETHERNET && ARM && ARCH_ACORN + depends on ARM && ARCH_ACORN select CRC32 help If you have an Acorn system with one of these network cards, you @@ -34,7 +34,7 @@ config ARM_ETHERH config ARM_AT91_ETHER tristate "AT91RM9200 Ethernet support" - depends on NET_ETHERNET && ARM && ARCH_AT91RM9200 + depends on ARM && ARCH_AT91RM9200 select MII help If you wish to compile a kernel for the AT91RM9200 and enable @@ -42,7 +42,8 @@ config ARM_AT91_ETHER config EP93XX_ETH tristate "EP93xx Ethernet support" - depends on NET_ETHERNET && ARM && ARCH_EP93XX + depends on ARM && ARCH_EP93XX + select MII help This is a driver for the ethernet hardware included in EP93xx CPUs. Say Y if you are building a kernel for EP93xx based devices. diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 2438c5bff237..f6ece1d43f6e 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -258,7 +258,7 @@ static int ep93xx_rx(struct net_device *dev, int *budget) skb_reserve(skb, 2); dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr, length, DMA_FROM_DEVICE); - eth_copy_and_sum(skb, ep->rx_buf[entry], length, 0); + skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); skb_put(skb, length); skb->protocol = eth_type_trans(skb, dev); diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index f21148e7b579..80f33b6d5713 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -36,7 +36,6 @@ #include <linux/types.h> #include <linux/fcntl.h> #include <linux/interrupt.h> -#include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/in.h> #include <linux/slab.h> @@ -75,7 +74,7 @@ static void ether1_timeout(struct net_device *dev); /* ------------------------------------------------------------------------- */ -static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; +static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; #define BUS_16 16 #define BUS_8 8 diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index da713500654d..3805506a3ab8 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -51,7 +51,6 @@ #include <linux/types.h> #include <linux/fcntl.h> #include <linux/interrupt.h> -#include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/in.h> #include <linux/slab.h> @@ -69,7 +68,7 @@ #include <asm/ecard.h> #include <asm/io.h> -static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; +static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; #include "ether3.h" @@ -464,7 +463,7 @@ static void ether3_setmulticastlist(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* promiscuous mode */ priv(dev)->regs.config1 |= CFG1_RECVPROMISC; - } else if (dev->flags & IFF_ALLMULTI) { + } else if (dev->flags & IFF_ALLMULTI || dev->mc_count) { priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI; } else priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD; diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 769ba69451f4..0d37d9d1fd78 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -31,7 +31,6 @@ #include <linux/types.h> #include <linux/fcntl.h> #include <linux/interrupt.h> -#include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/in.h> #include <linux/slab.h> diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c deleted file mode 100644 index 3d87bd2b4194..000000000000 --- a/drivers/net/atari_bionet.c +++ /dev/null @@ -1,675 +0,0 @@ -/* bionet.c BioNet-100 device driver for linux68k. - * - * Version: @(#)bionet.c 1.0 02/06/96 - * - * Author: Hartmut Laue <laue@ifk-mp.uni-kiel.de> - * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de> - * - * Little adaptions for integration into pl7 by Roman Hodek - * - * Some changes in bionet_poll_rx by Karl-Heinz Lohner - * - What is it ? - ------------ - This driver controls the BIONET-100 LAN-Adapter which connects - an ATARI ST/TT via the ACSI-port to an Ethernet-based network. - - This version can be compiled as a loadable module (See the - compile command at the bottom of this file). - At load time, you can optionally set the debugging level and the - fastest response time on the command line of 'insmod'. - - 'bionet_debug' - controls the amount of diagnostic messages: - 0 : no messages - >0 : see code for meaning of printed messages - - 'bionet_min_poll_time' (always >=1) - gives the time (in jiffies) between polls. Low values - increase the system load (beware!) - - When loaded, a net device with the name 'bio0' becomes available, - which can be controlled with the usual 'ifconfig' command. - - It is possible to compile this driver into the kernel like other - (net) drivers. For this purpose, some source files (e.g. config-files - makefiles, Space.c) must be changed accordingly. (You may refer to - other drivers how to do it.) In this case, the device will be detected - at boot time and (probably) appear as 'eth0'. - - This code is based on several sources: - - The driver code for a parallel port ethernet adapter by - Donald Becker (see file 'atp.c' from the PC linux distribution) - - The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support - and DMA handling. - - Very limited information about moving packets in and out of the - BIONET-adapter from the TCP package for TOS by BioData GmbH. - - Theory of Operation - ------------------- - Because the ATARI DMA port is usually shared between several - devices (eg. harddisk, floppy) we cannot block the ACSI bus - while waiting for interrupts. Therefore we use a polling mechanism - to fetch packets from the adapter. For the same reason, we send - packets without checking that the previous packet has been sent to - the LAN. We rely on the higher levels of the networking code to detect - missing packets and resend them. - - Before we access the ATARI DMA controller, we check if another - process is using the DMA. If not, we lock the DMA, perform one or - more packet transfers and unlock the DMA before returning. - We do not use 'stdma_lock' unconditionally because it is unclear - if the networking code can be set to sleep, which will happen if - another (possibly slow) device is using the DMA controller. - - The polling is done via timer interrupts which periodically - 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies) - between polls varies depending on an estimate of the net activity. - The allowed range is given by the variable 'bionet_min_poll_time' - for the lower (fastest) limit and the constant 'MAX_POLL_TIME' - for the higher (slowest) limit. - - Whenever a packet arrives, we switch to fastest response by setting - the polling time to its lowest limit. If the following poll fails, - because no packets have arrived, we increase the time for the next - poll. When the net activity is low, the polling time effectively - stays at its maximum value, resulting in the lowest load for the - machine. - */ - -#define MAX_POLL_TIME 10 - -static char version[] = - "bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n"; - -#include <linux/module.h> - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/jiffies.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/bitops.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <asm/setup.h> -#include <asm/pgtable.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/atarihw.h> -#include <asm/atariints.h> -#include <asm/atari_acsi.h> -#include <asm/atari_stdma.h> - - -/* use 0 for production, 1 for verification, >2 for debug - */ -#ifndef NET_DEBUG -#define NET_DEBUG 0 -#endif -/* - * Global variable 'bionet_debug'. Can be set at load time by 'insmod' - */ -unsigned int bionet_debug = NET_DEBUG; -module_param(bionet_debug, int, 0); -MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); -MODULE_LICENSE("GPL"); - -static unsigned int bionet_min_poll_time = 2; - - -/* Information that need to be kept for each board. - */ -struct net_local { - struct net_device_stats stats; - long open_time; /* for debugging */ - int poll_time; /* polling time varies with net load */ -}; - -static struct nic_pkt_s { /* packet format */ - unsigned char status; - unsigned char dummy; - unsigned char l_lo, l_hi; - unsigned char buffer[3000]; -} *nic_packet; -unsigned char *phys_nic_packet; - -/* Index to functions, as function prototypes. - */ -static int bionet_open(struct net_device *dev); -static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev); -static void bionet_poll_rx(struct net_device *); -static int bionet_close(struct net_device *dev); -static struct net_device_stats *net_get_stats(struct net_device *dev); -static void bionet_tick(unsigned long); - -static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0); - -#define STRAM_ADDR(a) (((a) & 0xff000000) == 0) - -/* The following routines access the ethernet board connected to the - * ACSI port via the st_dma chip. - */ -#define NODE_ADR 0x60 - -#define C_READ 8 -#define C_WRITE 0x0a -#define C_GETEA 0x0f -#define C_SETCR 0x0e - -static int -sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) { - unsigned int c; - - dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88); - dma_wd.fdc_acces_seccount = cmd; - dma_wd.dma_mode_status = (mod | 0x8a); - - if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */ - return -1; /* timeout */ - - c = dma_wd.fdc_acces_seccount; - return (c & 0xff); -} - - -static void -set_status(int cr) { - sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */ - sendcmd(1,0x100,cr); - - dma_wd.dma_mode_status = 0x80; -} - -static int -get_status(unsigned char *adr) { - int i,c; - - DISABLE_IRQ(); - c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/ - if( c < 0 ) goto gsend; - - /* now read status bytes */ - - for (i=0; i<6; i++) { - dma_wd.fdc_acces_seccount = 0; /* request next byte */ - - if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */ - c = -1; - goto gsend; /* timeout */ - } - c = dma_wd.fdc_acces_seccount; - *adr++ = (unsigned char)c; - } - c = 1; -gsend: - dma_wd.dma_mode_status = 0x80; - return c; -} - -static irqreturn_t -bionet_intr(int irq, void *data) { - return IRQ_HANDLED; -} - - -static int -get_frame(unsigned long paddr, int odd) { - int c; - unsigned long flags; - - DISABLE_IRQ(); - local_irq_save(flags); - - dma_wd.dma_mode_status = 0x9a; - dma_wd.dma_mode_status = 0x19a; - dma_wd.dma_mode_status = 0x9a; - dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */ - dma_wd.dma_lo = (unsigned char)paddr; - paddr >>= 8; - dma_wd.dma_md = (unsigned char)paddr; - paddr >>= 8; - dma_wd.dma_hi = (unsigned char)paddr; - local_irq_restore(flags); - - c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */ - if( c < 128 ) goto rend; - - /* now read block */ - - c = sendcmd(1,0x00,odd); /* odd flag for address shift */ - dma_wd.dma_mode_status = 0x0a; - - if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */ - c = -1; - goto rend; - } - dma_wd.dma_mode_status = 0x8a; - dma_wd.dma_mode_status = 0x18a; - dma_wd.dma_mode_status = 0x8a; - c = dma_wd.fdc_acces_seccount; - - dma_wd.dma_mode_status = 0x88; - c = dma_wd.fdc_acces_seccount; - c = 1; - -rend: - dma_wd.dma_mode_status = 0x80; - udelay(40); - acsi_wait_for_noIRQ(20); - return c; -} - - -static int -hardware_send_packet(unsigned long paddr, int cnt) { - unsigned int c; - unsigned long flags; - - DISABLE_IRQ(); - local_irq_save(flags); - - dma_wd.dma_mode_status = 0x19a; - dma_wd.dma_mode_status = 0x9a; - dma_wd.dma_mode_status = 0x19a; - dma_wd.dma_lo = (unsigned char)paddr; - paddr >>= 8; - dma_wd.dma_md = (unsigned char)paddr; - paddr >>= 8; - dma_wd.dma_hi = (unsigned char)paddr; - - dma_wd.fdc_acces_seccount = 0x4; /* sector count */ - local_irq_restore(flags); - - c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */ - c = sendcmd(1,0x100,cnt&0xff); - c = sendcmd(1,0x100,cnt>>8); - - /* now write block */ - - dma_wd.dma_mode_status = 0x10a; /* DMA enable */ - if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */ - goto end; - - dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */ - c = dma_wd.fdc_acces_seccount; - -end: - c = sendcmd(1,0x100,0); - c = sendcmd(1,0x100,0); - - dma_wd.dma_mode_status = 0x180; - udelay(40); - acsi_wait_for_noIRQ(20); - return( c & 0x02); -} - - -/* Check for a network adaptor of this type, and return '0' if one exists. - */ -struct net_device * __init bionet_probe(int unit) -{ - struct net_device *dev; - unsigned char station_addr[6]; - static unsigned version_printed; - static int no_more_found; /* avoid "Probing for..." printed 4 times */ - int i; - int err; - - if (!MACH_IS_ATARI || no_more_found) - return ERR_PTR(-ENODEV); - - dev = alloc_etherdev(sizeof(struct net_local)); - if (!dev) - return ERR_PTR(-ENOMEM); - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - } - SET_MODULE_OWNER(dev); - - printk("Probing for BioNet 100 Adapter...\n"); - - stdma_lock(bionet_intr, NULL); - i = get_status(station_addr); /* Read the station address PROM. */ - ENABLE_IRQ(); - stdma_release(); - - /* Check the first three octets of the S.A. for the manufactor's code. - */ - - if( i < 0 - || station_addr[0] != 'B' - || station_addr[1] != 'I' - || station_addr[2] != 'O' ) { - no_more_found = 1; - printk( "No BioNet 100 found.\n" ); - free_netdev(dev); - return ERR_PTR(-ENODEV); - } - - if (bionet_debug > 0 && version_printed++ == 0) - printk(version); - - printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n", - dev->name, "BioNet 100", - station_addr[0], station_addr[1], station_addr[2], - station_addr[3], station_addr[4], station_addr[5]); - - /* Initialize the device structure. */ - - nic_packet = (struct nic_pkt_s *)acsi_buffer; - phys_nic_packet = (unsigned char *)phys_acsi_buffer; - if (bionet_debug > 0) { - printk("nic_packet at 0x%p, phys at 0x%p\n", - nic_packet, phys_nic_packet ); - } - - dev->open = bionet_open; - dev->stop = bionet_close; - dev->hard_start_xmit = bionet_send_packet; - dev->get_stats = net_get_stats; - - /* Fill in the fields of the device structure with ethernet-generic - * values. This should be in a common file instead of per-driver. - */ - - for (i = 0; i < ETH_ALEN; i++) { -#if 0 - dev->broadcast[i] = 0xff; -#endif - dev->dev_addr[i] = station_addr[i]; - } - err = register_netdev(dev); - if (!err) - return dev; - free_netdev(dev); - return ERR_PTR(err); -} - -/* Open/initialize the board. This is called (in the current kernel) - sometime after booting when the 'ifconfig' program is run. - - This routine should set everything up anew at each open, even - registers that "should" only need to be set once at boot, so that - there is non-reboot way to recover if something goes wrong. - */ -static int -bionet_open(struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - - if (bionet_debug > 0) - printk("bionet_open\n"); - stdma_lock(bionet_intr, NULL); - - /* Reset the hardware here. - */ - set_status(4); - lp->open_time = 0; /*jiffies*/ - lp->poll_time = MAX_POLL_TIME; - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - stdma_release(); - bionet_timer.data = (long)dev; - bionet_timer.expires = jiffies + lp->poll_time; - add_timer(&bionet_timer); - return 0; -} - -static int -bionet_send_packet(struct sk_buff *skb, struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - unsigned long flags; - - /* Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - */ - local_irq_save(flags); - - if (stdma_islocked()) { - local_irq_restore(flags); - lp->stats.tx_errors++; - } - else { - int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned long buf = virt_to_phys(skb->data); - int stat; - - stdma_lock(bionet_intr, NULL); - local_irq_restore(flags); - if( !STRAM_ADDR(buf+length-1) ) { - skb_copy_from_linear_data(skb, nic_packet->buffer, - length); - buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; - } - - if (bionet_debug >1) { - u_char *data = nic_packet->buffer, *p; - int i; - - printk( "%s: TX pkt type 0x%4x from ", dev->name, - ((u_short *)data)[6]); - - for( p = &data[6], i = 0; i < 6; i++ ) - printk("%02x%s", *p++,i != 5 ? ":" : "" ); - printk(" to "); - - for( p = data, i = 0; i < 6; i++ ) - printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); - - printk( "%s: ", dev->name ); - printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" - " %02x%02x%02x%02x len %d\n", - data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], - data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], - data[28], data[29], data[30], data[31], data[32], data[33], - length ); - } - dma_cache_maintenance(buf, length, 1); - - stat = hardware_send_packet(buf, length); - ENABLE_IRQ(); - stdma_release(); - - dev->trans_start = jiffies; - dev->tbusy = 0; - lp->stats.tx_packets++; - lp->stats.tx_bytes+=length; - } - dev_kfree_skb(skb); - - return 0; -} - -/* We have a good packet(s), get it/them out of the buffers. - */ -static void -bionet_poll_rx(struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - int boguscount = 10; - int pkt_len, status; - unsigned long flags; - - local_irq_save(flags); - /* ++roman: Take care at locking the ST-DMA... This must be done with ints - * off, since otherwise an int could slip in between the question and the - * locking itself, and then we'd go to sleep... And locking itself is - * necessary to keep the floppy_change timer from working with ST-DMA - * registers. */ - if (stdma_islocked()) { - local_irq_restore(flags); - return; - } - stdma_lock(bionet_intr, NULL); - DISABLE_IRQ(); - local_irq_restore(flags); - - if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; - - while(boguscount--) { - status = get_frame((unsigned long)phys_nic_packet, 0); - - if( status == 0 ) break; - - /* Good packet... */ - - dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0); - - pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; - - lp->poll_time = bionet_min_poll_time; /* fast poll */ - if( pkt_len >= 60 && pkt_len <= 1520 ) { - /* ^^^^ war 1514 KHL */ - /* Malloc up new buffer. - */ - struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 ); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", - dev->name); - lp->stats.rx_dropped++; - break; - } - - skb_reserve( skb, 2 ); /* 16 Byte align */ - skb_put( skb, pkt_len ); /* make room */ - - /* 'skb->data' points to the start of sk_buff data area. - */ - skb_copy_to_linear_data(skb, nic_packet->buffer, - pkt_len); - skb->protocol = eth_type_trans( skb, dev ); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - lp->stats.rx_bytes+=pkt_len; - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(INET_BH) for us and will work on them - when we get to the bottom-half routine. - */ - - if (bionet_debug >1) { - u_char *data = nic_packet->buffer, *p; - int i; - - printk( "%s: RX pkt type 0x%4x from ", dev->name, - ((u_short *)data)[6]); - - - for( p = &data[6], i = 0; i < 6; i++ ) - printk("%02x%s", *p++,i != 5 ? ":" : "" ); - printk(" to "); - for( p = data, i = 0; i < 6; i++ ) - printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); - - printk( "%s: ", dev->name ); - printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" - " %02x%02x%02x%02x len %d\n", - data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], - data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], - data[28], data[29], data[30], data[31], data[32], data[33], - pkt_len ); - } - } - else { - printk(" Packet has wrong length: %04d bytes\n", pkt_len); - lp->stats.rx_errors++; - } - } - stdma_release(); - ENABLE_IRQ(); - return; -} - -/* bionet_tick: called by bionet_timer. Reads packets from the adapter, - * passes them to the higher layers and restarts the timer. - */ -static void -bionet_tick(unsigned long data) { - struct net_device *dev = (struct net_device *)data; - struct net_local *lp = netdev_priv(dev); - - if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 ) - printk("bionet_tick: %ld\n", lp->open_time); - - if( !stdma_islocked() ) bionet_poll_rx(dev); - - bionet_timer.expires = jiffies + lp->poll_time; - add_timer(&bionet_timer); -} - -/* The inverse routine to bionet_open(). - */ -static int -bionet_close(struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - - if (bionet_debug > 0) - printk("bionet_close, open_time=%ld\n", lp->open_time); - del_timer(&bionet_timer); - stdma_lock(bionet_intr, NULL); - - set_status(0); - lp->open_time = 0; - - dev->tbusy = 1; - dev->start = 0; - - stdma_release(); - return 0; -} - -/* Get the current statistics. - This may be called with the card open or closed. - */ -static struct net_device_stats *net_get_stats(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - return &lp->stats; -} - - -#ifdef MODULE - -static struct net_device *bio_dev; - -int init_module(void) -{ - bio_dev = bionet_probe(-1); - if (IS_ERR(bio_dev)) - return PTR_ERR(bio_dev); - return 0; -} - -void cleanup_module(void) -{ - unregister_netdev(bio_dev); - free_netdev(bio_dev); -} - -#endif /* MODULE */ - -/* Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include - -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 - -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c deleted file mode 100644 index 54714409a09b..000000000000 --- a/drivers/net/atari_pamsnet.c +++ /dev/null @@ -1,896 +0,0 @@ -/* atari_pamsnet.c PAMsNet device driver for linux68k. - * - * Version: @(#)PAMsNet.c 0.2ß 03/31/96 - * - * Author: Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de> - * <Torsten.Lang@jung.de> - * - * This driver is based on my driver PAMSDMA.c for MiNT-Net and - * on the driver bionet.c written by - * Hartmut Laue <laue@ifk-mp.uni-kiel.de> - * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de> - * - * Little adaptions for integration into pl7 by Roman Hodek - * - What is it ? - ------------ - This driver controls the PAMsNet LAN-Adapter which connects - an ATARI ST/TT via the ACSI-port to an Ethernet-based network. - - This version can be compiled as a loadable module (See the - compile command at the bottom of this file). - At load time, you can optionally set the debugging level and the - fastest response time on the command line of 'insmod'. - - 'pamsnet_debug' - controls the amount of diagnostic messages: - 0 : no messages - >0 : see code for meaning of printed messages - - 'pamsnet_min_poll_time' (always >=1) - gives the time (in jiffies) between polls. Low values - increase the system load (beware!) - - When loaded, a net device with the name 'eth?' becomes available, - which can be controlled with the usual 'ifconfig' command. - - It is possible to compile this driver into the kernel like other - (net) drivers. For this purpose, some source files (e.g. config-files - makefiles, Space.c) must be changed accordingly. (You may refer to - other drivers how to do it.) In this case, the device will be detected - at boot time and (probably) appear as 'eth0'. - - Theory of Operation - ------------------- - Because the ATARI DMA port is usually shared between several - devices (eg. harddisk, floppy) we cannot block the ACSI bus - while waiting for interrupts. Therefore we use a polling mechanism - to fetch packets from the adapter. For the same reason, we send - packets without checking that the previous packet has been sent to - the LAN. We rely on the higher levels of the networking code to detect - missing packets and resend them. - - Before we access the ATARI DMA controller, we check if another - process is using the DMA. If not, we lock the DMA, perform one or - more packet transfers and unlock the DMA before returning. - We do not use 'stdma_lock' unconditionally because it is unclear - if the networking code can be set to sleep, which will happen if - another (possibly slow) device is using the DMA controller. - - The polling is done via timer interrupts which periodically - 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies) - between polls varies depending on an estimate of the net activity. - The allowed range is given by the variable 'bionet_min_poll_time' - for the lower (fastest) limit and the constant 'MAX_POLL_TIME' - for the higher (slowest) limit. - - Whenever a packet arrives, we switch to fastest response by setting - the polling time to its lowest limit. If the following poll fails, - because no packets have arrived, we increase the time for the next - poll. When the net activity is low, the polling time effectively - stays at its maximum value, resulting in the lowest load for the - machine. - */ - -#define MAX_POLL_TIME 10 - -static char *version = - "pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/jiffies.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/bitops.h> -#include <asm/system.h> -#include <asm/pgtable.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> -#include <asm/atarihw.h> -#include <asm/atariints.h> -#include <asm/atari_stdma.h> -#include <asm/atari_acsi.h> - -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/init.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#undef READ -#undef WRITE - -/* use 0 for production, 1 for verification, >2 for debug - */ -#ifndef NET_DEBUG -#define NET_DEBUG 0 -#endif -/* - * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod' - */ -unsigned int pamsnet_debug = NET_DEBUG; -module_param(pamsnet_debug, int, 0); -MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)"); -MODULE_LICENSE("GPL"); - -static unsigned int pamsnet_min_poll_time = 2; - - -/* Information that need to be kept for each board. - */ -struct net_local { - struct net_device_stats stats; - long open_time; /* for debugging */ - int poll_time; /* polling time varies with net load */ -}; - -static struct nic_pkt_s { /* packet format */ - unsigned char buffer[2048]; -} *nic_packet = 0; -unsigned char *phys_nic_packet; - -typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */ - -/* Index to functions, as function prototypes. - */ -static void start (int target); -static int stop (int target); -static int testpkt (int target); -static int sendpkt (int target, unsigned char *buffer, int length); -static int receivepkt (int target, unsigned char *buffer); -static int inquiry (int target, unsigned char *buffer); -static HADDR *read_hw_addr(int target, unsigned char *buffer); -static void setup_dma (void *address, unsigned rw_flag, int num_blocks); -static int send_first (int target, unsigned char byte); -static int send_1_5 (int lun, unsigned char *command, int dma); -static int get_status (void); -static int calc_received (void *start_address); - -static int pamsnet_open(struct net_device *dev); -static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev); -static void pamsnet_poll_rx(struct net_device *); -static int pamsnet_close(struct net_device *dev); -static struct net_device_stats *net_get_stats(struct net_device *dev); -static void pamsnet_tick(unsigned long); - -static irqreturn_t pamsnet_intr(int irq, void *data); - -static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0); - -#define STRAM_ADDR(a) (((a) & 0xff000000) == 0) - -typedef struct -{ - unsigned char reserved1[0x38]; - HADDR hwaddr; - unsigned char reserved2[0x1c2]; -} DMAHWADDR; - -/* - * Definitions of commands understood by the PAMs DMA adaptor. - * - * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable - * by the PAM's Net software. - * - * LUN 0 works as a harddisk. You can boot the PAM's Net driver there. - * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW - * area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address - * of the adaptor. - * LUN 6 works as a harddisk and lets you access the firmware ROM. - * LUN 7 lets you send and receive packets. - * - * Some commands like the INQUIRY command work identical on all used LUNs. - * - * UNKNOWN1 seems to read some data. - * Command length is 6 bytes. - * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The - * following bytes seem to be something like an allocation length. - * Command length is 6 bytes. - * READPKT reads a packet received by the DMA adaptor. - * Command length is 6 bytes. - * WRITEPKT sends a packet transferred by the following DMA phase. The length - * of the packet is transferred in command bytes 3 and 4. - * The adaptor automatically replaces the src hw address in an ethernet - * packet by its own hw address. - * Command length is 6 bytes. - * INQUIRY has the same function as the INQUIRY command supported by harddisks - * and other SCSI devices. It lets you detect which device you found - * at a given address. - * Command length is 6 bytes. - * START initializes the DMA adaptor. After this command it is able to send - * and receive packets. There is no status byte returned! - * Command length is 1 byte. - * NUMPKTS gives back the number of received packets waiting in the queue in - * the status byte. - * Command length is 1 byte. - * UNKNOWN3 - * UNKNOWN4 Function of these three commands is unknown. - * UNKNOWN5 The command length of these three commands is 1 byte. - * DESELECT immediately deselects the DMA adaptor. May important with interrupt - * driven operation. - * Command length is 1 byte. - * STOP resets the DMA adaptor. After this command packets can no longer - * be received or transferred. - * Command length is 6 byte. - */ - -enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START, - NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP}; - -#define READSECTOR READPKT -#define WRITESECTOR WRITEPKT - -u_char *inquire8="MV PAM's NET/GK"; - -#define DMALOW dma_wd.dma_lo -#define DMAMID dma_wd.dma_md -#define DMAHIGH dma_wd.dma_hi -#define DACCESS dma_wd.fdc_acces_seccount - -#define MFP_GPIP mfp.par_dt_reg - -/* Some useful functions */ - -#define INT (!(MFP_GPIP & 0x20)) -#define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;}) -#define WRITEMODE(value) \ - ({ u_short dummy = value; \ - __asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy)); \ - DELAY; \ - }) -#define WRITEBOTH(value1, value2) \ - ({ u_long dummy = (u_long)(value1)<<16 | (u_short)(value2); \ - __asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy)); \ - DELAY; \ - }) - -/* Definitions for DMODE */ - -#define READ 0x000 -#define WRITE 0x100 - -#define DMA_FDC 0x080 -#define DMA_ACSI 0x000 - -#define DMA_DISABLE 0x040 - -#define SEC_COUNT 0x010 -#define DMA_WINDOW 0x000 - -#define REG_ACSI 0x008 -#define REG_FDC 0x000 - -#define A1 0x002 - -/* Timeout constants */ - -#define TIMEOUTCMD HZ/2 /* ca. 500ms */ -#define TIMEOUTDMA HZ /* ca. 1s */ -#define COMMAND_DELAY 500 /* ca. 0.5ms */ - -unsigned rw; -int lance_target = -1; -int if_up = 0; - -/* The following routines access the ethernet board connected to the - * ACSI port via the st_dma chip. - */ - -/* The following lowlevel routines work on physical addresses only and assume - * that eventually needed buffers are - * - completely located in ST RAM - * - are contigous in the physical address space - */ - -/* Setup the DMA counter */ - -static void -setup_dma (address, rw_flag, num_blocks) - void *address; - unsigned rw_flag; - int num_blocks; -{ - WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | - A1); - WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI | - A1); - WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | - A1); - DMALOW = (unsigned char)((unsigned long)address & 0xFF); - DMAMID = (unsigned char)(((unsigned long)address >> 8) & 0xFF); - DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF); - WRITEBOTH((unsigned)num_blocks & 0xFF, - rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1); - rw = rw_flag; -} - -/* Send the first byte of an command block */ - -static int -send_first (target, byte) - int target; - unsigned char byte; -{ - rw = READ; - acsi_delay_end(COMMAND_DELAY); - /* - * wake up ACSI - */ - WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI); - /* - * write command byte - */ - WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC | - DMA_WINDOW | REG_ACSI | A1); - return (!acsi_wait_for_IRQ(TIMEOUTCMD)); -} - -/* Send the rest of an command block */ - -static int -send_1_5 (lun, command, dma) - int lun; - unsigned char *command; - int dma; -{ - int i, j; - - for (i=0; i<5; i++) { - WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F)) - : command[i]), - rw | REG_ACSI | DMA_WINDOW | - ((i < 4) ? DMA_FDC - : (dma ? DMA_ACSI - : DMA_FDC)) | A1); - if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD))) - return (j); - } - return (0); -} - -/* Read a status byte */ - -static int -get_status (void) -{ - WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1); - acsi_delay_start(); - return ((int)(DACCESS & 0xFF)); -} - -/* Calculate the number of received bytes */ - -static int -calc_received (start_address) - void *start_address; -{ - return (int)( - (((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW) - - (unsigned long)start_address); -} - -/* The following midlevel routines still work on physical addresses ... */ - -/* start() starts the PAM's DMA adaptor */ - -static void -start (target) - int target; -{ - send_first(target, START); -} - -/* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */ - -static int -stop (target) - int target; -{ - int ret = -1; - unsigned char cmd_buffer[5]; - - if (send_first(target, STOP)) - goto bad; - cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = - cmd_buffer[3] = cmd_buffer[4] = 0; - if (send_1_5(7, cmd_buffer, 0) || - !acsi_wait_for_IRQ(TIMEOUTDMA) || - get_status()) - goto bad; - ret = 0; -bad: - return (ret); -} - -/* testpkt() returns the number of received packets waiting in the queue */ - -static int -testpkt(target) - int target; -{ - int ret = -1; - - if (send_first(target, NUMPKTS)) - goto bad; - ret = get_status(); -bad: - return (ret); -} - -/* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */ -/* Please note: The buffer is for internal use only but must be defined! */ - -static int -inquiry (target, buffer) - int target; - unsigned char *buffer; -{ - int ret = -1; - unsigned char *vbuffer = phys_to_virt((unsigned long)buffer); - unsigned char cmd_buffer[5]; - - if (send_first(target, INQUIRY)) - goto bad; - setup_dma(buffer, READ, 1); - vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */ - cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; - cmd_buffer[3] = 48; - if (send_1_5(5, cmd_buffer, 1) || - !acsi_wait_for_IRQ(TIMEOUTDMA) || - get_status() || - (calc_received(buffer) < 32)) - goto bad; - dma_cache_maintenance((unsigned long)(buffer+8), 20, 0); - if (memcmp(inquire8, vbuffer+8, 20)) - goto bad; - ret = 0; -bad: - if (!!NET_DEBUG) { - vbuffer[8+20]=0; - printk("inquiry of target %d: %s\n", target, vbuffer+8); - } - return (ret); -} - -/* - * read_hw_addr() reads the sector containing the hwaddr and returns - * a pointer to it (virtual address!) or 0 in case of an error - */ - -static HADDR -*read_hw_addr(target, buffer) - int target; - unsigned char *buffer; -{ - HADDR *ret = 0; - unsigned char cmd_buffer[5]; - - if (send_first(target, READSECTOR)) - goto bad; - setup_dma(buffer, READ, 1); - cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; - cmd_buffer[3] = 1; - if (send_1_5(5, cmd_buffer, 1) || - !acsi_wait_for_IRQ(TIMEOUTDMA) || - get_status()) - goto bad; - ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr)); - dma_cache_maintenance((unsigned long)buffer, 512, 0); -bad: - return (ret); -} - -static irqreturn_t -pamsnet_intr(irq, data, fp) - int irq; - void *data; -{ - return IRQ_HANDLED; -} - -/* receivepkt() loads a packet to a given buffer and returns its length */ - -static int -receivepkt (target, buffer) - int target; - unsigned char *buffer; -{ - int ret = -1; - unsigned char cmd_buffer[5]; - - if (send_first(target, READPKT)) - goto bad; - setup_dma(buffer, READ, 3); - cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; - cmd_buffer[3] = 3; - if (send_1_5(7, cmd_buffer, 1) || - !acsi_wait_for_IRQ(TIMEOUTDMA) || - get_status()) - goto bad; - ret = calc_received(buffer); -bad: - return (ret); -} - -/* sendpkt() sends a packet and returns a value of zero when the packet was sent - successfully */ - -static int -sendpkt (target, buffer, length) - int target; - unsigned char *buffer; - int length; -{ - int ret = -1; - unsigned char cmd_buffer[5]; - - if (send_first(target, WRITEPKT)) - goto bad; - setup_dma(buffer, WRITE, 3); - cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0; - cmd_buffer[2] = length >> 8; - cmd_buffer[3] = length & 0xFF; - if (send_1_5(7, cmd_buffer, 1) || - !acsi_wait_for_IRQ(TIMEOUTDMA) || - get_status()) - goto bad; - ret = 0; -bad: - return (ret); -} - -/* The following higher level routines work on virtual addresses and convert them to - * physical addresses when passed to the lowlevel routines. It's up to the higher level - * routines to copy data from Alternate RAM to ST RAM if neccesary! - */ - -/* Check for a network adaptor of this type, and return '0' if one exists. - */ - -struct net_device * __init pamsnet_probe (int unit) -{ - struct net_device *dev; - int i; - HADDR *hwaddr; - int err; - - unsigned char station_addr[6]; - static unsigned version_printed; - /* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */ - static int no_more_found; - - if (no_more_found) - return ERR_PTR(-ENODEV); - no_more_found = 1; - - dev = alloc_etherdev(sizeof(struct net_local)); - if (!dev) - return ERR_PTR(-ENOMEM); - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - } - SET_MODULE_OWNER(dev); - - printk("Probing for PAM's Net/GK Adapter...\n"); - - /* Allocate the DMA buffer here since we need it for probing! */ - - nic_packet = (struct nic_pkt_s *)acsi_buffer; - phys_nic_packet = (unsigned char *)phys_acsi_buffer; - if (pamsnet_debug > 0) { - printk("nic_packet at 0x%p, phys at 0x%p\n", - nic_packet, phys_nic_packet ); - } - - stdma_lock(pamsnet_intr, NULL); - DISABLE_IRQ(); - - for (i=0; i<8; i++) { - /* Do two inquiries to cover cases with strange equipment on previous ID */ - /* blocking the ACSI bus (like the SLMC804 laser printer controller... */ - inquiry(i, phys_nic_packet); - if (!inquiry(i, phys_nic_packet)) { - lance_target = i; - break; - } - } - - if (!!NET_DEBUG) - printk("ID: %d\n",i); - - if (lance_target >= 0) { - if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet))) - lance_target = -1; - else - memcpy (station_addr, hwaddr, ETH_ALEN); - } - - ENABLE_IRQ(); - stdma_release(); - - if (lance_target < 0) { - printk("No PAM's Net/GK found.\n"); - free_netdev(dev); - return ERR_PTR(-ENODEV); - } - - if (pamsnet_debug > 0 && version_printed++ == 0) - printk(version); - - printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n", - dev->name, "PAM's Net/GK", lance_target, - station_addr[0], station_addr[1], station_addr[2], - station_addr[3], station_addr[4], station_addr[5]); - - /* Initialize the device structure. */ - dev->open = pamsnet_open; - dev->stop = pamsnet_close; - dev->hard_start_xmit = pamsnet_send_packet; - dev->get_stats = net_get_stats; - - /* Fill in the fields of the device structure with ethernet-generic - * values. This should be in a common file instead of per-driver. - */ - - for (i = 0; i < ETH_ALEN; i++) { -#if 0 - dev->broadcast[i] = 0xff; -#endif - dev->dev_addr[i] = station_addr[i]; - } - err = register_netdev(dev); - if (!err) - return dev; - - free_netdev(dev); - return ERR_PTR(err); -} - -/* Open/initialize the board. This is called (in the current kernel) - sometime after booting when the 'ifconfig' program is run. - - This routine should set everything up anew at each open, even - registers that "should" only need to be set once at boot, so that - there is non-reboot way to recover if something goes wrong. - */ -static int -pamsnet_open(struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - - if (pamsnet_debug > 0) - printk("pamsnet_open\n"); - stdma_lock(pamsnet_intr, NULL); - DISABLE_IRQ(); - - /* Reset the hardware here. - */ - if (!if_up) - start(lance_target); - if_up = 1; - lp->open_time = 0; /*jiffies*/ - lp->poll_time = MAX_POLL_TIME; - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - ENABLE_IRQ(); - stdma_release(); - pamsnet_timer.data = (long)dev; - pamsnet_timer.expires = jiffies + lp->poll_time; - add_timer(&pamsnet_timer); - return 0; -} - -static int -pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - unsigned long flags; - - /* Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - */ - local_irq_save(flags); - - if (stdma_islocked()) { - local_irq_restore(flags); - lp->stats.tx_errors++; - } - else { - int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned long buf = virt_to_phys(skb->data); - int stat; - - stdma_lock(pamsnet_intr, NULL); - DISABLE_IRQ(); - - local_irq_restore(flags); - if( !STRAM_ADDR(buf+length-1) ) { - skb_copy_from_linear_data(skb, nic_packet->buffer, - length); - buf = (unsigned long)phys_nic_packet; - } - - dma_cache_maintenance(buf, length, 1); - - stat = sendpkt(lance_target, (unsigned char *)buf, length); - ENABLE_IRQ(); - stdma_release(); - - dev->trans_start = jiffies; - dev->tbusy = 0; - lp->stats.tx_packets++; - lp->stats.tx_bytes+=length; - } - dev_kfree_skb(skb); - - return 0; -} - -/* We have a good packet(s), get it/them out of the buffers. - */ -static void -pamsnet_poll_rx(struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - int boguscount; - int pkt_len; - struct sk_buff *skb; - unsigned long flags; - - local_irq_save(flags); - /* ++roman: Take care at locking the ST-DMA... This must be done with ints - * off, since otherwise an int could slip in between the question and the - * locking itself, and then we'd go to sleep... And locking itself is - * necessary to keep the floppy_change timer from working with ST-DMA - * registers. */ - if (stdma_islocked()) { - local_irq_restore(flags); - return; - } - stdma_lock(pamsnet_intr, NULL); - DISABLE_IRQ(); - local_irq_restore(flags); - - boguscount = testpkt(lance_target); - if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; - - while(boguscount--) { - pkt_len = receivepkt(lance_target, phys_nic_packet); - - if( pkt_len < 60 ) break; - - /* Good packet... */ - - dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0); - - lp->poll_time = pamsnet_min_poll_time; /* fast poll */ - if( pkt_len >= 60 && pkt_len <= 2048 ) { - if (pkt_len > 1514) - pkt_len = 1514; - - /* Malloc up new buffer. - */ - skb = alloc_skb(pkt_len, GFP_ATOMIC); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", - dev->name); - lp->stats.rx_dropped++; - break; - } - skb->len = pkt_len; - skb->dev = dev; - - /* 'skb->data' points to the start of sk_buff data area. - */ - skb_copy_to_linear_data(skb, nic_packet->buffer, - pkt_len); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - lp->stats.rx_bytes+=pkt_len; - } - } - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(INET_BH) for us and will work on them - when we get to the bottom-half routine. - */ - - ENABLE_IRQ(); - stdma_release(); - return; -} - -/* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter, - * passes them to the higher layers and restarts the timer. - */ -static void -pamsnet_tick(unsigned long data) { - struct net_device *dev = (struct net_device *)data; - struct net_local *lp = netdev_priv(dev); - - if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 ) - printk("pamsnet_tick: %ld\n", lp->open_time); - - pamsnet_poll_rx(dev); - - pamsnet_timer.expires = jiffies + lp->poll_time; - add_timer(&pamsnet_timer); -} - -/* The inverse routine to pamsnet_open(). - */ -static int -pamsnet_close(struct net_device *dev) { - struct net_local *lp = netdev_priv(dev); - - if (pamsnet_debug > 0) - printk("pamsnet_close, open_time=%ld\n", lp->open_time); - del_timer(&pamsnet_timer); - stdma_lock(pamsnet_intr, NULL); - DISABLE_IRQ(); - - if (if_up) - stop(lance_target); - if_up = 0; - - lp->open_time = 0; - - dev->tbusy = 1; - dev->start = 0; - - ENABLE_IRQ(); - stdma_release(); - return 0; -} - -/* Get the current statistics. - This may be called with the card open or closed. - */ -static struct net_device_stats *net_get_stats(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - return &lp->stats; -} - - -#ifdef MODULE - -static struct net_device *pam_dev; - -int init_module(void) -{ - pam_dev = pamsnet_probe(-1); - if (IS_ERR(pam_dev)) - return PTR_ERR(pam_dev); - return 0; -} - -void cleanup_module(void) -{ - unregister_netdev(pam_dev); - free_netdev(pam_dev); -} - -#endif /* MODULE */ - -/* Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include - -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 - -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h index b1c6034e68fa..ff4765f6c3de 100644 --- a/drivers/net/atl1/atl1.h +++ b/drivers/net/atl1/atl1.h @@ -43,6 +43,7 @@ extern const struct ethtool_ops atl1_ethtool_ops; struct atl1_adapter; #define ATL1_MAX_INTR 3 +#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */ #define ATL1_DEFAULT_TPD 256 #define ATL1_MAX_TPD 1024 @@ -57,29 +58,45 @@ struct atl1_adapter; #define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc) /* + * This detached comment is preserved for documentation purposes only. + * It was originally attached to some code that got deleted, but seems + * important enough to keep around... + * + * <begin detached comment> * Some workarounds require millisecond delays and are run during interrupt * context. Most notably, when establishing link, the phy may need tweaking * but cannot process phy register reads/writes faster than millisecond * intervals...and we establish link due to a "link status change" interrupt. + * <end detached comment> + */ + +/* + * atl1_ring_header represents a single, contiguous block of DMA space + * mapped for the three descriptor rings (tpd, rfd, rrd) and the two + * message blocks (cmb, smb) described below */ +struct atl1_ring_header { + void *desc; /* virtual address */ + dma_addr_t dma; /* physical address*/ + unsigned int size; /* length in bytes */ +}; /* - * wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer + * atl1_buffer is wrapper around a pointer to a socket buffer + * so a DMA handle can be stored along with the skb */ struct atl1_buffer { - struct sk_buff *skb; - u16 length; - u16 alloced; + struct sk_buff *skb; /* socket buffer */ + u16 length; /* rx buffer length */ + u16 alloced; /* 1 if skb allocated */ dma_addr_t dma; }; -#define MAX_TX_BUF_LEN 0x3000 /* 12KB */ - +/* transmit packet descriptor (tpd) ring */ struct atl1_tpd_ring { - void *desc; /* pointer to the descriptor ring memory */ - dma_addr_t dma; /* physical adress of the descriptor ring */ - u16 size; /* length of descriptor ring in bytes */ + void *desc; /* descriptor ring virtual address */ + dma_addr_t dma; /* descriptor ring physical address */ + u16 size; /* descriptor ring length in bytes */ u16 count; /* number of descriptors in the ring */ u16 hw_idx; /* hardware index */ atomic_t next_to_clean; @@ -87,36 +104,34 @@ struct atl1_tpd_ring { struct atl1_buffer *buffer_info; }; +/* receive free descriptor (rfd) ring */ struct atl1_rfd_ring { - void *desc; - dma_addr_t dma; - u16 size; - u16 count; + void *desc; /* descriptor ring virtual address */ + dma_addr_t dma; /* descriptor ring physical address */ + u16 size; /* descriptor ring length in bytes */ + u16 count; /* number of descriptors in the ring */ atomic_t next_to_use; u16 next_to_clean; struct atl1_buffer *buffer_info; }; +/* receive return descriptor (rrd) ring */ struct atl1_rrd_ring { - void *desc; - dma_addr_t dma; - unsigned int size; - u16 count; + void *desc; /* descriptor ring virtual address */ + dma_addr_t dma; /* descriptor ring physical address */ + unsigned int size; /* descriptor ring length in bytes */ + u16 count; /* number of descriptors in the ring */ u16 next_to_use; atomic_t next_to_clean; }; -struct atl1_ring_header { - void *desc; /* pointer to the descriptor ring memory */ - dma_addr_t dma; /* physical adress of the descriptor ring */ - unsigned int size; /* length of descriptor ring in bytes */ -}; - +/* coalescing message block (cmb) */ struct atl1_cmb { struct coals_msg_block *cmb; dma_addr_t dma; }; +/* statistics message block (smb) */ struct atl1_smb { struct stats_msg_block *smb; dma_addr_t dma; @@ -141,24 +156,26 @@ struct atl1_sft_stats { u64 tx_aborted_errors; u64 tx_window_errors; u64 tx_carrier_errors; - - u64 tx_pause; /* num Pause packet transmitted. */ - u64 excecol; /* num tx packets aborted due to excessive collisions. */ - u64 deffer; /* num deferred tx packets */ - u64 scc; /* num packets subsequently transmitted successfully w/ single prior collision. */ - u64 mcc; /* num packets subsequently transmitted successfully w/ multiple prior collisions. */ + u64 tx_pause; /* num pause packets transmitted. */ + u64 excecol; /* num tx packets w/ excessive collisions. */ + u64 deffer; /* num tx packets deferred */ + u64 scc; /* num packets subsequently transmitted + * successfully w/ single prior collision. */ + u64 mcc; /* num packets subsequently transmitted + * successfully w/ multiple prior collisions. */ u64 latecol; /* num tx packets w/ late collisions. */ - u64 tx_underun; /* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ - u64 tx_trunc; /* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */ + u64 tx_underun; /* num tx packets aborted due to transmit + * FIFO underrun, or TRD FIFO underrun */ + u64 tx_trunc; /* num tx packets truncated due to size + * exceeding MTU, regardless whether truncated + * by the chip or not. (The name doesn't really + * reflect the meaning in this case.) */ u64 rx_pause; /* num Pause packets received. */ u64 rx_rrd_ov; u64 rx_trunc; }; -/* board specific private data structure */ -#define ATL1_REGS_LEN 8 - -/* Structure containing variables used by the shared code */ +/* hardware structure */ struct atl1_hw { u8 __iomem *hw_addr; struct atl1_adapter *back; @@ -167,24 +184,35 @@ struct atl1_hw { enum atl1_dma_req_block dmar_block; enum atl1_dma_req_block dmaw_block; u8 preamble_len; - u8 max_retry; /* Retransmission maximum, after which the packet will be discarded */ - u8 jam_ipg; /* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */ - u8 ipgt; /* Desired back to back inter-packet gap. The default is 96-bit time */ - u8 min_ifg; /* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */ + u8 max_retry; /* Retransmission maximum, after which the + * packet will be discarded */ + u8 jam_ipg; /* IPG to start JAM for collision based flow + * control in half-duplex mode. In units of + * 8-bit time */ + u8 ipgt; /* Desired back to back inter-packet gap. + * The default is 96-bit time */ + u8 min_ifg; /* Minimum number of IFG to enforce in between + * receive frames. Frame gap below such IFP + * is dropped */ u8 ipgr1; /* 64bit Carrier-Sense window */ u8 ipgr2; /* 96-bit IPG window */ - u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */ - u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */ + u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned + * burst. Each TPD is 16 bytes long */ + u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned + * burst. Each RFD is 12 bytes long */ u8 rfd_fetch_gap; - u8 rrd_burst; /* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */ + u8 rrd_burst; /* Threshold number of RRDs that can be retired + * in a burst. Each RRD is 16 bytes long */ u8 tpd_fetch_th; u8 tpd_fetch_gap; u16 tx_jumbo_task_th; - u16 txf_burst; /* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is - 8 bytes long */ - u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */ + u16 txf_burst; /* Number of data bytes to read in a cache- + * aligned burst. Each SRAM entry is 8 bytes */ + u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN + * packets should add 4 bytes */ u16 rx_jumbo_lkah; - u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after every 512ns passes. */ + u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after + * every 512ns passes. */ u16 lcol; /* Collision Window */ u16 cmb_tpd; @@ -194,49 +222,35 @@ struct atl1_hw { u32 smb_timer; u16 media_type; u16 autoneg_advertised; - u16 pci_cmd_word; u16 mii_autoneg_adv_reg; u16 mii_1000t_ctrl_reg; - u32 mem_rang; - u32 txcw; u32 max_frame_size; u32 min_frame_size; - u32 mc_filter_type; - u32 num_mc_addrs; - u32 collision_delta; - u32 tx_packet_delta; - u16 phy_spd_default; u16 dev_rev; - u8 revision_id; /* spi flash */ u8 flash_vendor; - u8 dma_fairness; u8 mac_addr[ETH_ALEN]; u8 perm_mac_addr[ETH_ALEN]; - /* bool phy_preamble_sup; */ bool phy_configured; }; struct atl1_adapter { - /* OS defined structs */ struct net_device *netdev; struct pci_dev *pdev; struct net_device_stats net_stats; struct atl1_sft_stats soft_stats; - struct vlan_group *vlgrp; u32 rx_buffer_len; u32 wol; u16 link_speed; u16 link_duplex; spinlock_t lock; - atomic_t irq_sem; struct work_struct tx_timeout_task; struct work_struct link_chg_task; struct work_struct pcie_dma_to_rst_task; @@ -244,9 +258,7 @@ struct atl1_adapter { struct timer_list phy_config_timer; bool phy_timer_pending; - bool mac_disabled; - - /* All descriptor rings' memory */ + /* all descriptor rings' memory */ struct atl1_ring_header ring_header; /* TX */ @@ -259,25 +271,16 @@ struct atl1_adapter { u64 hw_csum_err; u64 hw_csum_good; - u32 gorcl; - u64 gorcl_old; - - /* Interrupt Moderator timer ( 2us resolution) */ - u16 imt; - /* Interrupt Clear timer (2us resolution) */ - u16 ict; - - /* MII interface info */ - struct mii_if_info mii; + u16 imt; /* interrupt moderator timer (2us resolution */ + u16 ict; /* interrupt clear timer (2us resolution */ + struct mii_if_info mii; /* MII interface info */ /* structs defined in atl1_hw.h */ - u32 bd_number; /* board number */ + u32 bd_number; /* board number */ bool pci_using_64; struct atl1_hw hw; struct atl1_smb smb; struct atl1_cmb cmb; - - u32 pci_state[16]; }; #endif /* _ATL1_H_ */ diff --git a/drivers/net/atl1/atl1_hw.h b/drivers/net/atl1/atl1_hw.h index 100c09c66e64..939aa0f53f6e 100644 --- a/drivers/net/atl1/atl1_hw.h +++ b/drivers/net/atl1/atl1_hw.h @@ -680,11 +680,6 @@ void atl1_check_options(struct atl1_adapter *adapter); #define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */ #define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */ -/* The size (in bytes) of a ethernet packet */ -#define ENET_HEADER_SIZE 14 -#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */ -#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */ -#define ETHERNET_FCS_SIZE 4 #define MAX_JUMBO_FRAME_SIZE 0x2800 #define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ @@ -929,8 +924,8 @@ enum atl1_dma_req_block { atl1_dma_req_128 = 0, atl1_dma_req_256 = 1, atl1_dma_req_512 = 2, - atl1_dam_req_1024 = 3, - atl1_dam_req_2048 = 4, + atl1_dma_req_1024 = 3, + atl1_dma_req_2048 = 4, atl1_dma_req_4096 = 5 }; diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c index 6862c11ff864..f23e13c8f9a6 100644 --- a/drivers/net/atl1/atl1_main.c +++ b/drivers/net/atl1/atl1_main.c @@ -38,7 +38,7 @@ * TODO: * Fix TSO; tx performance is horrible with TSO enabled. * Wake on LAN. - * Add more ethtool functions, including set ring parameters. + * Add more ethtool functions. * Fix abstruse irq enable/disable condition described here: * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2 * @@ -59,6 +59,7 @@ #include <linux/skbuff.h> #include <linux/etherdevice.h> #include <linux/if_vlan.h> +#include <linux/if_ether.h> #include <linux/irqreturn.h> #include <linux/workqueue.h> #include <linux/timer.h> @@ -75,6 +76,7 @@ #include <linux/compiler.h> #include <linux/delay.h> #include <linux/mii.h> +#include <linux/interrupt.h> #include <net/checksum.h> #include <asm/atomic.h> @@ -118,13 +120,9 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter) { struct atl1_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - /* PCI config space info */ - pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); - - hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; + hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; + hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; adapter->wol = 0; adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7; @@ -162,13 +160,70 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter) hw->cmb_tx_timer = 1; /* about 2us */ hw->smb_timer = 100000; /* about 200ms */ - atomic_set(&adapter->irq_sem, 0); spin_lock_init(&adapter->lock); spin_lock_init(&adapter->mb_lock); return 0; } +static int mdio_read(struct net_device *netdev, int phy_id, int reg_num) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + u16 result; + + atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result); + + return result; +} + +static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, + int val) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + + atl1_write_phy_reg(&adapter->hw, reg_num, val); +} + +/* + * atl1_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ +static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + int retval; + + if (!netif_running(netdev)) + return -EINVAL; + + spin_lock_irqsave(&adapter->lock, flags); + retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL); + spin_unlock_irqrestore(&adapter->lock, flags); + + return retval; +} + +/* + * atl1_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ +static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return atl1_mii_ioctl(netdev, ifr, cmd); + default: + return -EOPNOTSUPP; + } +} + /* * atl1_setup_mem_resources - allocate Tx / RX descriptor resources * @adapter: board private structure @@ -192,19 +247,22 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) goto err_nomem; } rfd_ring->buffer_info = - (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count); + (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count); - /* real ring DMA buffer */ - ring_header->size = size = sizeof(struct tx_packet_desc) * - tpd_ring->count - + sizeof(struct rx_free_desc) * rfd_ring->count - + sizeof(struct rx_return_desc) * rrd_ring->count - + sizeof(struct coals_msg_block) - + sizeof(struct stats_msg_block) - + 40; /* "40: for 8 bytes align" huh? -- CHS */ + /* real ring DMA buffer + * each ring/block may need up to 8 bytes for alignment, hence the + * additional 40 bytes tacked onto the end. + */ + ring_header->size = size = + sizeof(struct tx_packet_desc) * tpd_ring->count + + sizeof(struct rx_free_desc) * rfd_ring->count + + sizeof(struct rx_return_desc) * rrd_ring->count + + sizeof(struct coals_msg_block) + + sizeof(struct stats_msg_block) + + 40; ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, - &ring_header->dma); + &ring_header->dma); if (unlikely(!ring_header->desc)) { dev_err(&pdev->dev, "pci_alloc_consistent failed\n"); goto err_nomem; @@ -218,8 +276,6 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) tpd_ring->dma += offset; tpd_ring->desc = (u8 *) ring_header->desc + offset; tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count; - atomic_set(&tpd_ring->next_to_use, 0); - atomic_set(&tpd_ring->next_to_clean, 0); /* init RFD ring */ rfd_ring->dma = tpd_ring->dma + tpd_ring->size; @@ -227,9 +283,7 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) rfd_ring->dma += offset; rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset); rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count; - rfd_ring->next_to_clean = 0; - /* rfd_ring->next_to_use = rfd_ring->count - 1; */ - atomic_set(&rfd_ring->next_to_use, 0); + /* init RRD ring */ rrd_ring->dma = rfd_ring->dma + rfd_ring->size; @@ -237,23 +291,22 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) rrd_ring->dma += offset; rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset); rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count; - rrd_ring->next_to_use = 0; - atomic_set(&rrd_ring->next_to_clean, 0); + /* init CMB */ adapter->cmb.dma = rrd_ring->dma + rrd_ring->size; offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0; adapter->cmb.dma += offset; - adapter->cmb.cmb = - (struct coals_msg_block *) ((u8 *) rrd_ring->desc + - (rrd_ring->size + offset)); + adapter->cmb.cmb = (struct coals_msg_block *) + ((u8 *) rrd_ring->desc + (rrd_ring->size + offset)); /* init SMB */ adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block); offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0; adapter->smb.dma += offset; adapter->smb.smb = (struct stats_msg_block *) - ((u8 *) adapter->cmb.cmb + (sizeof(struct coals_msg_block) + offset)); + ((u8 *) adapter->cmb.cmb + + (sizeof(struct coals_msg_block) + offset)); return ATL1_SUCCESS; @@ -262,560 +315,133 @@ err_nomem: return -ENOMEM; } -/* - * atl1_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - */ -static void atl1_irq_enable(struct atl1_adapter *adapter) -{ - if (likely(!atomic_dec_and_test(&adapter->irq_sem))) - iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR); -} - -static void atl1_clear_phy_int(struct atl1_adapter *adapter) -{ - u16 phy_data; - unsigned long flags; - - spin_lock_irqsave(&adapter->lock, flags); - atl1_read_phy_reg(&adapter->hw, 19, &phy_data); - spin_unlock_irqrestore(&adapter->lock, flags); -} - -static void atl1_inc_smb(struct atl1_adapter *adapter) -{ - struct stats_msg_block *smb = adapter->smb.smb; - - /* Fill out the OS statistics structure */ - adapter->soft_stats.rx_packets += smb->rx_ok; - adapter->soft_stats.tx_packets += smb->tx_ok; - adapter->soft_stats.rx_bytes += smb->rx_byte_cnt; - adapter->soft_stats.tx_bytes += smb->tx_byte_cnt; - adapter->soft_stats.multicast += smb->rx_mcast; - adapter->soft_stats.collisions += (smb->tx_1_col + - smb->tx_2_col * 2 + - smb->tx_late_col + - smb->tx_abort_col * - adapter->hw.max_retry); - - /* Rx Errors */ - adapter->soft_stats.rx_errors += (smb->rx_frag + - smb->rx_fcs_err + - smb->rx_len_err + - smb->rx_sz_ov + - smb->rx_rxf_ov + - smb->rx_rrd_ov + smb->rx_align_err); - adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov; - adapter->soft_stats.rx_length_errors += smb->rx_len_err; - adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err; - adapter->soft_stats.rx_frame_errors += smb->rx_align_err; - adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov + - smb->rx_rxf_ov); - - adapter->soft_stats.rx_pause += smb->rx_pause; - adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov; - adapter->soft_stats.rx_trunc += smb->rx_sz_ov; - - /* Tx Errors */ - adapter->soft_stats.tx_errors += (smb->tx_late_col + - smb->tx_abort_col + - smb->tx_underrun + smb->tx_trunc); - adapter->soft_stats.tx_fifo_errors += smb->tx_underrun; - adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col; - adapter->soft_stats.tx_window_errors += smb->tx_late_col; - - adapter->soft_stats.excecol += smb->tx_abort_col; - adapter->soft_stats.deffer += smb->tx_defer; - adapter->soft_stats.scc += smb->tx_1_col; - adapter->soft_stats.mcc += smb->tx_2_col; - adapter->soft_stats.latecol += smb->tx_late_col; - adapter->soft_stats.tx_underun += smb->tx_underrun; - adapter->soft_stats.tx_trunc += smb->tx_trunc; - adapter->soft_stats.tx_pause += smb->tx_pause; - - adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets; - adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets; - adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes; - adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes; - adapter->net_stats.multicast = adapter->soft_stats.multicast; - adapter->net_stats.collisions = adapter->soft_stats.collisions; - adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors; - adapter->net_stats.rx_over_errors = - adapter->soft_stats.rx_missed_errors; - adapter->net_stats.rx_length_errors = - adapter->soft_stats.rx_length_errors; - adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors; - adapter->net_stats.rx_frame_errors = - adapter->soft_stats.rx_frame_errors; - adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors; - adapter->net_stats.rx_missed_errors = - adapter->soft_stats.rx_missed_errors; - adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors; - adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors; - adapter->net_stats.tx_aborted_errors = - adapter->soft_stats.tx_aborted_errors; - adapter->net_stats.tx_window_errors = - adapter->soft_stats.tx_window_errors; - adapter->net_stats.tx_carrier_errors = - adapter->soft_stats.tx_carrier_errors; -} - -static void atl1_rx_checksum(struct atl1_adapter *adapter, - struct rx_return_desc *rrd, - struct sk_buff *skb) +static void atl1_init_ring_ptrs(struct atl1_adapter *adapter) { - skb->ip_summed = CHECKSUM_NONE; - - if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { - if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC | - ERR_FLAG_CODE | ERR_FLAG_OV)) { - adapter->hw_csum_err++; - dev_dbg(&adapter->pdev->dev, "rx checksum error\n"); - return; - } - } + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; - /* not IPv4 */ - if (!(rrd->pkt_flg & PACKET_FLAG_IPV4)) - /* checksum is invalid, but it's not an IPv4 pkt, so ok */ - return; + atomic_set(&tpd_ring->next_to_use, 0); + atomic_set(&tpd_ring->next_to_clean, 0); - /* IPv4 packet */ - if (likely(!(rrd->err_flg & - (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_good++; - return; - } + rfd_ring->next_to_clean = 0; + atomic_set(&rfd_ring->next_to_use, 0); - /* IPv4, but hardware thinks its checksum is wrong */ - dev_dbg(&adapter->pdev->dev, - "hw csum wrong, pkt_flag:%x, err_flag:%x\n", - rrd->pkt_flg, rrd->err_flg); - skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum); - adapter->hw_csum_err++; - return; + rrd_ring->next_to_use = 0; + atomic_set(&rrd_ring->next_to_clean, 0); } /* - * atl1_alloc_rx_buffers - Replace used receive buffers - * @adapter: address of board private structure + * atl1_clean_rx_ring - Free RFD Buffers + * @adapter: board private structure */ -static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter) -{ - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct pci_dev *pdev = adapter->pdev; - struct page *page; - unsigned long offset; - struct atl1_buffer *buffer_info, *next_info; - struct sk_buff *skb; - u16 num_alloc = 0; - u16 rfd_next_to_use, next_next; - struct rx_free_desc *rfd_desc; - - next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use); - if (++next_next == rfd_ring->count) - next_next = 0; - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - - while (!buffer_info->alloced && !next_info->alloced) { - if (buffer_info->skb) { - buffer_info->alloced = 1; - goto next; - } - - rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use); - - skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); - if (unlikely(!skb)) { /* Better luck next round */ - adapter->net_stats.rx_dropped++; - break; - } - - /* - * Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - skb_reserve(skb, NET_IP_ALIGN); - - buffer_info->alloced = 1; - buffer_info->skb = skb; - buffer_info->length = (u16) adapter->rx_buffer_len; - page = virt_to_page(skb->data); - offset = (unsigned long)skb->data & ~PAGE_MASK; - buffer_info->dma = pci_map_page(pdev, page, offset, - adapter->rx_buffer_len, - PCI_DMA_FROMDEVICE); - rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len); - rfd_desc->coalese = 0; - -next: - rfd_next_to_use = next_next; - if (unlikely(++next_next == rfd_ring->count)) - next_next = 0; - - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - num_alloc++; - } - - if (num_alloc) { - /* - * Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use); - } - return num_alloc; -} - -static void atl1_intr_rx(struct atl1_adapter *adapter) +static void atl1_clean_rx_ring(struct atl1_adapter *adapter) { - int i, count; - u16 length; - u16 rrd_next_to_clean; - u32 value; struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; struct atl1_buffer *buffer_info; - struct rx_return_desc *rrd; - struct sk_buff *skb; - - count = 0; - - rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean); - - while (1) { - rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean); - i = 1; - if (likely(rrd->xsz.valid)) { /* packet valid */ -chk_rrd: - /* check rrd status */ - if (likely(rrd->num_buf == 1)) - goto rrd_ok; - - /* rrd seems to be bad */ - if (unlikely(i-- > 0)) { - /* rrd may not be DMAed completely */ - dev_dbg(&adapter->pdev->dev, - "incomplete RRD DMA transfer\n"); - udelay(1); - goto chk_rrd; - } - /* bad rrd */ - dev_dbg(&adapter->pdev->dev, "bad RRD\n"); - /* see if update RFD index */ - if (rrd->num_buf > 1) { - u16 num_buf; - num_buf = - (rrd->xsz.xsum_sz.pkt_size + - adapter->rx_buffer_len - - 1) / adapter->rx_buffer_len; - if (rrd->num_buf == num_buf) { - /* clean alloc flag for bad rrd */ - while (rfd_ring->next_to_clean != - (rrd->buf_indx + num_buf)) { - rfd_ring->buffer_info[rfd_ring-> - next_to_clean].alloced = 0; - if (++rfd_ring->next_to_clean == - rfd_ring->count) { - rfd_ring-> - next_to_clean = 0; - } - } - } - } - - /* update rrd */ - rrd->xsz.valid = 0; - if (++rrd_next_to_clean == rrd_ring->count) - rrd_next_to_clean = 0; - count++; - continue; - } else { /* current rrd still not be updated */ + struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; - break; - } -rrd_ok: - /* clean alloc flag for bad rrd */ - while (rfd_ring->next_to_clean != rrd->buf_indx) { - rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = - 0; - if (++rfd_ring->next_to_clean == rfd_ring->count) - rfd_ring->next_to_clean = 0; + /* Free all the Rx ring sk_buffs */ + for (i = 0; i < rfd_ring->count; i++) { + buffer_info = &rfd_ring->buffer_info[i]; + if (buffer_info->dma) { + pci_unmap_page(pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; } - - buffer_info = &rfd_ring->buffer_info[rrd->buf_indx]; - if (++rfd_ring->next_to_clean == rfd_ring->count) - rfd_ring->next_to_clean = 0; - - /* update rrd next to clean */ - if (++rrd_next_to_clean == rrd_ring->count) - rrd_next_to_clean = 0; - count++; - - if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { - if (!(rrd->err_flg & - (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM - | ERR_FLAG_LEN))) { - /* packet error, don't need upstream */ - buffer_info->alloced = 0; - rrd->xsz.valid = 0; - continue; - } + if (buffer_info->skb) { + dev_kfree_skb(buffer_info->skb); + buffer_info->skb = NULL; } - - /* Good Receive */ - pci_unmap_page(adapter->pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_FROMDEVICE); - skb = buffer_info->skb; - length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); - - skb_put(skb, length - ETHERNET_FCS_SIZE); - - /* Receive Checksum Offload */ - atl1_rx_checksum(adapter, rrd, skb); - skb->protocol = eth_type_trans(skb, adapter->netdev); - - if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) { - u16 vlan_tag = (rrd->vlan_tag >> 4) | - ((rrd->vlan_tag & 7) << 13) | - ((rrd->vlan_tag & 8) << 9); - vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); - } else - netif_rx(skb); - - /* let protocol layer free skb */ - buffer_info->skb = NULL; - buffer_info->alloced = 0; - rrd->xsz.valid = 0; - - adapter->netdev->last_rx = jiffies; } - atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean); - - atl1_alloc_rx_buffers(adapter); + size = sizeof(struct atl1_buffer) * rfd_ring->count; + memset(rfd_ring->buffer_info, 0, size); - /* update mailbox ? */ - if (count) { - u32 tpd_next_to_use; - u32 rfd_next_to_use; - u32 rrd_next_to_clean; + /* Zero out the descriptor ring */ + memset(rfd_ring->desc, 0, rfd_ring->size); - spin_lock(&adapter->mb_lock); + rfd_ring->next_to_clean = 0; + atomic_set(&rfd_ring->next_to_use, 0); - tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); - rfd_next_to_use = - atomic_read(&adapter->rfd_ring.next_to_use); - rrd_next_to_clean = - atomic_read(&adapter->rrd_ring.next_to_clean); - value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << - MB_RFD_PROD_INDX_SHIFT) | - ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << - MB_RRD_CONS_INDX_SHIFT) | - ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << - MB_TPD_PROD_INDX_SHIFT); - iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); - spin_unlock(&adapter->mb_lock); - } + rrd_ring->next_to_use = 0; + atomic_set(&rrd_ring->next_to_clean, 0); } -static void atl1_intr_tx(struct atl1_adapter *adapter) +/* + * atl1_clean_tx_ring - Free Tx Buffers + * @adapter: board private structure + */ +static void atl1_clean_tx_ring(struct atl1_adapter *adapter) { struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; struct atl1_buffer *buffer_info; - u16 sw_tpd_next_to_clean; - u16 cmb_tpd_next_to_clean; - u8 update = 0; - - sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean); - cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx); + struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; - while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) { - struct tx_packet_desc *tpd; - update = 1; - tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean); - buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean]; + /* Free all the Tx ring sk_buffs */ + for (i = 0; i < tpd_ring->count; i++) { + buffer_info = &tpd_ring->buffer_info[i]; if (buffer_info->dma) { - pci_unmap_page(adapter->pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); + pci_unmap_page(pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); buffer_info->dma = 0; } + } + for (i = 0; i < tpd_ring->count; i++) { + buffer_info = &tpd_ring->buffer_info[i]; if (buffer_info->skb) { - dev_kfree_skb_irq(buffer_info->skb); + dev_kfree_skb_any(buffer_info->skb); buffer_info->skb = NULL; } - tpd->buffer_addr = 0; - tpd->desc.data = 0; - - if (++sw_tpd_next_to_clean == tpd_ring->count) - sw_tpd_next_to_clean = 0; } - atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean); - - if (netif_queue_stopped(adapter->netdev) - && netif_carrier_ok(adapter->netdev)) - netif_wake_queue(adapter->netdev); -} - -static void atl1_check_for_link(struct atl1_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - u16 phy_data = 0; - - spin_lock(&adapter->lock); - adapter->phy_timer_pending = false; - atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - spin_unlock(&adapter->lock); - - /* notify upper layer link down ASAP */ - if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */ - if (netif_carrier_ok(netdev)) { /* old link state: Up */ - dev_info(&adapter->pdev->dev, "%s link is down\n", - netdev->name); - adapter->link_speed = SPEED_0; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - } - schedule_work(&adapter->link_chg_task); -} - -/* - * atl1_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - * @pt_regs: CPU registers structure - */ -static irqreturn_t atl1_intr(int irq, void *data) -{ - /*struct atl1_adapter *adapter = ((struct net_device *)data)->priv;*/ - struct atl1_adapter *adapter = netdev_priv(data); - u32 status; - u8 update_rx; - int max_ints = 10; - - status = adapter->cmb.cmb->int_stats; - if (!status) - return IRQ_NONE; - - update_rx = 0; - - do { - /* clear CMB interrupt status at once */ - adapter->cmb.cmb->int_stats = 0; - - if (status & ISR_GPHY) /* clear phy status */ - atl1_clear_phy_int(adapter); - - /* clear ISR status, and Enable CMB DMA/Disable Interrupt */ - iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR); - - /* check if SMB intr */ - if (status & ISR_SMB) - atl1_inc_smb(adapter); - - /* check if PCIE PHY Link down */ - if (status & ISR_PHY_LINKDOWN) { - dev_dbg(&adapter->pdev->dev, "pcie phy link down %x\n", - status); - if (netif_running(adapter->netdev)) { /* reset MAC */ - iowrite32(0, adapter->hw.hw_addr + REG_IMR); - schedule_work(&adapter->pcie_dma_to_rst_task); - return IRQ_HANDLED; - } - } - - /* check if DMA read/write error ? */ - if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { - dev_dbg(&adapter->pdev->dev, - "pcie DMA r/w error (status = 0x%x)\n", - status); - iowrite32(0, adapter->hw.hw_addr + REG_IMR); - schedule_work(&adapter->pcie_dma_to_rst_task); - return IRQ_HANDLED; - } - - /* link event */ - if (status & ISR_GPHY) { - adapter->soft_stats.tx_carrier_errors++; - atl1_check_for_link(adapter); - } - - /* transmit event */ - if (status & ISR_CMB_TX) - atl1_intr_tx(adapter); - - /* rx exception */ - if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | - ISR_RRD_OV | ISR_HOST_RFD_UNRUN | - ISR_HOST_RRD_OV | ISR_CMB_RX))) { - if (status & (ISR_RXF_OV | ISR_RFD_UNRUN | - ISR_RRD_OV | ISR_HOST_RFD_UNRUN | - ISR_HOST_RRD_OV)) - dev_dbg(&adapter->pdev->dev, - "rx exception, ISR = 0x%x\n", status); - atl1_intr_rx(adapter); - } - if (--max_ints < 0) - break; + size = sizeof(struct atl1_buffer) * tpd_ring->count; + memset(tpd_ring->buffer_info, 0, size); - } while ((status = adapter->cmb.cmb->int_stats)); + /* Zero out the descriptor ring */ + memset(tpd_ring->desc, 0, tpd_ring->size); - /* re-enable Interrupt */ - iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR); - return IRQ_HANDLED; + atomic_set(&tpd_ring->next_to_use, 0); + atomic_set(&tpd_ring->next_to_clean, 0); } /* - * atl1_set_multi - Multicast and Promiscuous mode set - * @netdev: network interface device structure + * atl1_free_ring_resources - Free Tx / RX descriptor Resources + * @adapter: board private structure * - * The set_multi entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast, - * promiscuous mode, and all-multi behavior. + * Free all transmit software resources */ -static void atl1_set_multi(struct net_device *netdev) +void atl1_free_ring_resources(struct atl1_adapter *adapter) { - struct atl1_adapter *adapter = netdev_priv(netdev); - struct atl1_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; - u32 rctl; - u32 hash_value; + struct pci_dev *pdev = adapter->pdev; + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_ring_header *ring_header = &adapter->ring_header; - /* Check for Promiscuous and All Multicast modes */ - rctl = ioread32(hw->hw_addr + REG_MAC_CTRL); - if (netdev->flags & IFF_PROMISC) - rctl |= MAC_CTRL_PROMIS_EN; - else if (netdev->flags & IFF_ALLMULTI) { - rctl |= MAC_CTRL_MC_ALL_EN; - rctl &= ~MAC_CTRL_PROMIS_EN; - } else - rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); + atl1_clean_tx_ring(adapter); + atl1_clean_rx_ring(adapter); - iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL); + kfree(tpd_ring->buffer_info); + pci_free_consistent(pdev, ring_header->size, ring_header->desc, + ring_header->dma); - /* clear the old settings from the multicast hash table */ - iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE); - iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); + tpd_ring->buffer_info = NULL; + tpd_ring->desc = NULL; + tpd_ring->dma = 0; - /* compute mc addresses' hash value ,and put it into hash table */ - for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { - hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr); - atl1_hash_set(hw, hash_value); - } + rfd_ring->buffer_info = NULL; + rfd_ring->desc = NULL; + rfd_ring->dma = 0; + + rrd_ring->desc = NULL; + rrd_ring->dma = 0; } static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) @@ -856,6 +482,31 @@ static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) iowrite32(value, hw->hw_addr + REG_MAC_CTRL); } +/* + * atl1_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + */ +static int atl1_set_mac(struct net_device *netdev, void *p) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (netif_running(netdev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + + atl1_set_mac_addr(&adapter->hw); + return 0; +} + static u32 atl1_check_link(struct atl1_adapter *adapter) { struct atl1_hw *hw = &adapter->hw; @@ -963,6 +614,103 @@ static u32 atl1_check_link(struct atl1_adapter *adapter) return ATL1_SUCCESS; } +static void atl1_check_for_link(struct atl1_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + u16 phy_data = 0; + + spin_lock(&adapter->lock); + adapter->phy_timer_pending = false; + atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + spin_unlock(&adapter->lock); + + /* notify upper layer link down ASAP */ + if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */ + if (netif_carrier_ok(netdev)) { /* old link state: Up */ + dev_info(&adapter->pdev->dev, "%s link is down\n", + netdev->name); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + } + schedule_work(&adapter->link_chg_task); +} + +/* + * atl1_set_multi - Multicast and Promiscuous mode set + * @netdev: network interface device structure + * + * The set_multi entry point is called whenever the multicast address + * list or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper multicast, + * promiscuous mode, and all-multi behavior. + */ +static void atl1_set_multi(struct net_device *netdev) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + struct dev_mc_list *mc_ptr; + u32 rctl; + u32 hash_value; + + /* Check for Promiscuous and All Multicast modes */ + rctl = ioread32(hw->hw_addr + REG_MAC_CTRL); + if (netdev->flags & IFF_PROMISC) + rctl |= MAC_CTRL_PROMIS_EN; + else if (netdev->flags & IFF_ALLMULTI) { + rctl |= MAC_CTRL_MC_ALL_EN; + rctl &= ~MAC_CTRL_PROMIS_EN; + } else + rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); + + iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL); + + /* clear the old settings from the multicast hash table */ + iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE); + iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); + + /* compute mc addresses' hash value ,and put it into hash table */ + for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr); + atl1_hash_set(hw, hash_value); + } +} + +/* + * atl1_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + */ +static int atl1_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + int old_mtu = netdev->mtu; + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; + + if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || + (max_frame > MAX_JUMBO_FRAME_SIZE)) { + dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); + return -EINVAL; + } + + adapter->hw.max_frame_size = max_frame; + adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3; + adapter->rx_buffer_len = (max_frame + 7) & ~7; + adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8; + + netdev->mtu = new_mtu; + if ((old_mtu != new_mtu) && netif_running(netdev)) { + atl1_down(adapter); + atl1_up(adapter); + } + + return 0; +} + static void set_flow_ctrl_old(struct atl1_adapter *adapter) { u32 hi, lo, value; @@ -975,7 +723,7 @@ static void set_flow_ctrl_old(struct atl1_adapter *adapter) lo = value * 7 / 8; value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); + ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH); /* RRD Flow Control */ @@ -985,7 +733,7 @@ static void set_flow_ctrl_old(struct atl1_adapter *adapter) if (lo < 2) lo = 2; value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); + ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH); } @@ -1002,7 +750,7 @@ static void set_flow_ctrl_new(struct atl1_hw *hw) if (hi < lo) hi = lo + 16; value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); + ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH); /* RRD Flow Control */ @@ -1014,7 +762,7 @@ static void set_flow_ctrl_new(struct atl1_hw *hw) if (hi < lo) hi = lo + 3; value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); + ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH); } @@ -1063,7 +811,8 @@ static u32 atl1_configure(struct atl1_adapter *adapter) value <<= 16; value += adapter->rfd_ring.count; iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE); - iowrite32(adapter->tpd_ring.count, hw->hw_addr + REG_DESC_TPD_RING_SIZE); + iowrite32(adapter->tpd_ring.count, hw->hw_addr + + REG_DESC_TPD_RING_SIZE); /* Load Ptr */ iowrite32(1, hw->hw_addr + REG_LOAD_PTR); @@ -1071,31 +820,31 @@ static u32 atl1_configure(struct atl1_adapter *adapter) /* config Mailbox */ value = ((atomic_read(&adapter->tpd_ring.next_to_use) & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) | - ((atomic_read(&adapter->rrd_ring.next_to_clean) - & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) | - ((atomic_read(&adapter->rfd_ring.next_to_use) - & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT); + ((atomic_read(&adapter->rrd_ring.next_to_clean) + & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) | + ((atomic_read(&adapter->rfd_ring.next_to_use) + & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT); iowrite32(value, hw->hw_addr + REG_MAILBOX); /* config IPG/IFG */ value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK) << MAC_IPG_IFG_IPGT_SHIFT) | - (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) - << MAC_IPG_IFG_MIFG_SHIFT) | - (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) - << MAC_IPG_IFG_IPGR1_SHIFT) | - (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) - << MAC_IPG_IFG_IPGR2_SHIFT); + (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) + << MAC_IPG_IFG_MIFG_SHIFT) | + (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) + << MAC_IPG_IFG_IPGR1_SHIFT) | + (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) + << MAC_IPG_IFG_IPGR2_SHIFT); iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG); /* config Half-Duplex Control */ value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) | - (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) - << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) | - MAC_HALF_DUPLX_CTRL_EXC_DEF_EN | - (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) | - (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) - << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT); + (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) + << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) | + MAC_HALF_DUPLX_CTRL_EXC_DEF_EN | + (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) | + (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) + << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT); iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL); /* set Interrupt Moderator Timer */ @@ -1111,10 +860,10 @@ static u32 atl1_configure(struct atl1_adapter *adapter) /* jumbo size & rrd retirement timer */ value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) << RXQ_JMBOSZ_TH_SHIFT) | - (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK) - << RXQ_JMBO_LKAH_SHIFT) | - (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK) - << RXQ_RRD_TIMER_SHIFT); + (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK) + << RXQ_JMBO_LKAH_SHIFT) | + (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK) + << RXQ_RRD_TIMER_SHIFT); iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM); /* Flow Control */ @@ -1133,42 +882,46 @@ static u32 atl1_configure(struct atl1_adapter *adapter) /* config TXQ */ value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK) << TXQ_CTRL_TPD_BURST_NUM_SHIFT) | - (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK) - << TXQ_CTRL_TXF_BURST_NUM_SHIFT) | - (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK) - << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN; + (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK) + << TXQ_CTRL_TXF_BURST_NUM_SHIFT) | + (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK) + << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | + TXQ_CTRL_EN; iowrite32(value, hw->hw_addr + REG_TXQ_CTRL); /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */ value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK) - << TX_JUMBO_TASK_TH_SHIFT) | - (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK) - << TX_TPD_MIN_IPG_SHIFT); + << TX_JUMBO_TASK_TH_SHIFT) | + (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK) + << TX_TPD_MIN_IPG_SHIFT); iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG); /* config RXQ */ value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK) - << RXQ_CTRL_RFD_BURST_NUM_SHIFT) | - (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK) - << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) | - (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK) - << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | - RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN; + << RXQ_CTRL_RFD_BURST_NUM_SHIFT) | + (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK) + << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) | + (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK) + << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN | + RXQ_CTRL_EN; iowrite32(value, hw->hw_addr + REG_RXQ_CTRL); /* config DMA Engine */ value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) - << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | - ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) - << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | - DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN; + << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | + ((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) + << DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN | + DMA_CTRL_DMAW_EN; value |= (u32) hw->dma_ord; if (atl1_rcb_128 == hw->rcb_value) value |= DMA_CTRL_RCB_VALUE; iowrite32(value, hw->hw_addr + REG_DMA_CTRL); /* config CMB / SMB */ - value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16); + value = (hw->cmb_tpd > adapter->tpd_ring.count) ? + hw->cmb_tpd : adapter->tpd_ring.count; + value <<= 16; + value |= hw->cmb_rrd; iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH); value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16); iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER); @@ -1191,56 +944,495 @@ static u32 atl1_configure(struct atl1_adapter *adapter) } /* + * atl1_pcie_patch - Patch for PCIE module + */ +static void atl1_pcie_patch(struct atl1_adapter *adapter) +{ + u32 value; + + /* much vendor magic here */ + value = 0x6500; + iowrite32(value, adapter->hw.hw_addr + 0x12FC); + /* pcie flow control mode change */ + value = ioread32(adapter->hw.hw_addr + 0x1008); + value |= 0x8000; + iowrite32(value, adapter->hw.hw_addr + 0x1008); +} + +/* + * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400 + * on PCI Command register is disable. + * The function enable this bit. + * Brackett, 2006/03/15 + */ +static void atl1_via_workaround(struct atl1_adapter *adapter) +{ + unsigned long value; + + value = ioread16(adapter->hw.hw_addr + PCI_COMMAND); + if (value & PCI_COMMAND_INTX_DISABLE) + value &= ~PCI_COMMAND_INTX_DISABLE; + iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND); +} + +/* + * atl1_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + */ +static void atl1_irq_enable(struct atl1_adapter *adapter) +{ + iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR); + ioread32(adapter->hw.hw_addr + REG_IMR); +} + +/* * atl1_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure */ static void atl1_irq_disable(struct atl1_adapter *adapter) { - atomic_inc(&adapter->irq_sem); iowrite32(0, adapter->hw.hw_addr + REG_IMR); ioread32(adapter->hw.hw_addr + REG_IMR); synchronize_irq(adapter->pdev->irq); } -static void atl1_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +static void atl1_clear_phy_int(struct atl1_adapter *adapter) { - struct atl1_adapter *adapter = netdev_priv(netdev); + u16 phy_data; unsigned long flags; - u32 ctrl; spin_lock_irqsave(&adapter->lock, flags); - /* atl1_irq_disable(adapter); */ - adapter->vlgrp = grp; + atl1_read_phy_reg(&adapter->hw, 19, &phy_data); + spin_unlock_irqrestore(&adapter->lock, flags); +} - if (grp) { - /* enable VLAN tag insert/strip */ - ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); - ctrl |= MAC_CTRL_RMV_VLAN; - iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); - } else { - /* disable VLAN tag insert/strip */ - ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); - ctrl &= ~MAC_CTRL_RMV_VLAN; - iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); +static void atl1_inc_smb(struct atl1_adapter *adapter) +{ + struct stats_msg_block *smb = adapter->smb.smb; + + /* Fill out the OS statistics structure */ + adapter->soft_stats.rx_packets += smb->rx_ok; + adapter->soft_stats.tx_packets += smb->tx_ok; + adapter->soft_stats.rx_bytes += smb->rx_byte_cnt; + adapter->soft_stats.tx_bytes += smb->tx_byte_cnt; + adapter->soft_stats.multicast += smb->rx_mcast; + adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 + + smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry); + + /* Rx Errors */ + adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err + + smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov + + smb->rx_rrd_ov + smb->rx_align_err); + adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov; + adapter->soft_stats.rx_length_errors += smb->rx_len_err; + adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err; + adapter->soft_stats.rx_frame_errors += smb->rx_align_err; + adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov + + smb->rx_rxf_ov); + + adapter->soft_stats.rx_pause += smb->rx_pause; + adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov; + adapter->soft_stats.rx_trunc += smb->rx_sz_ov; + + /* Tx Errors */ + adapter->soft_stats.tx_errors += (smb->tx_late_col + + smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc); + adapter->soft_stats.tx_fifo_errors += smb->tx_underrun; + adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col; + adapter->soft_stats.tx_window_errors += smb->tx_late_col; + + adapter->soft_stats.excecol += smb->tx_abort_col; + adapter->soft_stats.deffer += smb->tx_defer; + adapter->soft_stats.scc += smb->tx_1_col; + adapter->soft_stats.mcc += smb->tx_2_col; + adapter->soft_stats.latecol += smb->tx_late_col; + adapter->soft_stats.tx_underun += smb->tx_underrun; + adapter->soft_stats.tx_trunc += smb->tx_trunc; + adapter->soft_stats.tx_pause += smb->tx_pause; + + adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets; + adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets; + adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes; + adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes; + adapter->net_stats.multicast = adapter->soft_stats.multicast; + adapter->net_stats.collisions = adapter->soft_stats.collisions; + adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors; + adapter->net_stats.rx_over_errors = + adapter->soft_stats.rx_missed_errors; + adapter->net_stats.rx_length_errors = + adapter->soft_stats.rx_length_errors; + adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors; + adapter->net_stats.rx_frame_errors = + adapter->soft_stats.rx_frame_errors; + adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors; + adapter->net_stats.rx_missed_errors = + adapter->soft_stats.rx_missed_errors; + adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors; + adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors; + adapter->net_stats.tx_aborted_errors = + adapter->soft_stats.tx_aborted_errors; + adapter->net_stats.tx_window_errors = + adapter->soft_stats.tx_window_errors; + adapter->net_stats.tx_carrier_errors = + adapter->soft_stats.tx_carrier_errors; +} + +/* + * atl1_get_stats - Get System Network Statistics + * @netdev: network interface device structure + * + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. + */ +static struct net_device_stats *atl1_get_stats(struct net_device *netdev) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + return &adapter->net_stats; +} + +static void atl1_update_mailbox(struct atl1_adapter *adapter) +{ + unsigned long flags; + u32 tpd_next_to_use; + u32 rfd_next_to_use; + u32 rrd_next_to_clean; + u32 value; + + spin_lock_irqsave(&adapter->mb_lock, flags); + + tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); + rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use); + rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean); + + value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << + MB_RFD_PROD_INDX_SHIFT) | + ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << + MB_RRD_CONS_INDX_SHIFT) | + ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << + MB_TPD_PROD_INDX_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); + + spin_unlock_irqrestore(&adapter->mb_lock, flags); +} + +static void atl1_clean_alloc_flag(struct atl1_adapter *adapter, + struct rx_return_desc *rrd, u16 offset) +{ + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + + while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) { + rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0; + if (++rfd_ring->next_to_clean == rfd_ring->count) { + rfd_ring->next_to_clean = 0; + } } +} - /* atl1_irq_enable(adapter); */ - spin_unlock_irqrestore(&adapter->lock, flags); +static void atl1_update_rfd_index(struct atl1_adapter *adapter, + struct rx_return_desc *rrd) +{ + u16 num_buf; + + num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) / + adapter->rx_buffer_len; + if (rrd->num_buf == num_buf) + /* clean alloc flag for bad rrd */ + atl1_clean_alloc_flag(adapter, rrd, num_buf); } -static void atl1_restore_vlan(struct atl1_adapter *adapter) +static void atl1_rx_checksum(struct atl1_adapter *adapter, + struct rx_return_desc *rrd, struct sk_buff *skb) { - atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp); + struct pci_dev *pdev = adapter->pdev; + + skb->ip_summed = CHECKSUM_NONE; + + if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { + if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC | + ERR_FLAG_CODE | ERR_FLAG_OV)) { + adapter->hw_csum_err++; + dev_printk(KERN_DEBUG, &pdev->dev, + "rx checksum error\n"); + return; + } + } + + /* not IPv4 */ + if (!(rrd->pkt_flg & PACKET_FLAG_IPV4)) + /* checksum is invalid, but it's not an IPv4 pkt, so ok */ + return; + + /* IPv4 packet */ + if (likely(!(rrd->err_flg & + (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_good++; + return; + } + + /* IPv4, but hardware thinks its checksum is wrong */ + dev_printk(KERN_DEBUG, &pdev->dev, + "hw csum wrong, pkt_flag:%x, err_flag:%x\n", + rrd->pkt_flg, rrd->err_flg); + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum); + adapter->hw_csum_err++; + return; } -static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring) +/* + * atl1_alloc_rx_buffers - Replace used receive buffers + * @adapter: address of board private structure + */ +static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter) +{ + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct pci_dev *pdev = adapter->pdev; + struct page *page; + unsigned long offset; + struct atl1_buffer *buffer_info, *next_info; + struct sk_buff *skb; + u16 num_alloc = 0; + u16 rfd_next_to_use, next_next; + struct rx_free_desc *rfd_desc; + + next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use); + if (++next_next == rfd_ring->count) + next_next = 0; + buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; + next_info = &rfd_ring->buffer_info[next_next]; + + while (!buffer_info->alloced && !next_info->alloced) { + if (buffer_info->skb) { + buffer_info->alloced = 1; + goto next; + } + + rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use); + + skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); + if (unlikely(!skb)) { /* Better luck next round */ + adapter->net_stats.rx_dropped++; + break; + } + + /* + * Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + + buffer_info->alloced = 1; + buffer_info->skb = skb; + buffer_info->length = (u16) adapter->rx_buffer_len; + page = virt_to_page(skb->data); + offset = (unsigned long)skb->data & ~PAGE_MASK; + buffer_info->dma = pci_map_page(pdev, page, offset, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len); + rfd_desc->coalese = 0; + +next: + rfd_next_to_use = next_next; + if (unlikely(++next_next == rfd_ring->count)) + next_next = 0; + + buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; + next_info = &rfd_ring->buffer_info[next_next]; + num_alloc++; + } + + if (num_alloc) { + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use); + } + return num_alloc; +} + +static void atl1_intr_rx(struct atl1_adapter *adapter) +{ + int i, count; + u16 length; + u16 rrd_next_to_clean; + u32 value; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_buffer *buffer_info; + struct rx_return_desc *rrd; + struct sk_buff *skb; + + count = 0; + + rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean); + + while (1) { + rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean); + i = 1; + if (likely(rrd->xsz.valid)) { /* packet valid */ +chk_rrd: + /* check rrd status */ + if (likely(rrd->num_buf == 1)) + goto rrd_ok; + + /* rrd seems to be bad */ + if (unlikely(i-- > 0)) { + /* rrd may not be DMAed completely */ + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "incomplete RRD DMA transfer\n"); + udelay(1); + goto chk_rrd; + } + /* bad rrd */ + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "bad RRD\n"); + /* see if update RFD index */ + if (rrd->num_buf > 1) + atl1_update_rfd_index(adapter, rrd); + + /* update rrd */ + rrd->xsz.valid = 0; + if (++rrd_next_to_clean == rrd_ring->count) + rrd_next_to_clean = 0; + count++; + continue; + } else { /* current rrd still not be updated */ + + break; + } +rrd_ok: + /* clean alloc flag for bad rrd */ + atl1_clean_alloc_flag(adapter, rrd, 0); + + buffer_info = &rfd_ring->buffer_info[rrd->buf_indx]; + if (++rfd_ring->next_to_clean == rfd_ring->count) + rfd_ring->next_to_clean = 0; + + /* update rrd next to clean */ + if (++rrd_next_to_clean == rrd_ring->count) + rrd_next_to_clean = 0; + count++; + + if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { + if (!(rrd->err_flg & + (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM + | ERR_FLAG_LEN))) { + /* packet error, don't need upstream */ + buffer_info->alloced = 0; + rrd->xsz.valid = 0; + continue; + } + } + + /* Good Receive */ + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_FROMDEVICE); + skb = buffer_info->skb; + length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); + + skb_put(skb, length - ETH_FCS_LEN); + + /* Receive Checksum Offload */ + atl1_rx_checksum(adapter, rrd, skb); + skb->protocol = eth_type_trans(skb, adapter->netdev); + + if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) { + u16 vlan_tag = (rrd->vlan_tag >> 4) | + ((rrd->vlan_tag & 7) << 13) | + ((rrd->vlan_tag & 8) << 9); + vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); + } else + netif_rx(skb); + + /* let protocol layer free skb */ + buffer_info->skb = NULL; + buffer_info->alloced = 0; + rrd->xsz.valid = 0; + + adapter->netdev->last_rx = jiffies; + } + + atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean); + + atl1_alloc_rx_buffers(adapter); + + /* update mailbox ? */ + if (count) { + u32 tpd_next_to_use; + u32 rfd_next_to_use; + u32 rrd_next_to_clean; + + spin_lock(&adapter->mb_lock); + + tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); + rfd_next_to_use = + atomic_read(&adapter->rfd_ring.next_to_use); + rrd_next_to_clean = + atomic_read(&adapter->rrd_ring.next_to_clean); + value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << + MB_RFD_PROD_INDX_SHIFT) | + ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << + MB_RRD_CONS_INDX_SHIFT) | + ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << + MB_TPD_PROD_INDX_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); + spin_unlock(&adapter->mb_lock); + } +} + +static void atl1_intr_tx(struct atl1_adapter *adapter) +{ + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; + u16 sw_tpd_next_to_clean; + u16 cmb_tpd_next_to_clean; + + sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean); + cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx); + + while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) { + struct tx_packet_desc *tpd; + + tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean); + buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean]; + if (buffer_info->dma) { + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + + if (buffer_info->skb) { + dev_kfree_skb_irq(buffer_info->skb); + buffer_info->skb = NULL; + } + tpd->buffer_addr = 0; + tpd->desc.data = 0; + + if (++sw_tpd_next_to_clean == tpd_ring->count) + sw_tpd_next_to_clean = 0; + } + atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean); + + if (netif_queue_stopped(adapter->netdev) + && netif_carrier_ok(adapter->netdev)) + netif_wake_queue(adapter->netdev); +} + +static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring) { u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); u16 next_to_use = atomic_read(&tpd_ring->next_to_use); - return ((next_to_clean > - next_to_use) ? next_to_clean - next_to_use - - 1 : tpd_ring->count + next_to_clean - next_to_use - 1); + return ((next_to_clean > next_to_use) ? + next_to_clean - next_to_use - 1 : + tpd_ring->count + next_to_clean - next_to_use - 1); } static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, @@ -1263,17 +1455,16 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, iph->tot_len = 0; iph->check = 0; tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); + iph->daddr, 0, IPPROTO_TCP, 0); ipofst = skb_network_offset(skb); - if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */ + if (ipofst != ETH_HLEN) /* 802.3 frame */ tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT; tso->tsopl |= (iph->ihl & CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT; tso->tsopl |= (tcp_hdrlen(skb) & - TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT; + TSO_PARAM_TCPHDRLEN_MASK) << + TSO_PARAM_TCPHDRLEN_SHIFT; tso->tsopl |= (skb_shinfo(skb)->gso_size & TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT; tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT; @@ -1286,7 +1477,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, } static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, - struct csum_param *csum) + struct csum_param *csum) { u8 css, cso; @@ -1294,7 +1485,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, cso = skb_transport_offset(skb); css = cso + skb->csum_offset; if (unlikely(cso & 0x1)) { - dev_dbg(&adapter->pdev->dev, + dev_printk(KERN_DEBUG, &adapter->pdev->dev, "payload offset not an even number\n"); return -1; } @@ -1309,8 +1500,8 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, return true; } -static void atl1_tx_map(struct atl1_adapter *adapter, - struct sk_buff *skb, bool tcp_seg) +static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + bool tcp_seg) { /* We enter this function holding a spinlock. */ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; @@ -1347,26 +1538,25 @@ static void atl1_tx_map(struct atl1_adapter *adapter, if (first_buf_len > proto_hdr_len) { len12 = first_buf_len - proto_hdr_len; - m = (len12 + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; + m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) / + ATL1_MAX_TX_BUF_LEN; for (i = 0; i < m; i++) { buffer_info = &tpd_ring->buffer_info[tpd_next_to_use]; buffer_info->skb = NULL; buffer_info->length = - (MAX_TX_BUF_LEN >= - len12) ? MAX_TX_BUF_LEN : len12; + (ATL1_MAX_TX_BUF_LEN >= + len12) ? ATL1_MAX_TX_BUF_LEN : len12; len12 -= buffer_info->length; page = virt_to_page(skb->data + - (proto_hdr_len + - i * MAX_TX_BUF_LEN)); + (proto_hdr_len + + i * ATL1_MAX_TX_BUF_LEN)); offset = (unsigned long)(skb->data + - (proto_hdr_len + - i * MAX_TX_BUF_LEN)) & - ~PAGE_MASK; - buffer_info->dma = - pci_map_page(adapter->pdev, page, offset, - buffer_info->length, - PCI_DMA_TODEVICE); + (proto_hdr_len + + i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK; + buffer_info->dma = pci_map_page(adapter->pdev, + page, offset, buffer_info->length, + PCI_DMA_TODEVICE); if (++tpd_next_to_use == tpd_ring->count) tpd_next_to_use = 0; } @@ -1377,8 +1567,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, page = virt_to_page(skb->data); offset = (unsigned long)skb->data & ~PAGE_MASK; buffer_info->dma = pci_map_page(adapter->pdev, page, - offset, first_buf_len, - PCI_DMA_TODEVICE); + offset, first_buf_len, PCI_DMA_TODEVICE); if (++tpd_next_to_use == tpd_ring->count) tpd_next_to_use = 0; } @@ -1390,19 +1579,19 @@ static void atl1_tx_map(struct atl1_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; lenf = frag->size; - m = (lenf + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; + m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN; for (i = 0; i < m; i++) { buffer_info = &tpd_ring->buffer_info[tpd_next_to_use]; if (unlikely(buffer_info->skb)) BUG(); buffer_info->skb = NULL; - buffer_info->length = - (lenf > MAX_TX_BUF_LEN) ? MAX_TX_BUF_LEN : lenf; + buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ? + ATL1_MAX_TX_BUF_LEN : lenf; lenf -= buffer_info->length; - buffer_info->dma = - pci_map_page(adapter->pdev, frag->page, - frag->page_offset + i * MAX_TX_BUF_LEN, - buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = pci_map_page(adapter->pdev, + frag->page, + frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN), + buffer_info->length, PCI_DMA_TODEVICE); if (++tpd_next_to_use == tpd_ring->count) tpd_next_to_use = 0; @@ -1414,7 +1603,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, } static void atl1_tx_queue(struct atl1_adapter *adapter, int count, - union tpd_descr *descr) + union tpd_descr *descr) { /* We enter this function holding a spinlock. */ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; @@ -1458,31 +1647,6 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, int count, atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use); } -static void atl1_update_mailbox(struct atl1_adapter *adapter) -{ - unsigned long flags; - u32 tpd_next_to_use; - u32 rfd_next_to_use; - u32 rrd_next_to_clean; - u32 value; - - spin_lock_irqsave(&adapter->mb_lock, flags); - - tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); - rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use); - rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean); - - value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << - MB_RFD_PROD_INDX_SHIFT) | - ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << - MB_RRD_CONS_INDX_SHIFT) | - ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << - MB_TPD_PROD_INDX_SHIFT); - iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); - - spin_unlock_irqrestore(&adapter->mb_lock, flags); -} - static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct atl1_adapter *adapter = netdev_priv(netdev); @@ -1518,8 +1682,8 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) for (f = 0; f < nr_frags; f++) { frag_size = skb_shinfo(skb)->frags[f].size; if (frag_size) - count += - (frag_size + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; + count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) / + ATL1_MAX_TX_BUF_LEN; } /* mss will be nonzero if we're doing segment offload (TSO/GSO) */ @@ -1535,23 +1699,22 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* need additional TPD ? */ if (proto_hdr_len != len) count += (len - proto_hdr_len + - MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; + ATL1_MAX_TX_BUF_LEN - 1) / + ATL1_MAX_TX_BUF_LEN; } } - local_irq_save(flags); - if (!spin_trylock(&adapter->lock)) { + if (!spin_trylock_irqsave(&adapter->lock, flags)) { /* Can't get lock - tell upper layer to requeue */ - local_irq_restore(flags); - dev_dbg(&adapter->pdev->dev, "tx locked\n"); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n"); return NETDEV_TX_LOCKED; } - if (tpd_avail(&adapter->tpd_ring) < count) { + if (atl1_tpd_avail(&adapter->tpd_ring) < count) { /* not enough descriptors */ netif_stop_queue(netdev); spin_unlock_irqrestore(&adapter->lock, flags); - dev_dbg(&adapter->pdev->dev, "tx busy\n"); + dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n"); return NETDEV_TX_BUSY; } @@ -1593,131 +1756,208 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } /* - * atl1_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. + * atl1_intr - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure */ -static struct net_device_stats *atl1_get_stats(struct net_device *netdev) +static irqreturn_t atl1_intr(int irq, void *data) { - struct atl1_adapter *adapter = netdev_priv(netdev); - return &adapter->net_stats; -} + struct atl1_adapter *adapter = netdev_priv(data); + u32 status; + u8 update_rx; + int max_ints = 10; -/* - * atl1_clean_rx_ring - Free RFD Buffers - * @adapter: board private structure - */ -static void atl1_clean_rx_ring(struct atl1_adapter *adapter) -{ - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; + status = adapter->cmb.cmb->int_stats; + if (!status) + return IRQ_NONE; - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rfd_ring->count; i++) { - buffer_info = &rfd_ring->buffer_info[i]; - if (buffer_info->dma) { - pci_unmap_page(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_FROMDEVICE); - buffer_info->dma = 0; + update_rx = 0; + + do { + /* clear CMB interrupt status at once */ + adapter->cmb.cmb->int_stats = 0; + + if (status & ISR_GPHY) /* clear phy status */ + atl1_clear_phy_int(adapter); + + /* clear ISR status, and Enable CMB DMA/Disable Interrupt */ + iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR); + + /* check if SMB intr */ + if (status & ISR_SMB) + atl1_inc_smb(adapter); + + /* check if PCIE PHY Link down */ + if (status & ISR_PHY_LINKDOWN) { + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "pcie phy link down %x\n", status); + if (netif_running(adapter->netdev)) { /* reset MAC */ + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + schedule_work(&adapter->pcie_dma_to_rst_task); + return IRQ_HANDLED; + } } - if (buffer_info->skb) { - dev_kfree_skb(buffer_info->skb); - buffer_info->skb = NULL; + + /* check if DMA read/write error ? */ + if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "pcie DMA r/w error (status = 0x%x)\n", + status); + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + schedule_work(&adapter->pcie_dma_to_rst_task); + return IRQ_HANDLED; } - } - size = sizeof(struct atl1_buffer) * rfd_ring->count; - memset(rfd_ring->buffer_info, 0, size); + /* link event */ + if (status & ISR_GPHY) { + adapter->soft_stats.tx_carrier_errors++; + atl1_check_for_link(adapter); + } - /* Zero out the descriptor ring */ - memset(rfd_ring->desc, 0, rfd_ring->size); + /* transmit event */ + if (status & ISR_CMB_TX) + atl1_intr_tx(adapter); - rfd_ring->next_to_clean = 0; - atomic_set(&rfd_ring->next_to_use, 0); + /* rx exception */ + if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | + ISR_RRD_OV | ISR_HOST_RFD_UNRUN | + ISR_HOST_RRD_OV | ISR_CMB_RX))) { + if (status & (ISR_RXF_OV | ISR_RFD_UNRUN | + ISR_RRD_OV | ISR_HOST_RFD_UNRUN | + ISR_HOST_RRD_OV)) + dev_printk(KERN_DEBUG, &adapter->pdev->dev, + "rx exception, ISR = 0x%x\n", status); + atl1_intr_rx(adapter); + } - rrd_ring->next_to_use = 0; - atomic_set(&rrd_ring->next_to_clean, 0); + if (--max_ints < 0) + break; + + } while ((status = adapter->cmb.cmb->int_stats)); + + /* re-enable Interrupt */ + iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR); + return IRQ_HANDLED; } /* - * atl1_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure + * atl1_watchdog - Timer Call-back + * @data: pointer to netdev cast into an unsigned long */ -static void atl1_clean_tx_ring(struct atl1_adapter *adapter) +static void atl1_watchdog(unsigned long data) { - struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; - struct atl1_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; + struct atl1_adapter *adapter = (struct atl1_adapter *)data; - /* Free all the Tx ring sk_buffs */ - for (i = 0; i < tpd_ring->count; i++) { - buffer_info = &tpd_ring->buffer_info[i]; - if (buffer_info->dma) { - pci_unmap_page(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } - } + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); +} - for (i = 0; i < tpd_ring->count; i++) { - buffer_info = &tpd_ring->buffer_info[i]; - if (buffer_info->skb) { - dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; - } - } +/* + * atl1_phy_config - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + */ +static void atl1_phy_config(unsigned long data) +{ + struct atl1_adapter *adapter = (struct atl1_adapter *)data; + struct atl1_hw *hw = &adapter->hw; + unsigned long flags; - size = sizeof(struct atl1_buffer) * tpd_ring->count; - memset(tpd_ring->buffer_info, 0, size); + spin_lock_irqsave(&adapter->lock, flags); + adapter->phy_timer_pending = false; + atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); + atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg); + atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN); + spin_unlock_irqrestore(&adapter->lock, flags); +} - /* Zero out the descriptor ring */ - memset(tpd_ring->desc, 0, tpd_ring->size); +/* + * atl1_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + */ +static void atl1_tx_timeout(struct net_device *netdev) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + /* Do the reset outside of interrupt context */ + schedule_work(&adapter->tx_timeout_task); +} - atomic_set(&tpd_ring->next_to_use, 0); - atomic_set(&tpd_ring->next_to_clean, 0); +/* + * Orphaned vendor comment left intact here: + * <vendor comment> + * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT + * will assert. We do soft reset <0x1400=1> according + * with the SPEC. BUT, it seemes that PCIE or DMA + * state-machine will not be reset. DMAR_TO_INT will + * assert again and again. + * </vendor comment> + */ +static void atl1_tx_timeout_task(struct work_struct *work) +{ + struct atl1_adapter *adapter = + container_of(work, struct atl1_adapter, tx_timeout_task); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + atl1_down(adapter); + atl1_up(adapter); + netif_device_attach(netdev); } /* - * atl1_free_ring_resources - Free Tx / RX descriptor Resources - * @adapter: board private structure - * - * Free all transmit software resources + * atl1_link_chg_task - deal with link change event Out of interrupt context */ -void atl1_free_ring_resources(struct atl1_adapter *adapter) +static void atl1_link_chg_task(struct work_struct *work) { - struct pci_dev *pdev = adapter->pdev; - struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1_ring_header *ring_header = &adapter->ring_header; + struct atl1_adapter *adapter = + container_of(work, struct atl1_adapter, link_chg_task); + unsigned long flags; - atl1_clean_tx_ring(adapter); - atl1_clean_rx_ring(adapter); + spin_lock_irqsave(&adapter->lock, flags); + atl1_check_link(adapter); + spin_unlock_irqrestore(&adapter->lock, flags); +} - kfree(tpd_ring->buffer_info); - pci_free_consistent(pdev, ring_header->size, ring_header->desc, - ring_header->dma); +static void atl1_vlan_rx_register(struct net_device *netdev, + struct vlan_group *grp) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + u32 ctrl; - tpd_ring->buffer_info = NULL; - tpd_ring->desc = NULL; - tpd_ring->dma = 0; + spin_lock_irqsave(&adapter->lock, flags); + /* atl1_irq_disable(adapter); */ + adapter->vlgrp = grp; - rfd_ring->buffer_info = NULL; - rfd_ring->desc = NULL; - rfd_ring->dma = 0; + if (grp) { + /* enable VLAN tag insert/strip */ + ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); + ctrl |= MAC_CTRL_RMV_VLAN; + iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); + } else { + /* disable VLAN tag insert/strip */ + ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); + ctrl &= ~MAC_CTRL_RMV_VLAN; + iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); + } - rrd_ring->desc = NULL; - rrd_ring->dma = 0; + /* atl1_irq_enable(adapter); */ + spin_unlock_irqrestore(&adapter->lock, flags); +} + +static void atl1_restore_vlan(struct atl1_adapter *adapter) +{ + atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp); +} + +int atl1_reset(struct atl1_adapter *adapter) +{ + int ret; + + ret = atl1_reset_hw(&adapter->hw); + if (ret != ATL1_SUCCESS) + return ret; + return atl1_init_hw(&adapter->hw); } s32 atl1_up(struct atl1_adapter *adapter) @@ -1728,6 +1968,7 @@ s32 atl1_up(struct atl1_adapter *adapter) /* hardware has been reset, we need to reload some things */ atl1_set_multi(netdev); + atl1_init_ring_ptrs(adapter); atl1_restore_vlan(adapter); err = atl1_alloc_rx_buffers(adapter); if (unlikely(!err)) /* no RX BUFFER allocated */ @@ -1755,11 +1996,6 @@ s32 atl1_up(struct atl1_adapter *adapter) atl1_check_link(adapter); return 0; - /* FIXME: unreachable code! -- CHS */ - /* free irq disable any interrupt */ - iowrite32(0, adapter->hw.hw_addr + REG_IMR); - free_irq(adapter->pdev->irq, netdev); - err_up: pci_disable_msi(adapter->pdev); /* free rx_buffers */ @@ -1791,172 +2027,6 @@ void atl1_down(struct atl1_adapter *adapter) } /* - * atl1_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - */ -static int atl1_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - - if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); - return -EINVAL; - } - - adapter->hw.max_frame_size = max_frame; - adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3; - adapter->rx_buffer_len = (max_frame + 7) & ~7; - adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8; - - netdev->mtu = new_mtu; - if ((old_mtu != new_mtu) && netif_running(netdev)) { - atl1_down(adapter); - atl1_up(adapter); - } - - return 0; -} - -/* - * atl1_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - */ -static int atl1_set_mac(struct net_device *netdev, void *p) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (netif_running(netdev)) - return -EBUSY; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - - atl1_set_mac_addr(&adapter->hw); - return 0; -} - -/* - * atl1_watchdog - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1_watchdog(unsigned long data) -{ - struct atl1_adapter *adapter = (struct atl1_adapter *)data; - - /* Reset the timer */ - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); -} - -static int mdio_read(struct net_device *netdev, int phy_id, int reg_num) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - u16 result; - - atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result); - - return result; -} - -static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, int val) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - - atl1_write_phy_reg(&adapter->hw, reg_num, val); -} - -/* - * atl1_mii_ioctl - - * @netdev: - * @ifreq: - * @cmd: - */ -static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - int retval; - - if (!netif_running(netdev)) - return -EINVAL; - - spin_lock_irqsave(&adapter->lock, flags); - retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL); - spin_unlock_irqrestore(&adapter->lock, flags); - - return retval; -} - -/* - * atl1_ioctl - - * @netdev: - * @ifreq: - * @cmd: - */ -static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return atl1_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - -/* - * atl1_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - */ -static void atl1_tx_timeout(struct net_device *netdev) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->tx_timeout_task); -} - -/* - * atl1_phy_config - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1_phy_config(unsigned long data) -{ - struct atl1_adapter *adapter = (struct atl1_adapter *)data; - struct atl1_hw *hw = &adapter->hw; - unsigned long flags; - - spin_lock_irqsave(&adapter->lock, flags); - adapter->phy_timer_pending = false; - atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); - atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg); - atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN); - spin_unlock_irqrestore(&adapter->lock, flags); -} - -int atl1_reset(struct atl1_adapter *adapter) -{ - int ret; - - ret = atl1_reset_hw(&adapter->hw); - if (ret != ATL1_SUCCESS) - return ret; - return atl1_init_hw(&adapter->hw); -} - -/* * atl1_open - Called when a network interface is made active * @netdev: network interface device structure * @@ -2008,77 +2078,113 @@ static int atl1_close(struct net_device *netdev) return 0; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void atl1_poll_controller(struct net_device *netdev) -{ - disable_irq(netdev->irq); - atl1_intr(netdev->irq, netdev); - enable_irq(netdev->irq); -} -#endif - -/* - * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT - * will assert. We do soft reset <0x1400=1> according - * with the SPEC. BUT, it seemes that PCIE or DMA - * state-machine will not be reset. DMAR_TO_INT will - * assert again and again. - */ -static void atl1_tx_timeout_task(struct work_struct *work) +#ifdef CONFIG_PM +static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) { - struct atl1_adapter *adapter = - container_of(work, struct atl1_adapter, tx_timeout_task); - struct net_device *netdev = adapter->netdev; + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + u32 ctrl = 0; + u32 wufc = adapter->wol; netif_device_detach(netdev); - atl1_down(adapter); - atl1_up(adapter); - netif_device_attach(netdev); -} + if (netif_running(netdev)) + atl1_down(adapter); -/* - * atl1_link_chg_task - deal with link change event Out of interrupt context - */ -static void atl1_link_chg_task(struct work_struct *work) -{ - struct atl1_adapter *adapter = - container_of(work, struct atl1_adapter, link_chg_task); - unsigned long flags; + atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); + atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); + if (ctrl & BMSR_LSTATUS) + wufc &= ~ATL1_WUFC_LNKC; - spin_lock_irqsave(&adapter->lock, flags); - atl1_check_link(adapter); - spin_unlock_irqrestore(&adapter->lock, flags); + /* reduce speed to 10/100M */ + if (wufc) { + atl1_phy_enter_power_saving(hw); + /* if resume, let driver to re- setup link */ + hw->phy_configured = false; + atl1_set_mac_addr(hw); + atl1_set_multi(netdev); + + ctrl = 0; + /* turn on magic packet wol */ + if (wufc & ATL1_WUFC_MAG) + ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; + + /* turn on Link change WOL */ + if (wufc & ATL1_WUFC_LNKC) + ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); + iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); + + /* turn on all-multi mode if wake on multicast is enabled */ + ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); + ctrl &= ~MAC_CTRL_DBG; + ctrl &= ~MAC_CTRL_PROMIS_EN; + if (wufc & ATL1_WUFC_MC) + ctrl |= MAC_CTRL_MC_ALL_EN; + else + ctrl &= ~MAC_CTRL_MC_ALL_EN; + + /* turn on broadcast mode if wake on-BC is enabled */ + if (wufc & ATL1_WUFC_BC) + ctrl |= MAC_CTRL_BC_EN; + else + ctrl &= ~MAC_CTRL_BC_EN; + + /* enable RX */ + ctrl |= MAC_CTRL_RX_EN; + iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } else { + iowrite32(0, hw->hw_addr + REG_WOL_CTRL); + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + } + + pci_save_state(pdev); + pci_disable_device(pdev); + + pci_set_power_state(pdev, PCI_D3hot); + + return 0; } -/* - * atl1_pcie_patch - Patch for PCIE module - */ -static void atl1_pcie_patch(struct atl1_adapter *adapter) +static int atl1_resume(struct pci_dev *pdev) { - u32 value; - value = 0x6500; - iowrite32(value, adapter->hw.hw_addr + 0x12FC); - /* pcie flow control mode change */ - value = ioread32(adapter->hw.hw_addr + 0x1008); - value |= 0x8000; - iowrite32(value, adapter->hw.hw_addr + 0x1008); + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter = netdev_priv(netdev); + u32 ret_val; + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + + ret_val = pci_enable_device(pdev); + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); + atl1_reset(adapter); + + if (netif_running(netdev)) + atl1_up(adapter); + netif_device_attach(netdev); + + atl1_via_workaround(adapter); + + return 0; } +#else +#define atl1_suspend NULL +#define atl1_resume NULL +#endif -/* - * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400 - * on PCI Command register is disable. - * The function enable this bit. - * Brackett, 2006/03/15 - */ -static void atl1_via_workaround(struct atl1_adapter *adapter) +#ifdef CONFIG_NET_POLL_CONTROLLER +static void atl1_poll_controller(struct net_device *netdev) { - unsigned long value; - - value = ioread16(adapter->hw.hw_addr + PCI_COMMAND); - if (value & PCI_COMMAND_INTX_DISABLE) - value &= ~PCI_COMMAND_INTX_DISABLE; - iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND); + disable_irq(netdev->irq); + atl1_intr(netdev->irq, netdev); + enable_irq(netdev->irq); } +#endif /* * atl1_probe - Device Initialization Routine @@ -2092,26 +2198,25 @@ static void atl1_via_workaround(struct atl1_adapter *adapter) * and a hardware reset occur. */ static int __devinit atl1_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { struct net_device *netdev; struct atl1_adapter *adapter; static int cards_found = 0; - bool pci_using_64 = true; int err; err = pci_enable_device(pdev); if (err) return err; - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + /* + * 64-bit DMA currently has data corruption problems, so let's just + * use 32-bit DMA for now. This is a big hack that is probably wrong. + */ + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (err) { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - dev_err(&pdev->dev, "no usable DMA configuration\n"); - goto err_dma; - } - pci_using_64 = false; + dev_err(&pdev->dev, "no usable DMA configuration\n"); + goto err_dma; } /* Mark all PCI regions associated with PCI device * pdev as being reserved by owner atl1_driver_name @@ -2146,7 +2251,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev, } /* get device revision number */ adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr + - (REG_MASTER_CTRL + 2)); + (REG_MASTER_CTRL + 2)); dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION); /* set default ring resource counts */ @@ -2176,7 +2281,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netdev->ethtool_ops = &atl1_ethtool_ops; adapter->bd_number = cards_found; - adapter->pci_using_64 = pci_using_64; /* setup the private structure */ err = atl1_sw_init(adapter); @@ -2193,9 +2297,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev, */ /* netdev->features |= NETIF_F_TSO; */ - if (pci_using_64) - netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= NETIF_F_LLTX; /* @@ -2299,7 +2400,8 @@ static void __devexit atl1_remove(struct pci_dev *pdev) * address, we need to save the permanent one. */ if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) { - memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN); + memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, + ETH_ALEN); atl1_set_mac_addr(&adapter->hw); } @@ -2311,112 +2413,11 @@ static void __devexit atl1_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -#ifdef CONFIG_PM -static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1_adapter *adapter = netdev_priv(netdev); - struct atl1_hw *hw = &adapter->hw; - u32 ctrl = 0; - u32 wufc = adapter->wol; - - netif_device_detach(netdev); - if (netif_running(netdev)) - atl1_down(adapter); - - atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); - atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); - if (ctrl & BMSR_LSTATUS) - wufc &= ~ATL1_WUFC_LNKC; - - /* reduce speed to 10/100M */ - if (wufc) { - atl1_phy_enter_power_saving(hw); - /* if resume, let driver to re- setup link */ - hw->phy_configured = false; - atl1_set_mac_addr(hw); - atl1_set_multi(netdev); - - ctrl = 0; - /* turn on magic packet wol */ - if (wufc & ATL1_WUFC_MAG) - ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; - - /* turn on Link change WOL */ - if (wufc & ATL1_WUFC_LNKC) - ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); - iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); - - /* turn on all-multi mode if wake on multicast is enabled */ - ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); - ctrl &= ~MAC_CTRL_DBG; - ctrl &= ~MAC_CTRL_PROMIS_EN; - if (wufc & ATL1_WUFC_MC) - ctrl |= MAC_CTRL_MC_ALL_EN; - else - ctrl &= ~MAC_CTRL_MC_ALL_EN; - - /* turn on broadcast mode if wake on-BC is enabled */ - if (wufc & ATL1_WUFC_BC) - ctrl |= MAC_CTRL_BC_EN; - else - ctrl &= ~MAC_CTRL_BC_EN; - - /* enable RX */ - ctrl |= MAC_CTRL_RX_EN; - iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); /* 4 == D3 cold */ - } else { - iowrite32(0, hw->hw_addr + REG_WOL_CTRL); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */ - } - - pci_save_state(pdev); - pci_disable_device(pdev); - - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int atl1_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1_adapter *adapter = netdev_priv(netdev); - u32 ret_val; - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev); - - ret_val = pci_enable_device(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); - atl1_reset(adapter); - - if (netif_running(netdev)) - atl1_up(adapter); - netif_device_attach(netdev); - - atl1_via_workaround(adapter); - - return 0; -} -#else -#define atl1_suspend NULL -#define atl1_resume NULL -#endif - static struct pci_driver atl1_driver = { .name = atl1_driver_name, .id_table = atl1_pci_tbl, .probe = atl1_probe, .remove = __devexit_p(atl1_remove), - /* Power Managment Hooks */ - /* probably broken right now -- CHS */ .suspend = atl1_suspend, .resume = atl1_resume }; diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index c27cfcef45fa..e86b3691765b 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -1205,8 +1205,8 @@ static int au1000_rx(struct net_device *dev) continue; } skb_reserve(skb, 2); /* 16 byte IP header align */ - eth_copy_and_sum(skb, - (unsigned char *)pDB->vaddr, frmlen, 0); + skb_copy_to_linear_data(skb, + (unsigned char *)pDB->vaddr, frmlen); skb_put(skb, frmlen); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); /* pass the packet to upper layers */ diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 879a2fff474e..0795df235492 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -15,6 +15,7 @@ #include <linux/ethtool.h> #include <linux/mii.h> #include <linux/if_ether.h> +#include <linux/if_vlan.h> #include <linux/etherdevice.h> #include <linux/pci.h> #include <linux/delay.h> @@ -68,8 +69,8 @@ (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP)) #define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1)) -#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64) -#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8) +#define RX_PKT_OFFSET 30 +#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64) /* minimum number of free TX descriptors required to wake up TX process */ #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) @@ -599,8 +600,7 @@ static void b44_timer(unsigned long __opaque) spin_unlock_irq(&bp->lock); - bp->timer.expires = jiffies + HZ; - add_timer(&bp->timer); + mod_timer(&bp->timer, round_jiffies(jiffies + HZ)); } static void b44_tx(struct b44 *bp) @@ -653,7 +653,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) src_map = &bp->rx_buffers[src_idx]; dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1); map = &bp->rx_buffers[dest_idx]; - skb = dev_alloc_skb(RX_PKT_BUF_SZ); + skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ); if (skb == NULL) return -ENOMEM; @@ -669,7 +669,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (!dma_mapping_error(mapping)) pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE); dev_kfree_skb_any(skb); - skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA); + skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); if (skb == NULL) return -ENOMEM; mapping = pci_map_single(bp->pdev, skb->data, @@ -684,11 +684,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) } } - skb->dev = bp->dev; - skb_reserve(skb, bp->rx_offset); + rh = (struct rx_header *) skb->data; + skb_reserve(skb, RX_PKT_OFFSET); - rh = (struct rx_header *) - (skb->data - bp->rx_offset); rh->len = 0; rh->flags = 0; @@ -698,13 +696,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (src_map != NULL) src_map->skb = NULL; - ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset)); + ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET)); if (dest_idx == (B44_RX_RING_SIZE - 1)) ctrl |= DESC_CTRL_EOT; dp = &bp->rx_ring[dest_idx]; dp->ctrl = cpu_to_le32(ctrl); - dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset); + dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset); if (bp->flags & B44_FLAG_RX_RING_HACK) b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma, @@ -783,7 +781,7 @@ static int b44_rx(struct b44 *bp, int budget) PCI_DMA_FROMDEVICE); rh = (struct rx_header *) skb->data; len = le16_to_cpu(rh->len); - if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) || + if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) || (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) { drop_it: b44_recycle_rx(bp, cons, bp->rx_prod); @@ -815,8 +813,8 @@ static int b44_rx(struct b44 *bp, int budget) pci_unmap_single(bp->pdev, map, skb_size, PCI_DMA_FROMDEVICE); /* Leave out rx_header */ - skb_put(skb, len+bp->rx_offset); - skb_pull(skb,bp->rx_offset); + skb_put(skb, len + RX_PKT_OFFSET); + skb_pull(skb, RX_PKT_OFFSET); } else { struct sk_buff *copy_skb; @@ -828,7 +826,7 @@ static int b44_rx(struct b44 *bp, int budget) skb_reserve(copy_skb, 2); skb_put(copy_skb, len); /* DMA sync done above, copy just the actual packet */ - skb_copy_from_linear_data_offset(skb, bp->rx_offset, + skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET, copy_skb->data, len); skb = copy_skb; } @@ -969,7 +967,6 @@ static void b44_tx_timeout(struct net_device *dev) static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct b44 *bp = netdev_priv(dev); - struct sk_buff *bounce_skb; int rc = NETDEV_TX_OK; dma_addr_t mapping; u32 len, entry, ctrl; @@ -987,12 +984,13 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { + struct sk_buff *bounce_skb; + /* Chip can't handle DMA to/from >1GB, use bounce buffer */ if (!dma_mapping_error(mapping)) pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE); - bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ, - GFP_ATOMIC|GFP_DMA); + bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) goto err_out; @@ -1001,13 +999,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { if (!dma_mapping_error(mapping)) pci_unmap_single(bp->pdev, mapping, - len, PCI_DMA_TODEVICE); + len, PCI_DMA_TODEVICE); dev_kfree_skb_any(bounce_skb); goto err_out; } - skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), - skb->len); + skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len); dev_kfree_skb_any(skb); skb = bounce_skb; } @@ -1396,12 +1393,12 @@ static void b44_init_hw(struct b44 *bp, int reset_kind) bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ if (reset_kind == B44_PARTIAL_RESET) { bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | - (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))); } else { bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | - (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))); bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); bw32(bp, B44_DMARX_PTR, bp->rx_pending); @@ -1522,14 +1519,13 @@ static void b44_setup_pseudo_magicp(struct b44 *bp) u8 *pwol_pattern; u8 pwol_mask[B44_PMASK_SIZE]; - pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL); + pwol_pattern = kzalloc(B44_PATTERN_SIZE, GFP_KERNEL); if (!pwol_pattern) { printk(KERN_ERR PFX "Memory not available for WOL\n"); return; } /* Ipv4 magic packet pattern - pattern 0.*/ - memset(pwol_pattern, 0, B44_PATTERN_SIZE); memset(pwol_mask, 0, B44_PMASK_SIZE); plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, B44_ETHIPV4UDP_HLEN); @@ -2037,7 +2033,6 @@ static const struct ethtool_ops b44_ethtool_ops = { .get_strings = b44_get_strings, .get_stats_count = b44_get_stats_count, .get_ethtool_stats = b44_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -2093,11 +2088,6 @@ static int __devinit b44_get_invariants(struct b44 *bp) bp->phy_addr = eeprom[90] & 0x1f; - /* With this, plus the rx_header prepended to the data by the - * hardware, we'll land the ethernet header on a 2-byte boundary. - */ - bp->rx_offset = 30; - bp->imask = IMASK_DEF; bp->core_unit = ssb_core_unit(bp); @@ -2348,11 +2338,11 @@ static int b44_resume(struct pci_dev *pdev) netif_device_attach(bp->dev); spin_unlock_irq(&bp->lock); - bp->timer.expires = jiffies + HZ; - add_timer(&bp->timer); - b44_enable_ints(bp); netif_wake_queue(dev); + + mod_timer(&bp->timer, jiffies + 1); + return 0; } diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 18fc13336628..e537e63f292e 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -443,8 +443,6 @@ struct b44 { #define B44_FLAG_TX_RING_HACK 0x40000000 #define B44_FLAG_WOL_ENABLE 0x80000000 - u32 rx_offset; - u32 msg_enable; struct timer_list timer; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index ce3ed67a878e..66eed22cbd21 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.11" -#define DRV_MODULE_RELDATE "June 4, 2007" +#define DRV_MODULE_VERSION "1.6.5" +#define DRV_MODULE_RELDATE "September 20, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -126,91 +126,102 @@ static struct pci_device_id bnx2_pci_tbl[] = { static struct flash_spec flash_table[] = { +#define BUFFERED_FLAGS (BNX2_NV_BUFFERED | BNX2_NV_TRANSLATE) +#define NONBUFFERED_FLAGS (BNX2_NV_WREN) /* Slow EEPROM */ {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400, - 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, + BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, "EEPROM - slow"}, /* Expansion entry 0001 */ {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, 0, "Entry 0001"}, /* Saifun SA25F010 (non-buffered flash) */ /* strap, cfg1, & write1 need updates */ {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, "Non-buffered flash (128kB)"}, /* Saifun SA25F020 (non-buffered flash) */ /* strap, cfg1, & write1 need updates */ {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, "Non-buffered flash (256kB)"}, /* Expansion entry 0100 */ {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, 0, "Entry 0100"}, /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, - 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, /* Entry 0110: ST M45PE20 (non-buffered flash)*/ {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406, - 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4, "Entry 0110: ST M45PE20 (256kB non-bufferred)"}, /* Saifun SA25F005 (non-buffered flash) */ /* strap, cfg1, & write1 need updates */ {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, "Non-buffered flash (64kB)"}, /* Fast EEPROM */ {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400, - 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, + BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, "EEPROM - fast"}, /* Expansion entry 1001 */ {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, 0, "Entry 1001"}, /* Expansion entry 1010 */ {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, 0, "Entry 1010"}, /* ATMEL AT45DB011B (buffered flash) */ {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400, - 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, + BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, "Buffered flash (128kB)"}, /* Expansion entry 1100 */ {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, 0, "Entry 1100"}, /* Expansion entry 1101 */ {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406, - 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, 0, "Entry 1101"}, /* Ateml Expansion entry 1110 */ {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400, - 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, + BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, BUFFERED_FLASH_BYTE_ADDR_MASK, 0, "Entry 1110 (Atmel)"}, /* ATMEL AT45DB021B (buffered flash) */ {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400, - 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, + BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2, "Buffered flash (256kB)"}, }; +static struct flash_spec flash_5709 = { + .flags = BNX2_NV_BUFFERED, + .page_bits = BCM5709_FLASH_PAGE_BITS, + .page_size = BCM5709_FLASH_PAGE_SIZE, + .addr_mask = BCM5709_FLASH_BYTE_ADDR_MASK, + .total_size = BUFFERED_FLASH_TOTAL_SIZE*2, + .name = "5709 Buffered flash (256kB)", +}; + MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); static inline u32 bnx2_tx_avail(struct bnx2 *bp) @@ -550,6 +561,9 @@ bnx2_report_fw_link(struct bnx2 *bp) { u32 fw_link_status = 0; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return; + if (bp->link_up) { u32 bmsr; @@ -601,12 +615,21 @@ bnx2_report_fw_link(struct bnx2 *bp) REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status); } +static char * +bnx2_xceiver_str(struct bnx2 *bp) +{ + return ((bp->phy_port == PORT_FIBRE) ? "SerDes" : + ((bp->phy_flags & PHY_SERDES_FLAG) ? "Remote Copper" : + "Copper")); +} + static void bnx2_report_link(struct bnx2 *bp) { if (bp->link_up) { netif_carrier_on(bp->dev); - printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name); + printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name, + bnx2_xceiver_str(bp)); printk("%d Mbps ", bp->line_speed); @@ -630,7 +653,8 @@ bnx2_report_link(struct bnx2 *bp) } else { netif_carrier_off(bp->dev); - printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); + printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name, + bnx2_xceiver_str(bp)); } bnx2_report_fw_link(bp); @@ -1100,6 +1124,9 @@ bnx2_set_link(struct bnx2 *bp) return 0; } + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return 0; + link_up = bp->link_up; bnx2_enable_bmsr1(bp); @@ -1210,12 +1237,74 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp) return adv; } +static int bnx2_fw_sync(struct bnx2 *, u32, int); + static int -bnx2_setup_serdes_phy(struct bnx2 *bp) +bnx2_setup_remote_phy(struct bnx2 *bp, u8 port) +{ + u32 speed_arg = 0, pause_adv; + + pause_adv = bnx2_phy_get_pause_adv(bp); + + if (bp->autoneg & AUTONEG_SPEED) { + speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG; + if (bp->advertising & ADVERTISED_10baseT_Half) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF; + if (bp->advertising & ADVERTISED_10baseT_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL; + if (bp->advertising & ADVERTISED_100baseT_Half) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF; + if (bp->advertising & ADVERTISED_100baseT_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL; + if (bp->advertising & ADVERTISED_1000baseT_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL; + if (bp->advertising & ADVERTISED_2500baseX_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; + } else { + if (bp->req_line_speed == SPEED_2500) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; + else if (bp->req_line_speed == SPEED_1000) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL; + else if (bp->req_line_speed == SPEED_100) { + if (bp->req_duplex == DUPLEX_FULL) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL; + else + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF; + } else if (bp->req_line_speed == SPEED_10) { + if (bp->req_duplex == DUPLEX_FULL) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL; + else + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF; + } + } + + if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP)) + speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE; + if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM)) + speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE; + + if (port == PORT_TP) + speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE | + BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED; + + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg); + + spin_unlock_bh(&bp->phy_lock); + bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0); + spin_lock_bh(&bp->phy_lock); + + return 0; +} + +static int +bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port) { u32 adv, bmcr; u32 new_adv = 0; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return (bnx2_setup_remote_phy(bp, port)); + if (!(bp->autoneg & AUTONEG_SPEED)) { u32 new_bmcr; int force_link_down = 0; @@ -1323,7 +1412,9 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) } #define ETHTOOL_ALL_FIBRE_SPEED \ - (ADVERTISED_1000baseT_Full) + (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ? \ + (ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\ + (ADVERTISED_1000baseT_Full) #define ETHTOOL_ALL_COPPER_SPEED \ (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ @@ -1335,6 +1426,188 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL) +static void +bnx2_set_default_remote_link(struct bnx2 *bp) +{ + u32 link; + + if (bp->phy_port == PORT_TP) + link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK); + else + link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK); + + if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) { + bp->req_line_speed = 0; + bp->autoneg |= AUTONEG_SPEED; + bp->advertising = ADVERTISED_Autoneg; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) + bp->advertising |= ADVERTISED_10baseT_Half; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL) + bp->advertising |= ADVERTISED_10baseT_Full; + if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) + bp->advertising |= ADVERTISED_100baseT_Half; + if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL) + bp->advertising |= ADVERTISED_100baseT_Full; + if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) + bp->advertising |= ADVERTISED_1000baseT_Full; + if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) + bp->advertising |= ADVERTISED_2500baseX_Full; + } else { + bp->autoneg = 0; + bp->advertising = 0; + bp->req_duplex = DUPLEX_FULL; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10) { + bp->req_line_speed = SPEED_10; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) + bp->req_duplex = DUPLEX_HALF; + } + if (link & BNX2_NETLINK_SET_LINK_SPEED_100) { + bp->req_line_speed = SPEED_100; + if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) + bp->req_duplex = DUPLEX_HALF; + } + if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) + bp->req_line_speed = SPEED_1000; + if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) + bp->req_line_speed = SPEED_2500; + } +} + +static void +bnx2_set_default_link(struct bnx2 *bp) +{ + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return bnx2_set_default_remote_link(bp); + + bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; + bp->req_line_speed = 0; + if (bp->phy_flags & PHY_SERDES_FLAG) { + u32 reg; + + bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; + + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); + reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; + if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { + bp->autoneg = 0; + bp->req_line_speed = bp->line_speed = SPEED_1000; + bp->req_duplex = DUPLEX_FULL; + } + } else + bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; +} + +static void +bnx2_send_heart_beat(struct bnx2 *bp) +{ + u32 msg; + u32 addr; + + spin_lock(&bp->indirect_lock); + msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK); + addr = bp->shmem_base + BNX2_DRV_PULSE_MB; + REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr); + REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg); + spin_unlock(&bp->indirect_lock); +} + +static void +bnx2_remote_phy_event(struct bnx2 *bp) +{ + u32 msg; + u8 link_up = bp->link_up; + u8 old_port; + + msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); + + if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED) + bnx2_send_heart_beat(bp); + + msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED; + + if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN) + bp->link_up = 0; + else { + u32 speed; + + bp->link_up = 1; + speed = msg & BNX2_LINK_STATUS_SPEED_MASK; + bp->duplex = DUPLEX_FULL; + switch (speed) { + case BNX2_LINK_STATUS_10HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_10FULL: + bp->line_speed = SPEED_10; + break; + case BNX2_LINK_STATUS_100HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_100BASE_T4: + case BNX2_LINK_STATUS_100FULL: + bp->line_speed = SPEED_100; + break; + case BNX2_LINK_STATUS_1000HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_1000FULL: + bp->line_speed = SPEED_1000; + break; + case BNX2_LINK_STATUS_2500HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_2500FULL: + bp->line_speed = SPEED_2500; + break; + default: + bp->line_speed = 0; + break; + } + + spin_lock(&bp->phy_lock); + bp->flow_ctrl = 0; + if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != + (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) { + if (bp->duplex == DUPLEX_FULL) + bp->flow_ctrl = bp->req_flow_ctrl; + } else { + if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED) + bp->flow_ctrl |= FLOW_CTRL_TX; + if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED) + bp->flow_ctrl |= FLOW_CTRL_RX; + } + + old_port = bp->phy_port; + if (msg & BNX2_LINK_STATUS_SERDES_LINK) + bp->phy_port = PORT_FIBRE; + else + bp->phy_port = PORT_TP; + + if (old_port != bp->phy_port) + bnx2_set_default_link(bp); + + spin_unlock(&bp->phy_lock); + } + if (bp->link_up != link_up) + bnx2_report_link(bp); + + bnx2_set_mac_link(bp); +} + +static int +bnx2_set_remote_link(struct bnx2 *bp) +{ + u32 evt_code; + + evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB); + switch (evt_code) { + case BNX2_FW_EVT_CODE_LINK_EVENT: + bnx2_remote_phy_event(bp); + break; + case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT: + default: + bnx2_send_heart_beat(bp); + break; + } + return 0; +} + static int bnx2_setup_copper_phy(struct bnx2 *bp) { @@ -1433,13 +1706,13 @@ bnx2_setup_copper_phy(struct bnx2 *bp) } static int -bnx2_setup_phy(struct bnx2 *bp) +bnx2_setup_phy(struct bnx2 *bp, u8 port) { if (bp->loopback == MAC_LOOPBACK) return 0; if (bp->phy_flags & PHY_SERDES_FLAG) { - return (bnx2_setup_serdes_phy(bp)); + return (bnx2_setup_serdes_phy(bp, port)); } else { return (bnx2_setup_copper_phy(bp)); @@ -1659,6 +1932,9 @@ bnx2_init_phy(struct bnx2 *bp) REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + goto setup_phy; + bnx2_read_phy(bp, MII_PHYSID1, &val); bp->phy_id = val << 16; bnx2_read_phy(bp, MII_PHYSID2, &val); @@ -1676,7 +1952,9 @@ bnx2_init_phy(struct bnx2 *bp) rc = bnx2_init_copper_phy(bp); } - bnx2_setup_phy(bp); +setup_phy: + if (!rc) + rc = bnx2_setup_phy(bp, bp->phy_port); return rc; } @@ -1984,6 +2262,9 @@ bnx2_phy_int(struct bnx2 *bp) bnx2_set_link(bp); spin_unlock(&bp->phy_lock); } + if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_TIMER_ABORT)) + bnx2_set_remote_link(bp); + } static void @@ -2297,6 +2578,7 @@ bnx2_interrupt(int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct bnx2 *bp = netdev_priv(dev); + struct status_block *sblk = bp->status_blk; /* When using INTx, it is possible for the interrupt to arrive * at the CPU before the status block posted prior to the @@ -2304,7 +2586,7 @@ bnx2_interrupt(int irq, void *dev_instance) * When using MSI, the MSI message will always complete after * the status block write. */ - if ((bp->status_blk->status_idx == bp->last_status_idx) && + if ((sblk->status_idx == bp->last_status_idx) && (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) return IRQ_NONE; @@ -2313,16 +2595,25 @@ bnx2_interrupt(int irq, void *dev_instance) BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); + /* Read back to deassert IRQ immediately to avoid too many + * spurious interrupts. + */ + REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); + /* Return here if interrupt is shared and is disabled. */ if (unlikely(atomic_read(&bp->intr_sem) != 0)) return IRQ_HANDLED; - netif_rx_schedule(dev); + if (netif_rx_schedule_prep(dev)) { + bp->last_status_idx = sblk->status_idx; + __netif_rx_schedule(dev); + } return IRQ_HANDLED; } -#define STATUS_ATTN_EVENTS STATUS_ATTN_BITS_LINK_STATE +#define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \ + STATUS_ATTN_BITS_TIMER_ABORT) static inline int bnx2_has_work(struct bnx2 *bp) @@ -3009,7 +3300,7 @@ bnx2_enable_nvram_write(struct bnx2 *bp) val = REG_RD(bp, BNX2_MISC_CFG); REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI); - if (!bp->flash_info->buffered) { + if (bp->flash_info->flags & BNX2_NV_WREN) { int j; REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); @@ -3069,7 +3360,7 @@ bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset) u32 cmd; int j; - if (bp->flash_info->buffered) + if (bp->flash_info->flags & BNX2_NV_BUFFERED) /* Buffered flash, no erase needed */ return 0; @@ -3112,8 +3403,8 @@ bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags) /* Build the command word. */ cmd = BNX2_NVM_COMMAND_DOIT | cmd_flags; - /* Calculate an offset of a buffered flash. */ - if (bp->flash_info->buffered) { + /* Calculate an offset of a buffered flash, not needed for 5709. */ + if (bp->flash_info->flags & BNX2_NV_TRANSLATE) { offset = ((offset / bp->flash_info->page_size) << bp->flash_info->page_bits) + (offset % bp->flash_info->page_size); @@ -3159,8 +3450,8 @@ bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags) /* Build the command word. */ cmd = BNX2_NVM_COMMAND_DOIT | BNX2_NVM_COMMAND_WR | cmd_flags; - /* Calculate an offset of a buffered flash. */ - if (bp->flash_info->buffered) { + /* Calculate an offset of a buffered flash, not needed for 5709. */ + if (bp->flash_info->flags & BNX2_NV_TRANSLATE) { offset = ((offset / bp->flash_info->page_size) << bp->flash_info->page_bits) + (offset % bp->flash_info->page_size); @@ -3198,15 +3489,19 @@ static int bnx2_init_nvram(struct bnx2 *bp) { u32 val; - int j, entry_count, rc; + int j, entry_count, rc = 0; struct flash_spec *flash; + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + bp->flash_info = &flash_5709; + goto get_flash_size; + } + /* Determine the selected interface. */ val = REG_RD(bp, BNX2_NVM_CFG1); entry_count = sizeof(flash_table) / sizeof(struct flash_spec); - rc = 0; if (val & 0x40000000) { /* Flash interface has been reconfigured */ @@ -3262,6 +3557,7 @@ bnx2_init_nvram(struct bnx2 *bp) return -ENODEV; } +get_flash_size: val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2); val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK; if (val) @@ -3426,7 +3722,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, buf = align_buf; } - if (bp->flash_info->buffered == 0) { + if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { flash_buffer = kmalloc(264, GFP_KERNEL); if (flash_buffer == NULL) { rc = -ENOMEM; @@ -3459,7 +3755,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, bnx2_enable_nvram_access(bp); cmd_flags = BNX2_NVM_COMMAND_FIRST; - if (bp->flash_info->buffered == 0) { + if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { int j; /* Read the whole page into the buffer @@ -3487,7 +3783,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, /* Loop to write back the buffer data from page_start to * data_start */ i = 0; - if (bp->flash_info->buffered == 0) { + if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { /* Erase the page */ if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0) goto nvram_write_end; @@ -3511,7 +3807,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, /* Loop to write the new data from data_start to data_end */ for (addr = data_start; addr < data_end; addr += 4, i += 4) { if ((addr == page_end - 4) || - ((bp->flash_info->buffered) && + ((bp->flash_info->flags & BNX2_NV_BUFFERED) && (addr == data_end - 4))) { cmd_flags |= BNX2_NVM_COMMAND_LAST; @@ -3528,7 +3824,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, /* Loop to write back the buffer data from data_end * to page_end */ - if (bp->flash_info->buffered == 0) { + if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { for (addr = data_end; addr < page_end; addr += 4, i += 4) { @@ -3562,6 +3858,36 @@ nvram_write_end: return rc; } +static void +bnx2_init_remote_phy(struct bnx2 *bp) +{ + u32 val; + + bp->phy_flags &= ~REMOTE_PHY_CAP_FLAG; + if (!(bp->phy_flags & PHY_SERDES_FLAG)) + return; + + val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB); + if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE) + return; + + if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) { + if (netif_running(bp->dev)) { + val = BNX2_DRV_ACK_CAP_SIGNATURE | + BNX2_FW_CAP_REMOTE_PHY_CAPABLE; + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB, + val); + } + bp->phy_flags |= REMOTE_PHY_CAP_FLAG; + + val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); + if (val & BNX2_LINK_STATUS_SERDES_LINK) + bp->phy_port = PORT_FIBRE; + else + bp->phy_port = PORT_TP; + } +} + static int bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) { @@ -3608,11 +3934,13 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) /* Chip reset. */ REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); + /* Reading back any register after chip reset will hang the + * bus on 5706 A0 and A1. The msleep below provides plenty + * of margin for write posting. + */ if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || - (CHIP_ID(bp) == CHIP_ID_5706_A1)) { - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ / 50); - } + (CHIP_ID(bp) == CHIP_ID_5706_A1)) + msleep(20); /* Reset takes approximate 30 usec */ for (i = 0; i < 10; i++) { @@ -3642,6 +3970,12 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) if (rc) return rc; + spin_lock_bh(&bp->phy_lock); + bnx2_init_remote_phy(bp); + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + bnx2_set_default_remote_link(bp); + spin_unlock_bh(&bp->phy_lock); + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { /* Adjust the voltage regular to two steps lower. The default * of this register is 0x0000000e. */ @@ -3791,7 +4125,7 @@ bnx2_init_chip(struct bnx2 *bp) if (CHIP_NUM(bp) == CHIP_NUM_5708) REG_WR(bp, BNX2_HC_STATS_TICKS, 0); else - REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00); + REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks); REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ if (CHIP_ID(bp) == CHIP_ID_5706_A1) @@ -3811,10 +4145,6 @@ bnx2_init_chip(struct bnx2 *bp) REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS); - if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) & - BNX2_PORT_FEATURE_ASF_ENABLED) - bp->flags |= ASF_ENABLE_FLAG; - /* Initialize the receive filter. */ bnx2_set_rx_mode(bp->dev); @@ -3826,7 +4156,7 @@ bnx2_init_chip(struct bnx2 *bp) rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, 0); - REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff); + REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT); REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); udelay(20); @@ -4069,8 +4399,8 @@ bnx2_init_nic(struct bnx2 *bp) spin_lock_bh(&bp->phy_lock); bnx2_init_phy(bp); - spin_unlock_bh(&bp->phy_lock); bnx2_set_link(bp); + spin_unlock_bh(&bp->phy_lock); return 0; } @@ -4600,6 +4930,9 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) static void bnx2_5708_serdes_timer(struct bnx2 *bp) { + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return; + if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) { bp->serdes_an_pending = 0; return; @@ -4631,7 +4964,6 @@ static void bnx2_timer(unsigned long data) { struct bnx2 *bp = (struct bnx2 *) data; - u32 msg; if (!netif_running(bp->dev)) return; @@ -4639,8 +4971,7 @@ bnx2_timer(unsigned long data) if (atomic_read(&bp->intr_sem) != 0) goto bnx2_restart_timer; - msg = (u32) ++bp->fw_drv_pulse_wr_seq; - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg); + bnx2_send_heart_beat(bp); bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); @@ -5083,17 +5414,25 @@ static int bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct bnx2 *bp = netdev_priv(dev); + int support_serdes = 0, support_copper = 0; cmd->supported = SUPPORTED_Autoneg; - if (bp->phy_flags & PHY_SERDES_FLAG) { + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) { + support_serdes = 1; + support_copper = 1; + } else if (bp->phy_port == PORT_FIBRE) + support_serdes = 1; + else + support_copper = 1; + + if (support_serdes) { cmd->supported |= SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE; if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) cmd->supported |= SUPPORTED_2500baseX_Full; - cmd->port = PORT_FIBRE; } - else { + if (support_copper) { cmd->supported |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -5101,9 +5440,10 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_1000baseT_Full | SUPPORTED_TP; - cmd->port = PORT_TP; } + spin_lock_bh(&bp->phy_lock); + cmd->port = bp->phy_port; cmd->advertising = bp->advertising; if (bp->autoneg & AUTONEG_SPEED) { @@ -5121,6 +5461,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->speed = -1; cmd->duplex = -1; } + spin_unlock_bh(&bp->phy_lock); cmd->transceiver = XCVR_INTERNAL; cmd->phy_address = bp->phy_addr; @@ -5136,6 +5477,15 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) u8 req_duplex = bp->req_duplex; u16 req_line_speed = bp->req_line_speed; u32 advertising = bp->advertising; + int err = -EINVAL; + + spin_lock_bh(&bp->phy_lock); + + if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE) + goto err_out_unlock; + + if (cmd->port != bp->phy_port && !(bp->phy_flags & REMOTE_PHY_CAP_FLAG)) + goto err_out_unlock; if (cmd->autoneg == AUTONEG_ENABLE) { autoneg |= AUTONEG_SPEED; @@ -5148,44 +5498,41 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) (cmd->advertising == ADVERTISED_100baseT_Half) || (cmd->advertising == ADVERTISED_100baseT_Full)) { - if (bp->phy_flags & PHY_SERDES_FLAG) - return -EINVAL; + if (cmd->port == PORT_FIBRE) + goto err_out_unlock; advertising = cmd->advertising; } else if (cmd->advertising == ADVERTISED_2500baseX_Full) { - if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) - return -EINVAL; - } else if (cmd->advertising == ADVERTISED_1000baseT_Full) { + if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) || + (cmd->port == PORT_TP)) + goto err_out_unlock; + } else if (cmd->advertising == ADVERTISED_1000baseT_Full) advertising = cmd->advertising; - } - else if (cmd->advertising == ADVERTISED_1000baseT_Half) { - return -EINVAL; - } + else if (cmd->advertising == ADVERTISED_1000baseT_Half) + goto err_out_unlock; else { - if (bp->phy_flags & PHY_SERDES_FLAG) { + if (cmd->port == PORT_FIBRE) advertising = ETHTOOL_ALL_FIBRE_SPEED; - } - else { + else advertising = ETHTOOL_ALL_COPPER_SPEED; - } } advertising |= ADVERTISED_Autoneg; } else { - if (bp->phy_flags & PHY_SERDES_FLAG) { + if (cmd->port == PORT_FIBRE) { if ((cmd->speed != SPEED_1000 && cmd->speed != SPEED_2500) || (cmd->duplex != DUPLEX_FULL)) - return -EINVAL; + goto err_out_unlock; if (cmd->speed == SPEED_2500 && !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) - return -EINVAL; - } - else if (cmd->speed == SPEED_1000) { - return -EINVAL; + goto err_out_unlock; } + else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500) + goto err_out_unlock; + autoneg &= ~AUTONEG_SPEED; req_line_speed = cmd->speed; req_duplex = cmd->duplex; @@ -5197,13 +5544,12 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) bp->req_line_speed = req_line_speed; bp->req_duplex = req_duplex; - spin_lock_bh(&bp->phy_lock); - - bnx2_setup_phy(bp); + err = bnx2_setup_phy(bp, cmd->port); +err_out_unlock: spin_unlock_bh(&bp->phy_lock); - return 0; + return err; } static void @@ -5214,11 +5560,7 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) strcpy(info->driver, DRV_MODULE_NAME); strcpy(info->version, DRV_MODULE_VERSION); strcpy(info->bus_info, pci_name(bp->pdev)); - info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0'; - info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0'; - info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0'; - info->fw_version[1] = info->fw_version[3] = '.'; - info->fw_version[5] = 0; + strcpy(info->fw_version, bp->fw_version); } #define BNX2_REGDUMP_LEN (32 * 1024) @@ -5330,6 +5672,14 @@ bnx2_nway_reset(struct net_device *dev) spin_lock_bh(&bp->phy_lock); + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) { + int rc; + + rc = bnx2_setup_remote_phy(bp, bp->phy_port); + spin_unlock_bh(&bp->phy_lock); + return rc; + } + /* Force a link down visible on the other side */ if (bp->phy_flags & PHY_SERDES_FLAG) { bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); @@ -5450,8 +5800,9 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC) bp->stats_ticks = USEC_PER_SEC; } - if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00; - bp->stats_ticks &= 0xffff00; + if (bp->stats_ticks > BNX2_HC_STATS_TICKS_HC_STAT_TICKS) + bp->stats_ticks = BNX2_HC_STATS_TICKS_HC_STAT_TICKS; + bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS; if (netif_running(bp->dev)) { bnx2_netif_stop(bp); @@ -5543,7 +5894,7 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) spin_lock_bh(&bp->phy_lock); - bnx2_setup_phy(bp); + bnx2_setup_phy(bp, bp->phy_port); spin_unlock_bh(&bp->phy_lock); @@ -5882,7 +6233,7 @@ bnx2_set_tx_csum(struct net_device *dev, u32 data) struct bnx2 *bp = netdev_priv(dev); if (CHIP_NUM(bp) == CHIP_NUM_5709) - return (ethtool_op_set_tx_hw_csum(dev, data)); + return (ethtool_op_set_tx_ipv6_csum(dev, data)); else return (ethtool_op_set_tx_csum(dev, data)); } @@ -5920,7 +6271,6 @@ static const struct ethtool_ops bnx2_ethtool_ops = { .phys_id = bnx2_phys_id, .get_stats_count = bnx2_get_stats_count, .get_ethtool_stats = bnx2_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; /* Called with rtnl_lock */ @@ -5939,6 +6289,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: { u32 mii_regval; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return -EOPNOTSUPP; + if (!netif_running(dev)) return -EAGAIN; @@ -5955,6 +6308,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return -EOPNOTSUPP; + if (!netif_running(dev)) return -EAGAIN; @@ -6116,7 +6472,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) { struct bnx2 *bp; unsigned long mem_len; - int rc; + int rc, i, j; u32 reg; u64 dma_mask, persist_dma_mask; @@ -6273,7 +6629,47 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_unmap; } - bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); + for (i = 0, j = 0; i < 3; i++) { + u8 num, k, skip0; + + num = (u8) (reg >> (24 - (i * 8))); + for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) { + if (num >= k || !skip0 || k == 1) { + bp->fw_version[j++] = (num / k) + '0'; + skip0 = 0; + } + } + if (i != 2) + bp->fw_version[j++] = '.'; + } + if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) & + BNX2_PORT_FEATURE_ASF_ENABLED) { + bp->flags |= ASF_ENABLE_FLAG; + + for (i = 0; i < 30; i++) { + reg = REG_RD_IND(bp, bp->shmem_base + + BNX2_BC_STATE_CONDITION); + if (reg & BNX2_CONDITION_MFW_RUN_MASK) + break; + msleep(10); + } + } + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION); + reg &= BNX2_CONDITION_MFW_RUN_MASK; + if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN && + reg != BNX2_CONDITION_MFW_RUN_NONE) { + int i; + u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR); + + bp->fw_version[j++] = ' '; + for (i = 0; i < 3; i++) { + reg = REG_RD_IND(bp, addr + i * 4); + reg = swab32(reg); + memcpy(&bp->fw_version[j], ®, 4); + j += 4; + } + } reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER); bp->mac_addr[0] = (u8) (reg >> 8); @@ -6302,7 +6698,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->rx_ticks_int = 18; bp->rx_ticks = 18; - bp->stats_ticks = 1000000 & 0xffff00; + bp->stats_ticks = USEC_PER_SEC & BNX2_HC_STATS_TICKS_HC_STAT_TICKS; bp->timer_interval = HZ; bp->current_interval = HZ; @@ -6315,7 +6711,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) bp->phy_flags |= PHY_SERDES_FLAG; + bp->phy_port = PORT_TP; if (bp->phy_flags & PHY_SERDES_FLAG) { + bp->phy_port = PORT_FIBRE; bp->flags |= NO_WOL_FLAG; if (CHIP_NUM(bp) != CHIP_NUM_5706) { bp->phy_addr = 2; @@ -6324,10 +6722,13 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; } + bnx2_init_remote_phy(bp); + } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || CHIP_NUM(bp) == CHIP_NUM_5708) bp->phy_flags |= PHY_CRC_FIX_FLAG; - else if (CHIP_ID(bp) == CHIP_ID_5709_A0) + else if (CHIP_ID(bp) == CHIP_ID_5709_A0 || + CHIP_ID(bp) == CHIP_ID_5709_A1) bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG; if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || @@ -6363,10 +6764,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, amd_8132))) { - u8 rev; - pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev); - if (rev >= 0x10 && rev <= 0x13) { + if (amd_8132->revision >= 0x10 && + amd_8132->revision <= 0x13) { disable_msi = 1; pci_dev_put(amd_8132); break; @@ -6374,23 +6774,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) } } - bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; - bp->req_line_speed = 0; - if (bp->phy_flags & PHY_SERDES_FLAG) { - bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; - - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); - reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; - if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { - bp->autoneg = 0; - bp->req_line_speed = bp->line_speed = SPEED_1000; - bp->req_duplex = DUPLEX_FULL; - } - } - else { - bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; - } - + bnx2_set_default_link(bp); bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; init_timer(&bp->timer); @@ -6490,10 +6874,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) memcpy(dev->perm_addr, bp->mac_addr, 6); bp->name = board_info[ent->driver_data].name; + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; if (CHIP_NUM(bp) == CHIP_NUM_5709) - dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; - else - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; + dev->features |= NETIF_F_IPV6_CSUM; + #ifdef BCM_VLAN dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; #endif @@ -6556,6 +6940,11 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) struct bnx2 *bp = netdev_priv(dev); u32 reset_code; + /* PCI register 4 needs to be saved whether netif_running() or not. + * MSI address and data need to be saved if using MSI and + * netif_running(). + */ + pci_save_state(pdev); if (!netif_running(dev)) return 0; @@ -6571,7 +6960,6 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; bnx2_reset_chip(bp, reset_code); bnx2_free_skbs(bp); - pci_save_state(pdev); bnx2_set_power_state(bp, pci_choose_state(pdev, state)); return 0; } @@ -6582,10 +6970,10 @@ bnx2_resume(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct bnx2 *bp = netdev_priv(dev); + pci_restore_state(pdev); if (!netif_running(dev)) return 0; - pci_restore_state(pdev); bnx2_set_power_state(bp, PCI_D0); netif_device_attach(dev); bnx2_init_nic(bp); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 49a5de253b17..102adfe1e923 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6338,6 +6338,8 @@ struct l2_fhdr { #define RX_COPY_THRESH 92 +#define BNX2_MISC_ENABLE_DEFAULT 0x7ffffff + #define DMA_READ_CHANS 5 #define DMA_WRITE_CHANS 3 @@ -6431,6 +6433,11 @@ struct sw_bd { #define ST_MICRO_FLASH_PAGE_SIZE 256 #define ST_MICRO_FLASH_BASE_TOTAL_SIZE 65536 +#define BCM5709_FLASH_PAGE_BITS 8 +#define BCM5709_FLASH_PHY_PAGE_SIZE (1 << BCM5709_FLASH_PAGE_BITS) +#define BCM5709_FLASH_BYTE_ADDR_MASK (BCM5709_FLASH_PHY_PAGE_SIZE-1) +#define BCM5709_FLASH_PAGE_SIZE 256 + #define NVRAM_TIMEOUT_COUNT 30000 @@ -6447,7 +6454,10 @@ struct flash_spec { u32 config2; u32 config3; u32 write1; - u32 buffered; + u32 flags; +#define BNX2_NV_BUFFERED 0x00000001 +#define BNX2_NV_TRANSLATE 0x00000002 +#define BNX2_NV_WREN 0x00000004 u32 page_bits; u32 page_size; u32 addr_mask; @@ -6537,6 +6547,7 @@ struct bnx2 { #define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 #define PHY_INT_MODE_LINK_READY_FLAG 0x200 #define PHY_DIS_EARLY_DAC_FLAG 0x400 +#define REMOTE_PHY_CAP_FLAG 0x800 u32 mii_bmcr; u32 mii_bmsr; @@ -6625,6 +6636,7 @@ struct bnx2 { u16 req_line_speed; u8 req_duplex; + u8 phy_port; u8 link_up; u16 line_speed; @@ -6656,7 +6668,7 @@ struct bnx2 { u32 shmem_base; - u32 fw_ver; + char fw_version[32]; int pm_cap; int pcix_cap; @@ -6770,7 +6782,7 @@ struct fw_info { * the firmware has timed out, the driver will assume there is no firmware * running and there won't be any firmware-driver synchronization during a * driver reset. */ -#define FW_ACK_TIME_OUT_MS 100 +#define FW_ACK_TIME_OUT_MS 1000 #define BNX2_DRV_RESET_SIGNATURE 0x00000000 @@ -6788,6 +6800,7 @@ struct fw_info { #define BNX2_DRV_MSG_CODE_DIAG 0x07000000 #define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000 #define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN 0x0b000000 +#define BNX2_DRV_MSG_CODE_CMD_SET_LINK 0x10000000 #define BNX2_DRV_MSG_DATA 0x00ff0000 #define BNX2_DRV_MSG_DATA_WAIT0 0x00010000 @@ -6836,6 +6849,7 @@ struct fw_info { #define BNX2_LINK_STATUS_SERDES_LINK (1<<20) #define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21) #define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22) +#define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED (1<<31) #define BNX2_DRV_PULSE_MB 0x00000010 #define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff @@ -6845,6 +6859,30 @@ struct fw_info { * This is used for debugging. */ #define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000 +#define BNX2_DRV_MB_ARG0 0x00000014 +#define BNX2_NETLINK_SET_LINK_SPEED_10HALF (1<<0) +#define BNX2_NETLINK_SET_LINK_SPEED_10FULL (1<<1) +#define BNX2_NETLINK_SET_LINK_SPEED_10 \ + (BNX2_NETLINK_SET_LINK_SPEED_10HALF | \ + BNX2_NETLINK_SET_LINK_SPEED_10FULL) +#define BNX2_NETLINK_SET_LINK_SPEED_100HALF (1<<2) +#define BNX2_NETLINK_SET_LINK_SPEED_100FULL (1<<3) +#define BNX2_NETLINK_SET_LINK_SPEED_100 \ + (BNX2_NETLINK_SET_LINK_SPEED_100HALF | \ + BNX2_NETLINK_SET_LINK_SPEED_100FULL) +#define BNX2_NETLINK_SET_LINK_SPEED_1GHALF (1<<4) +#define BNX2_NETLINK_SET_LINK_SPEED_1GFULL (1<<5) +#define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF (1<<6) +#define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL (1<<7) +#define BNX2_NETLINK_SET_LINK_SPEED_10GHALF (1<<8) +#define BNX2_NETLINK_SET_LINK_SPEED_10GFULL (1<<9) +#define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG (1<<10) +#define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE (1<<11) +#define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE (1<<12) +#define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE (1<<13) +#define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED (1<<14) +#define BNX2_NETLINK_SET_LINK_PHY_RESET (1<<15) + #define BNX2_DEV_INFO_SIGNATURE 0x00000020 #define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900 #define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00 @@ -7006,6 +7044,8 @@ struct fw_info { #define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff #define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000 +#define BNX2_MFW_VER_PTR 0x00000014c + #define BNX2_BC_STATE_RESET_TYPE 0x000001c0 #define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254 #define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff @@ -7059,12 +7099,42 @@ struct fw_info { #define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600) #define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700) +#define BNX2_BC_STATE_CONDITION 0x000001c8 +#define BNX2_CONDITION_MFW_RUN_UNKNOWN 0x00000000 +#define BNX2_CONDITION_MFW_RUN_IPMI 0x00002000 +#define BNX2_CONDITION_MFW_RUN_UMP 0x00004000 +#define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000 +#define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000 +#define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000 + #define BNX2_BC_STATE_DEBUG_CMD 0x1dc #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000 #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000 #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff +#define BNX2_FW_EVT_CODE_MB 0x354 +#define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000 +#define BNX2_FW_EVT_CODE_LINK_EVENT 0x00000001 + +#define BNX2_DRV_ACK_CAP_MB 0x364 +#define BNX2_DRV_ACK_CAP_SIGNATURE 0x35450000 +#define BNX2_CAPABILITY_SIGNATURE_MASK 0xFFFF0000 + +#define BNX2_FW_CAP_MB 0x368 +#define BNX2_FW_CAP_SIGNATURE 0xaa550000 +#define BNX2_FW_ACK_DRV_SIGNATURE 0x52500000 +#define BNX2_FW_CAP_SIGNATURE_MASK 0xffff0000 +#define BNX2_FW_CAP_REMOTE_PHY_CAPABLE 0x00000001 +#define BNX2_FW_CAP_REMOTE_PHY_PRESENT 0x00000002 + +#define BNX2_RPHY_SIGNATURE 0x36c +#define BNX2_RPHY_LOAD_SIGNATURE 0x5a5a5a5a + +#define BNX2_RPHY_FLAGS 0x370 +#define BNX2_RPHY_SERDES_LINK 0x374 +#define BNX2_RPHY_COPPER_LINK 0x378 + #define HOST_VIEW_SHMEM_BASE 0x167c00 #endif diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 0af7bc8d411d..1afda3230def 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -187,7 +187,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond); /*---------------------------- General routines -----------------------------*/ -const char *bond_mode_name(int mode) +static const char *bond_mode_name(int mode) { switch (mode) { case BOND_MODE_ROUNDROBIN : @@ -613,38 +613,20 @@ down: static int bond_update_speed_duplex(struct slave *slave) { struct net_device *slave_dev = slave->dev; - static int (* ioctl)(struct net_device *, struct ifreq *, int); - struct ifreq ifr; struct ethtool_cmd etool; + int res; /* Fake speed and duplex */ slave->speed = SPEED_100; slave->duplex = DUPLEX_FULL; - if (slave_dev->ethtool_ops) { - int res; - - if (!slave_dev->ethtool_ops->get_settings) { - return -1; - } - - res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool); - if (res < 0) { - return -1; - } - - goto verify; - } + if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings) + return -1; - ioctl = slave_dev->do_ioctl; - strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ); - etool.cmd = ETHTOOL_GSET; - ifr.ifr_data = (char*)&etool; - if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) { + res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool); + if (res < 0) return -1; - } -verify: switch (etool.speed) { case SPEED_10: case SPEED_100: @@ -690,7 +672,6 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de static int (* ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; - struct ethtool_value etool; if (bond->params.use_carrier) { return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; @@ -721,9 +702,10 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de } } - /* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */ - /* for a period of time so we attempt to get link status */ - /* from it last if the above MII ioctls fail... */ + /* + * Some drivers cache ETHTOOL_GLINK for a period of time so we only + * attempt to get link status from it if the above MII ioctls fail. + */ if (slave_dev->ethtool_ops) { if (slave_dev->ethtool_ops->get_link) { u32 link; @@ -734,23 +716,9 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de } } - if (ioctl) { - strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ); - etool.cmd = ETHTOOL_GLINK; - ifr.ifr_data = (char*)&etool; - if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) { - if (etool.data == 1) { - return BMSR_LSTATUS; - } else { - dprintk("SIOCETHTOOL shows link down\n"); - return 0; - } - } - } - /* * If reporting, report that either there's no dev->do_ioctl, - * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we + * or both SIOCGMIIREG and get_link failed (meaning that we * cannot report link status). If not reporting, pretend * we're ok. */ @@ -1224,7 +1192,8 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave) /*---------------------------------- IOCTL ----------------------------------*/ -int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) +static int bond_sethwaddr(struct net_device *bond_dev, + struct net_device *slave_dev) { dprintk("bond_dev=%p\n", bond_dev); dprintk("slave_dev=%p\n", slave_dev); @@ -1246,10 +1215,14 @@ static int bond_compute_features(struct bonding *bond) { struct slave *slave; struct net_device *bond_dev = bond->dev; - unsigned long features = bond_dev->features & ~BOND_VLAN_FEATURES; + unsigned long features = bond_dev->features; unsigned short max_hard_header_len = ETH_HLEN; int i; + features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); + features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | + NETIF_F_GSO_MASK | NETIF_F_NO_CSUM; + bond_for_each_slave(bond, slave, i) { features = netdev_compute_features(features, slave->dev->features); @@ -1378,6 +1351,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_free; } + res = netdev_set_master(slave_dev, bond_dev); + if (res) { + dprintk("Error %d calling netdev_set_master\n", res); + goto err_close; + } /* open the slave since the application closed it */ res = dev_open(slave_dev); if (res) { @@ -1385,12 +1363,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_restore_mac; } - res = netdev_set_master(slave_dev, bond_dev); - if (res) { - dprintk("Error %d calling netdev_set_master\n", res); - goto err_close; - } - new_slave->dev = slave_dev; slave_dev->priv_flags |= IFF_BONDING; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index a89102116ccb..6dcbd25e3ef0 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -301,13 +301,11 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave); int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev); int bond_release(struct net_device *bond_dev, struct net_device *slave_dev); -int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev); void bond_mii_monitor(struct net_device *bond_dev); void bond_loadbalance_arp_mon(struct net_device *bond_dev); void bond_activebackup_arp_mon(struct net_device *bond_dev); void bond_set_mode_ops(struct bonding *bond, int mode); int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl); -const char *bond_mode_name(int mode); void bond_select_active_slave(struct bonding *bond); void bond_change_active_slave(struct bonding *bond, struct slave *new_active); void bond_register_arp(struct bonding *); diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c index 7845eaf6f29f..88edb986691a 100644 --- a/drivers/net/bsd_comp.c +++ b/drivers/net/bsd_comp.c @@ -395,20 +395,18 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp) * Allocate the main control structure for this instance. */ maxmaxcode = MAXCODE(bits); - db = kmalloc(sizeof (struct bsd_db), + db = kzalloc(sizeof (struct bsd_db), GFP_KERNEL); if (!db) { return NULL; } - memset (db, 0, sizeof(struct bsd_db)); /* * Allocate space for the dictionary. This may be more than one page in * length. */ - db->dict = (struct bsd_dict *) vmalloc (hsize * - sizeof (struct bsd_dict)); + db->dict = vmalloc(hsize * sizeof(struct bsd_dict)); if (!db->dict) { bsd_free (db); @@ -427,8 +425,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp) */ else { - db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) * - sizeof (db->lens[0])); + db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0])); if (!db->lens) { bsd_free (db); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 59b9943b077d..f6e4030c73d1 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -3422,21 +3422,19 @@ done: static void cas_check_pci_invariants(struct cas *cp) { struct pci_dev *pdev = cp->pdev; - u8 rev; cp->cas_flags = 0; - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); if ((pdev->vendor == PCI_VENDOR_ID_SUN) && (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) { - if (rev >= CAS_ID_REVPLUS) + if (pdev->revision >= CAS_ID_REVPLUS) cp->cas_flags |= CAS_FLAG_REG_PLUS; - if (rev < CAS_ID_REVPLUS02u) + if (pdev->revision < CAS_ID_REVPLUS02u) cp->cas_flags |= CAS_FLAG_TARGET_ABORT; /* Original Cassini supports HW CSUM, but it's not * enabled by default as it can trigger TX hangs. */ - if (rev < CAS_ID_REV2) + if (pdev->revision < CAS_ID_REV2) cp->cas_flags |= CAS_FLAG_NO_HW_CSUM; } else { /* Only sun has original cassini chips. */ @@ -4919,13 +4917,13 @@ static int __devinit cas_init_one(struct pci_dev *pdev, pci_cmd &= ~PCI_COMMAND_SERR; pci_cmd |= PCI_COMMAND_PARITY; pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - if (pci_set_mwi(pdev)) + if (pci_try_set_mwi(pdev)) printk(KERN_WARNING PFX "Could not enable MWI for %s\n", pci_name(pdev)); /* * On some architectures, the default cache line size set - * by pci_set_mwi reduces perforamnce. We have to increase + * by pci_try_set_mwi reduces perforamnce. We have to increase * it for this case. To start, we'll print some configuration * data. */ diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 80c3d8f268a7..20e887de2545 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -50,7 +50,9 @@ typedef irqreturn_t(*intr_handler_t) (int, void *); struct vlan_group; +struct adapter; struct port_info { + struct adapter *adapter; struct vlan_group *vlan_grp; const struct port_type_info *port_type; u8 port_id; @@ -71,27 +73,29 @@ enum { /* adapter flags */ QUEUES_BOUND = (1 << 3), }; +struct fl_pg_chunk { + struct page *page; + void *va; + unsigned int offset; +}; + struct rx_desc; struct rx_sw_desc; -struct sge_fl_page { - struct skb_frag_struct frag; - unsigned char *va; -}; - -struct sge_fl { /* SGE per free-buffer list state */ - unsigned int buf_size; /* size of each Rx buffer */ - unsigned int credits; /* # of available Rx buffers */ - unsigned int size; /* capacity of free list */ - unsigned int cidx; /* consumer index */ - unsigned int pidx; /* producer index */ - unsigned int gen; /* free list generation */ - unsigned int cntxt_id; /* SGE context id for the free list */ - struct sge_fl_page page; - struct rx_desc *desc; /* address of HW Rx descriptor ring */ - struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ - dma_addr_t phys_addr; /* physical address of HW ring start */ - unsigned long empty; /* # of times queue ran out of buffers */ +struct sge_fl { /* SGE per free-buffer list state */ + unsigned int buf_size; /* size of each Rx buffer */ + unsigned int credits; /* # of available Rx buffers */ + unsigned int size; /* capacity of free list */ + unsigned int cidx; /* consumer index */ + unsigned int pidx; /* producer index */ + unsigned int gen; /* free list generation */ + struct fl_pg_chunk pg_chunk;/* page chunk cache */ + unsigned int use_pages; /* whether FL uses pages or sk_buffs */ + struct rx_desc *desc; /* address of HW Rx descriptor ring */ + struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ + dma_addr_t phys_addr; /* physical address of HW ring start */ + unsigned int cntxt_id; /* SGE context id for the free list */ + unsigned long empty; /* # of times queue ran out of buffers */ unsigned long alloc_failed; /* # of times buffer allocation failed */ }; diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 8d1379633698..2129210a67c1 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -101,6 +101,7 @@ enum { TCB_SIZE = 128, /* TCB size */ NMTUS = 16, /* size of MTU table */ NCCTRL_WIN = 32, /* # of congestion control windows */ + PROTO_SRAM_LINES = 128, /* size of TP sram */ }; #define MAX_RX_COALESCING_LEN 16224U @@ -124,6 +125,30 @@ enum { /* adapter interrupt-maintained statistics */ }; enum { + TP_VERSION_MAJOR = 1, + TP_VERSION_MINOR = 0, + TP_VERSION_MICRO = 44 +}; + +#define S_TP_VERSION_MAJOR 16 +#define M_TP_VERSION_MAJOR 0xFF +#define V_TP_VERSION_MAJOR(x) ((x) << S_TP_VERSION_MAJOR) +#define G_TP_VERSION_MAJOR(x) \ + (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR) + +#define S_TP_VERSION_MINOR 8 +#define M_TP_VERSION_MINOR 0xFF +#define V_TP_VERSION_MINOR(x) ((x) << S_TP_VERSION_MINOR) +#define G_TP_VERSION_MINOR(x) \ + (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR) + +#define S_TP_VERSION_MICRO 0 +#define M_TP_VERSION_MICRO 0xFF +#define V_TP_VERSION_MICRO(x) ((x) << S_TP_VERSION_MICRO) +#define G_TP_VERSION_MICRO(x) \ + (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO) + +enum { SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */ SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */ SGE_TXQ_PER_SET = 3 /* # of Tx queues per set */ @@ -654,6 +679,10 @@ const struct adapter_info *t3_get_adapter_info(unsigned int board_id); int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data); int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data); int t3_seeprom_wp(struct adapter *adapter, int enable); +int t3_get_tp_version(struct adapter *adapter, u32 *vers); +int t3_check_tpsram_version(struct adapter *adapter, int *must_load); +int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size); +int t3_set_proto_sram(struct adapter *adap, u8 *data); int t3_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords, u32 *data, int byte_oriented); int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index d8a1f5452c51..5ab319cfe5de 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -43,6 +43,7 @@ #include <linux/proc_fs.h> #include <linux/rtnetlink.h> #include <linux/firmware.h> +#include <linux/log2.h> #include <asm/uaccess.h> #include "common.h" @@ -357,11 +358,14 @@ static int init_dummy_netdevs(struct adapter *adap) for (j = 0; j < pi->nqsets - 1; j++) { if (!adap->dummy_netdev[dummy_idx]) { - nd = alloc_netdev(0, "", ether_setup); + struct port_info *p; + + nd = alloc_netdev(sizeof(*p), "", ether_setup); if (!nd) goto free_all; - nd->priv = adap; + p = netdev_priv(nd); + p->adapter = adap; nd->weight = 64; set_bit(__LINK_STATE_START, &nd->state); adap->dummy_netdev[dummy_idx] = nd; @@ -481,7 +485,8 @@ static ssize_t attr_store(struct device *d, struct device_attribute *attr, #define CXGB3_SHOW(name, val_expr) \ static ssize_t format_##name(struct net_device *dev, char *buf) \ { \ - struct adapter *adap = dev->priv; \ + struct port_info *pi = netdev_priv(dev); \ + struct adapter *adap = pi->adapter; \ return sprintf(buf, "%u\n", val_expr); \ } \ static ssize_t show_##name(struct device *d, struct device_attribute *attr, \ @@ -492,7 +497,8 @@ static ssize_t show_##name(struct device *d, struct device_attribute *attr, \ static ssize_t set_nfilters(struct net_device *dev, unsigned int val) { - struct adapter *adap = dev->priv; + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; int min_tids = is_offload(adap) ? MC5_MIN_TIDS : 0; if (adap->flags & FULL_INIT_DONE) @@ -514,7 +520,8 @@ static ssize_t store_nfilters(struct device *d, struct device_attribute *attr, static ssize_t set_nservers(struct net_device *dev, unsigned int val) { - struct adapter *adap = dev->priv; + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; if (adap->flags & FULL_INIT_DONE) return -EBUSY; @@ -555,9 +562,10 @@ static struct attribute_group cxgb3_attr_group = {.attrs = cxgb3_attrs }; static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr, char *buf, int sched) { - ssize_t len; + struct port_info *pi = netdev_priv(to_net_dev(d)); + struct adapter *adap = pi->adapter; unsigned int v, addr, bpt, cpt; - struct adapter *adap = to_net_dev(d)->priv; + ssize_t len; addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2; rtnl_lock(); @@ -580,10 +588,11 @@ static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr, static ssize_t tm_attr_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len, int sched) { + struct port_info *pi = netdev_priv(to_net_dev(d)); + struct adapter *adap = pi->adapter; + unsigned int val; char *endp; ssize_t ret; - unsigned int val; - struct adapter *adap = to_net_dev(d)->priv; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -720,6 +729,7 @@ static void bind_qsets(struct adapter *adap) } #define FW_FNAME "t3fw-%d.%d.%d.bin" +#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin" static int upgrade_fw(struct adapter *adap) { @@ -738,6 +748,71 @@ static int upgrade_fw(struct adapter *adap) } ret = t3_load_fw(adap, fw->data, fw->size); release_firmware(fw); + + if (ret == 0) + dev_info(dev, "successful upgrade to firmware %d.%d.%d\n", + FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO); + else + dev_err(dev, "failed to upgrade to firmware %d.%d.%d\n", + FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO); + + return ret; +} + +static inline char t3rev2char(struct adapter *adapter) +{ + char rev = 0; + + switch(adapter->params.rev) { + case T3_REV_B: + case T3_REV_B2: + rev = 'b'; + break; + } + return rev; +} + +int update_tpsram(struct adapter *adap) +{ + const struct firmware *tpsram; + char buf[64]; + struct device *dev = &adap->pdev->dev; + int ret; + char rev; + + rev = t3rev2char(adap); + if (!rev) + return 0; + + snprintf(buf, sizeof(buf), TPSRAM_NAME, rev, + TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); + + ret = request_firmware(&tpsram, buf, dev); + if (ret < 0) { + dev_err(dev, "could not load TP SRAM: unable to load %s\n", + buf); + return ret; + } + + ret = t3_check_tpsram(adap, tpsram->data, tpsram->size); + if (ret) + goto release_tpsram; + + ret = t3_set_proto_sram(adap, tpsram->data); + if (ret == 0) + dev_info(dev, + "successful update of protocol engine " + "to %d.%d.%d\n", + TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); + else + dev_err(dev, "failed to update of protocol engine %d.%d.%d\n", + TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); + if (ret) + dev_err(dev, "loading protocol SRAM failed\n"); + +release_tpsram: + release_firmware(tpsram); + return ret; } @@ -754,6 +829,7 @@ static int upgrade_fw(struct adapter *adap) static int cxgb_up(struct adapter *adap) { int err = 0; + int must_load; if (!(adap->flags & FULL_INIT_DONE)) { err = t3_check_fw_version(adap); @@ -762,6 +838,13 @@ static int cxgb_up(struct adapter *adap) if (err) goto out; + err = t3_check_tpsram_version(adap, &must_load); + if (err == -EINVAL) { + err = update_tpsram(adap); + if (err && must_load) + goto out; + } + err = init_dummy_netdevs(adap); if (err) goto out; @@ -857,8 +940,9 @@ static void schedule_chk_task(struct adapter *adap) static int offload_open(struct net_device *dev) { - struct adapter *adapter = dev->priv; - struct t3cdev *tdev = T3CDEV(dev); + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; + struct t3cdev *tdev = dev2t3cdev(dev); int adap_up = adapter->open_device_map & PORT_MASK; int err = 0; @@ -923,10 +1007,10 @@ static int offload_close(struct t3cdev *tdev) static int cxgb_open(struct net_device *dev) { - int err; - struct adapter *adapter = dev->priv; struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int other_ports = adapter->open_device_map & PORT_MASK; + int err; if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) return err; @@ -950,17 +1034,17 @@ static int cxgb_open(struct net_device *dev) static int cxgb_close(struct net_device *dev) { - struct adapter *adapter = dev->priv; - struct port_info *p = netdev_priv(dev); + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; - t3_port_intr_disable(adapter, p->port_id); + t3_port_intr_disable(adapter, pi->port_id); netif_stop_queue(dev); - p->phy.ops->power_down(&p->phy, 1); + pi->phy.ops->power_down(&pi->phy, 1); netif_carrier_off(dev); - t3_mac_disable(&p->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); + t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); spin_lock(&adapter->work_lock); /* sync with update task */ - clear_bit(p->port_id, &adapter->open_device_map); + clear_bit(pi->port_id, &adapter->open_device_map); spin_unlock(&adapter->work_lock); if (!(adapter->open_device_map & PORT_MASK)) @@ -975,13 +1059,13 @@ static int cxgb_close(struct net_device *dev) static struct net_device_stats *cxgb_get_stats(struct net_device *dev) { - struct adapter *adapter = dev->priv; - struct port_info *p = netdev_priv(dev); - struct net_device_stats *ns = &p->netstats; + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; + struct net_device_stats *ns = &pi->netstats; const struct mac_stats *pstats; spin_lock(&adapter->stats_lock); - pstats = t3_mac_update_stats(&p->mac); + pstats = t3_mac_update_stats(&pi->mac); spin_unlock(&adapter->stats_lock); ns->tx_bytes = pstats->tx_octets; @@ -1014,14 +1098,16 @@ static struct net_device_stats *cxgb_get_stats(struct net_device *dev) static u32 get_msglevel(struct net_device *dev) { - struct adapter *adapter = dev->priv; + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; return adapter->msg_enable; } static void set_msglevel(struct net_device *dev, u32 val) { - struct adapter *adapter = dev->priv; + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; adapter->msg_enable = val; } @@ -1095,10 +1181,13 @@ static int get_eeprom_len(struct net_device *dev) static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; u32 fw_vers = 0; - struct adapter *adapter = dev->priv; + u32 tp_vers = 0; t3_get_fw_version(adapter, &fw_vers); + t3_get_tp_version(adapter, &tp_vers); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); @@ -1107,11 +1196,14 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) strcpy(info->fw_version, "N/A"); else { snprintf(info->fw_version, sizeof(info->fw_version), - "%s %u.%u.%u", + "%s %u.%u.%u TP %u.%u.%u", G_FW_VERSION_TYPE(fw_vers) ? "T" : "N", G_FW_VERSION_MAJOR(fw_vers), G_FW_VERSION_MINOR(fw_vers), - G_FW_VERSION_MICRO(fw_vers)); + G_FW_VERSION_MICRO(fw_vers), + G_TP_VERSION_MAJOR(tp_vers), + G_TP_VERSION_MINOR(tp_vers), + G_TP_VERSION_MICRO(tp_vers)); } } @@ -1135,8 +1227,8 @@ static unsigned long collect_sge_port_stats(struct adapter *adapter, static void get_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { - struct adapter *adapter = dev->priv; struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; const struct mac_stats *s; spin_lock(&adapter->stats_lock); @@ -1204,7 +1296,8 @@ static inline void reg_block_dump(struct adapter *ap, void *buf, static void get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) { - struct adapter *ap = dev->priv; + struct port_info *pi = netdev_priv(dev); + struct adapter *ap = pi->adapter; /* * Version scheme: @@ -1245,8 +1338,9 @@ static int restart_autoneg(struct net_device *dev) static int cxgb3_phys_id(struct net_device *dev, u32 data) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int i; - struct adapter *adapter = dev->priv; if (data == 0) data = 2; @@ -1407,8 +1501,8 @@ static int set_rx_csum(struct net_device *dev, u32 data) static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { - const struct adapter *adapter = dev->priv; - const struct port_info *pi = netdev_priv(dev); + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset]; e->rx_max_pending = MAX_RX_BUFFERS; @@ -1424,10 +1518,10 @@ static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { - int i; + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; struct qset_params *q; - struct adapter *adapter = dev->priv; - const struct port_info *pi = netdev_priv(dev); + int i; if (e->rx_pending > MAX_RX_BUFFERS || e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS || @@ -1456,7 +1550,8 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { - struct adapter *adapter = dev->priv; + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; struct qset_params *qsp = &adapter->params.sge.qset[0]; struct sge_qset *qs = &adapter->sge.qs[0]; @@ -1470,7 +1565,8 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { - struct adapter *adapter = dev->priv; + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; struct qset_params *q = adapter->params.sge.qset; c->rx_coalesce_usecs = q->coalesce_usecs; @@ -1480,8 +1576,9 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e, u8 * data) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int i, err = 0; - struct adapter *adapter = dev->priv; u8 *buf = kmalloc(EEPROMSIZE, GFP_KERNEL); if (!buf) @@ -1500,10 +1597,11 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e, static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 * data) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; + u32 aligned_offset, aligned_len, *p; u8 *buf; int err = 0; - u32 aligned_offset, aligned_len, *p; - struct adapter *adapter = dev->priv; if (eeprom->magic != EEPROM_MAGIC) return -EINVAL; @@ -1582,7 +1680,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .get_wol = get_wol, .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, - .get_perm_addr = ethtool_op_get_perm_addr }; static int in_range(int val, int lo, int hi) @@ -1592,9 +1689,10 @@ static int in_range(int val, int lo, int hi) static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) { - int ret; + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; u32 cmd; - struct adapter *adapter = dev->priv; + int ret; if (copy_from_user(&cmd, useraddr, sizeof(cmd))) return -EFAULT; @@ -1818,8 +1916,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) return -EBUSY; if (copy_from_user(&m, useraddr, sizeof(m))) return -EFAULT; - if (!m.rx_pg_sz || (m.rx_pg_sz & (m.rx_pg_sz - 1)) || - !m.tx_pg_sz || (m.tx_pg_sz & (m.tx_pg_sz - 1))) + if (!is_power_of_2(m.rx_pg_sz) || + !is_power_of_2(m.tx_pg_sz)) return -EINVAL; /* not power of 2 */ if (!(m.rx_pg_sz & 0x14000)) return -EINVAL; /* not 16KB or 64KB */ @@ -1923,10 +2021,10 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { - int ret, mmd; - struct adapter *adapter = dev->priv; - struct port_info *pi = netdev_priv(dev); struct mii_ioctl_data *data = if_mii(req); + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; + int ret, mmd; switch (cmd) { case SIOCGMIIPHY: @@ -1994,9 +2092,9 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) static int cxgb_change_mtu(struct net_device *dev, int new_mtu) { - int ret; - struct adapter *adapter = dev->priv; struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; + int ret; if (new_mtu < 81) /* accommodate SACK */ return -EINVAL; @@ -2013,8 +2111,8 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu) static int cxgb_set_mac_addr(struct net_device *dev, void *p) { - struct adapter *adapter = dev->priv; struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) @@ -2050,8 +2148,8 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p) static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct adapter *adapter = dev->priv; struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; pi->vlan_grp = grp; if (adapter->params.rev > 0) @@ -2070,8 +2168,8 @@ static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp) #ifdef CONFIG_NET_POLL_CONTROLLER static void cxgb_netpoll(struct net_device *dev) { - struct adapter *adapter = dev->priv; struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int qidx; for (qidx = pi->first_qset; qidx < pi->first_qset + pi->nqsets; qidx++) { @@ -2397,6 +2495,7 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->port[i] = netdev; pi = netdev_priv(netdev); + pi->adapter = adapter; pi->rx_csum_offload = 1; pi->nqsets = 1; pi->first_qset = i; @@ -2406,7 +2505,6 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->irq = pdev->irq; netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len - 1; - netdev->priv = adapter; netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; netdev->features |= NETIF_F_LLTX; if (pci_using_dac) @@ -2431,12 +2529,12 @@ static int __devinit init_one(struct pci_dev *pdev, SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops); } - pci_set_drvdata(pdev, adapter->port[0]); + pci_set_drvdata(pdev, adapter); if (t3_prep_adapter(adapter, ai, 1) < 0) { err = -ENODEV; goto out_free_dev; } - + /* * The card is now ready to go. If any errors occur during device * registration we do not fail the whole card but rather proceed only @@ -2504,11 +2602,10 @@ out_release_regions: static void __devexit remove_one(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); + struct adapter *adapter = pci_get_drvdata(pdev); - if (dev) { + if (adapter) { int i; - struct adapter *adapter = dev->priv; t3_sge_stop(adapter); sysfs_remove_group(&adapter->port[0]->dev.kobj, diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index ebcf35e4cf5b..bdff7baeb59d 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -593,6 +593,16 @@ int cxgb3_alloc_stid(struct t3cdev *tdev, struct cxgb3_client *client, EXPORT_SYMBOL(cxgb3_alloc_stid); +/* Get the t3cdev associated with a net_device */ +struct t3cdev *dev2t3cdev(struct net_device *dev) +{ + const struct port_info *pi = netdev_priv(dev); + + return (struct t3cdev *)pi->adapter; +} + +EXPORT_SYMBOL(dev2t3cdev); + static int do_smt_write_rpl(struct t3cdev *dev, struct sk_buff *skb) { struct cpl_smt_write_rpl *rpl = cplhdr(skb); @@ -699,7 +709,7 @@ static int do_cr(struct t3cdev *dev, struct sk_buff *skb) * the buffer. */ static struct sk_buff *cxgb3_get_cpl_reply_skb(struct sk_buff *skb, size_t len, - int gfp) + gfp_t gfp) { if (likely(!skb_cloned(skb))) { BUG_ON(skb->len < len); @@ -925,7 +935,7 @@ void cxgb_neigh_update(struct neighbour *neigh) struct net_device *dev = neigh->dev; if (dev && (is_offloading(dev))) { - struct t3cdev *tdev = T3CDEV(dev); + struct t3cdev *tdev = dev2t3cdev(dev); BUG_ON(!tdev); t3_l2t_update(tdev, neigh); @@ -973,9 +983,9 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) "device ignored.\n", __FUNCTION__); return; } - tdev = T3CDEV(olddev); + tdev = dev2t3cdev(olddev); BUG_ON(!tdev); - if (tdev != T3CDEV(newdev)) { + if (tdev != dev2t3cdev(newdev)) { printk(KERN_WARNING "%s: Redirect to different " "offload device ignored.\n", __FUNCTION__); return; diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h index f15446a32efc..7a379138b5a6 100644 --- a/drivers/net/cxgb3/cxgb3_offload.h +++ b/drivers/net/cxgb3/cxgb3_offload.h @@ -51,6 +51,8 @@ void cxgb3_offload_deactivate(struct adapter *adapter); void cxgb3_set_dummy_ops(struct t3cdev *dev); +struct t3cdev *dev2t3cdev(struct net_device *dev); + /* * Client registration. Users of T3 driver must register themselves. * The T3 driver will call the add function of every client for each T3 diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index 020859c855d7..aa80313c922e 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -1160,6 +1160,8 @@ #define A_TP_MOD_CHANNEL_WEIGHT 0x434 +#define A_TP_MOD_RATE_LIMIT 0x438 + #define A_TP_PIO_ADDR 0x440 #define A_TP_PIO_DATA 0x444 @@ -1214,6 +1216,15 @@ #define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \ M_TXDROPCNTCH0RCVD) +#define A_TP_PROXY_FLOW_CNTL 0x4b0 + +#define A_TP_EMBED_OP_FIELD0 0x4e8 +#define A_TP_EMBED_OP_FIELD1 0x4ec +#define A_TP_EMBED_OP_FIELD2 0x4f0 +#define A_TP_EMBED_OP_FIELD3 0x4f4 +#define A_TP_EMBED_OP_FIELD4 0x4f8 +#define A_TP_EMBED_OP_FIELD5 0x4fc + #define A_ULPRX_CTL 0x500 #define S_ROUND_ROBIN 4 diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index a60ec4d4707c..58a5f60521ed 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -46,23 +46,16 @@ #define SGE_RX_SM_BUF_SIZE 1536 -/* - * If USE_RX_PAGE is defined, the small freelist populated with (partial) - * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must - * be a multiple of the host page size). - */ -#define USE_RX_PAGE -#define RX_PAGE_SIZE 2048 - -/* - * skb freelist packets are copied into a new skb (and the freelist one is - * reused) if their len is <= - */ #define SGE_RX_COPY_THRES 256 +#define SGE_RX_PULL_LEN 128 /* - * Minimum number of freelist entries before we start dropping TUNNEL frames. + * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks. + * It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs + * directly. */ +#define FL0_PG_CHUNK_SIZE 2048 + #define SGE_RX_DROP_THRES 16 /* @@ -100,12 +93,12 @@ struct tx_sw_desc { /* SW state per Tx descriptor */ struct sk_buff *skb; }; -struct rx_sw_desc { /* SW state per Rx descriptor */ +struct rx_sw_desc { /* SW state per Rx descriptor */ union { struct sk_buff *skb; - struct sge_fl_page page; - } t; - DECLARE_PCI_UNMAP_ADDR(dma_addr); + struct fl_pg_chunk pg_chunk; + }; + DECLARE_PCI_UNMAP_ADDR(dma_addr); }; struct rsp_desc { /* response queue descriptor */ @@ -351,27 +344,26 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), q->buf_size, PCI_DMA_FROMDEVICE); - - if (q->buf_size != RX_PAGE_SIZE) { - kfree_skb(d->t.skb); - d->t.skb = NULL; + if (q->use_pages) { + put_page(d->pg_chunk.page); + d->pg_chunk.page = NULL; } else { - if (d->t.page.frag.page) - put_page(d->t.page.frag.page); - d->t.page.frag.page = NULL; + kfree_skb(d->skb); + d->skb = NULL; } if (++cidx == q->size) cidx = 0; } - if (q->page.frag.page) - put_page(q->page.frag.page); - q->page.frag.page = NULL; + if (q->pg_chunk.page) { + __free_page(q->pg_chunk.page); + q->pg_chunk.page = NULL; + } } /** * add_one_rx_buf - add a packet buffer to a free-buffer list - * @va: va of the buffer to add + * @va: buffer start VA * @len: the buffer length * @d: the HW Rx descriptor to write * @sd: the SW Rx descriptor to write @@ -381,7 +373,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) * Add a buffer of the given length to the supplied HW and SW Rx * descriptors. */ -static inline void add_one_rx_buf(unsigned char *va, unsigned int len, +static inline void add_one_rx_buf(void *va, unsigned int len, struct rx_desc *d, struct rx_sw_desc *sd, unsigned int gen, struct pci_dev *pdev) { @@ -397,6 +389,27 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len, d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); } +static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) +{ + if (!q->pg_chunk.page) { + q->pg_chunk.page = alloc_page(gfp); + if (unlikely(!q->pg_chunk.page)) + return -ENOMEM; + q->pg_chunk.va = page_address(q->pg_chunk.page); + q->pg_chunk.offset = 0; + } + sd->pg_chunk = q->pg_chunk; + + q->pg_chunk.offset += q->buf_size; + if (q->pg_chunk.offset == PAGE_SIZE) + q->pg_chunk.page = NULL; + else { + q->pg_chunk.va += q->buf_size; + get_page(q->pg_chunk.page); + } + return 0; +} + /** * refill_fl - refill an SGE free-buffer list * @adapter: the adapter @@ -410,49 +423,29 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len, */ static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) { + void *buf_start; struct rx_sw_desc *sd = &q->sdesc[q->pidx]; struct rx_desc *d = &q->desc[q->pidx]; - struct sge_fl_page *p = &q->page; while (n--) { - unsigned char *va; - - if (unlikely(q->buf_size != RX_PAGE_SIZE)) { - struct sk_buff *skb = alloc_skb(q->buf_size, gfp); - - if (!skb) { - q->alloc_failed++; + if (q->use_pages) { + if (unlikely(alloc_pg_chunk(q, sd, gfp))) { +nomem: q->alloc_failed++; break; } - va = skb->data; - sd->t.skb = skb; + buf_start = sd->pg_chunk.va; } else { - if (!p->frag.page) { - p->frag.page = alloc_pages(gfp, 0); - if (unlikely(!p->frag.page)) { - q->alloc_failed++; - break; - } else { - p->frag.size = RX_PAGE_SIZE; - p->frag.page_offset = 0; - p->va = page_address(p->frag.page); - } - } + struct sk_buff *skb = alloc_skb(q->buf_size, gfp); - memcpy(&sd->t, p, sizeof(*p)); - va = p->va; + if (!skb) + goto nomem; - p->frag.page_offset += RX_PAGE_SIZE; - BUG_ON(p->frag.page_offset > PAGE_SIZE); - p->va += RX_PAGE_SIZE; - if (p->frag.page_offset == PAGE_SIZE) - p->frag.page = NULL; - else - get_page(p->frag.page); + sd->skb = skb; + buf_start = skb->data; } - add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev); - + add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, + adap->pdev); d++; sd++; if (++q->pidx == q->size) { @@ -487,7 +480,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q, struct rx_desc *from = &q->desc[idx]; struct rx_desc *to = &q->desc[q->pidx]; - memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc)); + q->sdesc[q->pidx] = q->sdesc[idx]; to->addr_lo = from->addr_lo; /* already big endian */ to->addr_hi = from->addr_hi; /* likewise */ wmb(); @@ -650,6 +643,132 @@ static inline unsigned int flits_to_desc(unsigned int n) } /** + * get_packet - return the next ingress packet buffer from a free list + * @adap: the adapter that received the packet + * @fl: the SGE free list holding the packet + * @len: the packet length including any SGE padding + * @drop_thres: # of remaining buffers before we start dropping packets + * + * Get the next packet from a free list and complete setup of the + * sk_buff. If the packet is small we make a copy and recycle the + * original buffer, otherwise we use the original buffer itself. If a + * positive drop threshold is supplied packets are dropped and their + * buffers recycled if (a) the number of remaining buffers is under the + * threshold and the packet is too big to copy, or (b) the packet should + * be copied but there is no memory for the copy. + */ +static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl, + unsigned int len, unsigned int drop_thres) +{ + struct sk_buff *skb = NULL; + struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; + + prefetch(sd->skb->data); + fl->credits--; + + if (len <= SGE_RX_COPY_THRES) { + skb = alloc_skb(len, GFP_ATOMIC); + if (likely(skb != NULL)) { + __skb_put(skb, len); + pci_dma_sync_single_for_cpu(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + memcpy(skb->data, sd->skb->data, len); + pci_dma_sync_single_for_device(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + } else if (!drop_thres) + goto use_orig_buf; +recycle: + recycle_rx_buf(adap, fl, fl->cidx); + return skb; + } + + if (unlikely(fl->credits < drop_thres)) + goto recycle; + +use_orig_buf: + pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), + fl->buf_size, PCI_DMA_FROMDEVICE); + skb = sd->skb; + skb_put(skb, len); + __refill_fl(adap, fl); + return skb; +} + +/** + * get_packet_pg - return the next ingress packet buffer from a free list + * @adap: the adapter that received the packet + * @fl: the SGE free list holding the packet + * @len: the packet length including any SGE padding + * @drop_thres: # of remaining buffers before we start dropping packets + * + * Get the next packet from a free list populated with page chunks. + * If the packet is small we make a copy and recycle the original buffer, + * otherwise we attach the original buffer as a page fragment to a fresh + * sk_buff. If a positive drop threshold is supplied packets are dropped + * and their buffers recycled if (a) the number of remaining buffers is + * under the threshold and the packet is too big to copy, or (b) there's + * no system memory. + * + * Note: this function is similar to @get_packet but deals with Rx buffers + * that are page chunks rather than sk_buffs. + */ +static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, + unsigned int len, unsigned int drop_thres) +{ + struct sk_buff *skb = NULL; + struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; + + if (len <= SGE_RX_COPY_THRES) { + skb = alloc_skb(len, GFP_ATOMIC); + if (likely(skb != NULL)) { + __skb_put(skb, len); + pci_dma_sync_single_for_cpu(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + memcpy(skb->data, sd->pg_chunk.va, len); + pci_dma_sync_single_for_device(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + } else if (!drop_thres) + return NULL; +recycle: + fl->credits--; + recycle_rx_buf(adap, fl, fl->cidx); + return skb; + } + + if (unlikely(fl->credits <= drop_thres)) + goto recycle; + + skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); + if (unlikely(!skb)) { + if (!drop_thres) + return NULL; + goto recycle; + } + + pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), + fl->buf_size, PCI_DMA_FROMDEVICE); + __skb_put(skb, SGE_RX_PULL_LEN); + memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN); + skb_fill_page_desc(skb, 0, sd->pg_chunk.page, + sd->pg_chunk.offset + SGE_RX_PULL_LEN, + len - SGE_RX_PULL_LEN); + skb->len = len; + skb->data_len = len - SGE_RX_PULL_LEN; + skb->truesize += skb->data_len; + + fl->credits--; + /* + * We do not refill FLs here, we let the caller do it to overlap a + * prefetch. + */ + return skb; +} + +/** * get_imm_packet - return the next ingress packet buffer from a response * @resp: the response descriptor containing the packet data * @@ -954,7 +1073,7 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned int ndesc, pidx, credits, gen, compl; const struct port_info *pi = netdev_priv(dev); - struct adapter *adap = dev->priv; + struct adapter *adap = pi->adapter; struct sge_qset *qs = dev2qset(dev); struct sge_txq *q = &qs->txq[TXQ_ETH]; @@ -1207,7 +1326,8 @@ static void restart_ctrlq(unsigned long data) struct sk_buff *skb; struct sge_qset *qs = (struct sge_qset *)data; struct sge_txq *q = &qs->txq[TXQ_CTRL]; - struct adapter *adap = qs->netdev->priv; + const struct port_info *pi = netdev_priv(qs->netdev); + struct adapter *adap = pi->adapter; spin_lock(&q->lock); again:reclaim_completed_tx_imm(q); @@ -1412,7 +1532,8 @@ static void restart_offloadq(unsigned long data) struct sk_buff *skb; struct sge_qset *qs = (struct sge_qset *)data; struct sge_txq *q = &qs->txq[TXQ_OFLD]; - struct adapter *adap = qs->netdev->priv; + const struct port_info *pi = netdev_priv(qs->netdev); + struct adapter *adap = pi->adapter; spin_lock(&q->lock); again:reclaim_completed_tx(adap, q); @@ -1556,7 +1677,8 @@ static inline void deliver_partial_bundle(struct t3cdev *tdev, */ static int ofld_poll(struct net_device *dev, int *budget) { - struct adapter *adapter = dev->priv; + const struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; struct sge_qset *qs = dev2qset(dev); struct sge_rspq *q = &qs->rspq; int work_done, limit = min(*budget, dev->quota), avail = limit; @@ -1715,85 +1837,6 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, netif_rx(skb); } -#define SKB_DATA_SIZE 128 - -static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p, - unsigned int len) -{ - skb->len = len; - if (len <= SKB_DATA_SIZE) { - skb_copy_to_linear_data(skb, p->va, len); - skb->tail += len; - put_page(p->frag.page); - } else { - skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE); - skb_shinfo(skb)->frags[0].page = p->frag.page; - skb_shinfo(skb)->frags[0].page_offset = - p->frag.page_offset + SKB_DATA_SIZE; - skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE; - skb_shinfo(skb)->nr_frags = 1; - skb->data_len = len - SKB_DATA_SIZE; - skb->tail += SKB_DATA_SIZE; - skb->truesize += skb->data_len; - } -} - -/** -* get_packet - return the next ingress packet buffer from a free list -* @adap: the adapter that received the packet -* @fl: the SGE free list holding the packet -* @len: the packet length including any SGE padding -* @drop_thres: # of remaining buffers before we start dropping packets -* -* Get the next packet from a free list and complete setup of the -* sk_buff. If the packet is small we make a copy and recycle the -* original buffer, otherwise we use the original buffer itself. If a -* positive drop threshold is supplied packets are dropped and their -* buffers recycled if (a) the number of remaining buffers is under the -* threshold and the packet is too big to copy, or (b) the packet should -* be copied but there is no memory for the copy. -*/ -static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl, - unsigned int len, unsigned int drop_thres) -{ - struct sk_buff *skb = NULL; - struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; - - prefetch(sd->t.skb->data); - - if (len <= SGE_RX_COPY_THRES) { - skb = alloc_skb(len, GFP_ATOMIC); - if (likely(skb != NULL)) { - struct rx_desc *d = &fl->desc[fl->cidx]; - dma_addr_t mapping = - (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 | - be32_to_cpu(d->addr_lo)); - - __skb_put(skb, len); - pci_dma_sync_single_for_cpu(adap->pdev, mapping, len, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(sd->t.skb, skb->data, len); - pci_dma_sync_single_for_device(adap->pdev, mapping, len, - PCI_DMA_FROMDEVICE); - } else if (!drop_thres) - goto use_orig_buf; -recycle: - recycle_rx_buf(adap, fl, fl->cidx); - return skb; - } - - if (unlikely(fl->credits < drop_thres)) - goto recycle; - -use_orig_buf: - pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), - fl->buf_size, PCI_DMA_FROMDEVICE); - skb = sd->t.skb; - skb_put(skb, len); - __refill_fl(adap, fl); - return skb; -} - /** * handle_rsp_cntrl_info - handles control information in a response * @qs: the queue set corresponding to the response @@ -1935,7 +1978,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, } else if (flags & F_RSPD_IMM_DATA_VALID) { skb = get_imm_packet(r); if (unlikely(!skb)) { - no_mem: +no_mem: q->next_holdoff = NOMEM_INTR_DELAY; q->nomem++; /* consume one credit since we tried */ @@ -1945,53 +1988,29 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, q->imm_data++; ethpad = 0; } else if ((len = ntohl(r->len_cq)) != 0) { - struct sge_fl *fl = - (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; - - if (fl->buf_size == RX_PAGE_SIZE) { - struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; - struct sge_fl_page *p = &sd->t.page; + struct sge_fl *fl; - prefetch(p->va); - prefetch(p->va + L1_CACHE_BYTES); + fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; + if (fl->use_pages) { + void *addr = fl->sdesc[fl->cidx].pg_chunk.va; + prefetch(addr); +#if L1_CACHE_BYTES < 128 + prefetch(addr + L1_CACHE_BYTES); +#endif __refill_fl(adap, fl); - pci_unmap_single(adap->pdev, - pci_unmap_addr(sd, dma_addr), - fl->buf_size, - PCI_DMA_FROMDEVICE); - - if (eth) { - if (unlikely(fl->credits < - SGE_RX_DROP_THRES)) - goto eth_recycle; - - skb = alloc_skb(SKB_DATA_SIZE, - GFP_ATOMIC); - if (unlikely(!skb)) { -eth_recycle: - q->rx_drops++; - recycle_rx_buf(adap, fl, - fl->cidx); - goto eth_done; - } - } else { - skb = alloc_skb(SKB_DATA_SIZE, - GFP_ATOMIC); - if (unlikely(!skb)) - goto no_mem; - } - - skb_data_init(skb, p, G_RSPD_LEN(len)); -eth_done: - fl->credits--; - q->eth_pkts++; - } else { - fl->credits--; + skb = get_packet_pg(adap, fl, G_RSPD_LEN(len), + eth ? SGE_RX_DROP_THRES : 0); + } else skb = get_packet(adap, fl, G_RSPD_LEN(len), eth ? SGE_RX_DROP_THRES : 0); - } + if (unlikely(!skb)) { + if (!eth) + goto no_mem; + q->rx_drops++; + } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT)) + __skb_pull(skb, 2); if (++fl->cidx == fl->size) fl->cidx = 0; @@ -2016,20 +2035,15 @@ eth_done: q->credits = 0; } - if (skb) { - /* Preserve the RSS info in csum & priority */ - skb->csum = rss_hi; - skb->priority = rss_lo; - + if (likely(skb != NULL)) { if (eth) rx_eth(adap, q, skb, ethpad); else { - if (unlikely(r->rss_hdr.opcode == - CPL_TRACE_PKT)) - __skb_pull(skb, ethpad); - - ngathered = rx_offload(&adap->tdev, q, - skb, offload_skbs, + /* Preserve the RSS info in csum & priority */ + skb->csum = rss_hi; + skb->priority = rss_lo; + ngathered = rx_offload(&adap->tdev, q, skb, + offload_skbs, ngathered); } } @@ -2064,7 +2078,8 @@ static inline int is_pure_response(const struct rsp_desc *r) */ static int napi_rx_handler(struct net_device *dev, int *budget) { - struct adapter *adap = dev->priv; + const struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; struct sge_qset *qs = dev2qset(dev); int effective_budget = min(*budget, dev->quota); @@ -2194,7 +2209,8 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q) irqreturn_t t3_sge_intr_msix(int irq, void *cookie) { struct sge_qset *qs = cookie; - struct adapter *adap = qs->netdev->priv; + const struct port_info *pi = netdev_priv(qs->netdev); + struct adapter *adap = pi->adapter; struct sge_rspq *q = &qs->rspq; spin_lock(&q->lock); @@ -2213,7 +2229,8 @@ irqreturn_t t3_sge_intr_msix(int irq, void *cookie) irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie) { struct sge_qset *qs = cookie; - struct adapter *adap = qs->netdev->priv; + const struct port_info *pi = netdev_priv(qs->netdev); + struct adapter *adap = pi->adapter; struct sge_rspq *q = &qs->rspq; spin_lock(&q->lock); @@ -2497,7 +2514,8 @@ static void sge_timer_cb(unsigned long data) { spinlock_t *lock; struct sge_qset *qs = (struct sge_qset *)data; - struct adapter *adap = qs->netdev->priv; + const struct port_info *pi = netdev_priv(qs->netdev); + struct adapter *adap = pi->adapter; if (spin_trylock(&qs->txq[TXQ_ETH].lock)) { reclaim_completed_tx(adap, &qs->txq[TXQ_ETH]); @@ -2635,25 +2653,15 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->txq[TXQ_ETH].stop_thres = nports * flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); - if (!is_offload(adapter)) { -#ifdef USE_RX_PAGE - q->fl[0].buf_size = RX_PAGE_SIZE; +#if FL0_PG_CHUNK_SIZE > 0 + q->fl[0].buf_size = FL0_PG_CHUNK_SIZE; #else - q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 + - sizeof(struct cpl_rx_pkt); + q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data); #endif - q->fl[1].buf_size = MAX_FRAME_SIZE + 2 + - sizeof(struct cpl_rx_pkt); - } else { -#ifdef USE_RX_PAGE - q->fl[0].buf_size = RX_PAGE_SIZE; -#else - q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + - sizeof(struct cpl_rx_data); -#endif - q->fl[1].buf_size = (16 * 1024) - - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - } + q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0; + q->fl[1].buf_size = is_offload(adapter) ? + (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : + MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt); spin_lock(&adapter->sge.reg_lock); diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index fb485d0a43d8..b02d15daf5d9 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -847,6 +847,98 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr, return 0; } +/** + * t3_get_tp_version - read the tp sram version + * @adapter: the adapter + * @vers: where to place the version + * + * Reads the protocol sram version from sram. + */ +int t3_get_tp_version(struct adapter *adapter, u32 *vers) +{ + int ret; + + /* Get version loaded in SRAM */ + t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0); + ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0, + 1, 1, 5, 1); + if (ret) + return ret; + + *vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1); + + return 0; +} + +/** + * t3_check_tpsram_version - read the tp sram version + * @adapter: the adapter + * @must_load: set to 1 if loading a new microcode image is required + * + * Reads the protocol sram version from flash. + */ +int t3_check_tpsram_version(struct adapter *adapter, int *must_load) +{ + int ret; + u32 vers; + unsigned int major, minor; + + if (adapter->params.rev == T3_REV_A) + return 0; + + *must_load = 1; + + ret = t3_get_tp_version(adapter, &vers); + if (ret) + return ret; + + major = G_TP_VERSION_MAJOR(vers); + minor = G_TP_VERSION_MINOR(vers); + + if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR) + return 0; + + if (major != TP_VERSION_MAJOR) + CH_ERR(adapter, "found wrong TP version (%u.%u), " + "driver needs version %d.%d\n", major, minor, + TP_VERSION_MAJOR, TP_VERSION_MINOR); + else { + *must_load = 0; + CH_ERR(adapter, "found wrong TP version (%u.%u), " + "driver compiled for version %d.%d\n", major, minor, + TP_VERSION_MAJOR, TP_VERSION_MINOR); + } + return -EINVAL; +} + +/** + * t3_check_tpsram - check if provided protocol SRAM + * is compatible with this driver + * @adapter: the adapter + * @tp_sram: the firmware image to write + * @size: image size + * + * Checks if an adapter's tp sram is compatible with the driver. + * Returns 0 if the versions are compatible, a negative error otherwise. + */ +int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size) +{ + u32 csum; + unsigned int i; + const u32 *p = (const u32 *)tp_sram; + + /* Verify checksum */ + for (csum = 0, i = 0; i < size / sizeof(csum); i++) + csum += ntohl(p[i]); + if (csum != 0xffffffff) { + CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n", + csum); + return -EINVAL; + } + + return 0; +} + enum fw_version_type { FW_VERSION_N3, FW_VERSION_T3 @@ -921,7 +1013,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end) /* * t3_load_fw - download firmware * @adapter: the adapter - * @fw_data: the firrware image to write + * @fw_data: the firmware image to write * @size: image size * * Write the supplied firmware image to the card's serial flash. @@ -2362,7 +2454,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p) F_TCPCHECKSUMOFFLOAD | V_IPTTL(64)); t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) | F_MTUENABLE | V_WINDOWSCALEMODE(1) | - V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1)); + V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1)); t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) | V_AUTOSTATE2(1) | V_AUTOSTATE1(0) | V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) | @@ -2371,16 +2463,18 @@ static void tp_config(struct adapter *adap, const struct tp_params *p) F_IPV6ENABLE | F_NICMODE); t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814); t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105); - t3_set_reg_field(adap, A_TP_PARA_REG6, - adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND, - 0); + t3_set_reg_field(adap, A_TP_PARA_REG6, 0, + adap->params.rev > 0 ? F_ENABLEESND : + F_T3A_ENABLEESND); t3_set_reg_field(adap, A_TP_PC_CONFIG, - F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL, - F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE | - F_RXCONGESTIONMODE); + F_ENABLEEPCMDAFULL, + F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK | + F_TXCONGESTIONMODE | F_RXCONGESTIONMODE); t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0); - + t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080); + t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000); + if (adap->params.rev > 0) { tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE); t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO, @@ -2390,9 +2484,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p) } else t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED); - t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212); - t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212); - t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212); + t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0); + t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0); + t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0); + t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000); } /* Desired TP timer resolution in usec */ @@ -2468,6 +2563,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh) val |= F_RXCOALESCEENABLE; if (psh) val |= F_RXCOALESCEPSHEN; + size = min(MAX_RX_COALESCING_LEN, size); t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) | V_MAXRXDATA(MAX_RX_COALESCING_LEN)); } @@ -2496,11 +2592,11 @@ static void __devinit init_mtus(unsigned short mtus[]) * it can accomodate max size TCP/IP headers when SACK and timestamps * are enabled and still have at least 8 bytes of payload. */ - mtus[0] = 88; - mtus[1] = 256; - mtus[2] = 512; - mtus[3] = 576; - mtus[4] = 808; + mtus[1] = 88; + mtus[1] = 88; + mtus[2] = 256; + mtus[3] = 512; + mtus[4] = 576; mtus[5] = 1024; mtus[6] = 1280; mtus[7] = 1492; @@ -2682,6 +2778,34 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p) t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff); } +/** + * t3_set_proto_sram - set the contents of the protocol sram + * @adapter: the adapter + * @data: the protocol image + * + * Write the contents of the protocol SRAM. + */ +int t3_set_proto_sram(struct adapter *adap, u8 *data) +{ + int i; + u32 *buf = (u32 *)data; + + for (i = 0; i < PROTO_SRAM_LINES; i++) { + t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++)); + + t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31); + if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1)) + return -EIO; + } + t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0); + + return 0; +} + void t3_config_trace_filter(struct adapter *adapter, const struct trace_params *tp, int filter_index, int invert, int enable) @@ -2802,7 +2926,7 @@ static void init_hw_for_avail_ports(struct adapter *adap, int nports) t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0); t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN | F_PORT0ACTIVE | F_ENFORCEPKT); - t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000); + t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff); } else { t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN); t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB); @@ -3097,7 +3221,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) else t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN); - t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000); + t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff); init_hw_for_avail_ports(adapter, adapter->params.nports); t3_sge_init(adapter, &adapter->params.sge); diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h index fa4099bc0416..77fcc1a4984e 100644 --- a/drivers/net/cxgb3/t3cdev.h +++ b/drivers/net/cxgb3/t3cdev.h @@ -42,9 +42,6 @@ #define T3CNAMSIZ 16 -/* Get the t3cdev associated with a net_device */ -#define T3CDEV(netdev) (struct t3cdev *)(netdev->priv) - struct cxgb3_client; enum t3ctype { diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index b112317f033e..eb508bf8022a 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -39,6 +39,6 @@ /* Firmware version */ #define FW_VERSION_MAJOR 4 -#define FW_VERSION_MINOR 0 +#define FW_VERSION_MINOR 3 #define FW_VERSION_MICRO 0 #endif /* __CHELSIO_VERSION_H */ diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 7df23dc28190..9c8e3f9f5e58 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -200,6 +200,7 @@ /* Include files */ #include <linux/bitops.h> +#include <linux/compiler.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/eisa.h> @@ -240,8 +241,6 @@ static char version[] __devinitdata = */ #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128) -#define __unused __attribute__ ((unused)) - #ifdef CONFIG_PCI #define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type) #else @@ -375,7 +374,7 @@ static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data) static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data) { - struct device __unused *bdev = bp->bus_dev; + struct device __maybe_unused *bdev = bp->bus_dev; int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; @@ -399,7 +398,7 @@ static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data) static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data) { - struct device __unused *bdev = bp->bus_dev; + struct device __maybe_unused *bdev = bp->bus_dev; int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; @@ -866,7 +865,7 @@ static void __devinit dfx_bus_uninit(struct net_device *dev) static void __devinit dfx_bus_config_check(DFX_board_t *bp) { - struct device __unused *bdev = bp->bus_dev; + struct device __maybe_unused *bdev = bp->bus_dev; int dfx_bus_eisa = DFX_BUS_EISA(bdev); int status; /* return code from adapter port control call */ u32 host_data; /* LW data returned from port control call */ @@ -3624,8 +3623,8 @@ static void __devexit dfx_unregister(struct device *bdev) } -static int __devinit __unused dfx_dev_register(struct device *); -static int __devexit __unused dfx_dev_unregister(struct device *); +static int __devinit __maybe_unused dfx_dev_register(struct device *); +static int __devexit __maybe_unused dfx_dev_unregister(struct device *); #ifdef CONFIG_PCI static int __devinit dfx_pci_register(struct pci_dev *, @@ -3699,7 +3698,7 @@ static struct tc_driver dfx_tc_driver = { }; #endif /* CONFIG_TC */ -static int __devinit __unused dfx_dev_register(struct device *dev) +static int __devinit __maybe_unused dfx_dev_register(struct device *dev) { int status; @@ -3709,7 +3708,7 @@ static int __devinit __unused dfx_dev_register(struct device *dev) return status; } -static int __devexit __unused dfx_dev_unregister(struct device *dev) +static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev) { put_device(dev); dfx_unregister(dev); diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 74ec64a1625d..04e3710c9082 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -250,7 +250,6 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) np->an_enable = 1; mii_set_media (dev); } - pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id); err = register_netdev (dev); if (err) @@ -866,9 +865,9 @@ receive_packet (struct net_device *dev) PCI_DMA_FROMDEVICE); /* 16 byte align the IP header */ skb_reserve (skb, 2); - eth_copy_and_sum (skb, + skb_copy_to_linear_data (skb, np->rx_skbuff[entry]->data, - pkt_len, 0); + pkt_len); skb_put (skb, pkt_len); pci_dma_sync_single_for_device(np->pdev, desc->fraginfo & @@ -879,7 +878,7 @@ receive_packet (struct net_device *dev) skb->protocol = eth_type_trans (skb, dev); #if 0 /* Checksum done by hw, but csum value unavailable. */ - if (np->pci_rev_id >= 0x0c && + if (np->pdev->pci_rev_id >= 0x0c && !(frame_status & (TCPError | UDPError | IPError))) { skb->ip_summed = CHECKSUM_UNNECESSARY; } diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h index 814c449c359f..e443065a452e 100644 --- a/drivers/net/dl2k.h +++ b/drivers/net/dl2k.h @@ -668,7 +668,6 @@ struct netdev_private { unsigned int rx_flow:1; /* Rx flow control enable */ unsigned int phy_media:1; /* 1: fiber, 0: copper */ unsigned int link_status:1; /* Current link status */ - unsigned char pci_rev_id; /* PCI revision ID */ struct netdev_desc *last_tx; /* Last Tx descriptor used. */ unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */ unsigned long cur_tx, old_tx; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 264fa0e2e075..738aa5906514 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -104,6 +104,18 @@ #define PRINTK(args...) printk(KERN_DEBUG args) #endif +#ifdef CONFIG_BLACKFIN +#define readsb insb +#define readsw insw +#define readsl insl +#define writesb outsb +#define writesw outsw +#define writesl outsl +#define DM9000_IRQ_FLAGS (IRQF_SHARED | IRQF_TRIGGER_HIGH) +#else +#define DM9000_IRQ_FLAGS IRQF_SHARED +#endif + /* * Transmit timeout, default 5 seconds. */ @@ -431,6 +443,9 @@ dm9000_probe(struct platform_device *pdev) db->io_addr = (void __iomem *)base; db->io_data = (void __iomem *)(base + 4); + /* ensure at least we have a default set of IO routines */ + dm9000_set_io(db, 2); + } else { db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -614,7 +629,7 @@ dm9000_open(struct net_device *dev) PRINTK2("entering dm9000_open\n"); - if (request_irq(dev->irq, &dm9000_interrupt, IRQF_SHARED, dev->name, dev)) + if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev)) return -EAGAIN; /* Initialize DM9000 board */ @@ -685,6 +700,7 @@ dm9000_init_dm9000(struct net_device *dev) static int dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) { + unsigned long flags; board_info_t *db = (board_info_t *) dev->priv; PRINTK3("dm9000_start_xmit\n"); @@ -692,10 +708,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) if (db->tx_pkt_cnt > 1) return 1; - netif_stop_queue(dev); - - /* Disable all interrupts */ - iow(db, DM9000_IMR, IMR_PAR); + spin_lock_irqsave(&db->lock, flags); /* Move data to DM9000 TX RAM */ writeb(DM9000_MWCMD, db->io_addr); @@ -703,12 +716,9 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) (db->outblk)(db->io_data, skb->data, skb->len); db->stats.tx_bytes += skb->len; + db->tx_pkt_cnt++; /* TX control: First packet immediately send, second packet queue */ - if (db->tx_pkt_cnt == 0) { - - /* First Packet */ - db->tx_pkt_cnt++; - + if (db->tx_pkt_cnt == 1) { /* Set TX length to DM9000 */ iow(db, DM9000_TXPLL, skb->len & 0xff); iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff); @@ -717,23 +727,17 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ dev->trans_start = jiffies; /* save the time stamp */ - } else { /* Second packet */ - db->tx_pkt_cnt++; db->queue_pkt_len = skb->len; + netif_stop_queue(dev); } + spin_unlock_irqrestore(&db->lock, flags); + /* free this SKB */ dev_kfree_skb(skb); - /* Re-enable resource check */ - if (db->tx_pkt_cnt == 1) - netif_wake_queue(dev); - - /* Re-enable interrupt */ - iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); - return 0; } diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 60673bc292c0..756a6bcb038d 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -34,11 +34,12 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/moduleparam.h> +#include <linux/rtnetlink.h> +#include <net/rtnetlink.h> static int numdummies = 1; static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); -static struct net_device_stats *dummy_get_stats(struct net_device *dev); static int dummy_set_address(struct net_device *dev, void *p) { @@ -56,13 +57,13 @@ static void set_multicast_list(struct net_device *dev) { } -static void __init dummy_setup(struct net_device *dev) +static void dummy_setup(struct net_device *dev) { /* Initialize the device structure. */ - dev->get_stats = dummy_get_stats; dev->hard_start_xmit = dummy_xmit; dev->set_multicast_list = set_multicast_list; dev->set_mac_address = dummy_set_address; + dev->destructor = free_netdev; /* Fill in device structure with ethernet-generic values. */ ether_setup(dev); @@ -76,77 +77,80 @@ static void __init dummy_setup(struct net_device *dev) static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = netdev_priv(dev); - - stats->tx_packets++; - stats->tx_bytes+=skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev_kfree_skb(skb); return 0; } -static struct net_device_stats *dummy_get_stats(struct net_device *dev) +static int dummy_validate(struct nlattr *tb[], struct nlattr *data[]) { - return netdev_priv(dev); + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + return 0; } -static struct net_device **dummies; +static struct rtnl_link_ops dummy_link_ops __read_mostly = { + .kind = "dummy", + .setup = dummy_setup, + .validate = dummy_validate, +}; /* Number of dummy devices to be set up by this module. */ module_param(numdummies, int, 0); MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); -static int __init dummy_init_one(int index) +static int __init dummy_init_one(void) { struct net_device *dev_dummy; int err; - dev_dummy = alloc_netdev(sizeof(struct net_device_stats), - "dummy%d", dummy_setup); - + dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup); if (!dev_dummy) return -ENOMEM; - if ((err = register_netdev(dev_dummy))) { - free_netdev(dev_dummy); - dev_dummy = NULL; - } else { - dummies[index] = dev_dummy; - } + err = dev_alloc_name(dev_dummy, dev_dummy->name); + if (err < 0) + goto err; - return err; -} + dev_dummy->rtnl_link_ops = &dummy_link_ops; + err = register_netdevice(dev_dummy); + if (err < 0) + goto err; + return 0; -static void dummy_free_one(int index) -{ - unregister_netdev(dummies[index]); - free_netdev(dummies[index]); +err: + free_netdev(dev_dummy); + return err; } static int __init dummy_init_module(void) { int i, err = 0; - dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL); - if (!dummies) - return -ENOMEM; + + rtnl_lock(); + err = __rtnl_link_register(&dummy_link_ops); + for (i = 0; i < numdummies && !err; i++) - err = dummy_init_one(i); - if (err) { - i--; - while (--i >= 0) - dummy_free_one(i); - } + err = dummy_init_one(); + if (err < 0) + __rtnl_link_unregister(&dummy_link_ops); + rtnl_unlock(); + return err; } static void __exit dummy_cleanup_module(void) { - int i; - for (i = 0; i < numdummies; i++) - dummy_free_one(i); - kfree(dummies); + rtnl_link_unregister(&dummy_link_ops); } module_init(dummy_init_module); module_exit(dummy_cleanup_module); MODULE_LICENSE("GPL"); +MODULE_ALIAS_RTNL_LINK("dummy"); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 763810c7f33a..280313b9b069 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -159,7 +159,7 @@ #define DRV_NAME "e100" #define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.17-k4"DRV_EXT +#define DRV_VERSION "3.5.23-k4"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" #define PFX DRV_NAME ": " @@ -583,7 +583,6 @@ struct nic { u32 rx_tco_frames; u32 rx_over_length_errors; - u8 rev_id; u16 leds; u16 eeprom_wc; u16 eeprom[256]; @@ -937,9 +936,8 @@ static void e100_get_defaults(struct nic *nic) struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id; + nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; if(nic->mac == mac_unknown) nic->mac = mac_82557_D100_A; @@ -1024,10 +1022,16 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) config->mwi_enable = 0x1; /* 1=enable, 0=disable */ config->standard_tcb = 0x0; /* 1=standard, 0=extended */ config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if(nic->mac >= mac_82559_D101M) + if (nic->mac >= mac_82559_D101M) { config->tno_intr = 0x1; /* TCO stats enable */ - else + /* Enable TCO in extended config */ + if (nic->mac >= mac_82551_10) { + config->byte_count = 0x20; /* extended bytes */ + config->rx_d102_mode = 0x1; /* GMRC for TCO */ + } + } else { config->standard_stat_counter = 0x0; + } } DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", @@ -1273,7 +1277,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb if (nic->flags & ich) goto noloaducode; - /* Search for ucode match against h/w rev_id */ + /* Search for ucode match against h/w revision */ for (opts = ucode_opts; opts->mac; opts++) { int i; u32 *ucode = opts->ucode; @@ -2232,7 +2236,7 @@ static void e100_get_regs(struct net_device *netdev, u32 *buff = p; int i; - regs->version = (1 << 24) | nic->rev_id; + regs->version = (1 << 24) | nic->pdev->revision; buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | ioread8(&nic->csr->scb.cmd_lo) << 16 | ioread16(&nic->csr->scb.status); @@ -2502,7 +2506,6 @@ static const struct ethtool_ops e100_ethtool_ops = { .phys_id = e100_phys_id, .get_stats_count = e100_get_stats_count, .get_ethtool_stats = e100_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index bb08375b5f13..9ecc3adcf6c1 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1706,6 +1706,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546GB_QUAD_COPPER: case E1000_DEV_ID_82546GB_PCIE: + case E1000_DEV_ID_82571EB_SERDES_QUAD: /* these don't support WoL at all */ wol->supported = 0; break; @@ -1723,7 +1724,9 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol retval = 0; break; case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_FIBER: case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: + case E1000_DEV_ID_82571PT_QUAD_COPPER: case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: /* quad port adapters only support WoL on port A */ if (!adapter->quad_port_a) { @@ -1973,7 +1976,6 @@ static const struct ethtool_ops e1000_ethtool_ops = { .phys_id = e1000_phys_id, .get_stats_count = e1000_get_stats_count, .get_ethtool_stats = e1000_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; void e1000_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 9be44699300b..8604adbe351c 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -384,7 +384,11 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82571EB_COPPER: case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82571EB_SERDES: + case E1000_DEV_ID_82571EB_SERDES_DUAL: + case E1000_DEV_ID_82571EB_SERDES_QUAD: case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571PT_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_FIBER: case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: hw->mac_type = e1000_82571; break; @@ -485,6 +489,8 @@ e1000_set_media_type(struct e1000_hw *hw) case E1000_DEV_ID_82545GM_SERDES: case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82571EB_SERDES: + case E1000_DEV_ID_82571EB_SERDES_DUAL: + case E1000_DEV_ID_82571EB_SERDES_QUAD: case E1000_DEV_ID_82572EI_SERDES: case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->media_type = e1000_media_type_internal_serdes; diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index bd000b802ee7..07f0ea73676e 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -475,7 +475,11 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); #define E1000_DEV_ID_82571EB_FIBER 0x105F #define E1000_DEV_ID_82571EB_SERDES 0x1060 #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 +#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 +#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 #define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC +#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 +#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index cf8af928a69c..e7c8951f47fa 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -100,6 +100,7 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x1099), INTEL_E1000_ETHERNET_DEVICE(0x109A), INTEL_E1000_ETHERNET_DEVICE(0x10A4), + INTEL_E1000_ETHERNET_DEVICE(0x10A5), INTEL_E1000_ETHERNET_DEVICE(0x10B5), INTEL_E1000_ETHERNET_DEVICE(0x10B9), INTEL_E1000_ETHERNET_DEVICE(0x10BA), @@ -107,6 +108,9 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x10BC), INTEL_E1000_ETHERNET_DEVICE(0x10C4), INTEL_E1000_ETHERNET_DEVICE(0x10C5), + INTEL_E1000_ETHERNET_DEVICE(0x10D5), + INTEL_E1000_ETHERNET_DEVICE(0x10D9), + INTEL_E1000_ETHERNET_DEVICE(0x10DA), /* required last entry */ {0,} }; @@ -1096,7 +1100,9 @@ e1000_probe(struct pci_dev *pdev, break; case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_FIBER: case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: + case E1000_DEV_ID_82571PT_QUAD_COPPER: /* if quad port adapter, disable WoL on all but port A */ if (global_quad_port_a != 0) adapter->eeprom_wol = 0; @@ -1266,8 +1272,7 @@ e1000_sw_init(struct e1000_adapter *adapter) hw->device_id = pdev->device; hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_id = pdev->subsystem_device; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + hw->revision_id = pdev->revision; pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 9800341956a2..3c54014acece 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -1801,7 +1801,7 @@ speedo_rx(struct net_device *dev) #if 1 || USE_IP_CSUM /* Packet is in one chunk -- we can copy + cksum. */ - eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); #else skb_copy_from_linear_data(sp->rx_skbuff[entry], @@ -2292,10 +2292,15 @@ static int eepro100_resume(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); struct speedo_private *sp = netdev_priv(dev); void __iomem *ioaddr = sp->regs; + int rc; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - pci_enable_device(pdev); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + pci_set_master(pdev); if (!netif_running(dev)) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index c0f81b5a30fb..8d58be56f4e3 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -39,7 +39,13 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0064" +#define DRV_VERSION "EHEA_0074" + +/* eHEA capability flags */ +#define DLPAR_PORT_ADD_REM 1 +#define DLPAR_MEM_ADD 2 +#define DLPAR_MEM_REM 4 +#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM) #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) @@ -107,6 +113,8 @@ /* Memory Regions */ #define EHEA_MR_ACC_CTRL 0x00800000 +#define EHEA_BUSMAP_START 0x8000000000000000ULL + #define EHEA_WATCH_DOG_TIMEOUT 10*HZ /* utility functions */ @@ -136,10 +144,10 @@ void ehea_dump(void *adr, int len, char *msg); (0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff)) #define EHEA_BMASK_SET(mask, value) \ - ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask)) + ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask)) #define EHEA_BMASK_GET(mask, value) \ - (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask))) + (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask))) /* * Generic ehea page @@ -180,6 +188,12 @@ struct h_epas { set to 0 if unused */ }; +struct ehea_busmap { + unsigned int entries; /* total number of entries */ + unsigned int valid_sections; /* number of valid sections */ + u64 *vaddr; +}; + struct ehea_qp; struct ehea_cq; struct ehea_eq; @@ -190,7 +204,7 @@ struct ehea_av; * Queue attributes passed to ehea_create_qp() */ struct ehea_qp_init_attr { - /* input parameter */ + /* input parameter */ u32 qp_token; /* queue token */ u8 low_lat_rq1; u8 signalingtype; /* cqe generation flag */ @@ -212,7 +226,7 @@ struct ehea_qp_init_attr { u64 recv_cq_handle; u64 aff_eq_handle; - /* output parameter */ + /* output parameter */ u32 qp_nr; u16 act_nr_send_wqes; u16 act_nr_rwqes_rq1; @@ -279,12 +293,12 @@ struct ehea_qp { * Completion Queue attributes */ struct ehea_cq_attr { - /* input parameter */ + /* input parameter */ u32 max_nr_of_cqes; u32 cq_token; u64 eq_handle; - /* output parameter */ + /* output parameter */ u32 act_nr_of_cqes; u32 nr_pages; }; @@ -376,6 +390,8 @@ struct ehea_adapter { struct ehea_mr mr; u32 pd; /* protection domain */ u64 max_mc_mac; /* max number of multicast mac addresses */ + int active_ports; + struct list_head list; }; @@ -386,6 +402,8 @@ struct ehea_mc_list { #define EHEA_PORT_UP 1 #define EHEA_PORT_DOWN 0 +#define EHEA_PHY_LINK_UP 1 +#define EHEA_PHY_LINK_DOWN 0 #define EHEA_MAX_PORT_RES 16 struct ehea_port { struct ehea_adapter *adapter; /* adapter that owns this port */ @@ -411,6 +429,7 @@ struct ehea_port { u32 msg_enable; u32 sig_comp_iv; u32 state; + u8 phy_link; u8 full_duplex; u8 autoneg; u8 num_def_qps; @@ -425,6 +444,9 @@ struct port_res_cfg { int max_entries_rq3; }; +enum ehea_flag_bits { + __EHEA_STOP_XFER +}; void ehea_set_ethtool_ops(struct net_device *netdev); int ehea_sense_port_attr(struct ehea_port *port); diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h index 1246757f2c22..1af7ca499ec5 100644 --- a/drivers/net/ehea/ehea_hw.h +++ b/drivers/net/ehea/ehea_hw.h @@ -211,34 +211,34 @@ static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value) } #define epa_store_eq(epa, offset, value)\ - epa_store(epa, EQTEMM_OFFSET(offset), value) + epa_store(epa, EQTEMM_OFFSET(offset), value) #define epa_load_eq(epa, offset)\ - epa_load(epa, EQTEMM_OFFSET(offset)) + epa_load(epa, EQTEMM_OFFSET(offset)) #define epa_store_cq(epa, offset, value)\ - epa_store(epa, CQTEMM_OFFSET(offset), value) + epa_store(epa, CQTEMM_OFFSET(offset), value) #define epa_load_cq(epa, offset)\ - epa_load(epa, CQTEMM_OFFSET(offset)) + epa_load(epa, CQTEMM_OFFSET(offset)) #define epa_store_qp(epa, offset, value)\ - epa_store(epa, QPTEMM_OFFSET(offset), value) + epa_store(epa, QPTEMM_OFFSET(offset), value) #define epa_load_qp(epa, offset)\ - epa_load(epa, QPTEMM_OFFSET(offset)) + epa_load(epa, QPTEMM_OFFSET(offset)) #define epa_store_qped(epa, offset, value)\ - epa_store(epa, QPEDMM_OFFSET(offset), value) + epa_store(epa, QPEDMM_OFFSET(offset), value) #define epa_load_qped(epa, offset)\ - epa_load(epa, QPEDMM_OFFSET(offset)) + epa_load(epa, QPEDMM_OFFSET(offset)) #define epa_store_mrmw(epa, offset, value)\ - epa_store(epa, MRMWMM_OFFSET(offset), value) + epa_store(epa, MRMWMM_OFFSET(offset), value) #define epa_load_mrmw(epa, offset)\ - epa_load(epa, MRMWMM_OFFSET(offset)) + epa_load(epa, MRMWMM_OFFSET(offset)) #define epa_store_base(epa, offset, value)\ - epa_store(epa, HCAGR_OFFSET(offset), value) + epa_store(epa, HCAGR_OFFSET(offset), value) #define epa_load_base(epa, offset)\ - epa_load(epa, HCAGR_OFFSET(offset)) + epa_load(epa, HCAGR_OFFSET(offset)) static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes) { diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 9e13433a268a..717b12984d10 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -53,17 +53,21 @@ static int rq3_entries = EHEA_DEF_ENTRIES_RQ3; static int sq_entries = EHEA_DEF_ENTRIES_SQ; static int use_mcs = 0; static int num_tx_qps = EHEA_NUM_TX_QP; +static int prop_carrier_state = 0; module_param(msg_level, int, 0); module_param(rq1_entries, int, 0); module_param(rq2_entries, int, 0); module_param(rq3_entries, int, 0); module_param(sq_entries, int, 0); +module_param(prop_carrier_state, int, 0); module_param(use_mcs, int, 0); module_param(num_tx_qps, int, 0); MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS"); MODULE_PARM_DESC(msg_level, "msg_level"); +MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical " + "port to stack. 1:yes, 0:no. Default = 0 "); MODULE_PARM_DESC(rq3_entries, "Number of entries for Receive Queue 3 " "[2^x - 1], x = [6..14]. Default = " __MODULE_STRING(EHEA_DEF_ENTRIES_RQ3) ")"); @@ -76,12 +80,17 @@ MODULE_PARM_DESC(rq1_entries, "Number of entries for Receive Queue 1 " MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue " "[2^x - 1], x = [6..14]. Default = " __MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")"); -MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 "); +MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 "); static int port_name_cnt = 0; +static LIST_HEAD(adapter_list); +u64 ehea_driver_flags = 0; +struct workqueue_struct *ehea_driver_wq; +struct work_struct ehea_rereg_mr_task; + static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, - const struct of_device_id *id); + const struct of_device_id *id); static int __devexit ehea_remove(struct ibmebus_dev *dev); @@ -236,15 +245,19 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr, rwqe = ehea_get_next_rwqe(qp, rq_nr); rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type) - | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index); + | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index); rwqe->sg_list[0].l_key = pr->recv_mr.lkey; - rwqe->sg_list[0].vaddr = (u64)skb->data; + rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data); rwqe->sg_list[0].len = packet_size; rwqe->data_segments = 1; index++; index &= max_index_mask; + + if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) + goto out; } + q_skba->index = index; /* Ring doorbell */ @@ -253,7 +266,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr, ehea_update_rq2a(pr->qp, i); else ehea_update_rq3a(pr->qp, i); - +out: return ret; } @@ -427,7 +440,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, break; } skb_copy_to_linear_data(skb, ((char*)cqe) + 64, - cqe->num_bytes_transfered - 4); + cqe->num_bytes_transfered - 4); ehea_fill_skb(port->netdev, skb, cqe); } else if (rq == 2) { /* RQ2 */ skb = get_skb_by_index(skb_arr_rq2, @@ -457,6 +470,8 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, cqe->vlan_tag); else netif_receive_skb(skb); + + port->netdev->last_rx = jiffies; } else { pr->p_stats.poll_receive_errors++; port_reset = ehea_treat_poll_error(pr, rq, cqe, @@ -578,6 +593,23 @@ static int ehea_poll(struct net_device *dev, int *budget) return 1; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void ehea_netpoll(struct net_device *dev) +{ + struct ehea_port *port = netdev_priv(dev); + + netif_rx_schedule(port->port_res[0].d_netdev); +} +#endif + +static int ehea_poll_firstqueue(struct net_device *dev, int *budget) +{ + struct ehea_port *port = netdev_priv(dev); + struct net_device *d_dev = port->port_res[0].d_netdev; + + return ehea_poll(d_dev, budget); +} + static irqreturn_t ehea_recv_irq_handler(int irq, void *param) { struct ehea_port_res *pr = param; @@ -618,7 +650,7 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter, for (i = 0; i < EHEA_MAX_PORTS; i++) if (adapter->port[i]) - if (adapter->port[i]->logical_port_id == logical_port) + if (adapter->port[i]->logical_port_id == logical_port) return adapter->port[i]; return NULL; } @@ -786,7 +818,9 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed) ehea_error("Failed setting port speed"); } } - netif_carrier_on(port->netdev); + if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP)) + netif_carrier_on(port->netdev); + kfree(cb4); out: return ret; @@ -841,13 +875,19 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe) } if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) { + port->phy_link = EHEA_PHY_LINK_UP; if (netif_msg_link(port)) ehea_info("%s: Physical port up", port->netdev->name); + if (prop_carrier_state) + netif_carrier_on(port->netdev); } else { + port->phy_link = EHEA_PHY_LINK_DOWN; if (netif_msg_link(port)) ehea_info("%s: Physical port down", port->netdev->name); + if (prop_carrier_state) + netif_carrier_off(port->netdev); } if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PRIMARY, eqe)) @@ -1298,7 +1338,6 @@ static void write_swqe2_TSO(struct sk_buff *skb, u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0]; int skb_data_size = skb->len - skb->data_len; int headersize; - u64 tmp_addr; /* Packet is TCP with TSO enabled */ swqe->tx_control |= EHEA_SWQE_TSO; @@ -1319,9 +1358,8 @@ static void write_swqe2_TSO(struct sk_buff *skb, /* set sg1entry data */ sg1entry->l_key = lkey; sg1entry->len = skb_data_size - headersize; - - tmp_addr = (u64)(skb->data + headersize); - sg1entry->vaddr = tmp_addr; + sg1entry->vaddr = + ehea_map_vaddr(skb->data + headersize); swqe->descriptors++; } } else @@ -1334,7 +1372,6 @@ static void write_swqe2_nonTSO(struct sk_buff *skb, int skb_data_size = skb->len - skb->data_len; u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0]; struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry; - u64 tmp_addr; /* Packet is any nonTSO type * @@ -1351,8 +1388,8 @@ static void write_swqe2_nonTSO(struct sk_buff *skb, /* copy sg1entry data */ sg1entry->l_key = lkey; sg1entry->len = skb_data_size - SWQE2_MAX_IMM; - tmp_addr = (u64)(skb->data + SWQE2_MAX_IMM); - sg1entry->vaddr = tmp_addr; + sg1entry->vaddr = + ehea_map_vaddr(skb->data + SWQE2_MAX_IMM); swqe->descriptors++; } } else { @@ -1367,7 +1404,6 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev, struct ehea_vsgentry *sg_list, *sg1entry, *sgentry; skb_frag_t *frag; int nfrags, sg1entry_contains_frag_data, i; - u64 tmp_addr; nfrags = skb_shinfo(skb)->nr_frags; sg1entry = &swqe->u.immdata_desc.sg_entry; @@ -1389,9 +1425,9 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev, /* copy sg1entry data */ sg1entry->l_key = lkey; sg1entry->len = frag->size; - tmp_addr = (u64)(page_address(frag->page) - + frag->page_offset); - sg1entry->vaddr = tmp_addr; + sg1entry->vaddr = + ehea_map_vaddr(page_address(frag->page) + + frag->page_offset); swqe->descriptors++; sg1entry_contains_frag_data = 1; } @@ -1403,10 +1439,9 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev, sgentry->l_key = lkey; sgentry->len = frag->size; - - tmp_addr = (u64)(page_address(frag->page) - + frag->page_offset); - sgentry->vaddr = tmp_addr; + sgentry->vaddr = + ehea_map_vaddr(page_address(frag->page) + + frag->page_offset); swqe->descriptors++; } } @@ -1424,7 +1459,8 @@ static int ehea_broadcast_reg_helper(struct ehea_port *port, u32 hcallid) port->logical_port_id, reg_type, port->mac_addr, 0, hcallid); if (hret != H_SUCCESS) { - ehea_error("reg_dereg_bcmc failed (tagged)"); + ehea_error("%sregistering bc address failed (tagged)", + hcallid == H_REG_BCMC ? "" : "de"); ret = -EIO; goto out_herr; } @@ -1435,7 +1471,8 @@ static int ehea_broadcast_reg_helper(struct ehea_port *port, u32 hcallid) port->logical_port_id, reg_type, port->mac_addr, 0, hcallid); if (hret != H_SUCCESS) { - ehea_error("reg_dereg_bcmc failed (vlan)"); + ehea_error("%sregistering bc address failed (vlan)", + hcallid == H_REG_BCMC ? "" : "de"); ret = -EIO; } out_herr: @@ -1695,6 +1732,7 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev, { if (skb->protocol == htons(ETH_P_IP)) { const struct iphdr *iph = ip_hdr(skb); + /* IPv4 */ swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IP_CHECKSUM @@ -1705,13 +1743,12 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev, write_ip_start_end(swqe, skb); if (iph->protocol == IPPROTO_UDP) { - if ((iph->frag_off & IP_MF) || - (iph->frag_off & IP_OFFSET)) + if ((iph->frag_off & IP_MF) + || (iph->frag_off & IP_OFFSET)) /* IP fragment, so don't change cs */ swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM; else write_udp_offset_end(swqe, skb); - } else if (iph->protocol == IPPROTO_TCP) { write_tcp_offset_end(swqe, skb); } @@ -1739,6 +1776,7 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev, if (skb->protocol == htons(ETH_P_IP)) { const struct iphdr *iph = ip_hdr(skb); + /* IPv4 */ write_ip_start_end(swqe, skb); @@ -1751,8 +1789,8 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev, write_tcp_offset_end(swqe, skb); } else if (iph->protocol == IPPROTO_UDP) { - if ((iph->frag_off & IP_MF) || - (iph->frag_off & IP_OFFSET)) + if ((iph->frag_off & IP_MF) + || (iph->frag_off & IP_OFFSET)) /* IP fragment, so don't change cs */ swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IMM_DATA_PRESENT; @@ -1877,6 +1915,9 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) ehea_dump(swqe, 512, "swqe"); } + if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) + goto out; + ehea_post_swqe(pr->qp, swqe); pr->tx_packets++; @@ -1891,7 +1932,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) } dev->trans_start = jiffies; spin_unlock(&pr->xmit_lock); - +out: return NETDEV_TX_OK; } @@ -2131,24 +2172,18 @@ static int ehea_clean_all_portres(struct ehea_port *port) return ret; } -static void ehea_remove_adapter_mr (struct ehea_adapter *adapter) +static void ehea_remove_adapter_mr(struct ehea_adapter *adapter) { - int i; - - for (i=0; i < EHEA_MAX_PORTS; i++) - if (adapter->port[i]) - return; + if (adapter->active_ports) + return; ehea_rem_mr(&adapter->mr); } -static int ehea_add_adapter_mr (struct ehea_adapter *adapter) +static int ehea_add_adapter_mr(struct ehea_adapter *adapter) { - int i; - - for (i=0; i < EHEA_MAX_PORTS; i++) - if (adapter->port[i]) - return 0; + if (adapter->active_ports) + return 0; return ehea_reg_kernel_mr(adapter, &adapter->mr); } @@ -2157,7 +2192,6 @@ static int ehea_up(struct net_device *dev) { int ret, i; struct ehea_port *port = netdev_priv(dev); - u64 mac_addr = 0; if (port->state == EHEA_PORT_UP) return 0; @@ -2176,18 +2210,10 @@ static int ehea_up(struct net_device *dev) goto out_clean_pr; } - ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); - if (ret) { - ret = -EIO; - ehea_error("out_clean_pr"); - goto out_clean_pr; - } - mac_addr = (*(u64*)dev->dev_addr) >> 16; - ret = ehea_reg_interrupts(dev); if (ret) { - ehea_error("out_dereg_bc"); - goto out_dereg_bc; + ehea_error("reg_interrupts failed. ret:%d", ret); + goto out_clean_pr; } for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { @@ -2213,12 +2239,12 @@ static int ehea_up(struct net_device *dev) out_free_irqs: ehea_free_interrupts(dev); -out_dereg_bc: - ehea_broadcast_reg_helper(port, H_DEREG_BCMC); - out_clean_pr: ehea_clean_all_portres(port); out: + if (ret) + ehea_info("Failed starting %s. ret=%i", dev->name, ret); + return ret; } @@ -2257,9 +2283,13 @@ static int ehea_down(struct net_device *dev) &port->port_res[i].d_netdev->state)) msleep(1); - ehea_broadcast_reg_helper(port, H_DEREG_BCMC); - ret = ehea_clean_all_portres(port); port->state = EHEA_PORT_DOWN; + + ret = ehea_clean_all_portres(port); + if (ret) + ehea_info("Failed freeing resources for %s. ret=%i", + dev->name, ret); + return ret; } @@ -2291,15 +2321,11 @@ static void ehea_reset_port(struct work_struct *work) netif_stop_queue(dev); netif_poll_disable(dev); - ret = ehea_down(dev); - if (ret) - ehea_error("ehea_down failed. not all resources are freed"); + ehea_down(dev); ret = ehea_up(dev); - if (ret) { - ehea_error("Reset device %s failed: ret=%d", dev->name, ret); + if (ret) goto out; - } if (netif_msg_timer(port)) ehea_info("Device %s resetted successfully", dev->name); @@ -2311,6 +2337,88 @@ out: return; } +static void ehea_rereg_mrs(struct work_struct *work) +{ + int ret, i; + struct ehea_adapter *adapter; + + ehea_info("LPAR memory enlarged - re-initializing driver"); + + list_for_each_entry(adapter, &adapter_list, list) + if (adapter->active_ports) { + /* Shutdown all ports */ + for (i = 0; i < EHEA_MAX_PORTS; i++) { + struct ehea_port *port = adapter->port[i]; + + if (port) { + struct net_device *dev = port->netdev; + + if (dev->flags & IFF_UP) { + ehea_info("stopping %s", + dev->name); + down(&port->port_lock); + netif_stop_queue(dev); + netif_poll_disable(dev); + ehea_down(dev); + up(&port->port_lock); + } + } + } + + /* Unregister old memory region */ + ret = ehea_rem_mr(&adapter->mr); + if (ret) { + ehea_error("unregister MR failed - driver" + " inoperable!"); + goto out; + } + } + + ehea_destroy_busmap(); + + ret = ehea_create_busmap(); + if (ret) + goto out; + + clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags); + + list_for_each_entry(adapter, &adapter_list, list) + if (adapter->active_ports) { + /* Register new memory region */ + ret = ehea_reg_kernel_mr(adapter, &adapter->mr); + if (ret) { + ehea_error("register MR failed - driver" + " inoperable!"); + goto out; + } + + /* Restart all ports */ + for (i = 0; i < EHEA_MAX_PORTS; i++) { + struct ehea_port *port = adapter->port[i]; + + if (port) { + struct net_device *dev = port->netdev; + + if (dev->flags & IFF_UP) { + ehea_info("restarting %s", + dev->name); + down(&port->port_lock); + + ret = ehea_up(dev); + if (!ret) { + netif_poll_enable(dev); + netif_wake_queue(dev); + } + + up(&port->port_lock); + } + } + } + } +out: + return; +} + static void ehea_tx_watchdog(struct net_device *dev) { struct ehea_port *port = netdev_priv(dev); @@ -2394,7 +2502,7 @@ static ssize_t ehea_show_port_id(struct device *dev, struct device_attribute *attr, char *buf) { struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev); - return sprintf(buf, "0x%X", port->logical_port_id); + return sprintf(buf, "%d", port->logical_port_id); } static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id, @@ -2407,7 +2515,7 @@ static void __devinit logical_port_release(struct device *dev) } static int ehea_driver_sysfs_add(struct device *dev, - struct device_driver *driver) + struct device_driver *driver) { int ret; @@ -2424,7 +2532,7 @@ static int ehea_driver_sysfs_add(struct device *dev, } static void ehea_driver_sysfs_remove(struct device *dev, - struct device_driver *driver) + struct device_driver *driver) { struct device_driver *drv = driver; @@ -2453,7 +2561,7 @@ static struct device *ehea_register_port(struct ehea_port *port, } ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id); - if (ret) { + if (ret) { ehea_error("failed to register attributes, ret=%d", ret); goto out_unreg_of_dev; } @@ -2536,7 +2644,10 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN); dev->open = ehea_open; - dev->poll = ehea_poll; + dev->poll = ehea_poll_firstqueue; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = ehea_netpoll; +#endif dev->weight = 64; dev->stop = ehea_stop; dev->hard_start_xmit = ehea_start_xmit; @@ -2556,12 +2667,18 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, INIT_WORK(&port->reset_task, ehea_reset_port); + ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); + if (ret) { + ret = -EIO; + goto out_unreg_port; + } + ehea_set_ethtool_ops(dev); ret = register_netdev(dev); if (ret) { ehea_error("register_netdev failed. ret=%d", ret); - goto out_unreg_port; + goto out_dereg_bc; } ret = ehea_get_jumboframe_status(port, &jumbo); @@ -2572,8 +2689,13 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, ehea_info("%s: Jumbo frames are %sabled", dev->name, jumbo == 1 ? "en" : "dis"); + adapter->active_ports++; + return port; +out_dereg_bc: + ehea_broadcast_reg_helper(port, H_DEREG_BCMC); + out_unreg_port: ehea_unregister_port(port); @@ -2593,14 +2715,17 @@ static void ehea_shutdown_single_port(struct ehea_port *port) { unregister_netdev(port->netdev); ehea_unregister_port(port); + ehea_broadcast_reg_helper(port, H_DEREG_BCMC); kfree(port->mc_list); free_netdev(port->netdev); + port->adapter->active_ports--; } static int ehea_setup_ports(struct ehea_adapter *adapter) { struct device_node *lhea_dn; struct device_node *eth_dn = NULL; + const u32 *dn_log_port_id; int i = 0; @@ -2608,7 +2733,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter) while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", - NULL); + NULL); if (!dn_log_port_id) { ehea_error("bad device node: eth_dn name=%s", eth_dn->full_name); @@ -2648,7 +2773,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter, while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", - NULL); + NULL); if (dn_log_port_id) if (*dn_log_port_id == logical_port_id) return eth_dn; @@ -2668,7 +2793,7 @@ static ssize_t ehea_probe_port(struct device *dev, u32 logical_port_id; - sscanf(buf, "%X", &logical_port_id); + sscanf(buf, "%d", &logical_port_id); port = ehea_get_port(adapter, logical_port_id); @@ -2721,7 +2846,7 @@ static ssize_t ehea_remove_port(struct device *dev, int i; u32 logical_port_id; - sscanf(buf, "%X", &logical_port_id); + sscanf(buf, "%d", &logical_port_id); port = ehea_get_port(adapter, logical_port_id); @@ -2786,10 +2911,12 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, goto out; } + list_add(&adapter->list, &adapter_list); + adapter->ebus_dev = dev; adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle", - NULL); + NULL); if (adapter_handle) adapter->handle = *adapter_handle; @@ -2889,7 +3016,10 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev) ehea_destroy_eq(adapter->neq); ehea_remove_adapter_mr(adapter); + list_del(&adapter->list); + kfree(adapter); + return 0; } @@ -2921,6 +3051,15 @@ static int check_module_parm(void) return ret; } +static ssize_t ehea_show_capabilities(struct device_driver *drv, + char *buf) +{ + return sprintf(buf, "%d", EHEA_CAPABILITIES); +} + +static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH, + ehea_show_capabilities, NULL); + int __init ehea_module_init(void) { int ret; @@ -2928,12 +3067,32 @@ int __init ehea_module_init(void) printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n", DRV_VERSION); + ehea_driver_wq = create_workqueue("ehea_driver_wq"); + + INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs); + ret = check_module_parm(); if (ret) goto out; - ret = ibmebus_register_driver(&ehea_driver); + + ret = ehea_create_busmap(); if (ret) + goto out; + + ret = ibmebus_register_driver(&ehea_driver); + if (ret) { ehea_error("failed registering eHEA device driver on ebus"); + goto out; + } + + ret = driver_create_file(&ehea_driver.driver, + &driver_attr_capabilities); + if (ret) { + ehea_error("failed to register capabilities attribute, ret=%d", + ret); + ibmebus_unregister_driver(&ehea_driver); + goto out; + } out: return ret; @@ -2941,7 +3100,10 @@ out: static void __exit ehea_module_exit(void) { + destroy_workqueue(ehea_driver_wq); + driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); ibmebus_unregister_driver(&ehea_driver); + ehea_destroy_busmap(); } module_init(ehea_module_init); diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h index d17a45a7e717..89b63531ff26 100644 --- a/drivers/net/ehea/ehea_phyp.h +++ b/drivers/net/ehea/ehea_phyp.h @@ -60,6 +60,9 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code) } } +/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */ +#define EHEA_MAX_RPAGE 512 + /* Notification Event Queue (NEQ) Entry bit masks */ #define NEQE_EVENT_CODE EHEA_BMASK_IBM(2, 7) #define NEQE_PORTNUM EHEA_BMASK_IBM(32, 47) diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index f24a8862977d..c82e24596074 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -31,6 +31,13 @@ #include "ehea_phyp.h" #include "ehea_qmr.h" + +struct ehea_busmap ehea_bmap = { 0, 0, NULL }; +extern u64 ehea_driver_flags; +extern struct workqueue_struct *ehea_driver_wq; +extern struct work_struct ehea_rereg_mr_task; + + static void *hw_qpageit_get_inc(struct hw_queue *queue) { void *retvalue = hw_qeit_get(queue); @@ -211,7 +218,7 @@ u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force) u64 hret; u64 adapter_handle = cq->adapter->handle; - /* deregister all previous registered pages */ + /* deregister all previous registered pages */ hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force); if (hret != H_SUCCESS) return hret; @@ -228,6 +235,8 @@ int ehea_destroy_cq(struct ehea_cq *cq) if (!cq) return 0; + hcp_epas_dtor(&cq->epas); + if ((hret = ehea_destroy_cq_res(cq, NORMAL_FREE)) == H_R_STATE) { ehea_error_data(cq->adapter, cq->fw_handle); hret = ehea_destroy_cq_res(cq, FORCE_FREE); @@ -354,6 +363,8 @@ int ehea_destroy_eq(struct ehea_eq *eq) if (!eq) return 0; + hcp_epas_dtor(&eq->epas); + if ((hret = ehea_destroy_eq_res(eq, NORMAL_FREE)) == H_R_STATE) { ehea_error_data(eq->adapter, eq->fw_handle); hret = ehea_destroy_eq_res(eq, FORCE_FREE); @@ -362,7 +373,7 @@ int ehea_destroy_eq(struct ehea_eq *eq) if (hret != H_SUCCESS) { ehea_error("destroy EQ failed"); return -EIO; - } + } return 0; } @@ -507,58 +518,126 @@ out_freemem: u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force) { - u64 hret; - struct ehea_qp_init_attr *qp_attr = &qp->init_attr; + u64 hret; + struct ehea_qp_init_attr *qp_attr = &qp->init_attr; - ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); - hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force); - if (hret != H_SUCCESS) - return hret; + ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); + hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force); + if (hret != H_SUCCESS) + return hret; - hw_queue_dtor(&qp->hw_squeue); - hw_queue_dtor(&qp->hw_rqueue1); + hw_queue_dtor(&qp->hw_squeue); + hw_queue_dtor(&qp->hw_rqueue1); - if (qp_attr->rq_count > 1) - hw_queue_dtor(&qp->hw_rqueue2); - if (qp_attr->rq_count > 2) - hw_queue_dtor(&qp->hw_rqueue3); - kfree(qp); + if (qp_attr->rq_count > 1) + hw_queue_dtor(&qp->hw_rqueue2); + if (qp_attr->rq_count > 2) + hw_queue_dtor(&qp->hw_rqueue3); + kfree(qp); - return hret; + return hret; } int ehea_destroy_qp(struct ehea_qp *qp) { - u64 hret; - if (!qp) - return 0; + u64 hret; + if (!qp) + return 0; + + hcp_epas_dtor(&qp->epas); + + if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) { + ehea_error_data(qp->adapter, qp->fw_handle); + hret = ehea_destroy_qp_res(qp, FORCE_FREE); + } + + if (hret != H_SUCCESS) { + ehea_error("destroy QP failed"); + return -EIO; + } + + return 0; +} + +int ehea_create_busmap( void ) +{ + u64 vaddr = EHEA_BUSMAP_START; + unsigned long abs_max_pfn = 0; + unsigned long sec_max_pfn; + int i; - if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) { - ehea_error_data(qp->adapter, qp->fw_handle); - hret = ehea_destroy_qp_res(qp, FORCE_FREE); - } + /* + * Sections are not in ascending order -> Loop over all sections and + * find the highest PFN to compute the required map size. + */ + ehea_bmap.valid_sections = 0; + + for (i = 0; i < NR_MEM_SECTIONS; i++) + if (valid_section_nr(i)) { + sec_max_pfn = section_nr_to_pfn(i); + if (sec_max_pfn > abs_max_pfn) + abs_max_pfn = sec_max_pfn; + ehea_bmap.valid_sections++; + } + + ehea_bmap.entries = abs_max_pfn / EHEA_PAGES_PER_SECTION + 1; + ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr)); + + if (!ehea_bmap.vaddr) + return -ENOMEM; - if (hret != H_SUCCESS) { - ehea_error("destroy QP failed"); - return -EIO; - } + for (i = 0 ; i < ehea_bmap.entries; i++) { + unsigned long pfn = section_nr_to_pfn(i); - return 0; + if (pfn_valid(pfn)) { + ehea_bmap.vaddr[i] = vaddr; + vaddr += EHEA_SECTSIZE; + } else + ehea_bmap.vaddr[i] = 0; + } + + return 0; +} + +void ehea_destroy_busmap( void ) +{ + vfree(ehea_bmap.vaddr); +} + +u64 ehea_map_vaddr(void *caddr) +{ + u64 mapped_addr; + unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS; + + if (likely(index < ehea_bmap.entries)) { + mapped_addr = ehea_bmap.vaddr[index]; + if (likely(mapped_addr)) + mapped_addr |= (((unsigned long)caddr) + & (EHEA_SECTSIZE - 1)); + else + mapped_addr = -1; + } else + mapped_addr = -1; + + if (unlikely(mapped_addr == -1)) + if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags)) + queue_work(ehea_driver_wq, &ehea_rereg_mr_task); + + return mapped_addr; } int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) { - int i, k, ret; - u64 hret, pt_abs, start, end, nr_pages; - u32 acc_ctrl = EHEA_MR_ACC_CTRL; + int ret; u64 *pt; + void *pg; + u64 hret, pt_abs, i, j, m, mr_len; + u32 acc_ctrl = EHEA_MR_ACC_CTRL; - start = KERNELBASE; - end = (u64)high_memory; - nr_pages = (end - start) / EHEA_PAGESIZE; + mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE; - pt = kzalloc(PAGE_SIZE, GFP_KERNEL); + pt = kzalloc(EHEA_MAX_RPAGE * sizeof(u64), GFP_KERNEL); if (!pt) { ehea_error("no mem"); ret = -ENOMEM; @@ -566,7 +645,8 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) } pt_abs = virt_to_abs(pt); - hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start, + hret = ehea_h_alloc_resource_mr(adapter->handle, + EHEA_BUSMAP_START, mr_len, acc_ctrl, adapter->pd, &mr->handle, &mr->lkey); if (hret != H_SUCCESS) { @@ -575,49 +655,43 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) goto out; } - mr->vaddr = KERNELBASE; - k = 0; - - while (nr_pages > 0) { - if (nr_pages > 1) { - u64 num_pages = min(nr_pages, (u64)512); - for (i = 0; i < num_pages; i++) - pt[i] = virt_to_abs((void*)(((u64)start) + - ((k++) * - EHEA_PAGESIZE))); - - hret = ehea_h_register_rpage_mr(adapter->handle, - mr->handle, 0, - 0, (u64)pt_abs, - num_pages); - nr_pages -= num_pages; - } else { - u64 abs_adr = virt_to_abs((void*)(((u64)start) + - (k * EHEA_PAGESIZE))); - - hret = ehea_h_register_rpage_mr(adapter->handle, - mr->handle, 0, - 0, abs_adr,1); - nr_pages--; - } - - if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) { - ehea_h_free_resource(adapter->handle, - mr->handle, FORCE_FREE); - ehea_error("register_rpage_mr failed"); - ret = -EIO; - goto out; + for (i = 0 ; i < ehea_bmap.entries; i++) + if (ehea_bmap.vaddr[i]) { + void *sectbase = __va(i << SECTION_SIZE_BITS); + unsigned long k = 0; + + for (j = 0; j < (PAGES_PER_SECTION / EHEA_MAX_RPAGE); + j++) { + + for (m = 0; m < EHEA_MAX_RPAGE; m++) { + pg = sectbase + ((k++) * EHEA_PAGESIZE); + pt[m] = virt_to_abs(pg); + } + + hret = ehea_h_register_rpage_mr(adapter->handle, + mr->handle, + 0, 0, pt_abs, + EHEA_MAX_RPAGE); + if ((hret != H_SUCCESS) + && (hret != H_PAGE_REGISTERED)) { + ehea_h_free_resource(adapter->handle, + mr->handle, + FORCE_FREE); + ehea_error("register_rpage_mr failed"); + ret = -EIO; + goto out; + } + } } - } if (hret != H_SUCCESS) { - ehea_h_free_resource(adapter->handle, mr->handle, - FORCE_FREE); - ehea_error("register_rpage failed for last page"); + ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE); + ehea_error("registering mr failed"); ret = -EIO; goto out; } + mr->vaddr = EHEA_BUSMAP_START; mr->adapter = adapter; ret = 0; out: diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index c0eb3e03a102..b71f8452a5e3 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -36,8 +36,14 @@ * page size of ehea hardware queues */ -#define EHEA_PAGESHIFT 12 -#define EHEA_PAGESIZE 4096UL +#define EHEA_PAGESHIFT 12 +#define EHEA_PAGESIZE (1UL << EHEA_PAGESHIFT) +#define EHEA_SECTSIZE (1UL << 24) +#define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> PAGE_SHIFT) + +#if (1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE +#error eHEA module can't work if kernel sectionsize < ehea sectionsize +#endif /* Some abbreviations used here: * @@ -372,4 +378,8 @@ int ehea_rem_mr(struct ehea_mr *mr); void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle); +int ehea_create_busmap( void ); +void ehea_destroy_busmap( void ); +u64 ehea_map_vaddr(void *caddr); + #endif /* __EHEA_QMR_H__ */ diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 5e517946f46a..119778401e48 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1201,7 +1201,7 @@ static int epic_rx(struct net_device *dev, int budget) ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(ep->pci_dev, ep->rx_ring[entry].bufaddr, diff --git a/drivers/net/eql.c b/drivers/net/eql.c index a93700e5661a..102218c4a907 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -391,7 +391,7 @@ static int __eql_insert_slave(slave_queue_t *queue, slave_t *slave) slave_t *duplicate_slave = NULL; duplicate_slave = __eql_find_slave_dev(queue, slave->dev); - if (duplicate_slave != 0) + if (duplicate_slave) eql_kill_one_slave(queue, duplicate_slave); list_add(&slave->list, &queue->all_slaves); diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index abe9b089c610..ff9f177d7157 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1727,8 +1727,8 @@ static int netdev_rx(struct net_device *dev) /* Call copy + cksum if available. */ #if ! defined(__alpha__) - eth_copy_and_sum(skb, - np->cur_rx->skbuff->data, pkt_len, 0); + skb_copy_to_linear_data(skb, + np->cur_rx->skbuff->data, pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 938426953149..b7cb59a51c55 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -51,6 +51,7 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/pgtable.h> +#include <asm/cacheflush.h> #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ @@ -113,8 +114,6 @@ static unsigned char fec_mac_default[] = { #define FEC_FLASHMAC 0xf0006006 #elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES) #define FEC_FLASHMAC 0xf0006000 -#elif defined (CONFIG_MTD_KeyTechnology) -#define FEC_FLASHMAC 0xffe04000 #elif defined(CONFIG_CANCam) #define FEC_FLASHMAC 0xf0020000 #elif defined (CONFIG_M5272C3) @@ -212,6 +211,8 @@ struct fec_enet_private { /* Hardware registers of the FEC device */ volatile fec_t *hwp; + struct net_device *netdev; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; @@ -236,7 +237,6 @@ struct fec_enet_private { uint phy_speed; phy_info_t const *phy; struct work_struct phy_task; - struct net_device *net; uint sequence_done; uint mii_phy_task_queued; @@ -675,7 +675,7 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { fep->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); fec_dcache_inv_range(data, data+pkt_len -4); - + /* This does 16 byte alignment, exactly what we need. * The packet length includes FCS, but we don't want to * include that when passing upstream as it messes up @@ -702,9 +702,9 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { fep->rx_skbuff[rx_index] = skb; skb->data = FEC_ADDR_ALIGNMENT(skb->data); bdp->cbd_bufaddr = __pa(skb->data); - skb_put(pskb,pkt_len-4); /* Make room */ - skb = pskb; - } + skb_put(pskb,pkt_len-4); /* Make room */ + skb = pskb; + } skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); } @@ -1340,7 +1340,7 @@ static void __inline__ fec_request_intrs(struct net_device *dev) icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3); *icrp = 0x00000ddd; icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x70777777) | 0x0d000000; + *icrp = 0x0d000000; } static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) @@ -1402,7 +1402,7 @@ static void __inline__ fec_disable_phy_intr(void) { volatile unsigned long *icrp; icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x70777777) | 0x08000000; + *icrp = 0x08000000; } static void __inline__ fec_phy_ack_intr(void) @@ -1410,7 +1410,7 @@ static void __inline__ fec_phy_ack_intr(void) volatile unsigned long *icrp; /* Acknowledge the interrupt */ icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x77777777) | 0x08000000; + *icrp = 0x0d000000; } static void __inline__ fec_localhw_setup(void) @@ -1538,6 +1538,29 @@ static void __inline__ fec_request_intrs(struct net_device *dev) *gpio_pehlpar = 0xc0; } #endif + +#if defined(CONFIG_M527x) + /* Set up gpio outputs for MII lines */ + { + volatile u8 *gpio_par_fec; + volatile u16 *gpio_par_feci2c; + + gpio_par_feci2c = (volatile u16 *)(MCF_IPSBAR + 0x100082); + /* Set up gpio outputs for FEC0 MII lines */ + gpio_par_fec = (volatile u8 *)(MCF_IPSBAR + 0x100078); + + *gpio_par_feci2c |= 0x0f00; + *gpio_par_fec |= 0xc0; + +#if defined(CONFIG_FEC2) + /* Set up gpio outputs for FEC1 MII lines */ + gpio_par_fec = (volatile u8 *)(MCF_IPSBAR + 0x100079); + + *gpio_par_feci2c |= 0x00a0; + *gpio_par_fec |= 0xc0; +#endif /* CONFIG_FEC2 */ + } +#endif /* CONFIG_M527x */ } static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) @@ -2363,9 +2386,8 @@ static void mii_display_status(struct net_device *dev) static void mii_display_config(struct work_struct *work) { - struct fec_enet_private *fep = - container_of(work, struct fec_enet_private, phy_task); - struct net_device *dev = fep->net; + struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->netdev; uint status = fep->phy_status; /* @@ -2401,9 +2423,8 @@ static void mii_display_config(struct work_struct *work) static void mii_relink(struct work_struct *work) { - struct fec_enet_private *fep = - container_of(work, struct fec_enet_private, phy_task); - struct net_device *dev = fep->net; + struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->netdev; int duplex; /* @@ -2447,7 +2468,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) return; fep->mii_phy_task_queued = 1; - INIT_WORK(&fep->phy_task, (void*)mii_relink); + INIT_WORK(&fep->phy_task, mii_relink); schedule_work(&fep->phy_task); } @@ -2460,7 +2481,7 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev) return; fep->mii_phy_task_queued = 1; - INIT_WORK(&fep->phy_task, (void*)mii_display_config); + INIT_WORK(&fep->phy_task, mii_display_config); schedule_work(&fep->phy_task); } @@ -2744,9 +2765,7 @@ int __init fec_enet_init(struct net_device *dev) /* Only allow us to be probed once. */ if (index >= FEC_MAX_PORTS) return -ENXIO; - - fep->net = dev; - + spin_lock_init(&(fep->lock)); /* Allocate memory for buffer descriptors. @@ -2764,6 +2783,7 @@ int __init fec_enet_init(struct net_device *dev) fep->index = index; fep->hwp = fecp; + fep->netdev = dev; /* Whack a reset. We should wait for this. */ diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig index a84c232395e3..afb34ded26ee 100644 --- a/drivers/net/fec_8xx/Kconfig +++ b/drivers/net/fec_8xx/Kconfig @@ -1,6 +1,6 @@ config FEC_8XX tristate "Motorola 8xx FEC driver" - depends on NET_ETHERNET && 8xx + depends on 8XX select MII config FEC_8XX_GENERIC_PHY diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 4a7b5f4ff7a7..1938d6dfc863 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -178,6 +178,7 @@ #define DEV_HAS_STATISTICS_V2 0x0800 /* device supports hw statistics version 2 */ #define DEV_HAS_TEST_EXTENDED 0x1000 /* device supports extended diagnostic test */ #define DEV_HAS_MGMT_UNIT 0x2000 /* device supports management unit */ +#define DEV_HAS_CORRECT_MACADDR 0x4000 /* device supports correct mac address order */ enum { NvRegIrqStatus = 0x000, @@ -551,7 +552,7 @@ union ring_type { #define PHY_OUI_MARVELL 0x5043 #define PHY_OUI_CICADA 0x03f1 #define PHY_OUI_VITESSE 0x01c1 -#define PHY_OUI_REALTEK 0x01c1 +#define PHY_OUI_REALTEK 0x0732 #define PHYID1_OUI_MASK 0x03ff #define PHYID1_OUI_SHFT 6 #define PHYID2_OUI_MASK 0xfc00 @@ -4706,7 +4707,6 @@ static const struct ethtool_ops ops = { .get_regs_len = nv_get_regs_len, .get_regs = nv_get_regs, .nway_reset = nv_nway_reset, - .get_perm_addr = ethtool_op_get_perm_addr, .get_tso = ethtool_op_get_tso, .set_tso = nv_set_tso, .get_ringparam = nv_get_ringparam, @@ -5137,12 +5137,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i goto out_unmap; np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size]; } - np->rx_skb = kmalloc(sizeof(struct nv_skb_map) * np->rx_ring_size, GFP_KERNEL); - np->tx_skb = kmalloc(sizeof(struct nv_skb_map) * np->tx_ring_size, GFP_KERNEL); + np->rx_skb = kcalloc(np->rx_ring_size, sizeof(struct nv_skb_map), GFP_KERNEL); + np->tx_skb = kcalloc(np->tx_ring_size, sizeof(struct nv_skb_map), GFP_KERNEL); if (!np->rx_skb || !np->tx_skb) goto out_freering; - memset(np->rx_skb, 0, sizeof(struct nv_skb_map) * np->rx_ring_size); - memset(np->tx_skb, 0, sizeof(struct nv_skb_map) * np->tx_ring_size); dev->open = nv_open; dev->stop = nv_close; @@ -5174,7 +5172,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* check the workaround bit for correct mac address order */ txreg = readl(base + NvRegTransmitPoll); - if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) { + if ((txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) || + (id->driver_data & DEV_HAS_CORRECT_MACADDR)) { /* mac address is already in correct order */ dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; @@ -5226,15 +5225,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->wolenabled = 0; if (id->driver_data & DEV_HAS_POWER_CNTRL) { - u8 revision_id; - pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id); /* take phy and nic out of low power mode */ powerstate = readl(base + NvRegPowerState2); powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) && - revision_id >= 0xA3) + pci_dev->revision >= 0xA3) powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; writel(powerstate, base + NvRegPowerState2); } @@ -5504,51 +5501,67 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, {0,}, }; diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig index 6aaee67dd4b7..e27ee210b605 100644 --- a/drivers/net/fs_enet/Kconfig +++ b/drivers/net/fs_enet/Kconfig @@ -1,6 +1,6 @@ config FS_ENET tristate "Freescale Ethernet Driver" - depends on NET_ETHERNET && (CPM1 || CPM2) + depends on CPM1 || CPM2 select MII config FS_ENET_HAS_SCC diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 9d2d8145b876..3b0ef781b8b2 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -130,6 +130,9 @@ static int gfar_remove(struct platform_device *pdev); static void free_skb_resources(struct gfar_private *priv); static void gfar_set_multi(struct net_device *dev); static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); +static void gfar_configure_serdes(struct net_device *dev); +extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value); +extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct net_device *dev, int *budget); #endif @@ -417,8 +420,18 @@ static phy_interface_t gfar_get_interface(struct net_device *dev) if (ecntrl & ECNTRL_REDUCED_MODE) { if (ecntrl & ECNTRL_REDUCED_MII_MODE) return PHY_INTERFACE_MODE_RMII; - else + else { + phy_interface_t interface = priv->einfo->interface; + + /* + * This isn't autodetected right now, so it must + * be set by the device tree or platform code. + */ + if (interface == PHY_INTERFACE_MODE_RGMII_ID) + return PHY_INTERFACE_MODE_RGMII_ID; + return PHY_INTERFACE_MODE_RGMII; + } } if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT) @@ -451,6 +464,9 @@ static int init_phy(struct net_device *dev) phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface); + if (interface == PHY_INTERFACE_MODE_SGMII) + gfar_configure_serdes(dev); + if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); return PTR_ERR(phydev); @@ -465,6 +481,27 @@ static int init_phy(struct net_device *dev) return 0; } +static void gfar_configure_serdes(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + struct gfar_mii __iomem *regs = + (void __iomem *)&priv->regs->gfar_mii_regs; + + /* Initialise TBI i/f to communicate with serdes (lynx phy) */ + + /* Single clk mode, mii mode off(for aerdes communication) */ + gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT); + + /* Supported pause and full-duplex, no half-duplex */ + gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE, + ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | + ADVERTISE_1000XPSE_ASYM); + + /* ANEG enable, restart ANEG, full duplex mode, speed[1] set */ + gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE | + BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); +} + static void init_registers(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 39e9e321fcbc..d8e779c102fa 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -136,6 +136,12 @@ extern const char gfar_driver_version[]; #define MIIMCFG_RESET 0x80000000 #define MIIMIND_BUSY 0x00000001 +/* TBI register addresses */ +#define MII_TBICON 0x11 + +/* TBICON register bit fields */ +#define TBICON_CLK_SELECT 0x0020 + /* MAC register bits */ #define MACCFG1_SOFT_RESET 0x80000000 #define MACCFG1_RESET_RX_MC 0x00080000 diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index bcc6b82f4a33..100bf410bf5f 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -31,7 +31,6 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <asm/ocp.h> #include <linux/crc32.h> #include <linux/mii.h> #include <linux/phy.h> @@ -43,13 +42,18 @@ #include "gianfar.h" #include "gianfar_mii.h" -/* Write value to the PHY at mii_id at register regnum, - * on the bus, waiting until the write is done before returning. - * All PHY configuration is done through the TSEC1 MIIM regs */ -int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) +/* + * Write value to the PHY at mii_id at register regnum, + * on the bus attached to the local interface, which may be different from the + * generic mdio bus (tied to a single interface), waiting until the write is + * done before returning. This is helpful in programming interfaces like + * the TBI which control interfaces like onchip SERDES and are always tied to + * the local mdio pins, which may not be the same as system mdio bus, used for + * controlling the external PHYs, for example. + */ +int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, + int regnum, u16 value) { - struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; - /* Set the PHY address and the register address we want to write */ gfar_write(®s->miimadd, (mii_id << 8) | regnum); @@ -63,12 +67,19 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) return 0; } -/* Read the bus for PHY at addr mii_id, register regnum, and - * return the value. Clears miimcom first. All PHY - * configuration has to be done through the TSEC1 MIIM regs */ -int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +/* + * Read the bus for PHY at addr mii_id, register regnum, and + * return the value. Clears miimcom first. All PHY operation + * done on the bus attached to the local interface, + * which may be different from the generic mdio bus + * This is helpful in programming interfaces like + * the TBI which, inturn, control interfaces like onchip SERDES + * and are always tied to the local mdio pins, which may not be the + * same as system mdio bus, used for controlling the external PHYs, for eg. + */ +int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum) + { - struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; u16 value; /* Set the PHY address and the register address we want to read */ @@ -88,6 +99,27 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) return value; } +/* Write value to the PHY at mii_id at register regnum, + * on the bus, waiting until the write is done before returning. + * All PHY configuration is done through the TSEC1 MIIM regs */ +int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) +{ + struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; + + /* Write to the local MII regs */ + return(gfar_local_mdio_write(regs, mii_id, regnum, value)); +} + +/* Read the bus for PHY at addr mii_id, register regnum, and + * return the value. Clears miimcom first. All PHY + * configuration has to be done through the TSEC1 MIIM regs */ +int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; + + /* Read the local MII regs */ + return(gfar_local_mdio_read(regs, mii_id, regnum)); +} /* Reset the MIIM registers, and wait for the bus to free */ int gfar_mdio_reset(struct mii_bus *bus) @@ -213,7 +245,7 @@ int __init gfar_mdio_init(void) return driver_register(&gianfar_mdio_driver); } -void __exit gfar_mdio_exit(void) +void gfar_mdio_exit(void) { driver_unregister(&gianfar_mdio_driver); } diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 5d3400469514..b373091c7031 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h @@ -42,5 +42,5 @@ struct gfar_mii { int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum); int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); int __init gfar_mdio_init(void); -void __exit gfar_mdio_exit(void); +void gfar_mdio_exit(void); #endif /* GIANFAR_PHY_H */ diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 2521b111b3a5..15254dc7876a 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1575,8 +1575,8 @@ static int hamachi_rx(struct net_device *dev) PCI_DMA_FROMDEVICE); /* Call copy + cksum if available. */ #if 1 || USE_IP_COPYSUM - eth_copy_and_sum(skb, - hmp->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, + hmp->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 84aa2117c0ee..355c6cf3d112 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -320,7 +320,7 @@ static int eppconfig(struct baycom_state *bc) sprintf(portarg, "%ld", bc->pdev->port->base); printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg); - return call_usermodehelper(eppconfig_path, argv, envp, 1); + return call_usermodehelper(eppconfig_path, argv, envp, UMH_WAIT_PROC); } /* ---------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 656f2789c9ba..cc0ee93669ea 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -413,12 +413,12 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos) ++*pos; if (v == SEQ_START_TOKEN) - p = bpq_devices.next; + p = rcu_dereference(bpq_devices.next); else - p = ((struct bpqdev *)v)->bpq_list.next; + p = rcu_dereference(((struct bpqdev *)v)->bpq_list.next); return (p == &bpq_devices) ? NULL - : rcu_dereference(list_entry(p, struct bpqdev, bpq_list)); + : list_entry(p, struct bpqdev, bpq_list); } static void bpq_seq_stop(struct seq_file *seq, void *v) diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 3be8c5047599..205f09672492 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -453,8 +453,8 @@ static int __init setup_adapter(int card_base, int type, int n) int scc_base = card_base + hw[type].scc_offset; char *chipnames[] = CHIPNAMES; - /* Allocate memory */ - info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA); + /* Initialize what is necessary for write_scc and write_scc_data */ + info = kzalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA); if (!info) { printk(KERN_ERR "dmascc: " "could not allocate memory for %s at %#3x\n", @@ -462,8 +462,6 @@ static int __init setup_adapter(int card_base, int type, int n) goto out; } - /* Initialize what is necessary for write_scc and write_scc_data */ - memset(info, 0, sizeof(struct scc_info)); info->dev[0] = alloc_netdev(0, "", dev_setup); if (!info->dev[0]) { diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 6ec3d500f334..acba90f1638e 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -963,7 +963,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ { int rc, i; struct net_device *netdev; - struct ibmveth_adapter *adapter = NULL; + struct ibmveth_adapter *adapter; unsigned char *mac_addr_p; unsigned int *mcastFilterSize_p; @@ -997,7 +997,6 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ SET_MODULE_OWNER(netdev); adapter = netdev->priv; - memset(adapter, 0, sizeof(adapter)); dev->dev.driver_data = netdev; adapter->vdev = dev; @@ -1280,24 +1279,28 @@ const char * buf, size_t count) int i; /* Make sure there is a buffer pool with buffers that can hold a packet of the size of the MTU */ - for(i = 0; i<IbmVethNumBufferPools; i++) { + for (i = 0; i < IbmVethNumBufferPools; i++) { if (pool == &adapter->rx_buff_pool[i]) continue; if (!adapter->rx_buff_pool[i].active) continue; - if (mtu < adapter->rx_buff_pool[i].buff_size) { - pool->active = 0; - h_free_logical_lan_buffer(adapter-> - vdev-> - unit_address, - pool-> - buff_size); - } + if (mtu <= adapter->rx_buff_pool[i].buff_size) + break; } - if (pool->active) { + + if (i == IbmVethNumBufferPools) { ibmveth_error_printk("no active pool >= MTU\n"); return -EPERM; } + + pool->active = 0; + if (netif_running(netdev)) { + adapter->pool_config = 1; + ibmveth_close(netdev); + adapter->pool_config = 0; + if ((rc = ibmveth_open(netdev))) + return rc; + } } } else if (attr == &veth_num_attr) { if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) @@ -1337,7 +1340,7 @@ const char * buf, size_t count) #define ATTR(_name, _mode) \ struct attribute veth_##_name##_attr = { \ - .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \ + .name = __stringify(_name), .mode = _mode, \ }; static ATTR(active, 0644); diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h index bb69ccae8ace..72cc15a6cab7 100644 --- a/drivers/net/ibmveth.h +++ b/drivers/net/ibmveth.h @@ -73,9 +73,6 @@ static inline long h_send_logical_lan(unsigned long unit_address, #define h_change_logical_lan_mac(ua, mac) \ plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) -#define h_free_logical_lan_buffer(ua, bufsize) \ - plpar_hcall_norets(H_FREE_LOGICAL_LAN_BUFFER, ua, bufsize) - #define IbmVethNumBufferPools 5 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */ #define IBMVETH_MAX_MTU 68 diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 07b4c0d7a75c..f5c3598e59af 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -136,13 +136,14 @@ resched: } -static void __init ifb_setup(struct net_device *dev) +static void ifb_setup(struct net_device *dev) { /* Initialize the device structure. */ dev->get_stats = ifb_get_stats; dev->hard_start_xmit = ifb_xmit; dev->open = &ifb_open; dev->stop = &ifb_close; + dev->destructor = free_netdev; /* Fill in device structure with ethernet-generic values. */ ether_setup(dev); @@ -197,12 +198,6 @@ static struct net_device_stats *ifb_get_stats(struct net_device *dev) return stats; } -static struct net_device **ifbs; - -/* Number of ifb devices to be set up by this module. */ -module_param(numifbs, int, 0); -MODULE_PARM_DESC(numifbs, "Number of ifb devices"); - static int ifb_close(struct net_device *dev) { struct ifb_private *dp = netdev_priv(dev); @@ -226,6 +221,28 @@ static int ifb_open(struct net_device *dev) return 0; } +static int ifb_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + return 0; +} + +static struct rtnl_link_ops ifb_link_ops __read_mostly = { + .kind = "ifb", + .priv_size = sizeof(struct ifb_private), + .setup = ifb_setup, + .validate = ifb_validate, +}; + +/* Number of ifb devices to be set up by this module. */ +module_param(numifbs, int, 0); +MODULE_PARM_DESC(numifbs, "Number of ifb devices"); + static int __init ifb_init_one(int index) { struct net_device *dev_ifb; @@ -237,49 +254,44 @@ static int __init ifb_init_one(int index) if (!dev_ifb) return -ENOMEM; - if ((err = register_netdev(dev_ifb))) { - free_netdev(dev_ifb); - dev_ifb = NULL; - } else { - ifbs[index] = dev_ifb; - } + err = dev_alloc_name(dev_ifb, dev_ifb->name); + if (err < 0) + goto err; - return err; -} + dev_ifb->rtnl_link_ops = &ifb_link_ops; + err = register_netdevice(dev_ifb); + if (err < 0) + goto err; + return 0; -static void ifb_free_one(int index) -{ - unregister_netdev(ifbs[index]); - free_netdev(ifbs[index]); +err: + free_netdev(dev_ifb); + return err; } static int __init ifb_init_module(void) { - int i, err = 0; - ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); - if (!ifbs) - return -ENOMEM; + int i, err; + + rtnl_lock(); + err = __rtnl_link_register(&ifb_link_ops); + for (i = 0; i < numifbs && !err; i++) err = ifb_init_one(i); - if (err) { - i--; - while (--i >= 0) - ifb_free_one(i); - } + if (err) + __rtnl_link_unregister(&ifb_link_ops); + rtnl_unlock(); return err; } static void __exit ifb_cleanup_module(void) { - int i; - - for (i = 0; i < numifbs; i++) - ifb_free_one(i); - kfree(ifbs); + rtnl_link_unregister(&ifb_link_ops); } module_init(ifb_init_module); module_exit(ifb_cleanup_module); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jamal Hadi Salim"); +MODULE_ALIAS_RTNL_LINK("ifb"); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index f749e07c6425..0834ef0eddb4 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -48,6 +48,7 @@ #ifdef CONFIG_SERIAL_8250 #include <linux/serial_core.h> #include <linux/serial_8250.h> +#include <linux/serial_reg.h> #endif #include <linux/netdevice.h> @@ -352,13 +353,12 @@ static u64 nic_find(struct ioc3 *ioc3, int *last) static int nic_init(struct ioc3 *ioc3) { - const char *type; + const char *unknown = "unknown"; + const char *type = unknown; u8 crc; u8 serial[6]; int save = 0, i; - type = "unknown"; - while (1) { u64 reg; reg = nic_find(ioc3, &save); @@ -392,7 +392,7 @@ static int nic_init(struct ioc3 *ioc3) } printk("Found %s NIC", type); - if (type != "unknown") { + if (type != unknown) { printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x," " CRC %02x", serial[0], serial[1], serial[2], serial[3], serial[4], serial[5], crc); @@ -1103,20 +1103,28 @@ static int ioc3_close(struct net_device *dev) * MiniDINs; all other subdevices are left swinging in the wind, leave * them disabled. */ -static inline int ioc3_is_menet(struct pci_dev *pdev) + +static int ioc3_adjacent_is_ioc3(struct pci_dev *pdev, int slot) { - struct pci_dev *dev; - - return pdev->bus->parent == NULL - && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(0, 0))) - && dev->vendor == PCI_VENDOR_ID_SGI - && dev->device == PCI_DEVICE_ID_SGI_IOC3 - && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(1, 0))) - && dev->vendor == PCI_VENDOR_ID_SGI - && dev->device == PCI_DEVICE_ID_SGI_IOC3 - && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(2, 0))) - && dev->vendor == PCI_VENDOR_ID_SGI - && dev->device == PCI_DEVICE_ID_SGI_IOC3; + struct pci_dev *dev = pci_get_slot(pdev->bus, PCI_DEVFN(slot, 0)); + int ret = 0; + + if (dev) { + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3) + ret = 1; + pci_dev_put(dev); + } + + return ret; +} + +static int ioc3_is_menet(struct pci_dev *pdev) +{ + return pdev->bus->parent == NULL && + ioc3_adjacent_is_ioc3(pdev, 0) && + ioc3_adjacent_is_ioc3(pdev, 1) && + ioc3_adjacent_is_ioc3(pdev, 2); } #ifdef CONFIG_SERIAL_8250 @@ -1144,13 +1152,41 @@ static inline int ioc3_is_menet(struct pci_dev *pdev) * Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working * around ioc3 oddities in this respect. * - * The IOC3 serials use a 22MHz clock rate with an additional divider by 3. + * The IOC3 serials use a 22MHz clock rate with an additional divider which + * can be programmed in the SCR register if the DLAB bit is set. + * + * Register to interrupt zero because we share the interrupt with + * the serial driver which we don't properly support yet. + * + * Can't use UPF_IOREMAP as the whole of IOC3 resources have already been + * registered. */ +static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart) +{ +#define COSMISC_CONSTANT 6 + + struct uart_port port = { + .irq = 0, + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 0, + .uartclk = (22000000 << 1) / COSMISC_CONSTANT, + + .membase = (unsigned char __iomem *) uart, + .mapbase = (unsigned long) uart, + }; + unsigned char lcr; + + lcr = uart->iu_lcr; + uart->iu_lcr = lcr | UART_LCR_DLAB; + uart->iu_scr = COSMISC_CONSTANT, + uart->iu_lcr = lcr; + uart->iu_lcr; + serial8250_register_port(&port); +} static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) { - struct uart_port port; - /* * We need to recognice and treat the fourth MENET serial as it * does not have an SuperIO chip attached to it, therefore attempting @@ -1164,24 +1200,35 @@ static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) return; /* - * Register to interrupt zero because we share the interrupt with - * the serial driver which we don't properly support yet. - * - * Can't use UPF_IOREMAP as the whole of IOC3 resources have already - * been registered. + * Switch IOC3 to PIO mode. It probably already was but let's be + * paranoid */ - memset(&port, 0, sizeof(port)); - port.irq = 0; - port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - port.iotype = UPIO_MEM; - port.regshift = 0; - port.uartclk = 22000000 / 3; - - port.membase = (unsigned char *) &ioc3->sregs.uarta; - serial8250_register_port(&port); - - port.membase = (unsigned char *) &ioc3->sregs.uartb; - serial8250_register_port(&port); + ioc3->gpcr_s = GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL; + ioc3->gpcr_s; + ioc3->gppr_6 = 0; + ioc3->gppr_6; + ioc3->gppr_7 = 0; + ioc3->gppr_7; + ioc3->sscr_a = ioc3->sscr_a & ~SSCR_DMA_EN; + ioc3->sscr_a; + ioc3->sscr_b = ioc3->sscr_b & ~SSCR_DMA_EN; + ioc3->sscr_b; + /* Disable all SA/B interrupts except for SA/B_INT in SIO_IEC. */ + ioc3->sio_iec &= ~ (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL | + SIO_IR_SA_RX_HIGH | SIO_IR_SA_RX_TIMER | + SIO_IR_SA_DELTA_DCD | SIO_IR_SA_DELTA_CTS | + SIO_IR_SA_TX_EXPLICIT | SIO_IR_SA_MEMERR); + ioc3->sio_iec |= SIO_IR_SA_INT; + ioc3->sscr_a = 0; + ioc3->sio_iec &= ~ (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL | + SIO_IR_SB_RX_HIGH | SIO_IR_SB_RX_TIMER | + SIO_IR_SB_DELTA_DCD | SIO_IR_SB_DELTA_CTS | + SIO_IR_SB_TX_EXPLICIT | SIO_IR_SB_MEMERR); + ioc3->sio_iec |= SIO_IR_SB_INT; + ioc3->sscr_b = 0; + + ioc3_8250_register(&ioc3->sregs.uarta); + ioc3_8250_register(&ioc3->sregs.uartb); } #endif diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 4c4b63d02534..bff101cba8aa 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -155,6 +155,15 @@ config KINGSUN_DONGLE To compile it as a module, choose M here: the module will be called kingsun-sir. +config EP7211_DONGLE + tristate "EP7211 I/R support" + depends on IRTTY_SIR && ARCH_EP7211 && IRDA && EXPERIMENTAL + help + Say Y here if you want to build support for the Cirrus logic + EP7211 chipset's infrared module. + + + comment "Old SIR device drivers" config IRPORT_SIR @@ -355,7 +364,7 @@ config WINBOND_FIR config TOSHIBA_FIR tristate "Toshiba Type-O IR Port" - depends on IRDA && PCI && !64BIT + depends on IRDA && PCI && !64BIT && VIRT_TO_BUS help Say Y here if you want to build support for the Toshiba Type-O IR and Donau oboe chipsets. These chipsets are used by the Toshiba diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index ad99af5a29ce..cdd49e31a27e 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o +obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o # The SIR helper module diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 0ac240ca905b..3b0fd83fa266 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1561,10 +1561,9 @@ static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_interf struct irda_class_desc *desc; int ret; - desc = kmalloc(sizeof (*desc), GFP_KERNEL); - if (desc == NULL) + desc = kzalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) return NULL; - memset(desc, 0, sizeof(*desc)); /* USB-IrDA class spec 1.0: * 6.1.3: Standard "Get Descriptor" Device Request is not @@ -1617,7 +1616,7 @@ static int irda_usb_probe(struct usb_interface *intf, { struct net_device *net; struct usb_device *dev = interface_to_usbdev(intf); - struct irda_usb_cb *self = NULL; + struct irda_usb_cb *self; struct usb_host_interface *interface; struct irda_class_desc *irda_desc; int ret = -ENOMEM; @@ -1655,7 +1654,7 @@ static int irda_usb_probe(struct usb_interface *intf, self->header_length = USB_IRDA_HEADER; } - self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *), + self->rx_urb = kcalloc(self->max_rx_urb, sizeof(struct urb *), GFP_KERNEL); for (i = 0; i < self->max_rx_urb; i++) { @@ -1715,7 +1714,7 @@ static int irda_usb_probe(struct usb_interface *intf, /* Find IrDA class descriptor */ irda_desc = irda_usb_find_class_desc(intf); ret = -ENODEV; - if (irda_desc == NULL) + if (!irda_desc) goto err_out_3; if (self->needspatch) { @@ -1738,15 +1737,13 @@ static int irda_usb_probe(struct usb_interface *intf, /* Don't change this buffer size and allocation without doing * some heavy and complete testing. Don't ask why :-( * Jean II */ - self->speed_buff = kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); - if (self->speed_buff == NULL) + self->speed_buff = kzalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); + if (!self->speed_buff) goto err_out_3; - memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); - self->tx_buff = kzalloc(IRDA_SKB_MAX_MTU + self->header_length, GFP_KERNEL); - if (self->tx_buff == NULL) + if (!self->tx_buff) goto err_out_4; ret = irda_usb_open(self); @@ -1767,12 +1764,11 @@ static int irda_usb_probe(struct usb_interface *intf, /* replace IrDA class descriptor with what patched device is now reporting */ irda_desc = irda_usb_find_class_desc (self->usbintf); - if (irda_desc == NULL) { + if (!irda_desc) { ret = -ENODEV; goto err_out_6; } - if (self->irda_desc) - kfree (self->irda_desc); + kfree(self->irda_desc); self->irda_desc = irda_desc; irda_usb_init_qos(self); } diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 3078c419cb02..20732458f5ac 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -164,14 +164,13 @@ irport_open(int i, unsigned int iobase, unsigned int irq) /* Allocate memory if needed */ if (self->tx_buff.truesize > 0) { - self->tx_buff.head = kmalloc(self->tx_buff.truesize, + self->tx_buff.head = kzalloc(self->tx_buff.truesize, GFP_KERNEL); if (self->tx_buff.head == NULL) { IRDA_ERROR("%s(), can't allocate memory for " "transmit buffer!\n", __FUNCTION__); goto err_out4; } - memset(self->tx_buff.head, 0, self->tx_buff.truesize); } self->tx_buff.data = self->tx_buff.head; diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index ad1857364d51..6f5f697ec9f8 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -505,10 +505,9 @@ static int irtty_open(struct tty_struct *tty) } /* allocate private device info block */ - priv = kmalloc(sizeof(*priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) goto out_put; - memset(priv, 0, sizeof(*priv)); priv->magic = IRTTY_MAGIC; priv->tty = tty; diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c index 217429122e79..4e5101a45c3c 100644 --- a/drivers/net/irda/kingsun-sir.c +++ b/drivers/net/irda/kingsun-sir.c @@ -4,7 +4,7 @@ * Version: 0.1.1 * Description: Irda KingSun/DonShine USB Dongle * Status: Experimental -* Author: Alex Villac�s Lasso <a_villacis@palosanto.com> +* Author: Alex VillacÃs Lasso <a_villacis@palosanto.com> * * Based on stir4200 and mcs7780 drivers, with (strange?) differences * @@ -509,12 +509,12 @@ static int kingsun_probe(struct usb_interface *intf, spin_lock_init(&kingsun->lock); /* Allocate input buffer */ - kingsun->in_buf = (__u8 *)kmalloc(kingsun->max_rx, GFP_KERNEL); + kingsun->in_buf = kmalloc(kingsun->max_rx, GFP_KERNEL); if (!kingsun->in_buf) goto free_mem; /* Allocate output buffer */ - kingsun->out_buf = (__u8 *)kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); + kingsun->out_buf = kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); if (!kingsun->out_buf) goto free_mem; @@ -652,6 +652,6 @@ static void __exit kingsun_cleanup(void) } module_exit(kingsun_cleanup); -MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>"); +MODULE_AUTHOR("Alex VillacÃs Lasso <a_villacis@palosanto.com>"); MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index bf78ef1120ad..0538ca9ce058 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -44,6 +44,7 @@ MODULE_LICENSE("GPL"); #include <linux/time.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/byteorder.h> @@ -1660,8 +1661,8 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) idev = ndev->priv; spin_lock_init(&idev->lock); - init_MUTEX(&idev->sem); - down(&idev->sem); + mutex_init(&idev->mtx); + mutex_lock(&idev->mtx); idev->pdev = pdev; if (vlsi_irda_init(ndev) < 0) @@ -1689,12 +1690,12 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) IRDA_MESSAGE("%s: registered device %s\n", drivername, ndev->name); pci_set_drvdata(pdev, ndev); - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; out_freedev: - up(&idev->sem); + mutex_unlock(&idev->mtx); free_netdev(ndev); out_disable: pci_disable_device(pdev); @@ -1716,12 +1717,12 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev) unregister_netdev(ndev); idev = ndev->priv; - down(&idev->sem); + mutex_lock(&idev->mtx); if (idev->proc_entry) { remove_proc_entry(ndev->name, vlsi_proc_root); idev->proc_entry = NULL; } - up(&idev->sem); + mutex_unlock(&idev->mtx); free_netdev(ndev); @@ -1751,7 +1752,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } idev = ndev->priv; - down(&idev->sem); + mutex_lock(&idev->mtx); if (pdev->current_state != 0) { /* already suspended */ if (state.event > pdev->current_state) { /* simply go deeper */ pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -1759,7 +1760,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) } else IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, pci_name(pdev), pdev->current_state, state.event); - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } @@ -1775,7 +1776,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) pci_set_power_state(pdev, pci_choose_state(pdev, state)); pdev->current_state = state.event; idev->resume_ok = 1; - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } @@ -1790,9 +1791,9 @@ static int vlsi_irda_resume(struct pci_dev *pdev) return 0; } idev = ndev->priv; - down(&idev->sem); + mutex_lock(&idev->mtx); if (pdev->current_state == 0) { - up(&idev->sem); + mutex_unlock(&idev->mtx); IRDA_WARNING("%s - %s: already resumed\n", __FUNCTION__, pci_name(pdev)); return 0; @@ -1814,7 +1815,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev) * device and independently resume_ok should catch any garbage config. */ IRDA_WARNING("%s - hm, nothing to resume?\n", __FUNCTION__); - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } @@ -1824,7 +1825,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev) netif_device_attach(ndev); } idev->resume_ok = 0; - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index 2d3b773d8e35..ca12a6096419 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -728,7 +728,7 @@ typedef struct vlsi_irda_dev { struct timeval last_rx; spinlock_t lock; - struct semaphore sem; + struct mutex mtx; u8 resume_ok; struct proc_dir_entry *proc_entry; diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 347d50cd77d4..0433c41f9029 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -822,10 +822,9 @@ static int veth_init_connection(u8 rlp) || ! HvLpConfig_doLpsCommunicateOnVirtualLan(this_lp, rlp) ) return 0; - cnx = kmalloc(sizeof(*cnx), GFP_KERNEL); + cnx = kzalloc(sizeof(*cnx), GFP_KERNEL); if (! cnx) return -ENOMEM; - memset(cnx, 0, sizeof(*cnx)); cnx->remote_lp = rlp; spin_lock_init(&cnx->lock); @@ -852,14 +851,13 @@ static int veth_init_connection(u8 rlp) if (rc != 0) return rc; - msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL); + msgs = kcalloc(VETH_NUMBUFFERS, sizeof(struct veth_msg), GFP_KERNEL); if (! msgs) { veth_error("Can't allocate buffers for LPAR %d.\n", rlp); return -ENOMEM; } cnx->msgs = msgs; - memset(msgs, 0, VETH_NUMBUFFERS * sizeof(struct veth_msg)); for (i = 0; i < VETH_NUMBUFFERS; i++) { msgs[i].token = i; diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index afde84868bea..0413cd95eda7 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -724,7 +724,6 @@ static const struct ethtool_ops ixgb_ethtool_ops = { .phys_id = ixgb_phys_id, .get_stats_count = ixgb_get_stats_count, .get_ethtool_stats = ixgb_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; void ixgb_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index d5f694fc4a21..d9ce1aef148a 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -111,7 +111,7 @@ static int ixpdev_rx(struct net_device *dev, int *budget) skb = dev_alloc_skb(desc->pkt_length + 2); if (likely(skb != NULL)) { skb_reserve(skb, 2); - eth_copy_and_sum(skb, buf, desc->pkt_length, 0); + skb_copy_to_linear_data(skb, buf, desc->pkt_length); skb_put(skb, desc->pkt_length); skb->protocol = eth_type_trans(skb, nds[desc->channel]); diff --git a/drivers/net/lance.c b/drivers/net/lance.c index 0fe96c85828b..a4e5fab12628 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -533,11 +533,10 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int dev->base_addr = ioaddr; /* Make certain the data structures used by the LANCE are aligned and DMAble. */ - lp = kmalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL); + lp = kzalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL); if(lp==NULL) return -ENODEV; if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp); - memset(lp, 0, sizeof(*lp)); dev->priv = lp; lp->name = chipname; lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE, @@ -1186,9 +1185,9 @@ lance_rx(struct net_device *dev) } skb_reserve(skb,2); /* 16 byte align */ skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)), - pkt_len,0); + pkt_len); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 741780e14b2c..efbae4b8398e 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -86,93 +86,36 @@ #include <linux/dma-mapping.h> #include <asm/io.h> -#include <asm/pgtable.h> #include <asm/irq.h> #include <asm/pdc.h> -#include <asm/cache.h> #include <asm/parisc-device.h> #define LASI_82596_DRIVER_VERSION "LASI 82596 driver - Revision: 1.30" -/* DEBUG flags - */ - -#define DEB_INIT 0x0001 -#define DEB_PROBE 0x0002 -#define DEB_SERIOUS 0x0004 -#define DEB_ERRORS 0x0008 -#define DEB_MULTI 0x0010 -#define DEB_TDR 0x0020 -#define DEB_OPEN 0x0040 -#define DEB_RESET 0x0080 -#define DEB_ADDCMD 0x0100 -#define DEB_STATUS 0x0200 -#define DEB_STARTTX 0x0400 -#define DEB_RXADDR 0x0800 -#define DEB_TXADDR 0x1000 -#define DEB_RXFRAME 0x2000 -#define DEB_INTS 0x4000 -#define DEB_STRUCT 0x8000 -#define DEB_ANY 0xffff - - -#define DEB(x,y) if (i596_debug & (x)) { y; } - - -#define CHECK_WBACK(priv, addr,len) \ - do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0) - -#define CHECK_INV(priv, addr,len) \ - do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0) - -#define CHECK_WBACK_INV(priv, addr,len) \ - do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) - - #define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/ #define PA_CPU_PORT_L_ACCESS 4 #define PA_CHANNEL_ATTENTION 8 +#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */ -/* - * Define various macros for Channel Attention, word swapping etc., dependent - * on architecture. MVME and BVME are 680x0 based, otherwise it is Intel. - */ +#define DMA_ALLOC dma_alloc_noncoherent +#define DMA_FREE dma_free_noncoherent +#define DMA_WBACK(ndev, addr, len) \ + do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0) -#ifdef __BIG_ENDIAN -#define WSWAPrfd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPrbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPscb(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPcmd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPtbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define ISCP_BUSY 0x00010000 -#define MACH_IS_APRICOT 0 -#else -#define WSWAPrfd(x) ((struct i596_rfd *)(x)) -#define WSWAPrbd(x) ((struct i596_rbd *)(x)) -#define WSWAPiscp(x) ((struct i596_iscp *)(x)) -#define WSWAPscb(x) ((struct i596_scb *)(x)) -#define WSWAPcmd(x) ((struct i596_cmd *)(x)) -#define WSWAPtbd(x) ((struct i596_tbd *)(x)) -#define WSWAPchar(x) ((char *)(x)) -#define ISCP_BUSY 0x0001 -#define MACH_IS_APRICOT 1 -#endif +#define DMA_INV(ndev, addr, len) \ + do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_FROM_DEVICE); } while (0) -/* - * The MPU_PORT command allows direct access to the 82596. With PORT access - * the following commands are available (p5-18). The 32-bit port command - * must be word-swapped with the most significant word written first. - * This only applies to VME boards. - */ -#define PORT_RESET 0x00 /* reset 82596 */ -#define PORT_SELFTEST 0x01 /* selftest */ -#define PORT_ALTSCP 0x02 /* alternate SCB address */ -#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */ +#define DMA_WBACK_INV(ndev, addr, len) \ + do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) + +#define SYSBUS 0x0000006c; + +/* big endian CPU, 82596 "big" endian mode */ +#define SWAP32(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define SWAP16(x) (x) -static int i596_debug = (DEB_SERIOUS|DEB_PROBE); +#include "lib82596.c" MODULE_AUTHOR("Richard Hirst"); MODULE_DESCRIPTION("i82596 driver"); @@ -180,255 +123,15 @@ MODULE_LICENSE("GPL"); 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 - * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). - */ -static int rx_copybreak = 100; - -#define MAX_DRIVERS 4 /* max count of drivers */ - -#define PKT_BUF_SZ 1536 -#define MAX_MC_CNT 64 - -#define I596_NULL ((u32)0xffffffff) - -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -#define CMD_FLEX 0x0008 /* Enable flexible memory model */ - -enum commands { - CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7 -}; - -#define STAT_C 0x8000 /* Set to 0 after execution */ -#define STAT_B 0x4000 /* Command being executed */ -#define STAT_OK 0x2000 /* Command executed ok */ -#define STAT_A 0x1000 /* Command aborted */ - -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define CUC_ABORT 0x0400 -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 -#define RX_ABORT 0x0040 - -#define TX_TIMEOUT 5 - -#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */ - - -struct i596_reg { - unsigned short porthi; - unsigned short portlo; - u32 ca; -}; - -#define EOF 0x8000 -#define SIZE_MASK 0x3fff - -struct i596_tbd { - unsigned short size; - unsigned short pad; - dma_addr_t next; - dma_addr_t data; - u32 cache_pad[5]; /* Total 32 bytes... */ -}; - -/* The command structure has two 'next' pointers; v_next is the address of - * the next command as seen by the CPU, b_next is the address of the next - * command as seen by the 82596. The b_next pointer, as used by the 82596 - * always references the status field of the next command, rather than the - * v_next field, because the 82596 is unaware of v_next. It may seem more - * logical to put v_next at the end of the structure, but we cannot do that - * because the 82596 expects other fields to be there, depending on command - * type. - */ - -struct i596_cmd { - struct i596_cmd *v_next; /* Address from CPUs viewpoint */ - unsigned short status; - unsigned short command; - dma_addr_t b_next; /* Address from i596 viewpoint */ -}; - -struct tx_cmd { - struct i596_cmd cmd; - dma_addr_t tbd; - unsigned short size; - unsigned short pad; - struct sk_buff *skb; /* So we can free it after tx */ - dma_addr_t dma_addr; -#ifdef __LP64__ - u32 cache_pad[6]; /* Total 64 bytes... */ -#else - u32 cache_pad[1]; /* Total 32 bytes... */ -#endif -}; - -struct tdr_cmd { - struct i596_cmd cmd; - unsigned short status; - unsigned short pad; -}; - -struct mc_cmd { - struct i596_cmd cmd; - short mc_cnt; - char mc_addrs[MAX_MC_CNT*6]; -}; - -struct sa_cmd { - struct i596_cmd cmd; - char eth_addr[8]; -}; - -struct cf_cmd { - struct i596_cmd cmd; - char i596_config[16]; -}; - -struct i596_rfd { - unsigned short stat; - unsigned short cmd; - dma_addr_t b_next; /* Address from i596 viewpoint */ - dma_addr_t rbd; - unsigned short count; - unsigned short size; - struct i596_rfd *v_next; /* Address from CPUs viewpoint */ - struct i596_rfd *v_prev; -#ifndef __LP64__ - u32 cache_pad[2]; /* Total 32 bytes... */ -#endif -}; - -struct i596_rbd { - /* hardware data */ - unsigned short count; - unsigned short zero1; - dma_addr_t b_next; - dma_addr_t b_data; /* Address from i596 viewpoint */ - unsigned short size; - unsigned short zero2; - /* driver data */ - struct sk_buff *skb; - struct i596_rbd *v_next; - dma_addr_t b_addr; /* This rbd addr from i596 view */ - unsigned char *v_data; /* Address from CPUs viewpoint */ - /* Total 32 bytes... */ -#ifdef __LP64__ - u32 cache_pad[4]; -#endif -}; - -/* These values as chosen so struct i596_private fits in one page... */ - -#define TX_RING_SIZE 32 -#define RX_RING_SIZE 16 - -struct i596_scb { - unsigned short status; - unsigned short command; - dma_addr_t cmd; - dma_addr_t rfd; - u32 crc_err; - u32 align_err; - u32 resource_err; - u32 over_err; - u32 rcvdt_err; - u32 short_err; - unsigned short t_on; - unsigned short t_off; -}; - -struct i596_iscp { - u32 stat; - dma_addr_t scb; -}; - -struct i596_scp { - u32 sysbus; - u32 pad; - dma_addr_t iscp; -}; - -struct i596_private { - volatile struct i596_scp scp __attribute__((aligned(32))); - volatile struct i596_iscp iscp __attribute__((aligned(32))); - volatile struct i596_scb scb __attribute__((aligned(32))); - struct sa_cmd sa_cmd __attribute__((aligned(32))); - struct cf_cmd cf_cmd __attribute__((aligned(32))); - struct tdr_cmd tdr_cmd __attribute__((aligned(32))); - struct mc_cmd mc_cmd __attribute__((aligned(32))); - struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32))); - struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32))); - struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32))); - struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32))); - u32 stat; - int last_restart; - struct i596_rfd *rfd_head; - struct i596_rbd *rbd_head; - struct i596_cmd *cmd_tail; - struct i596_cmd *cmd_head; - int cmd_backlog; - u32 last_cmd; - struct net_device_stats stats; - int next_tx_cmd; - int options; - spinlock_t lock; - dma_addr_t dma_addr; - struct device *dev; -}; - -static const char init_setup[] = -{ - 0x8E, /* length, prefetch on */ - 0xC8, /* fifo to 8, monitor off */ - 0x80, /* don't save bad frames */ - 0x2E, /* No source address insertion, 8 byte preamble */ - 0x00, /* priority and backoff defaults */ - 0x60, /* interframe spacing */ - 0x00, /* slot time LSB */ - 0xf2, /* slot time and retries */ - 0x00, /* promiscuous mode */ - 0x00, /* collision detect */ - 0x40, /* minimum frame length */ - 0xff, - 0x00, - 0x7f /* *multi IA */ }; - -static int i596_open(struct net_device *dev); -static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t i596_interrupt(int irq, void *dev_id); -static int i596_close(struct net_device *dev); -static struct net_device_stats *i596_get_stats(struct net_device *dev); -static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd); -static void i596_tx_timeout (struct net_device *dev); -static void print_eth(unsigned char *buf, char *str); -static void set_multicast_list(struct net_device *dev); - -static int rx_ring_size = RX_RING_SIZE; -static int ticks_limit = 100; -static int max_cmd_backlog = TX_RING_SIZE-1; - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void i596_poll_controller(struct net_device *dev); -#endif - - -static inline void CA(struct net_device *dev) +static inline void ca(struct net_device *dev) { gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION); } -static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x) +static void mpu_port(struct net_device *dev, int c, dma_addr_t x) { - struct i596_private *lp = dev->priv; + struct i596_private *lp = netdev_priv(dev); u32 v = (u32) (c) | (u32) (x); u16 a, b; @@ -446,1078 +149,15 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x) gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS); } - -static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) -{ - CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); - while (--delcnt && lp->iscp.stat) { - udelay(10); - CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); - } - if (!delcnt) { - printk("%s: %s, iscp.stat %04x, didn't clear\n", - dev->name, str, lp->iscp.stat); - return -1; - } - else - return 0; -} - - -static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) -{ - CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); - while (--delcnt && lp->scb.command) { - udelay(10); - CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); - } - if (!delcnt) { - printk("%s: %s, status %4.4x, cmd %4.4x.\n", - dev->name, str, lp->scb.status, lp->scb.command); - return -1; - } - else - return 0; -} - - -static void i596_display_data(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct i596_cmd *cmd; - struct i596_rfd *rfd; - struct i596_rbd *rbd; - - printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n", - &lp->scp, lp->scp.sysbus, lp->scp.iscp); - printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n", - &lp->iscp, lp->iscp.stat, lp->iscp.scb); - printk("scb at %p, scb.status = %04x, .command = %04x," - " .cmd = %08x, .rfd = %08x\n", - &lp->scb, lp->scb.status, lp->scb.command, - lp->scb.cmd, lp->scb.rfd); - printk(" errors: crc %x, align %x, resource %x," - " over %x, rcvdt %x, short %x\n", - lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err, - lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err); - cmd = lp->cmd_head; - while (cmd != NULL) { - printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n", - cmd, cmd->status, cmd->command, cmd->b_next); - cmd = cmd->v_next; - } - rfd = lp->rfd_head; - printk("rfd_head = %p\n", rfd); - do { - printk(" %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x," - " count %04x\n", - rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd, - rfd->count); - rfd = rfd->v_next; - } while (rfd != lp->rfd_head); - rbd = lp->rbd_head; - printk("rbd_head = %p\n", rbd); - do { - printk(" %p .count %04x, b_next %08x, b_data %08x, size %04x\n", - rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size); - rbd = rbd->v_next; - } while (rbd != lp->rbd_head); - CHECK_INV(lp, lp, sizeof(struct i596_private)); -} - - -#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET) -static void i596_error(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; - - pcc2[0x28] = 1; - pcc2[0x2b] = 0x1d; - printk("%s: Error interrupt\n", dev->name); - i596_display_data(dev); -} -#endif - -#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp))) - -static inline void init_rx_bufs(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - int i; - struct i596_rfd *rfd; - struct i596_rbd *rbd; - - /* First build the Receive Buffer Descriptor List */ - - for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { - dma_addr_t dma_addr; - struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4); - - if (skb == NULL) - panic("%s: alloc_skb() failed", __FILE__); - skb_reserve(skb, 2); - dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ, - DMA_FROM_DEVICE); - skb->dev = dev; - rbd->v_next = rbd+1; - rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1)); - rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd)); - rbd->skb = skb; - rbd->v_data = skb->data; - rbd->b_data = WSWAPchar(dma_addr); - rbd->size = PKT_BUF_SZ; - } - lp->rbd_head = lp->rbds; - rbd = lp->rbds + rx_ring_size - 1; - rbd->v_next = lp->rbds; - rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds)); - - /* Now build the Receive Frame Descriptor List */ - - for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) { - rfd->rbd = I596_NULL; - rfd->v_next = rfd+1; - rfd->v_prev = rfd-1; - rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1)); - rfd->cmd = CMD_FLEX; - } - lp->rfd_head = lp->rfds; - lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - rfd = lp->rfds; - rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head)); - rfd->v_prev = lp->rfds + rx_ring_size - 1; - rfd = lp->rfds + rx_ring_size - 1; - rfd->v_next = lp->rfds; - rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - rfd->cmd = CMD_EOL|CMD_FLEX; - - CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); -} - -static inline void remove_rx_bufs(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct i596_rbd *rbd; - int i; - - for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { - if (rbd->skb == NULL) - break; - dma_unmap_single(lp->dev, - (dma_addr_t)WSWAPchar(rbd->b_data), - PKT_BUF_SZ, DMA_FROM_DEVICE); - dev_kfree_skb(rbd->skb); - } -} - - -static void rebuild_rx_bufs(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - int i; - - /* Ensure rx frame/buffer descriptors are tidy */ - - for (i = 0; i < rx_ring_size; i++) { - lp->rfds[i].rbd = I596_NULL; - lp->rfds[i].cmd = CMD_FLEX; - } - lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX; - lp->rfd_head = lp->rfds; - lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - lp->rbd_head = lp->rbds; - lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds)); - - CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); -} - - -static int init_i596_mem(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - unsigned long flags; - - disable_irq(dev->irq); /* disable IRQs from LAN */ - DEB(DEB_INIT, - printk("RESET 82596 port: %lx (with IRQ %d disabled)\n", - (dev->base_addr + PA_I82596_RESET), - dev->irq)); - - gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */ - udelay(100); /* Wait 100us - seems to help */ - - /* change the scp address */ - - lp->last_cmd = jiffies; - - - lp->scp.sysbus = 0x0000006c; - lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp))); - lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb))); - lp->iscp.stat = ISCP_BUSY; - lp->cmd_backlog = 0; - - lp->cmd_head = NULL; - lp->scb.cmd = I596_NULL; - - DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name)); - - CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp)); - CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp)); - - MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp)); - - CA(dev); - - if (wait_istat(dev, lp, 1000, "initialization timed out")) - goto failed; - DEB(DEB_INIT, printk("%s: i82596 initialization successful\n", dev->name)); - - /* Ensure rx frame/buffer descriptors are tidy */ - rebuild_rx_bufs(dev); - - lp->scb.command = 0; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - - enable_irq(dev->irq); /* enable IRQs from LAN */ - - DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name)); - memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup)); - lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd)); - i596_add_cmd(dev, &lp->cf_cmd.cmd); - - DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name)); - memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6); - lp->sa_cmd.cmd.command = CmdSASetup; - CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd)); - i596_add_cmd(dev, &lp->sa_cmd.cmd); - - DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name)); - lp->tdr_cmd.cmd.command = CmdTDR; - CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd)); - i596_add_cmd(dev, &lp->tdr_cmd.cmd); - - spin_lock_irqsave (&lp->lock, flags); - - if (wait_cmd(dev, lp, 1000, "timed out waiting to issue RX_START")) { - spin_unlock_irqrestore (&lp->lock, flags); - goto failed; - } - DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name)); - lp->scb.command = RX_START; - lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - - CA(dev); - - spin_unlock_irqrestore (&lp->lock, flags); - - if (wait_cmd(dev, lp, 1000, "RX_START not processed")) - goto failed; - DEB(DEB_INIT, printk("%s: Receive unit started OK\n", dev->name)); - - return 0; - -failed: - printk("%s: Failed to initialise 82596\n", dev->name); - MPU_PORT(dev, PORT_RESET, 0); - return -1; -} - - -static inline int i596_rx(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct i596_rfd *rfd; - struct i596_rbd *rbd; - int frames = 0; - - DEB(DEB_RXFRAME, printk("i596_rx(), rfd_head %p, rbd_head %p\n", - lp->rfd_head, lp->rbd_head)); - - - rfd = lp->rfd_head; /* Ref next frame to check */ - - CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); - while ((rfd->stat) & STAT_C) { /* Loop while complete frames */ - if (rfd->rbd == I596_NULL) - rbd = NULL; - else if (rfd->rbd == lp->rbd_head->b_addr) { - rbd = lp->rbd_head; - CHECK_INV(lp, rbd, sizeof(struct i596_rbd)); - } - else { - printk("%s: rbd chain broken!\n", dev->name); - /* XXX Now what? */ - rbd = NULL; - } - DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %08x, rfd.stat %04x\n", - rfd, rfd->rbd, rfd->stat)); - - if (rbd != NULL && ((rfd->stat) & STAT_OK)) { - /* a good frame */ - int pkt_len = rbd->count & 0x3fff; - struct sk_buff *skb = rbd->skb; - int rx_in_place = 0; - - DEB(DEB_RXADDR,print_eth(rbd->v_data, "received")); - frames++; - - /* Check if the packet is long enough to just accept - * without copying to a properly sized skbuff. - */ - - if (pkt_len > rx_copybreak) { - struct sk_buff *newskb; - dma_addr_t dma_addr; - - dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); - /* Get fresh skbuff to replace filled one. */ - newskb = dev_alloc_skb(PKT_BUF_SZ + 4); - if (newskb == NULL) { - skb = NULL; /* drop pkt */ - goto memory_squeeze; - } - skb_reserve(newskb, 2); - - /* Pass up the skb already on the Rx ring. */ - skb_put(skb, pkt_len); - rx_in_place = 1; - rbd->skb = newskb; - newskb->dev = dev; - dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE); - rbd->v_data = newskb->data; - rbd->b_data = WSWAPchar(dma_addr); - CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); - } - else - skb = dev_alloc_skb(pkt_len + 2); -memory_squeeze: - if (skb == NULL) { - /* XXX tulip.c can defer packets here!! */ - printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - } - else { - if (!rx_in_place) { - /* 16 byte align the data fields */ - dma_sync_single_for_cpu(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); - skb_reserve(skb, 2); - memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len); - dma_sync_single_for_device(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); - } - skb->len = pkt_len; - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - lp->stats.rx_bytes+=pkt_len; - } - } - else { - DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n", - dev->name, rfd->stat)); - lp->stats.rx_errors++; - if ((rfd->stat) & 0x0001) - lp->stats.collisions++; - if ((rfd->stat) & 0x0080) - lp->stats.rx_length_errors++; - if ((rfd->stat) & 0x0100) - lp->stats.rx_over_errors++; - if ((rfd->stat) & 0x0200) - lp->stats.rx_fifo_errors++; - if ((rfd->stat) & 0x0400) - lp->stats.rx_frame_errors++; - if ((rfd->stat) & 0x0800) - lp->stats.rx_crc_errors++; - if ((rfd->stat) & 0x1000) - lp->stats.rx_length_errors++; - } - - /* Clear the buffer descriptor count and EOF + F flags */ - - if (rbd != NULL && (rbd->count & 0x4000)) { - rbd->count = 0; - lp->rbd_head = rbd->v_next; - CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); - } - - /* Tidy the frame descriptor, marking it as end of list */ - - rfd->rbd = I596_NULL; - rfd->stat = 0; - rfd->cmd = CMD_EOL|CMD_FLEX; - rfd->count = 0; - - /* Remove end-of-list from old end descriptor */ - - rfd->v_prev->cmd = CMD_FLEX; - - /* Update record of next frame descriptor to process */ - - lp->scb.rfd = rfd->b_next; - lp->rfd_head = rfd->v_next; - CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd)); - CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd)); - rfd = lp->rfd_head; - CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); - } - - DEB(DEB_RXFRAME, printk("frames %d\n", frames)); - - return 0; -} - - -static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp) -{ - struct i596_cmd *ptr; - - while (lp->cmd_head != NULL) { - ptr = lp->cmd_head; - lp->cmd_head = ptr->v_next; - lp->cmd_backlog--; - - switch ((ptr->command) & 0x7) { - case CmdTx: - { - struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; - struct sk_buff *skb = tx_cmd->skb; - dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE); - - dev_kfree_skb(skb); - - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - - ptr->v_next = NULL; - ptr->b_next = I596_NULL; - tx_cmd->cmd.command = 0; /* Mark as free */ - break; - } - default: - ptr->v_next = NULL; - ptr->b_next = I596_NULL; - } - CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd)); - } - - wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out"); - lp->scb.cmd = I596_NULL; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); -} - - -static inline void i596_reset(struct net_device *dev, struct i596_private *lp) -{ - unsigned long flags; - - DEB(DEB_RESET, printk("i596_reset\n")); - - spin_lock_irqsave (&lp->lock, flags); - - wait_cmd(dev, lp, 100, "i596_reset timed out"); - - netif_stop_queue(dev); - - /* FIXME: this command might cause an lpmc */ - lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - CA(dev); - - /* wait for shutdown */ - wait_cmd(dev, lp, 1000, "i596_reset 2 timed out"); - spin_unlock_irqrestore (&lp->lock, flags); - - i596_cleanup_cmd(dev,lp); - i596_rx(dev); - - netif_start_queue(dev); - init_i596_mem(dev); -} - - -static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) -{ - struct i596_private *lp = dev->priv; - unsigned long flags; - - DEB(DEB_ADDCMD, printk("i596_add_cmd cmd_head %p\n", lp->cmd_head)); - - cmd->status = 0; - cmd->command |= (CMD_EOL | CMD_INTR); - cmd->v_next = NULL; - cmd->b_next = I596_NULL; - CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd)); - - spin_lock_irqsave (&lp->lock, flags); - - if (lp->cmd_head != NULL) { - lp->cmd_tail->v_next = cmd; - lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status)); - CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd)); - } else { - lp->cmd_head = cmd; - wait_cmd(dev, lp, 100, "i596_add_cmd timed out"); - lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status)); - lp->scb.command = CUC_START; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - CA(dev); - } - lp->cmd_tail = cmd; - lp->cmd_backlog++; - - spin_unlock_irqrestore (&lp->lock, flags); - - if (lp->cmd_backlog > max_cmd_backlog) { - unsigned long tickssofar = jiffies - lp->last_cmd; - - if (tickssofar < ticks_limit) - return; - - printk("%s: command unit timed out, status resetting.\n", dev->name); -#if 1 - i596_reset(dev, lp); -#endif - } -} - -#if 0 -/* this function makes a perfectly adequate probe... but we have a - device list */ -static int i596_test(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - volatile int *tint; - u32 data; - - tint = (volatile int *)(&(lp->scp)); - data = virt_to_dma(lp,tint); - - tint[1] = -1; - CHECK_WBACK(lp, tint, PAGE_SIZE); - - MPU_PORT(dev, 1, data); - - for(data = 1000000; data; data--) { - CHECK_INV(lp, tint, PAGE_SIZE); - if(tint[1] != -1) - break; - - } - - printk("i596_test result %d\n", tint[1]); - -} -#endif - - -static int i596_open(struct net_device *dev) -{ - DEB(DEB_OPEN, printk("%s: i596_open() irq %d.\n", dev->name, dev->irq)); - - if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) { - printk("%s: IRQ %d not free\n", dev->name, dev->irq); - goto out; - } - - init_rx_bufs(dev); - - if (init_i596_mem(dev)) { - printk("%s: Failed to init memory\n", dev->name); - goto out_remove_rx_bufs; - } - - netif_start_queue(dev); - - return 0; - -out_remove_rx_bufs: - remove_rx_bufs(dev); - free_irq(dev->irq, dev); -out: - return -EAGAIN; -} - -static void i596_tx_timeout (struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - - /* Transmitter timeout, serious problems. */ - DEB(DEB_ERRORS, printk("%s: transmit timed out, status resetting.\n", - dev->name)); - - lp->stats.tx_errors++; - - /* Try to restart the adaptor */ - if (lp->last_restart == lp->stats.tx_packets) { - DEB(DEB_ERRORS, printk("Resetting board.\n")); - /* Shutdown and restart */ - i596_reset (dev, lp); - } else { - /* Issue a channel attention signal */ - DEB(DEB_ERRORS, printk("Kicking board.\n")); - lp->scb.command = CUC_START | RX_START; - CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); - CA (dev); - lp->last_restart = lp->stats.tx_packets; - } - - dev->trans_start = jiffies; - netif_wake_queue (dev); -} - - -static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct tx_cmd *tx_cmd; - struct i596_tbd *tbd; - short length = skb->len; - dev->trans_start = jiffies; - - DEB(DEB_STARTTX, printk("%s: i596_start_xmit(%x,%p) called\n", dev->name, - skb->len, skb->data)); - - if (length < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - return 0; - length = ETH_ZLEN; - } - - netif_stop_queue(dev); - - tx_cmd = lp->tx_cmds + lp->next_tx_cmd; - tbd = lp->tbds + lp->next_tx_cmd; - - if (tx_cmd->cmd.command) { - DEB(DEB_ERRORS, printk("%s: xmit ring full, dropping packet.\n", - dev->name)); - lp->stats.tx_dropped++; - - dev_kfree_skb(skb); - } else { - if (++lp->next_tx_cmd == TX_RING_SIZE) - lp->next_tx_cmd = 0; - tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd)); - tbd->next = I596_NULL; - - tx_cmd->cmd.command = CMD_FLEX | CmdTx; - tx_cmd->skb = skb; - - tx_cmd->pad = 0; - tx_cmd->size = 0; - tbd->pad = 0; - tbd->size = EOF | length; - - tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len, - DMA_TO_DEVICE); - tbd->data = WSWAPchar(tx_cmd->dma_addr); - - DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued")); - CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd)); - CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd)); - i596_add_cmd(dev, &tx_cmd->cmd); - - lp->stats.tx_packets++; - lp->stats.tx_bytes += length; - } - - netif_start_queue(dev); - - return 0; -} - -static void print_eth(unsigned char *add, char *str) -{ - int i; - - printk("i596 0x%p, ", add); - for (i = 0; i < 6; i++) - printk(" %02X", add[i + 6]); - printk(" -->"); - for (i = 0; i < 6; i++) - printk(" %02X", add[i]); - printk(" %02X%02X, %s\n", add[12], add[13], str); -} - - #define LAN_PROM_ADDR 0xF0810000 -static int __devinit i82596_probe(struct net_device *dev, - struct device *gen_dev) -{ - int i; - struct i596_private *lp; - char eth_addr[6]; - dma_addr_t dma_addr; - - /* This lot is ensure things have been cache line aligned. */ - BUILD_BUG_ON(sizeof(struct i596_rfd) != 32); - BUILD_BUG_ON(sizeof(struct i596_rbd) & 31); - BUILD_BUG_ON(sizeof(struct tx_cmd) & 31); - BUILD_BUG_ON(sizeof(struct i596_tbd) != 32); -#ifndef __LP64__ - BUILD_BUG_ON(sizeof(struct i596_private) > 4096); -#endif - - if (!dev->base_addr || !dev->irq) - return -ENODEV; - - if (pdc_lan_station_id(eth_addr, dev->base_addr)) { - for (i=0; i < 6; i++) { - eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i); - } - printk(KERN_INFO "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__); - } - - dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev, - sizeof(struct i596_private), &dma_addr, GFP_KERNEL); - if (!dev->mem_start) { - printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__); - return -ENOMEM; - } - - for (i = 0; i < 6; i++) - dev->dev_addr[i] = eth_addr[i]; - - /* The 82596-specific entries in the device structure. */ - dev->open = i596_open; - dev->stop = i596_close; - dev->hard_start_xmit = i596_start_xmit; - dev->get_stats = i596_get_stats; - dev->set_multicast_list = set_multicast_list; - dev->tx_timeout = i596_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = i596_poll_controller; -#endif - - dev->priv = (void *)(dev->mem_start); - - lp = dev->priv; - memset(lp, 0, sizeof(struct i596_private)); - - lp->scb.command = 0; - lp->scb.cmd = I596_NULL; - lp->scb.rfd = I596_NULL; - spin_lock_init(&lp->lock); - lp->dma_addr = dma_addr; - lp->dev = gen_dev; - - CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private)); - - i = register_netdev(dev); - if (i) { - lp = dev->priv; - dma_free_noncoherent(lp->dev, sizeof(struct i596_private), - (void *)dev->mem_start, lp->dma_addr); - return i; - }; - - DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr)); - for (i = 0; i < 6; i++) - DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i])); - DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq)); - DEB(DEB_INIT, printk(KERN_INFO "%s: lp at 0x%p (%d bytes), lp->scb at 0x%p\n", - dev->name, lp, (int)sizeof(struct i596_private), &lp->scb)); - - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void i596_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - i596_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static irqreturn_t i596_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct i596_private *lp; - unsigned short status, ack_cmd = 0; - - if (dev == NULL) { - printk("%s: irq %d for unknown device.\n", __FUNCTION__, irq); - return IRQ_NONE; - } - - lp = dev->priv; - - spin_lock (&lp->lock); - - wait_cmd(dev, lp, 100, "i596 interrupt, timeout"); - status = lp->scb.status; - - DEB(DEB_INTS, printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n", - dev->name, irq, status)); - - ack_cmd = status & 0xf000; - - if (!ack_cmd) { - DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name)); - spin_unlock (&lp->lock); - return IRQ_NONE; - } - - if ((status & 0x8000) || (status & 0x2000)) { - struct i596_cmd *ptr; - - if ((status & 0x8000)) - DEB(DEB_INTS, printk("%s: i596 interrupt completed command.\n", dev->name)); - if ((status & 0x2000)) - DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); - - while (lp->cmd_head != NULL) { - CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd)); - if (!(lp->cmd_head->status & STAT_C)) - break; - - ptr = lp->cmd_head; - - DEB(DEB_STATUS, printk("cmd_head->status = %04x, ->command = %04x\n", - lp->cmd_head->status, lp->cmd_head->command)); - lp->cmd_head = ptr->v_next; - lp->cmd_backlog--; - - switch ((ptr->command) & 0x7) { - case CmdTx: - { - struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; - struct sk_buff *skb = tx_cmd->skb; - - if ((ptr->status) & STAT_OK) { - DEB(DEB_TXADDR, print_eth(skb->data, "tx-done")); - } else { - lp->stats.tx_errors++; - if ((ptr->status) & 0x0020) - lp->stats.collisions++; - if (!((ptr->status) & 0x0040)) - lp->stats.tx_heartbeat_errors++; - if ((ptr->status) & 0x0400) - lp->stats.tx_carrier_errors++; - if ((ptr->status) & 0x0800) - lp->stats.collisions++; - if ((ptr->status) & 0x1000) - lp->stats.tx_aborted_errors++; - } - dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq(skb); - - tx_cmd->cmd.command = 0; /* Mark free */ - break; - } - case CmdTDR: - { - unsigned short status = ((struct tdr_cmd *)ptr)->status; - - if (status & 0x8000) { - DEB(DEB_ANY, printk("%s: link ok.\n", dev->name)); - } else { - if (status & 0x4000) - printk("%s: Transceiver problem.\n", dev->name); - if (status & 0x2000) - printk("%s: Termination problem.\n", dev->name); - if (status & 0x1000) - printk("%s: Short circuit.\n", dev->name); - - DEB(DEB_TDR, printk("%s: Time %d.\n", dev->name, status & 0x07ff)); - } - break; - } - case CmdConfigure: - /* Zap command so set_multicast_list() knows it is free */ - ptr->command = 0; - break; - } - ptr->v_next = NULL; - ptr->b_next = I596_NULL; - CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd)); - lp->last_cmd = jiffies; - } - - /* This mess is arranging that only the last of any outstanding - * commands has the interrupt bit set. Should probably really - * only add to the cmd queue when the CU is stopped. - */ - ptr = lp->cmd_head; - while ((ptr != NULL) && (ptr != lp->cmd_tail)) { - struct i596_cmd *prev = ptr; - - ptr->command &= 0x1fff; - ptr = ptr->v_next; - CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd)); - } - - if ((lp->cmd_head != NULL)) - ack_cmd |= CUC_START; - lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status)); - CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb)); - } - if ((status & 0x1000) || (status & 0x4000)) { - if ((status & 0x4000)) - DEB(DEB_INTS, printk("%s: i596 interrupt received a frame.\n", dev->name)); - i596_rx(dev); - /* Only RX_START if stopped - RGH 07-07-96 */ - if (status & 0x1000) { - if (netif_running(dev)) { - DEB(DEB_ERRORS, printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status)); - ack_cmd |= RX_START; - lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; - rebuild_rx_bufs(dev); - } - } - } - wait_cmd(dev, lp, 100, "i596 interrupt, timeout"); - lp->scb.command = ack_cmd; - CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); - - /* DANGER: I suspect that some kind of interrupt - acknowledgement aside from acking the 82596 might be needed - here... but it's running acceptably without */ - - CA(dev); - - wait_cmd(dev, lp, 100, "i596 interrupt, exit timeout"); - DEB(DEB_INTS, printk("%s: exiting interrupt.\n", dev->name)); - - spin_unlock (&lp->lock); - return IRQ_HANDLED; -} - -static int i596_close(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - unsigned long flags; - - netif_stop_queue(dev); - - DEB(DEB_INIT, printk("%s: Shutting down ethercard, status was %4.4x.\n", - dev->name, lp->scb.status)); - - spin_lock_irqsave(&lp->lock, flags); - - wait_cmd(dev, lp, 100, "close1 timed out"); - lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); - - CA(dev); - - wait_cmd(dev, lp, 100, "close2 timed out"); - spin_unlock_irqrestore(&lp->lock, flags); - DEB(DEB_STRUCT,i596_display_data(dev)); - i596_cleanup_cmd(dev,lp); - - disable_irq(dev->irq); - - free_irq(dev->irq, dev); - remove_rx_bufs(dev); - - return 0; -} - -static struct net_device_stats * - i596_get_stats(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - - return &lp->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - */ - -static void set_multicast_list(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - int config = 0, cnt; - - DEB(DEB_MULTI, printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", - dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", - dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); - - if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) { - lp->cf_cmd.i596_config[8] |= 0x01; - config = 1; - } - if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) { - lp->cf_cmd.i596_config[8] &= ~0x01; - config = 1; - } - if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) { - lp->cf_cmd.i596_config[11] &= ~0x20; - config = 1; - } - if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) { - lp->cf_cmd.i596_config[11] |= 0x20; - config = 1; - } - if (config) { - if (lp->cf_cmd.cmd.command) - printk("%s: config change request already queued\n", - dev->name); - else { - lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd)); - i596_add_cmd(dev, &lp->cf_cmd.cmd); - } - } - - cnt = dev->mc_count; - if (cnt > MAX_MC_CNT) - { - cnt = MAX_MC_CNT; - printk("%s: Only %d multicast addresses supported", - dev->name, cnt); - } - - if (dev->mc_count > 0) { - struct dev_mc_list *dmi; - unsigned char *cp; - struct mc_cmd *cmd; - - cmd = &lp->mc_cmd; - cmd->cmd.command = CmdMulticastList; - cmd->mc_cnt = dev->mc_count * 6; - cp = cmd->mc_addrs; - for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) { - memcpy(cp, dmi->dmi_addr, 6); - if (i596_debug > 1) - DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5])); - } - CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd)); - i596_add_cmd(dev, &cmd->cmd); - } -} - -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]; - static int __devinit lan_init_chip(struct parisc_device *dev) { struct net_device *netdevice; + struct i596_private *lp; int retval; - - if (num_drivers >= MAX_DRIVERS) { - /* max count of possible i82596 drivers reached */ - return -ENOMEM; - } - - if (num_drivers == 0) - printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n"); + int i; if (!dev->irq) { printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n", @@ -1528,28 +168,45 @@ lan_init_chip(struct parisc_device *dev) printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start, dev->irq); - netdevice = alloc_etherdev(0); + netdevice = alloc_etherdev(sizeof(struct i596_private)); if (!netdevice) return -ENOMEM; + SET_NETDEV_DEV(netdevice, &dev->dev); + parisc_set_drvdata (dev, netdevice); netdevice->base_addr = dev->hpa.start; netdevice->irq = dev->irq; - retval = i82596_probe(netdevice, &dev->dev); + if (pdc_lan_station_id(netdevice->dev_addr, netdevice->base_addr)) { + for (i = 0; i < 6; i++) { + netdevice->dev_addr[i] = gsc_readb(LAN_PROM_ADDR + i); + } + printk(KERN_INFO + "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__); + } + + lp = netdev_priv(netdevice); + lp->options = dev->id.sversion == 0x72 ? OPT_SWAP_PORT : 0; + + retval = i82596_probe(netdevice); if (retval) { free_netdev(netdevice); return -ENODEV; } - - if (dev->id.sversion == 0x72) { - ((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT; - } - - netdevs[num_drivers++] = netdevice; - return retval; } +static int __devexit lan_remove_chip (struct parisc_device *pdev) +{ + struct net_device *dev = parisc_get_drvdata(pdev); + struct i596_private *lp = netdev_priv(dev); + + unregister_netdev (dev); + DMA_FREE(&pdev->dev, sizeof(struct i596_private), + (void *)lp->dma, lp->dma_addr); + free_netdev (dev); + return 0; +} static struct parisc_device_id lan_tbl[] = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a }, @@ -1563,12 +220,12 @@ static struct parisc_driver lan_driver = { .name = "lasi_82596", .id_table = lan_tbl, .probe = lan_init_chip, + .remove = __devexit_p(lan_remove_chip), }; static int __devinit lasi_82596_init(void) { - if (debug >= 0) - i596_debug = debug; + printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n"); return register_parisc_driver(&lan_driver); } @@ -1576,25 +233,6 @@ module_init(lasi_82596_init); static void __exit lasi_82596_exit(void) { - int i; - - for (i=0; i<MAX_DRIVERS; i++) { - struct i596_private *lp; - struct net_device *netdevice; - - netdevice = netdevs[i]; - if (!netdevice) - continue; - - unregister_netdev(netdevice); - - lp = netdevice->priv; - dma_free_noncoherent(lp->dev, sizeof(struct i596_private), - (void *)netdevice->mem_start, lp->dma_addr); - free_netdev(netdevice); - } - num_drivers = 0; - unregister_parisc_driver(&lan_driver); } diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index 5c86e737f954..c429a5002dd6 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -143,6 +143,52 @@ static void __NS8390_init(struct net_device *dev, int startp); * annoying the transmit function is called bh atomic. That places * restrictions on the user context callers as disable_irq won't save * them. + * + * Additional explanation of problems with locking by Alan Cox: + * + * "The author (me) didn't use spin_lock_irqsave because the slowness of the + * card means that approach caused horrible problems like losing serial data + * at 38400 baud on some chips. Rememeber many 8390 nics on PCI were ISA + * chips with FPGA front ends. + * + * Ok the logic behind the 8390 is very simple: + * + * Things to know + * - IRQ delivery is asynchronous to the PCI bus + * - Blocking the local CPU IRQ via spin locks was too slow + * - The chip has register windows needing locking work + * + * So the path was once (I say once as people appear to have changed it + * in the mean time and it now looks rather bogus if the changes to use + * disable_irq_nosync_irqsave are disabling the local IRQ) + * + * + * Take the page lock + * Mask the IRQ on chip + * Disable the IRQ (but not mask locally- someone seems to have + * broken this with the lock validator stuff) + * [This must be _nosync as the page lock may otherwise + * deadlock us] + * Drop the page lock and turn IRQs back on + * + * At this point an existing IRQ may still be running but we can't + * get a new one + * + * Take the lock (so we know the IRQ has terminated) but don't mask + * the IRQs on the processor + * Set irqlock [for debug] + * + * Transmit (slow as ****) + * + * re-enable the IRQ + * + * + * We have to use disable_irq because otherwise you will get delayed + * interrupts on the APIC bus deadlocking the transmit path. + * + * Quite hairy but the chip simply wasn't designed for SMP and you can't + * even ACK an interrupt without risking corrupting other parallel + * activities on the chip." [lkml, 25 Jul 2007] */ @@ -219,15 +265,6 @@ static void ei_tx_timeout(struct net_device *dev) int txsr, isr, tickssofar = jiffies - dev->trans_start; unsigned long flags; -#if defined(CONFIG_M32R) && defined(CONFIG_SMP) - unsigned long icucr; - - local_irq_save(flags); - icucr = inl(M32R_ICU_CR1_PORTL); - icucr |= M32R_ICUCR_ISMOD11; - outl(icucr, M32R_ICU_CR1_PORTL); - local_irq_restore(flags); -#endif ei_local->stat.tx_errors++; spin_lock_irqsave(&ei_local->page_lock, flags); diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 6ba6ed2b480a..5106c2328d12 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -229,7 +229,12 @@ struct net_device loopback_dev = { /* Setup and register the loopback device. */ static int __init loopback_init(void) { - return register_netdev(&loopback_dev); + int err = register_netdev(&loopback_dev); + + if (err) + panic("loopback: Failed to register netdevice: %d\n", err); + + return err; }; module_init(loopback_init); diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index 26a3b45a4a34..62c1c6262feb 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c @@ -608,7 +608,7 @@ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)"); MODULE_LICENSE("GPL"); -int +int __init init_module(void) { net_debug = debug; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 0e04f7ac3f2e..a4bb0264180a 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -17,13 +17,12 @@ #include <linux/init.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> -#include <linux/mii.h> -#include <linux/mutex.h> #include <linux/dma-mapping.h> -#include <linux/ethtool.h> #include <linux/platform_device.h> +#include <linux/phy.h> #include <asm/arch/board.h> +#include <asm/arch/cpu.h> #include "macb.h" @@ -85,172 +84,202 @@ static void __init macb_get_hwaddr(struct macb *bp) memcpy(bp->dev->dev_addr, addr, sizeof(addr)); } -static void macb_enable_mdio(struct macb *bp) +static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&bp->lock, flags); - reg = macb_readl(bp, NCR); - reg |= MACB_BIT(MPE); - macb_writel(bp, NCR, reg); - macb_writel(bp, IER, MACB_BIT(MFD)); - spin_unlock_irqrestore(&bp->lock, flags); -} - -static void macb_disable_mdio(struct macb *bp) -{ - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&bp->lock, flags); - reg = macb_readl(bp, NCR); - reg &= ~MACB_BIT(MPE); - macb_writel(bp, NCR, reg); - macb_writel(bp, IDR, MACB_BIT(MFD)); - spin_unlock_irqrestore(&bp->lock, flags); -} - -static int macb_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct macb *bp = netdev_priv(dev); + struct macb *bp = bus->priv; int value; - mutex_lock(&bp->mdio_mutex); - - macb_enable_mdio(bp); macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_READ) - | MACB_BF(PHYA, phy_id) - | MACB_BF(REGA, location) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, regnum) | MACB_BF(CODE, MACB_MAN_CODE))); - wait_for_completion(&bp->mdio_complete); + /* wait for end of transfer */ + while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR))) + cpu_relax(); value = MACB_BFEXT(DATA, macb_readl(bp, MAN)); - macb_disable_mdio(bp); - mutex_unlock(&bp->mdio_mutex); return value; } -static void macb_mdio_write(struct net_device *dev, int phy_id, - int location, int val) +static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + u16 value) { - struct macb *bp = netdev_priv(dev); - - dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n", - phy_id, location, val); - - mutex_lock(&bp->mdio_mutex); - macb_enable_mdio(bp); + struct macb *bp = bus->priv; macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_WRITE) - | MACB_BF(PHYA, phy_id) - | MACB_BF(REGA, location) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, regnum) | MACB_BF(CODE, MACB_MAN_CODE) - | MACB_BF(DATA, val))); + | MACB_BF(DATA, value))); - wait_for_completion(&bp->mdio_complete); + /* wait for end of transfer */ + while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR))) + cpu_relax(); - macb_disable_mdio(bp); - mutex_unlock(&bp->mdio_mutex); + return 0; } -static int macb_phy_probe(struct macb *bp) +static int macb_mdio_reset(struct mii_bus *bus) { - int phy_address; - u16 phyid1, phyid2; + return 0; +} - for (phy_address = 0; phy_address < 32; phy_address++) { - phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1); - phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2); +static void macb_handle_link_change(struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + unsigned long flags; - if (phyid1 != 0xffff && phyid1 != 0x0000 - && phyid2 != 0xffff && phyid2 != 0x0000) - break; + int status_change = 0; + + spin_lock_irqsave(&bp->lock, flags); + + if (phydev->link) { + if ((bp->speed != phydev->speed) || + (bp->duplex != phydev->duplex)) { + u32 reg; + + reg = macb_readl(bp, NCFGR); + reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + + if (phydev->duplex) + reg |= MACB_BIT(FD); + if (phydev->speed) + reg |= MACB_BIT(SPD); + + macb_writel(bp, NCFGR, reg); + + bp->speed = phydev->speed; + bp->duplex = phydev->duplex; + status_change = 1; + } } - if (phy_address == 32) - return -ENODEV; + if (phydev->link != bp->link) { + if (phydev->link) + netif_schedule(dev); + else { + bp->speed = 0; + bp->duplex = -1; + } + bp->link = phydev->link; - dev_info(&bp->pdev->dev, - "detected PHY at address %d (ID %04x:%04x)\n", - phy_address, phyid1, phyid2); + status_change = 1; + } - bp->mii.phy_id = phy_address; - return 0; + spin_unlock_irqrestore(&bp->lock, flags); + + if (status_change) { + if (phydev->link) + printk(KERN_INFO "%s: link up (%d/%s)\n", + dev->name, phydev->speed, + DUPLEX_FULL == phydev->duplex ? "Full":"Half"); + else + printk(KERN_INFO "%s: link down\n", dev->name); + } } -static void macb_set_media(struct macb *bp, int media) +/* based on au1000_eth. c*/ +static int macb_mii_probe(struct net_device *dev) { - u32 reg; + struct macb *bp = netdev_priv(dev); + struct phy_device *phydev = NULL; + struct eth_platform_data *pdata; + int phy_addr; - spin_lock_irq(&bp->lock); - reg = macb_readl(bp, NCFGR); - reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); - if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL)) - reg |= MACB_BIT(SPD); - if (media & ADVERTISE_FULL) - reg |= MACB_BIT(FD); - macb_writel(bp, NCFGR, reg); - spin_unlock_irq(&bp->lock); + /* find the first phy */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + if (bp->mii_bus.phy_map[phy_addr]) { + phydev = bp->mii_bus.phy_map[phy_addr]; + break; + } + } + + if (!phydev) { + printk (KERN_ERR "%s: no PHY found\n", dev->name); + return -1; + } + + pdata = bp->pdev->dev.platform_data; + /* TODO : add pin_irq */ + + /* attach the mac to the phy */ + if (pdata && pdata->is_rmii) { + phydev = phy_connect(dev, phydev->dev.bus_id, + &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); + } else { + phydev = phy_connect(dev, phydev->dev.bus_id, + &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII); + } + + if (IS_ERR(phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); + return PTR_ERR(phydev); + } + + /* mask with MAC supported features */ + phydev->supported &= PHY_BASIC_FEATURES; + + phydev->advertising = phydev->supported; + + bp->link = 0; + bp->speed = 0; + bp->duplex = -1; + bp->phy_dev = phydev; + + return 0; } -static void macb_check_media(struct macb *bp, int ok_to_print, int init_media) +static int macb_mii_init(struct macb *bp) { - struct mii_if_info *mii = &bp->mii; - unsigned int old_carrier, new_carrier; - int advertise, lpa, media, duplex; + struct eth_platform_data *pdata; + int err = -ENXIO, i; - /* if forced media, go no further */ - if (mii->force_media) - return; + /* Enable managment port */ + macb_writel(bp, NCR, MACB_BIT(MPE)); - /* check current and old link status */ - old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; - new_carrier = (unsigned int) mii_link_ok(mii); + bp->mii_bus.name = "MACB_mii_bus", + bp->mii_bus.read = &macb_mdio_read, + bp->mii_bus.write = &macb_mdio_write, + bp->mii_bus.reset = &macb_mdio_reset, + bp->mii_bus.id = bp->pdev->id, + bp->mii_bus.priv = bp, + bp->mii_bus.dev = &bp->dev->dev; + pdata = bp->pdev->dev.platform_data; - /* if carrier state did not change, assume nothing else did */ - if (!init_media && old_carrier == new_carrier) - return; + if (pdata) + bp->mii_bus.phy_mask = pdata->phy_mask; - /* no carrier, nothing much to do */ - if (!new_carrier) { - netif_carrier_off(mii->dev); - printk(KERN_INFO "%s: link down\n", mii->dev->name); - return; + bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + if (!bp->mii_bus.irq) { + err = -ENOMEM; + goto err_out; } - /* - * we have carrier, see who's on the other end - */ - netif_carrier_on(mii->dev); + for (i = 0; i < PHY_MAX_ADDR; i++) + bp->mii_bus.irq[i] = PHY_POLL; - /* get MII advertise and LPA values */ - if (!init_media && mii->advertising) { - advertise = mii->advertising; - } else { - advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); - mii->advertising = advertise; - } - lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); + platform_set_drvdata(bp->dev, &bp->mii_bus); - /* figure out media and duplex from advertise and LPA values */ - media = mii_nway_result(lpa & advertise); - duplex = (media & ADVERTISE_FULL) ? 1 : 0; + if (mdiobus_register(&bp->mii_bus)) + goto err_out_free_mdio_irq; - if (ok_to_print) - printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", - mii->dev->name, - media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10", - duplex ? "full" : "half", lpa); + if (macb_mii_probe(bp->dev) != 0) { + goto err_out_unregister_bus; + } - mii->full_duplex = duplex; + return 0; - /* Let the MAC know about the new link state */ - macb_set_media(bp, media); +err_out_unregister_bus: + mdiobus_unregister(&bp->mii_bus); +err_out_free_mdio_irq: + kfree(bp->mii_bus.irq); +err_out: + return err; } static void macb_update_stats(struct macb *bp) @@ -265,16 +294,6 @@ static void macb_update_stats(struct macb *bp) *p += __raw_readl(reg); } -static void macb_periodic_task(struct work_struct *work) -{ - struct macb *bp = container_of(work, struct macb, periodic_task.work); - - macb_update_stats(bp); - macb_check_media(bp, 1, 0); - - schedule_delayed_work(&bp->periodic_task, HZ); -} - static void macb_tx(struct macb *bp) { unsigned int tail; @@ -519,9 +538,6 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) spin_lock(&bp->lock); while (status) { - if (status & MACB_BIT(MFD)) - complete(&bp->mdio_complete); - /* close possible race with dev_close */ if (unlikely(!netif_running(dev))) { macb_writel(bp, IDR, ~0UL); @@ -535,7 +551,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) * until we have processed the buffers */ macb_writel(bp, IDR, MACB_RX_INT_FLAGS); - dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n"); + dev_dbg(&bp->pdev->dev, + "scheduling RX softirq\n"); __netif_rx_schedule(dev); } } @@ -765,7 +782,7 @@ static void macb_init_hw(struct macb *bp) macb_writel(bp, TBQP, bp->tx_ring_dma); /* Enable TX and RX */ - macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE)); + macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE)); /* Enable interrupts */ macb_writel(bp, IER, (MACB_BIT(RCOMP) @@ -776,18 +793,126 @@ static void macb_init_hw(struct macb *bp) | MACB_BIT(TCOMP) | MACB_BIT(ISR_ROVR) | MACB_BIT(HRESP))); + } -static void macb_init_phy(struct net_device *dev) +/* + * 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. + * + * hi[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47] + * hi[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46] + * hi[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45] + * hi[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44] + * hi[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43] + * hi[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, hi[n], 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. + */ + +static inline int hash_bit_value(int bitnr, __u8 *addr) { + if (addr[bitnr / 8] & (1 << (bitnr % 8))) + return 1; + return 0; +} + +/* + * 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 macb_sethashtable(struct net_device *dev) +{ + struct dev_mc_list *curr; + unsigned long mc_filter[2]; + unsigned int i, bitnr; + struct macb *bp = netdev_priv(dev); + + 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); + } + + macb_writel(bp, HRB, mc_filter[0]); + macb_writel(bp, HRT, mc_filter[1]); +} + +/* + * Enable/Disable promiscuous and multicast modes. + */ +static void macb_set_rx_mode(struct net_device *dev) +{ + unsigned long cfg; struct macb *bp = netdev_priv(dev); - /* Set some reasonable default settings */ - macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE, - ADVERTISE_CSMA | ADVERTISE_ALL); - macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR, - (BMCR_SPEED100 | BMCR_ANENABLE - | BMCR_ANRESTART | BMCR_FULLDPLX)); + cfg = macb_readl(bp, NCFGR); + + if (dev->flags & IFF_PROMISC) + /* Enable promiscuous mode */ + cfg |= MACB_BIT(CAF); + else if (dev->flags & (~IFF_PROMISC)) + /* Disable promiscuous mode */ + cfg &= ~MACB_BIT(CAF); + + if (dev->flags & IFF_ALLMULTI) { + /* Enable all multicast mode */ + macb_writel(bp, HRB, -1); + macb_writel(bp, HRT, -1); + cfg |= MACB_BIT(NCFGR_MTI); + } else if (dev->mc_count > 0) { + /* Enable specific multicasts */ + macb_sethashtable(dev); + cfg |= MACB_BIT(NCFGR_MTI); + } else if (dev->flags & (~IFF_ALLMULTI)) { + /* Disable all multicast mode */ + macb_writel(bp, HRB, 0); + macb_writel(bp, HRT, 0); + cfg &= ~MACB_BIT(NCFGR_MTI); + } + + macb_writel(bp, NCFGR, cfg); } static int macb_open(struct net_device *dev) @@ -797,6 +922,10 @@ static int macb_open(struct net_device *dev) dev_dbg(&bp->pdev->dev, "open\n"); + /* if the phy is not yet register, retry later*/ + if (!bp->phy_dev) + return -EAGAIN; + if (!is_valid_ether_addr(dev->dev_addr)) return -EADDRNOTAVAIL; @@ -810,12 +939,11 @@ static int macb_open(struct net_device *dev) macb_init_rings(bp); macb_init_hw(bp); - macb_init_phy(dev); - macb_check_media(bp, 1, 1); - netif_start_queue(dev); + /* schedule a link state check */ + phy_start(bp->phy_dev); - schedule_delayed_work(&bp->periodic_task, HZ); + netif_start_queue(dev); return 0; } @@ -825,10 +953,11 @@ static int macb_close(struct net_device *dev) struct macb *bp = netdev_priv(dev); unsigned long flags; - cancel_rearming_delayed_work(&bp->periodic_task); - netif_stop_queue(dev); + if (bp->phy_dev) + phy_stop(bp->phy_dev); + spin_lock_irqsave(&bp->lock, flags); macb_reset_hw(bp); netif_carrier_off(dev); @@ -845,6 +974,9 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) struct net_device_stats *nstat = &bp->stats; struct macb_stats *hwstat = &bp->hw_stats; + /* read stats from hardware */ + macb_update_stats(bp); + /* Convert HW stats into netdevice stats */ nstat->rx_errors = (hwstat->rx_fcs_errors + hwstat->rx_align_errors + @@ -882,18 +1014,27 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct macb *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; - return mii_ethtool_gset(&bp->mii, cmd); + if (!phydev) + return -ENODEV; + + return phy_ethtool_gset(phydev, cmd); } static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct macb *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!phydev) + return -ENODEV; - return mii_ethtool_sset(&bp->mii, cmd); + return phy_ethtool_sset(phydev, cmd); } -static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +static void macb_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) { struct macb *bp = netdev_priv(dev); @@ -902,104 +1043,34 @@ static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf strcpy(info->bus_info, bp->pdev->dev.bus_id); } -static int macb_nway_reset(struct net_device *dev) -{ - struct macb *bp = netdev_priv(dev); - return mii_nway_restart(&bp->mii); -} - static struct ethtool_ops macb_ethtool_ops = { .get_settings = macb_get_settings, .set_settings = macb_set_settings, .get_drvinfo = macb_get_drvinfo, - .nway_reset = macb_nway_reset, .get_link = ethtool_op_get_link, }; static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct macb *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; if (!netif_running(dev)) return -EINVAL; - return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL); -} - -static ssize_t macb_mii_show(const struct device *_dev, char *buf, - unsigned long addr) -{ - struct net_device *dev = to_net_dev(_dev); - struct macb *bp = netdev_priv(dev); - ssize_t ret = -EINVAL; - - if (netif_running(dev)) { - int value; - value = macb_mdio_read(dev, bp->mii.phy_id, addr); - ret = sprintf(buf, "0x%04x\n", (uint16_t)value); - } - - return ret; -} - -#define MII_ENTRY(name, addr) \ -static ssize_t show_##name(struct device *_dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - return macb_mii_show(_dev, buf, addr); \ -} \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) - -MII_ENTRY(bmcr, MII_BMCR); -MII_ENTRY(bmsr, MII_BMSR); -MII_ENTRY(physid1, MII_PHYSID1); -MII_ENTRY(physid2, MII_PHYSID2); -MII_ENTRY(advertise, MII_ADVERTISE); -MII_ENTRY(lpa, MII_LPA); -MII_ENTRY(expansion, MII_EXPANSION); - -static struct attribute *macb_mii_attrs[] = { - &dev_attr_bmcr.attr, - &dev_attr_bmsr.attr, - &dev_attr_physid1.attr, - &dev_attr_physid2.attr, - &dev_attr_advertise.attr, - &dev_attr_lpa.attr, - &dev_attr_expansion.attr, - NULL, -}; - -static struct attribute_group macb_mii_group = { - .name = "mii", - .attrs = macb_mii_attrs, -}; - -static void macb_unregister_sysfs(struct net_device *net) -{ - struct device *_dev = &net->dev; + if (!phydev) + return -ENODEV; - sysfs_remove_group(&_dev->kobj, &macb_mii_group); + return phy_mii_ioctl(phydev, if_mii(rq), cmd); } -static int macb_register_sysfs(struct net_device *net) -{ - struct device *_dev = &net->dev; - int ret; - - ret = sysfs_create_group(&_dev->kobj, &macb_mii_group); - if (ret) - printk(KERN_WARNING - "%s: sysfs mii attribute registration failed: %d\n", - net->name, ret); - return ret; -} static int __devinit macb_probe(struct platform_device *pdev) { struct eth_platform_data *pdata; struct resource *regs; struct net_device *dev; struct macb *bp; + struct phy_device *phydev; unsigned long pclk_hz; u32 config; int err = -ENXIO; @@ -1073,6 +1144,7 @@ static int __devinit macb_probe(struct platform_device *pdev) dev->stop = macb_close; dev->hard_start_xmit = macb_start_xmit; dev->get_stats = macb_get_stats; + dev->set_multicast_list = macb_set_rx_mode; dev->do_ioctl = macb_ioctl; dev->poll = macb_poll; dev->weight = 64; @@ -1080,10 +1152,6 @@ static int __devinit macb_probe(struct platform_device *pdev) dev->base_addr = regs->start; - INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task); - mutex_init(&bp->mdio_mutex); - init_completion(&bp->mdio_complete); - /* Set MII management clock divider */ pclk_hz = clk_get_rate(bp->pclk); if (pclk_hz <= 20000000) @@ -1096,20 +1164,9 @@ static int __devinit macb_probe(struct platform_device *pdev) config = MACB_BF(CLK, MACB_CLK_DIV64); macb_writel(bp, NCFGR, config); - bp->mii.dev = dev; - bp->mii.mdio_read = macb_mdio_read; - bp->mii.mdio_write = macb_mdio_write; - bp->mii.phy_id_mask = 0x1f; - bp->mii.reg_num_mask = 0x1f; - macb_get_hwaddr(bp); - err = macb_phy_probe(bp); - if (err) { - dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n"); - goto err_out_free_irq; - } - pdata = pdev->dev.platform_data; + if (pdata && pdata->is_rmii) #if defined(CONFIG_ARCH_AT91) macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) ); @@ -1131,9 +1188,11 @@ static int __devinit macb_probe(struct platform_device *pdev) goto err_out_free_irq; } - platform_set_drvdata(pdev, dev); + if (macb_mii_init(bp) != 0) { + goto err_out_unregister_netdev; + } - macb_register_sysfs(dev); + platform_set_drvdata(pdev, dev); printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d " "(%02x:%02x:%02x:%02x:%02x:%02x)\n", @@ -1141,8 +1200,15 @@ static int __devinit macb_probe(struct platform_device *pdev) dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + phydev = bp->phy_dev; + printk(KERN_INFO "%s: attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, irq=%d)\n", + dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + return 0; +err_out_unregister_netdev: + unregister_netdev(dev); err_out_free_irq: free_irq(dev->irq, dev); err_out_iounmap: @@ -1153,7 +1219,9 @@ err_out_disable_clocks: clk_put(bp->hclk); #endif clk_disable(bp->pclk); +#ifndef CONFIG_ARCH_AT91 err_out_put_pclk: +#endif clk_put(bp->pclk); err_out_free_dev: free_netdev(dev); @@ -1171,7 +1239,8 @@ static int __devexit macb_remove(struct platform_device *pdev) if (dev) { bp = netdev_priv(dev); - macb_unregister_sysfs(dev); + mdiobus_unregister(&bp->mii_bus); + kfree(bp->mii_bus.irq); unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(bp->regs); diff --git a/drivers/net/macb.h b/drivers/net/macb.h index b3bb2182edd1..4e3283ebd97c 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -383,11 +383,11 @@ struct macb { unsigned int rx_pending, tx_pending; - struct delayed_work periodic_task; - - struct mutex mdio_mutex; - struct completion mdio_complete; - struct mii_if_info mii; + struct mii_bus mii_bus; + struct phy_device *phy_dev; + unsigned int link; + unsigned int speed; + unsigned int duplex; }; #endif /* _MACB_H */ diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index fef3193121f9..9a343b965975 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -577,7 +577,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) struct mace_data *mp = netdev_priv(dev); volatile struct mace *mb = mp->mace; int intr, fs; - unsigned int flags; + unsigned long flags; /* don't want the dma interrupt handler to fire */ local_irq_save(flags); diff --git a/drivers/net/meth.c b/drivers/net/meth.c index 92b403bf38b0..32bed6bc6c06 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -405,7 +405,7 @@ static void meth_rx(struct net_device* dev, unsigned long int_status) priv->stats.rx_length_errors++; skb = priv->rx_skbs[priv->rx_write]; } else { - skb = alloc_skb(METH_RX_BUFF_SIZE, GFP_ATOMIC | GFP_DMA); + skb = alloc_skb(METH_RX_BUFF_SIZE, GFP_ATOMIC); if (!skb) { /* Ouch! No memory! Drop packet on the floor */ DPRINTK("No mem: dropping packet\n"); diff --git a/drivers/net/mlx4/catas.c b/drivers/net/mlx4/catas.c index 1bb088aeaf71..6b32ec94b3a8 100644 --- a/drivers/net/mlx4/catas.c +++ b/drivers/net/mlx4/catas.c @@ -30,41 +30,133 @@ * SOFTWARE. */ +#include <linux/workqueue.h> + #include "mlx4.h" -void mlx4_handle_catas_err(struct mlx4_dev *dev) +enum { + MLX4_CATAS_POLL_INTERVAL = 5 * HZ, +}; + +static DEFINE_SPINLOCK(catas_lock); + +static LIST_HEAD(catas_list); +static struct workqueue_struct *catas_wq; +static struct work_struct catas_work; + +static int internal_err_reset = 1; +module_param(internal_err_reset, int, 0644); +MODULE_PARM_DESC(internal_err_reset, + "Reset device on internal errors if non-zero (default 1)"); + +static void dump_err_buf(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); int i; - mlx4_err(dev, "Catastrophic error detected:\n"); + mlx4_err(dev, "Internal error detected:\n"); for (i = 0; i < priv->fw.catas_size; ++i) mlx4_err(dev, " buf[%02x]: %08x\n", i, swab32(readl(priv->catas_err.map + i))); +} - mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0); +static void poll_catas(unsigned long dev_ptr) +{ + struct mlx4_dev *dev = (struct mlx4_dev *) dev_ptr; + struct mlx4_priv *priv = mlx4_priv(dev); + + if (readl(priv->catas_err.map)) { + dump_err_buf(dev); + + mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0); + + if (internal_err_reset) { + spin_lock(&catas_lock); + list_add(&priv->catas_err.list, &catas_list); + spin_unlock(&catas_lock); + + queue_work(catas_wq, &catas_work); + } + } else + mod_timer(&priv->catas_err.timer, + round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL)); } -void mlx4_map_catas_buf(struct mlx4_dev *dev) +static void catas_reset(struct work_struct *work) +{ + struct mlx4_priv *priv, *tmppriv; + struct mlx4_dev *dev; + + LIST_HEAD(tlist); + int ret; + + spin_lock_irq(&catas_lock); + list_splice_init(&catas_list, &tlist); + spin_unlock_irq(&catas_lock); + + list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) { + ret = mlx4_restart_one(priv->dev.pdev); + dev = &priv->dev; + if (ret) + mlx4_err(dev, "Reset failed (%d)\n", ret); + else + mlx4_dbg(dev, "Reset succeeded\n"); + } +} + +void mlx4_start_catas_poll(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); unsigned long addr; + INIT_LIST_HEAD(&priv->catas_err.list); + init_timer(&priv->catas_err.timer); + priv->catas_err.map = NULL; + addr = pci_resource_start(dev->pdev, priv->fw.catas_bar) + priv->fw.catas_offset; priv->catas_err.map = ioremap(addr, priv->fw.catas_size * 4); - if (!priv->catas_err.map) - mlx4_warn(dev, "Failed to map catastrophic error buffer at 0x%lx\n", + if (!priv->catas_err.map) { + mlx4_warn(dev, "Failed to map internal error buffer at 0x%lx\n", addr); + return; + } + priv->catas_err.timer.data = (unsigned long) dev; + priv->catas_err.timer.function = poll_catas; + priv->catas_err.timer.expires = + round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL); + add_timer(&priv->catas_err.timer); } -void mlx4_unmap_catas_buf(struct mlx4_dev *dev) +void mlx4_stop_catas_poll(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); + del_timer_sync(&priv->catas_err.timer); + if (priv->catas_err.map) iounmap(priv->catas_err.map); + + spin_lock_irq(&catas_lock); + list_del(&priv->catas_err.list); + spin_unlock_irq(&catas_lock); +} + +int __init mlx4_catas_init(void) +{ + INIT_WORK(&catas_work, catas_reset); + + catas_wq = create_singlethread_workqueue("mlx4_err"); + if (!catas_wq) + return -ENOMEM; + + return 0; +} + +void mlx4_catas_cleanup(void) +{ + destroy_workqueue(catas_wq); } diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c index c1f81a993f5d..a9f31753661a 100644 --- a/drivers/net/mlx4/cmd.c +++ b/drivers/net/mlx4/cmd.c @@ -246,8 +246,6 @@ void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param) context->result = mlx4_status_to_errno(status); context->out_param = out_param; - context->token += priv->cmd.token_mask + 1; - complete(&context->done); } @@ -264,6 +262,7 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, spin_lock(&cmd->context_lock); BUG_ON(cmd->free_head < 0); context = &cmd->context[cmd->free_head]; + context->token += cmd->token_mask + 1; cmd->free_head = context->next; spin_unlock(&cmd->context_lock); diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 27a82cecd693..2095c843fa15 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -89,14 +89,12 @@ struct mlx4_eq_context { (1ull << MLX4_EVENT_TYPE_PATH_MIG_FAILED) | \ (1ull << MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \ (1ull << MLX4_EVENT_TYPE_WQ_ACCESS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR) | \ (1ull << MLX4_EVENT_TYPE_PORT_CHANGE) | \ (1ull << MLX4_EVENT_TYPE_ECC_DETECT) | \ (1ull << MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) | \ (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \ (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \ (1ull << MLX4_EVENT_TYPE_CMD)) -#define MLX4_CATAS_EVENT_MASK (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR) struct mlx4_eqe { u8 reserved1; @@ -264,7 +262,7 @@ static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr) writel(priv->eq_table.clr_mask, priv->eq_table.clr_int); - for (i = 0; i < MLX4_EQ_CATAS; ++i) + for (i = 0; i < MLX4_NUM_EQ; ++i) work |= mlx4_eq_int(dev, &priv->eq_table.eq[i]); return IRQ_RETVAL(work); @@ -281,14 +279,6 @@ static irqreturn_t mlx4_msi_x_interrupt(int irq, void *eq_ptr) return IRQ_HANDLED; } -static irqreturn_t mlx4_catas_interrupt(int irq, void *dev_ptr) -{ - mlx4_handle_catas_err(dev_ptr); - - /* MSI-X vectors always belong to us */ - return IRQ_HANDLED; -} - static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap, int eq_num) { @@ -490,11 +480,9 @@ static void mlx4_free_irqs(struct mlx4_dev *dev) if (eq_table->have_irq) free_irq(dev->pdev->irq, dev); - for (i = 0; i < MLX4_EQ_CATAS; ++i) + for (i = 0; i < MLX4_NUM_EQ; ++i) if (eq_table->eq[i].have_irq) free_irq(eq_table->eq[i].irq, eq_table->eq + i); - if (eq_table->eq[MLX4_EQ_CATAS].have_irq) - free_irq(eq_table->eq[MLX4_EQ_CATAS].irq, dev); } static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev) @@ -598,32 +586,19 @@ int __devinit mlx4_init_eq_table(struct mlx4_dev *dev) if (dev->flags & MLX4_FLAG_MSI_X) { static const char *eq_name[] = { [MLX4_EQ_COMP] = DRV_NAME " (comp)", - [MLX4_EQ_ASYNC] = DRV_NAME " (async)", - [MLX4_EQ_CATAS] = DRV_NAME " (catas)" + [MLX4_EQ_ASYNC] = DRV_NAME " (async)" }; - err = mlx4_create_eq(dev, 1, MLX4_EQ_CATAS, - &priv->eq_table.eq[MLX4_EQ_CATAS]); - if (err) - goto err_out_async; - - for (i = 0; i < MLX4_EQ_CATAS; ++i) { + for (i = 0; i < MLX4_NUM_EQ; ++i) { err = request_irq(priv->eq_table.eq[i].irq, mlx4_msi_x_interrupt, 0, eq_name[i], priv->eq_table.eq + i); if (err) - goto err_out_catas; + goto err_out_async; priv->eq_table.eq[i].have_irq = 1; } - err = request_irq(priv->eq_table.eq[MLX4_EQ_CATAS].irq, - mlx4_catas_interrupt, 0, - eq_name[MLX4_EQ_CATAS], dev); - if (err) - goto err_out_catas; - - priv->eq_table.eq[MLX4_EQ_CATAS].have_irq = 1; } else { err = request_irq(dev->pdev->irq, mlx4_interrupt, IRQF_SHARED, DRV_NAME, dev); @@ -639,22 +614,11 @@ int __devinit mlx4_init_eq_table(struct mlx4_dev *dev) mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n", priv->eq_table.eq[MLX4_EQ_ASYNC].eqn, err); - for (i = 0; i < MLX4_EQ_CATAS; ++i) + for (i = 0; i < MLX4_NUM_EQ; ++i) eq_set_ci(&priv->eq_table.eq[i], 1); - if (dev->flags & MLX4_FLAG_MSI_X) { - err = mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 0, - priv->eq_table.eq[MLX4_EQ_CATAS].eqn); - if (err) - mlx4_warn(dev, "MAP_EQ for catas EQ %d failed (%d)\n", - priv->eq_table.eq[MLX4_EQ_CATAS].eqn, err); - } - return 0; -err_out_catas: - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]); - err_out_async: mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_ASYNC]); @@ -675,19 +639,13 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int i; - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 1, - priv->eq_table.eq[MLX4_EQ_CATAS].eqn); - mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1, priv->eq_table.eq[MLX4_EQ_ASYNC].eqn); mlx4_free_irqs(dev); - for (i = 0; i < MLX4_EQ_CATAS; ++i) + for (i = 0; i < MLX4_NUM_EQ; ++i) mlx4_free_eq(dev, &priv->eq_table.eq[i]); - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]); mlx4_unmap_clr_int(dev); diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index d2b065351e45..c45cbe43a0c4 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -138,6 +138,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35 #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36 #define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37 +#define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET 0x38 #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f @@ -220,6 +221,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->local_ca_ack_delay = field & 0x1f; MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); dev_cap->num_ports = field & 0xf; + MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET); + dev_cap->max_msg_sz = 1 << (field & 0x1f); MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); dev_cap->stat_rate_support = stat_rate; MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index 296254ac27c1..7e1dd9e25cfb 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h @@ -60,6 +60,7 @@ struct mlx4_dev_cap { int max_rdma_global; int local_ca_ack_delay; int num_ports; + u32 max_msg_sz; int max_mtu[MLX4_MAX_PORTS + 1]; int max_port_width[MLX4_MAX_PORTS + 1]; int max_vl[MLX4_MAX_PORTS + 1]; diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c index 9ae951bf6aa6..be5d9e90ccf2 100644 --- a/drivers/net/mlx4/intf.c +++ b/drivers/net/mlx4/intf.c @@ -142,6 +142,7 @@ int mlx4_register_device(struct mlx4_dev *dev) mlx4_add_device(intf, priv); mutex_unlock(&intf_mutex); + mlx4_start_catas_poll(dev); return 0; } @@ -151,6 +152,7 @@ void mlx4_unregister_device(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_interface *intf; + mlx4_stop_catas_poll(dev); mutex_lock(&intf_mutex); list_for_each_entry(intf, &intf_list, list) diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index c3da2a2f5431..4dc9dc19b716 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -78,7 +78,7 @@ static const char mlx4_version[] __devinitdata = static struct mlx4_profile default_profile = { .num_qp = 1 << 16, .num_srq = 1 << 16, - .rdmarc_per_qp = 4, + .rdmarc_per_qp = 1 << 4, .num_cq = 1 << 16, .num_mcg = 1 << 13, .num_mpt = 1 << 17, @@ -154,6 +154,7 @@ static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev dev->caps.reserved_uars = dev_cap->reserved_uars; dev->caps.reserved_pds = dev_cap->reserved_pds; dev->caps.mtt_entry_sz = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz; + dev->caps.max_msg_sz = dev_cap->max_msg_sz; dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); dev->caps.flags = dev_cap->flags; dev->caps.stat_rate_support = dev_cap->stat_rate_support; @@ -582,13 +583,11 @@ static int __devinit mlx4_setup_hca(struct mlx4_dev *dev) goto err_pd_table_free; } - mlx4_map_catas_buf(dev); - err = mlx4_init_eq_table(dev); if (err) { mlx4_err(dev, "Failed to initialize " "event queue table, aborting.\n"); - goto err_catas_buf; + goto err_mr_table_free; } err = mlx4_cmd_use_events(dev); @@ -658,8 +657,7 @@ err_cmd_poll: err_eq_table_free: mlx4_cleanup_eq_table(dev); -err_catas_buf: - mlx4_unmap_catas_buf(dev); +err_mr_table_free: mlx4_cleanup_mr_table(dev); err_pd_table_free: @@ -835,9 +833,6 @@ err_cleanup: mlx4_cleanup_cq_table(dev); mlx4_cmd_use_polling(dev); mlx4_cleanup_eq_table(dev); - - mlx4_unmap_catas_buf(dev); - mlx4_cleanup_mr_table(dev); mlx4_cleanup_pd_table(dev); mlx4_cleanup_uar_table(dev); @@ -884,9 +879,6 @@ static void __devexit mlx4_remove_one(struct pci_dev *pdev) mlx4_cleanup_cq_table(dev); mlx4_cmd_use_polling(dev); mlx4_cleanup_eq_table(dev); - - mlx4_unmap_catas_buf(dev); - mlx4_cleanup_mr_table(dev); mlx4_cleanup_pd_table(dev); @@ -907,6 +899,12 @@ static void __devexit mlx4_remove_one(struct pci_dev *pdev) } } +int mlx4_restart_one(struct pci_dev *pdev) +{ + mlx4_remove_one(pdev); + return mlx4_init_one(pdev, NULL); +} + static struct pci_device_id mlx4_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */ { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */ @@ -929,6 +927,10 @@ static int __init mlx4_init(void) { int ret; + ret = mlx4_catas_init(); + if (ret) + return ret; + ret = pci_register_driver(&mlx4_driver); return ret < 0 ? ret : 0; } @@ -936,6 +938,7 @@ static int __init mlx4_init(void) static void __exit mlx4_cleanup(void) { pci_unregister_driver(&mlx4_driver); + mlx4_catas_cleanup(); } module_init(mlx4_init); diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 3d3b6d24d8d3..be304a7c2c91 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -37,7 +37,9 @@ #ifndef MLX4_H #define MLX4_H +#include <linux/mutex.h> #include <linux/radix-tree.h> +#include <linux/timer.h> #include <linux/mlx4/device.h> #include <linux/mlx4/doorbell.h> @@ -66,7 +68,6 @@ enum { enum { MLX4_EQ_ASYNC, MLX4_EQ_COMP, - MLX4_EQ_CATAS, MLX4_NUM_EQ }; @@ -247,7 +248,8 @@ struct mlx4_mcg_table { struct mlx4_catas_err { u32 __iomem *map; - int size; + struct timer_list timer; + struct list_head list; }; struct mlx4_priv { @@ -310,9 +312,11 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev); void mlx4_cleanup_srq_table(struct mlx4_dev *dev); void mlx4_cleanup_mcg_table(struct mlx4_dev *dev); -void mlx4_map_catas_buf(struct mlx4_dev *dev); -void mlx4_unmap_catas_buf(struct mlx4_dev *dev); - +void mlx4_start_catas_poll(struct mlx4_dev *dev); +void mlx4_stop_catas_poll(struct mlx4_dev *dev); +int mlx4_catas_init(void); +void mlx4_catas_cleanup(void); +int mlx4_restart_one(struct pci_dev *pdev); int mlx4_register_device(struct mlx4_dev *dev); void mlx4_unregister_device(struct mlx4_dev *dev); void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type, diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index d0808fa3ec82..5b87183e62ce 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -255,10 +255,8 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, int err; index = mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); - if (index == -1) { - err = -ENOMEM; - goto err; - } + if (index == -1) + return -ENOMEM; mr->iova = iova; mr->size = size; @@ -269,15 +267,8 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); if (err) - goto err_index; - - return 0; - -err_index: - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); + mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); -err: - kfree(mr); return err; } EXPORT_SYMBOL_GPL(mlx4_mr_alloc); diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c index 7f8b7d55b6e1..19b48c71cf7f 100644 --- a/drivers/net/mlx4/qp.c +++ b/drivers/net/mlx4/qp.c @@ -113,8 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, struct mlx4_cmd_mailbox *mailbox; int ret = 0; - if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE || - new_state < 0 || cur_state >= MLX4_QP_NUM_STATE || + if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE || !op[cur_state][new_state]) return -EINVAL; @@ -278,3 +277,24 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev) mlx4_CONF_SPECIAL_QP(dev, 0); mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap); } + +int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp, + struct mlx4_qp_context *context) +{ + struct mlx4_cmd_mailbox *mailbox; + int err; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0, + MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A); + if (!err) + memcpy(context, mailbox->buf + 8, sizeof *context); + + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} +EXPORT_SYMBOL_GPL(mlx4_qp_query); + diff --git a/drivers/net/mlx4/reset.c b/drivers/net/mlx4/reset.c index e4dfd4b11a4a..e199715fabd0 100644 --- a/drivers/net/mlx4/reset.c +++ b/drivers/net/mlx4/reset.c @@ -119,6 +119,9 @@ int mlx4_reset(struct mlx4_dev *dev) writel(MLX4_RESET_VALUE, reset + MLX4_RESET_OFFSET); iounmap(reset); + /* Docs say to wait one second before accessing device */ + msleep(1000); + end = jiffies + MLX4_RESET_TIMEOUT_JIFFIES; do { if (!pci_read_config_word(dev->pdev, PCI_VENDOR_ID, &vendor) && diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c index 2134f83aed87..b061c86d6839 100644 --- a/drivers/net/mlx4/srq.c +++ b/drivers/net/mlx4/srq.c @@ -102,6 +102,13 @@ static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark) MLX4_CMD_TIME_CLASS_B); } +static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, + int srq_num) +{ + return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ, + MLX4_CMD_TIME_CLASS_A); +} + int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq) { @@ -205,6 +212,29 @@ int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark } EXPORT_SYMBOL_GPL(mlx4_srq_arm); +int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark) +{ + struct mlx4_cmd_mailbox *mailbox; + struct mlx4_srq_context *srq_context; + int err; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + srq_context = mailbox->buf; + + err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn); + if (err) + goto err_out; + *limit_watermark = srq_context->limit_watermark; + +err_out: + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} +EXPORT_SYMBOL_GPL(mlx4_srq_query); + int __devinit mlx4_init_srq_table(struct mlx4_dev *dev) { struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 1799eee88db7..315335671f0f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -534,7 +534,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id) } /* PHY status changed */ - if (eth_int_cause_ext & ETH_INT_CAUSE_PHY) { + if (eth_int_cause_ext & (ETH_INT_CAUSE_PHY | ETH_INT_CAUSE_STATE)) { struct ethtool_cmd cmd; if (mii_link_ok(&mp->mii)) { @@ -1222,7 +1222,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&mp->lock, flags); eth_tx_submit_descs_for_skb(mp, skb); - stats->tx_bytes = skb->len; + stats->tx_bytes += skb->len; stats->tx_packets++; dev->trans_start = jiffies; @@ -1357,7 +1357,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) #endif dev->watchdog_timeo = 2 * HZ; - dev->tx_queue_len = mp->tx_ring_size; dev->base_addr = 0; dev->change_mtu = mv643xx_eth_change_mtu; dev->do_ioctl = mv643xx_eth_do_ioctl; @@ -2768,8 +2767,6 @@ static const struct ethtool_ops mv643xx_ethtool_ops = { .get_stats_count = mv643xx_get_stats_count, .get_ethtool_stats = mv643xx_get_ethtool_stats, .get_strings = mv643xx_get_strings, - .get_stats_count = mv643xx_get_stats_count, - .get_ethtool_stats = mv643xx_get_ethtool_stats, .nway_reset = mv643xx_eth_nway_restart, }; diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 82f8c0cbfb64..565b96696aca 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -64,7 +64,9 @@ #define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8) #define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR) #define ETH_INT_CAUSE_PHY 0x00010000 -#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY) +#define ETH_INT_CAUSE_STATE 0x00100000 +#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \ + ETH_INT_CAUSE_STATE) #define ETH_INT_MASK_ALL 0x00000000 #define ETH_INT_MASK_ALL_EXT 0x00000000 diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index d0cc122fa3f0..556962f9612d 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -60,6 +60,7 @@ #include <linux/crc32.h> #include <linux/moduleparam.h> #include <linux/io.h> +#include <linux/log2.h> #include <net/checksum.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -71,7 +72,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.1-1.248" +#define MYRI10GE_VERSION_STR "1.3.2-1.269" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -190,6 +191,7 @@ struct myri10ge_priv { struct timer_list watchdog_timer; int watchdog_tx_done; int watchdog_tx_req; + int watchdog_pause; int watchdog_resets; int tx_linearized; int pause; @@ -1059,7 +1061,6 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) struct myri10ge_tx_buf *tx = &mgp->tx; struct sk_buff *skb; int idx, len; - int limit = 0; while (tx->pkt_done != mcp_index) { idx = tx->done & tx->mask; @@ -1090,11 +1091,6 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) bus), len, PCI_DMA_TODEVICE); } - - /* limit potential for livelock by only handling - * 2 full tx rings per call */ - if (unlikely(++limit > 2 * tx->mask)) - break; } /* start the queue if we've stopped it */ if (netif_queue_stopped(mgp->dev) @@ -1804,7 +1800,7 @@ static int myri10ge_open(struct net_device *dev) */ big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) { - while ((big_pow2 & (big_pow2 - 1)) != 0) + while (!is_power_of_2(big_pow2)) big_pow2++; mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; } else { @@ -2518,26 +2514,20 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) { struct pci_dev *pdev = mgp->pdev; struct device *dev = &pdev->dev; - int cap, status; - u16 val; + int status; mgp->tx.boundary = 4096; /* * Verify the max read request size was set to 4KB * before trying the test with 4KB. */ - cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (cap < 64) { - dev_err(dev, "Bad PCI_CAP_ID_EXP location %d\n", cap); - goto abort; - } - status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val); - if (status != 0) { + status = pcie_get_readrq(pdev); + if (status < 0) { dev_err(dev, "Couldn't read max read req size: %d\n", status); goto abort; } - if ((val & (5 << 12)) != (5 << 12)) { - dev_warn(dev, "Max Read Request size != 4096 (0x%x)\n", val); + if (status != 4096) { + dev_warn(dev, "Max Read Request size != 4096 (%d)\n", status); mgp->tx.boundary = 2048; } /* @@ -2805,6 +2795,7 @@ static void myri10ge_watchdog(struct work_struct *work) static void myri10ge_watchdog_timer(unsigned long arg) { struct myri10ge_priv *mgp; + u32 rx_pause_cnt; mgp = (struct myri10ge_priv *)arg; @@ -2821,19 +2812,28 @@ static void myri10ge_watchdog_timer(unsigned long arg) myri10ge_fill_thresh) mgp->rx_big.watchdog_needed = 0; } + rx_pause_cnt = ntohl(mgp->fw_stats->dropped_pause); if (mgp->tx.req != mgp->tx.done && mgp->tx.done == mgp->watchdog_tx_done && - mgp->watchdog_tx_req != mgp->watchdog_tx_done) + mgp->watchdog_tx_req != mgp->watchdog_tx_done) { /* nic seems like it might be stuck.. */ - schedule_work(&mgp->watchdog_work); - else - /* rearm timer */ - mod_timer(&mgp->watchdog_timer, - jiffies + myri10ge_watchdog_timeout * HZ); - + if (rx_pause_cnt != mgp->watchdog_pause) { + if (net_ratelimit()) + printk(KERN_WARNING "myri10ge %s:" + "TX paused, check link partner\n", + mgp->dev->name); + } else { + schedule_work(&mgp->watchdog_work); + return; + } + } + /* rearm timer */ + mod_timer(&mgp->watchdog_timer, + jiffies + myri10ge_watchdog_timeout * HZ); mgp->watchdog_tx_done = mgp->tx.done; mgp->watchdog_tx_req = mgp->tx.req; + mgp->watchdog_pause = rx_pause_cnt; } static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -2844,9 +2844,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) size_t bytes; int i; int status = -ENXIO; - int cap; int dac_enabled; - u16 val; netdev = alloc_etherdev(sizeof(*mgp)); if (netdev == NULL) { @@ -2878,19 +2876,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) = pci_find_capability(pdev, PCI_CAP_ID_VNDR); /* Set our max read request to 4KB */ - cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (cap < 64) { - dev_err(&pdev->dev, "Bad PCI_CAP_ID_EXP location %d\n", cap); - goto abort_with_netdev; - } - status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val); - if (status != 0) { - dev_err(&pdev->dev, "Error %d reading PCI_EXP_DEVCTL\n", - status); - goto abort_with_netdev; - } - val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12); - status = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, val); + status = pcie_set_readrq(pdev, 4096); if (status != 0) { dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n", status); @@ -3108,9 +3094,12 @@ static void myri10ge_remove(struct pci_dev *pdev) } #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008 +#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9 0x0009 static struct pci_device_id myri10ge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)}, + {PCI_DEVICE + (PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)}, {0}, }; diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 460a08718c69..b47a12d684f9 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -671,7 +671,7 @@ static ssize_t natsemi_show_##_name(struct device *dev, \ #define NATSEMI_CREATE_FILE(_dev, _name) \ device_create_file(&_dev->dev, &dev_attr_##_name) #define NATSEMI_REMOVE_FILE(_dev, _name) \ - device_create_file(&_dev->dev, &dev_attr_##_name) + device_remove_file(&_dev->dev, &dev_attr_##_name) NATSEMI_ATTR(dspcfg_workaround); @@ -2357,8 +2357,8 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) np->rx_dma[entry], buflen, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, - np->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, + np->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, np->rx_dma[entry], @@ -2438,13 +2438,16 @@ static void netdev_error(struct net_device *dev, int intr_status) dev->name); } np->stats.rx_fifo_errors++; + np->stats.rx_errors++; } /* Hmmmmm, it's not clear how to recover from PCI faults. */ if (intr_status & IntrPCIErr) { printk(KERN_NOTICE "%s: PCI error %#08x\n", dev->name, intr_status & IntrPCIErr); np->stats.tx_fifo_errors++; + np->stats.tx_errors++; np->stats.rx_fifo_errors++; + np->stats.rx_errors++; } spin_unlock(&np->lock); } diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 995c0a5d4066..f81d9398d605 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -638,7 +638,6 @@ static const struct ethtool_ops ne2k_pci_ethtool_ops = { .get_drvinfo = ne2k_pci_get_drvinfo, .get_tx_csum = ethtool_op_get_tx_csum, .get_sg = ethtool_op_get_sg, - .get_perm_addr = ethtool_op_get_perm_addr, }; static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) @@ -669,10 +668,15 @@ static int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state) static int ne2k_pci_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + int rc; pci_set_power_state(pdev, 0); pci_restore_state(pdev); - pci_enable_device(pdev); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + NS8390_init(dev, 1); netif_device_attach(dev); diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 619503742b7d..d4c92cc879d4 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1097,109 +1097,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); int netxen_nic_set_mac(struct net_device *netdev, void *p); struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); -static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) -{ - uint32_t mask = 0x7ff; - int retries = 32; - - DPRINTK(1, INFO, "Entered ISR Disable \n"); - - switch (adapter->portnum) { - case 0: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); - break; - case 1: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); - break; - case 2: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); - break; - case 3: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); - break; - } - - if (adapter->intr_scheme != -1 && - adapter->intr_scheme != INTR_SCHEME_PERPORT) { - writel(mask, - (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); - } - - /* Window = 0 or 1 */ - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - do { - writel(0xffffffff, (void *) - (PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS))); - mask = readl((void *) - (pci_base_offset(adapter, ISR_INT_VECTOR))); - if (!(mask & 0x80)) - break; - udelay(10); - } while (--retries); - - if (!retries) { - printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", - netxen_nic_driver_name); - } - } - - DPRINTK(1, INFO, "Done with Disable Int\n"); - - return; -} - -static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) -{ - u32 mask; - - DPRINTK(1, INFO, "Entered ISR Enable \n"); - - if (adapter->intr_scheme != -1 && - adapter->intr_scheme != INTR_SCHEME_PERPORT) { - switch (adapter->ahw.board_type) { - case NETXEN_NIC_GBE: - mask = 0x77b; - break; - case NETXEN_NIC_XGBE: - mask = 0x77f; - break; - default: - mask = 0x7ff; - break; - } - - writel(mask, - (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); - } - switch (adapter->portnum) { - case 0: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); - break; - case 1: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); - break; - case 2: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); - break; - case 3: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); - break; - } - - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - mask = 0xbff; - if (adapter->intr_scheme != -1 && - adapter->intr_scheme != INTR_SCHEME_PERPORT) { - writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - } - writel(mask, - (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK))); - } - - DPRINTK(1, INFO, "Done with enable Int\n"); - - return; -} /* * NetXen Board information @@ -1282,8 +1179,7 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) printk(KERN_ERR "failed to read dma watchdog status\n"); - return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) && - (netxen_get_dma_watchdog_disabled(ctrl) == 0)); + return (netxen_get_dma_watchdog_enabled(ctrl) == 0); } static inline int diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 0175f6c353f6..a6138b474b4a 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -755,5 +755,4 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .get_strings = netxen_nic_get_strings, .get_stats_count = netxen_nic_get_stats_count, .get_ethtool_stats = netxen_nic_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 3276866b17e2..d72f8f8fcb50 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -649,9 +649,11 @@ enum { #define PCIX_INT_VECTOR (0x10100) #define PCIX_INT_MASK (0x10104) -#define PCIX_MN_WINDOW (0x10200) +#define PCIX_MN_WINDOW_F0 (0x10200) +#define PCIX_MN_WINDOW(_f) (PCIX_MN_WINDOW_F0 + (0x20 * (_f))) #define PCIX_MS_WINDOW (0x10204) -#define PCIX_SN_WINDOW (0x10208) +#define PCIX_SN_WINDOW_F0 (0x10208) +#define PCIX_SN_WINDOW(_f) (PCIX_SN_WINDOW_F0 + (0x20 * (_f))) #define PCIX_CRB_WINDOW (0x10210) #define PCIX_CRB_WINDOW_F0 (0x10210) #define PCIX_CRB_WINDOW_F1 (0x10230) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index aac15421bd1e..a7b8d7f23259 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -904,11 +904,11 @@ netxen_nic_pci_set_window(struct netxen_adapter *adapter, ddr_mn_window = window; writel(window, PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCIX_PH_REG - (PCIX_MN_WINDOW))); + (PCIX_MN_WINDOW(adapter->ahw.pci_func)))); /* MUST make sure window is set before we forge on... */ readl(PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCIX_PH_REG - (PCIX_MN_WINDOW))); + (PCIX_MN_WINDOW(adapter->ahw.pci_func)))); } addr -= (window * NETXEN_WINDOW_ONE); addr += NETXEN_PCI_DDR_NET; @@ -929,11 +929,11 @@ netxen_nic_pci_set_window(struct netxen_adapter *adapter, writel((window << 22), PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCIX_PH_REG - (PCIX_SN_WINDOW))); + (PCIX_SN_WINDOW(adapter->ahw.pci_func)))); /* MUST make sure window is set before we forge on... */ readl(PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCIX_PH_REG - (PCIX_SN_WINDOW))); + (PCIX_SN_WINDOW(adapter->ahw.pci_func)))); } addr -= (window * 0x400000); addr += NETXEN_PCI_QDR_NET; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index a66ff58366cf..3122d0101638 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -46,7 +46,7 @@ MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); -char netxen_nic_driver_name[] = "netxen-nic"; +char netxen_nic_driver_name[] = "netxen_nic"; static char netxen_nic_driver_string[] = "NetXen Network Driver version " NETXEN_NIC_LINUX_VERSIONID; @@ -54,8 +54,6 @@ static char netxen_nic_driver_string[] = "NetXen Network Driver version " #define NETXEN_ADAPTER_UP_MAGIC 777 #define NETXEN_NIC_PEG_TUNE 0 -u8 nx_p2_id = NX_P2_C0; - #define DMA_32BIT_MASK 0x00000000ffffffffULL #define DMA_35BIT_MASK 0x00000007ffffffffULL @@ -156,6 +154,103 @@ static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter #define ADAPTER_LIST_SIZE 12 int netxen_cards_found; +static void netxen_nic_disable_int(struct netxen_adapter *adapter) +{ + uint32_t mask = 0x7ff; + int retries = 32; + + DPRINTK(1, INFO, "Entered ISR Disable \n"); + + switch (adapter->portnum) { + case 0: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); + break; + case 1: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); + break; + case 2: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); + break; + case 3: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); + break; + } + + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) + writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); + + /* Window = 0 or 1 */ + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + do { + writel(0xffffffff, + PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS)); + mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR)); + if (!(mask & 0x80)) + break; + udelay(10); + } while (--retries); + + if (!retries) { + printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", + netxen_nic_driver_name); + } + } + + DPRINTK(1, INFO, "Done with Disable Int\n"); +} + +static void netxen_nic_enable_int(struct netxen_adapter *adapter) +{ + u32 mask; + + DPRINTK(1, INFO, "Entered ISR Enable \n"); + + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) { + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + mask = 0x77b; + break; + case NETXEN_NIC_XGBE: + mask = 0x77f; + break; + default: + mask = 0x7ff; + break; + } + + writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); + } + + switch (adapter->portnum) { + case 0: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); + break; + case 1: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); + break; + case 2: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); + break; + case 3: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); + break; + } + + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + mask = 0xbff; + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) { + writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + } + writel(mask, + PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK)); + } + + DPRINTK(1, INFO, "Done with enable Int\n"); +} + /* * netxen_nic_probe() * @@ -210,8 +305,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_disable_pdev; pci_set_master(pdev); - pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id); - if (nx_p2_id == NX_P2_C1 && + if (pdev->revision == NX_P2_C1 && (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) && (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) { pci_using_dac = 1; @@ -241,7 +335,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ahw.pdev = pdev; adapter->ahw.pci_func = pci_func_id; spin_lock_init(&adapter->tx_lock); - spin_lock_init(&adapter->lock); /* remap phys address */ mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ @@ -455,7 +548,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); adapter->ahw.pdev = pdev; adapter->proc_cmd_buf_counter = 0; - adapter->ahw.revision_id = nx_p2_id; + adapter->ahw.revision_id = pdev->revision; /* make sure Window == 1 */ netxen_nic_pci_change_crbwindow(adapter, 1); @@ -653,9 +746,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_nic_disable_int(adapter); - if (adapter->irq) - free_irq(adapter->irq, adapter); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { init_firmware_done++; netxen_free_hw_resources(adapter); @@ -679,28 +769,22 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) } } - if (adapter->flags & NETXEN_NIC_MSI_ENABLED) - pci_disable_msi(pdev); - vfree(adapter->cmd_buf_arr); - pci_disable_device(pdev); - if (adapter->portnum == 0) { if (init_firmware_done) { - dma_watchdog_shutdown_request(adapter); - msleep(100); i = 100; - while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { - printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + do { + if (dma_watchdog_shutdown_request(adapter) == 1) + break; msleep(100); - i--; - } + if (dma_watchdog_shutdown_poll_result(adapter) == 1) + break; + } while (--i); - if (i == 0) { - printk(KERN_ERR "dma_watchdog_shutdown_request failed\n"); - return; - } + if (i == 0) + printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", + netdev->name); /* clear the register for future unloads/loads */ writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); @@ -709,11 +793,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) /* leave the hw in the same state as reboot */ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); - if (netxen_pinit_from_rom(adapter, 0)) - return; + netxen_pinit_from_rom(adapter, 0); msleep(1); - if (netxen_load_firmware(adapter)) - return; + netxen_load_firmware(adapter); netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); } @@ -722,30 +804,36 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) printk(KERN_INFO "State: 0x%0x\n", readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); - dma_watchdog_shutdown_request(adapter); - msleep(100); i = 100; - while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { - printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + do { + if (dma_watchdog_shutdown_request(adapter) == 1) + break; msleep(100); - i--; - } + if (dma_watchdog_shutdown_poll_result(adapter) == 1) + break; + } while (--i); if (i) { netxen_free_adapter_offload(adapter); } else { - printk(KERN_ERR "failed to dma shutdown\n"); - return; + printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", + netdev->name); } - } + if (adapter->irq) + free_irq(adapter->irq, adapter); + + if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + pci_disable_msi(pdev); + iounmap(adapter->ahw.db_base); iounmap(adapter->ahw.pci_base0); iounmap(adapter->ahw.pci_base1); iounmap(adapter->ahw.pci_base2); pci_release_regions(pdev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_netdev(netdev); @@ -801,8 +889,6 @@ static int netxen_nic_open(struct net_device *netdev) /* Done here again so that even if phantom sw overwrote it, * we set it */ - if (adapter->macaddr_set) - adapter->macaddr_set(adapter, netdev->dev_addr); if (adapter->init_port && adapter->init_port(adapter, adapter->portnum) != 0) { del_timer_sync(&adapter->watchdog_timer); @@ -810,6 +896,8 @@ static int netxen_nic_open(struct net_device *netdev) netxen_nic_driver_name, adapter->portnum); return -EIO; } + if (adapter->macaddr_set) + adapter->macaddr_set(adapter, netdev->dev_addr); netxen_nic_set_link_parameters(adapter); @@ -836,6 +924,8 @@ static int netxen_nic_close(struct net_device *netdev) netif_carrier_off(netdev); netif_stop_queue(netdev); + netxen_nic_disable_int(adapter); + cmd_buff = adapter->cmd_buf_arr; for (i = 0; i < adapter->max_tx_desc_count; i++) { buffrag = cmd_buff->frag_array; @@ -1132,15 +1222,12 @@ static void netxen_tx_timeout_task(struct work_struct *work) { struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, tx_timeout_task); - unsigned long flags; printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", netxen_nic_driver_name, adapter->netdev->name); - spin_lock_irqsave(&adapter->lock, flags); netxen_nic_close(adapter->netdev); netxen_nic_open(adapter->netdev); - spin_unlock_irqrestore(&adapter->lock, flags); adapter->netdev->trans_start = jiffies; netif_wake_queue(adapter->netdev); } @@ -1149,28 +1236,12 @@ static int netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) { u32 ret = 0; - u32 our_int = 0; DPRINTK(INFO, "Entered handle ISR\n"); adapter->stats.ints++; - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - /* not our interrupt */ - if ((our_int & (0x80 << adapter->portnum)) == 0) - return ret; - } - netxen_nic_disable_int(adapter); - if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { - /* claim interrupt */ - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - writel(our_int & ~((u32)(0x80 << adapter->portnum)), - NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - } - } - if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { if (netif_rx_schedule_prep(netdev)) { /* @@ -1204,6 +1275,7 @@ irqreturn_t netxen_intr(int irq, void *data) { struct netxen_adapter *adapter; struct net_device *netdev; + u32 our_int = 0; if (unlikely(!irq)) { return IRQ_NONE; /* Not our interrupt */ @@ -1211,7 +1283,22 @@ irqreturn_t netxen_intr(int irq, void *data) adapter = (struct netxen_adapter *)data; netdev = adapter->netdev; - /* process our status queue (for all 4 ports) */ + + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + /* not our interrupt */ + if ((our_int & (0x80 << adapter->portnum)) == 0) + return IRQ_NONE; + } + + if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { + /* claim interrupt */ + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + writel(our_int & ~((u32)(0x80 << adapter->portnum)), + NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + } + } + if (netif_running(netdev)) netxen_handle_int(adapter, netdev); diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index 75102d30730f..05e0577a0e10 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -724,7 +724,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) __u32 mac_cfg0; u32 port = physical_port[adapter->portnum]; - if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + if (port > NETXEN_NIU_MAX_GBE_PORTS) return -EINVAL; mac_cfg0 = 0; netxen_gb_soft_reset(mac_cfg0); @@ -757,7 +757,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, __u32 reg; u32 port = physical_port[adapter->portnum]; - if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + if (port > NETXEN_NIU_MAX_GBE_PORTS) return -EINVAL; /* save previous contents */ @@ -894,7 +894,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, __u32 reg; u32 port = physical_port[adapter->portnum]; - if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) + if (port > NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; if (netxen_nic_hw_read_wx(adapter, diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 3d5b4232f65f..22a3b3dc7d89 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -670,14 +670,10 @@ static void ni5010_set_multicast_list(struct net_device *dev) PRINTK2((KERN_DEBUG "%s: entering set_multicast_list\n", dev->name)); - if (dev->flags&IFF_PROMISC || dev->flags&IFF_ALLMULTI) { + if (dev->flags&IFF_PROMISC || dev->flags&IFF_ALLMULTI || dev->mc_list) { dev->flags |= IFF_PROMISC; outb(RMD_PROMISC, EDLC_RMODE); /* Enable promiscuous mode */ PRINTK((KERN_DEBUG "%s: Entering promiscuous mode\n", dev->name)); - } else if (dev->mc_list) { - /* Sorry, multicast not supported */ - PRINTK((KERN_DEBUG "%s: No multicast, entering broadcast mode\n", dev->name)); - outb(RMD_BROADCAST, EDLC_RMODE); } else { PRINTK((KERN_DEBUG "%s: Entering broadcast mode\n", dev->name)); outb(RMD_BROADCAST, EDLC_RMODE); /* Disable promiscuous mode, use normal mode */ diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 8dbd6d1900b5..5e7999db2096 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -936,7 +936,7 @@ static void ni52_rcv_int(struct net_device *dev) { skb_reserve(skb,2); skb_put(skb,totlen); - eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0); + skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index 3818edf0ac18..4ef5fe345191 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -1096,7 +1096,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) #ifdef RCV_VIA_SKB if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) { skb_put(skb,len); - eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0); + skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len); } else { struct sk_buff *skb1 = p->recv_skb[p->rmdnum]; @@ -1108,7 +1108,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) } #else skb_put(skb,len); - eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0); + skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len); #endif p->stats.rx_packets++; p->stats.rx_bytes += len; diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 104aab3c957f..ea80e6cb3dec 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1582,7 +1582,7 @@ static void ns83820_set_multicast(struct net_device *ndev) else and_mask &= ~(RFCR_AAU | RFCR_AAM); - if (ndev->flags & IFF_ALLMULTI) + if (ndev->flags & IFF_ALLMULTI || ndev->mc_count) or_mask |= RFCR_AAM; else and_mask &= ~RFCR_AAM; diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 8d38425e46c3..0b3066a6fe40 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -755,7 +755,7 @@ static int pasemi_mac_open(struct net_device *dev) flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G; pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch), - PAS_IOB_DMA_RXCH_CFG_CNTTH(1)); + PAS_IOB_DMA_RXCH_CFG_CNTTH(0)); pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch), PAS_IOB_DMA_TXCH_CFG_CNTTH(32)); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index df8998b4f37e..3cdbe118200b 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -1567,7 +1567,7 @@ static void netdrv_rx_interrupt (struct net_device *dev, if (skb) { skb_reserve (skb, 2); /* 16 byte align the IP fields. */ - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); + skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); skb_put (skb, pkt_size); skb->protocol = eth_type_trans (skb, dev); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 808fae1577e0..50dff1b81d34 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -521,6 +521,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) static int axnet_open(struct net_device *dev) { + int ret; axnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; @@ -529,9 +530,11 @@ static int axnet_open(struct net_device *dev) if (!pcmcia_dev_present(link)) return -ENODEV; - link->open++; + ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev); + if (ret) + return ret; - request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev); + link->open++; info->link_status = 0x00; init_timer(&info->watchdog); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 0d1c7a41c9c6..ea9414c4d900 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -147,7 +147,7 @@ static int com20020_probe(struct pcmcia_device *p_dev) DEBUG(0, "com20020_attach()\n"); /* Create new network device */ - info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); + info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); if (!info) goto fail_alloc_info; @@ -155,7 +155,6 @@ static int com20020_probe(struct pcmcia_device *p_dev) if (!dev) goto fail_alloc_dev; - memset(info, 0, sizeof(struct com20020_dev_t)); lp = dev->priv; lp->timeout = timeout; lp->backplane = backplane; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 3f93d4933235..85d5f2ca4bb5 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -109,7 +109,7 @@ static const struct ethtool_ops netdev_ethtool_ops; card type */ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, - XXX10304 + XXX10304, NEC, KME } cardtype_t; /* @@ -374,6 +374,18 @@ static int fmvj18x_config(struct pcmcia_device *link) link->io.NumPorts2 = 8; } break; + case MANFID_NEC: + cardtype = NEC; /* MultiFunction Card */ + link->conf.ConfigBase = 0x800; + link->conf.ConfigIndex = 0x47; + link->io.NumPorts2 = 8; + break; + case MANFID_KME: + cardtype = KME; /* MultiFunction Card */ + link->conf.ConfigBase = 0x800; + link->conf.ConfigIndex = 0x47; + link->io.NumPorts2 = 8; + break; case MANFID_CONTEC: cardtype = CONTEC; break; @@ -450,6 +462,8 @@ static int fmvj18x_config(struct pcmcia_device *link) case TDK: case LA501: case CONTEC: + case NEC: + case KME: tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); @@ -469,6 +483,10 @@ static int fmvj18x_config(struct pcmcia_device *link) card_name = "TDK LAK-CD021"; } else if( cardtype == LA501 ) { card_name = "LA501"; + } else if( cardtype == NEC ) { + card_name = "PK-UG-J001"; + } else if( cardtype == KME ) { + card_name = "Panasonic"; } else { card_name = "C-NET(PC)C"; } @@ -678,8 +696,11 @@ static struct pcmcia_device_id fmvj18x_ids[] = { PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da), PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080), PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids); diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 4ecb8ca5a992..4eafa4f42cff 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -146,9 +146,8 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link) DEBUG(0, "ibmtr_attach()\n"); /* Create new token-ring device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - memset(info,0,sizeof(*info)); dev = alloc_trdev(sizeof(struct tok_info)); if (!dev) { kfree(info); diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 73da611fd536..997c2d0c83bb 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -996,7 +996,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; mace_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr; int status; int IntrCnt = MACE_MAX_IR_ITERATIONS; @@ -1006,6 +1006,8 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) return IRQ_NONE; } + ioaddr = dev->base_addr; + if (lp->tx_irq_disabled) { printk( (lp->tx_irq_disabled? diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d88e9b2e93cf..63de89e93b70 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -960,6 +960,7 @@ static void mii_phy_probe(struct net_device *dev) static int pcnet_open(struct net_device *dev) { + int ret; pcnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; @@ -968,10 +969,12 @@ static int pcnet_open(struct net_device *dev) if (!pcmcia_dev_present(link)) return -ENODEV; - link->open++; - set_misc_reg(dev); - request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev); + ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev); + if (ret) + return ret; + + link->open++; info->phy_id = info->eth_phy; info->link_status = 0x00; @@ -1552,6 +1555,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555), PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c), @@ -1577,6 +1581,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103), PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121), PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e), PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b), PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b), PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e), diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 7912dbd14251..af6728cb49c3 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1368,6 +1368,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) kio_addr_t ioaddr = dev->base_addr; u_short num_pages; short time_out, ir; + unsigned long flags; netif_stop_queue(dev); @@ -1395,6 +1396,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) /* A packet is now waiting. */ smc->packets_waiting++; + spin_lock_irqsave(&smc->lock, flags); SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */ /* need MC_RESET to keep the memory consistent. errata? */ @@ -1411,6 +1413,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Acknowledge the interrupt, send the packet. */ outw((ir&0xff00) | IM_ALLOC_INT, ioaddr + INTERRUPT); smc_hardware_send_packet(dev); /* Send the packet now.. */ + spin_unlock_irqrestore(&smc->lock, flags); return 0; } } @@ -1418,6 +1421,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Otherwise defer until the Tx-space-allocated interrupt. */ DEBUG(2, "%s: memory allocation deferred.\n", dev->name); outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT); + spin_unlock_irqrestore(&smc->lock, flags); return 0; } @@ -1523,6 +1527,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, irq, ioaddr); + spin_lock(&smc->lock); smc->watchdog = 0; saved_bank = inw(ioaddr + BANK_SELECT); if ((saved_bank & 0xff00) != 0x3300) { @@ -1620,6 +1625,7 @@ irq_done: readb(smc->base+MEGAHERTZ_ISR); } #endif + spin_unlock(&smc->lock); return IRQ_RETVAL(handled); } @@ -1902,6 +1908,9 @@ static void media_check(u_long arg) kio_addr_t ioaddr = dev->base_addr; u_short i, media, saved_bank; u_short link; + unsigned long flags; + + spin_lock_irqsave(&smc->lock, flags); saved_bank = inw(ioaddr + BANK_SELECT); @@ -1934,6 +1943,7 @@ static void media_check(u_long arg) smc->media.expires = jiffies + HZ/100; add_timer(&smc->media); SMC_SELECT_BANK(saved_bank); + spin_unlock_irqrestore(&smc->lock, flags); return; } @@ -2007,6 +2017,7 @@ reschedule: smc->media.expires = jiffies + HZ; add_timer(&smc->media); SMC_SELECT_BANK(saved_bank); + spin_unlock_irqrestore(&smc->lock, flags); } static int smc_link_ok(struct net_device *dev) @@ -2094,14 +2105,14 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); + SMC_SELECT_BANK(3); if (smc->cfg & CFG_MII_SELECT) ret = mii_ethtool_gset(&smc->mii_if, ecmd); else ret = smc_netdev_get_ecmd(dev, ecmd); - spin_unlock_irq(&smc->lock); SMC_SELECT_BANK(saved_bank); + spin_unlock_irq(&smc->lock); return ret; } @@ -2112,14 +2123,14 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); + SMC_SELECT_BANK(3); if (smc->cfg & CFG_MII_SELECT) ret = mii_ethtool_sset(&smc->mii_if, ecmd); else ret = smc_netdev_set_ecmd(dev, ecmd); - spin_unlock_irq(&smc->lock); SMC_SELECT_BANK(saved_bank); + spin_unlock_irq(&smc->lock); return ret; } @@ -2130,11 +2141,11 @@ static u32 smc_get_link(struct net_device *dev) u16 saved_bank = inw(ioaddr + BANK_SELECT); u32 ret; - SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); + SMC_SELECT_BANK(3); ret = smc_link_ok(dev); - spin_unlock_irq(&smc->lock); SMC_SELECT_BANK(saved_bank); + spin_unlock_irq(&smc->lock); return ret; } diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 9c171a7390e2..e6a67531de99 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1235,9 +1235,9 @@ static void pcnet32_rx_entry(struct net_device *dev, lp->rx_dma_addr[entry], pkt_len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)(lp->rx_skbuff[entry]->data), - pkt_len, 0); + pkt_len); pci_dma_sync_single_for_device(lp->pci_dev, lp->rx_dma_addr[entry], pkt_len, @@ -1515,7 +1515,6 @@ static const struct ethtool_ops pcnet32_ethtool_ops = { .phys_id = pcnet32_phys_id, .get_regs_len = pcnet32_get_regs_len, .get_regs = pcnet32_get_regs, - .get_perm_addr = ethtool_op_get_perm_addr, }; /* only probes for non-PCI devices, the rest are handled by diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 09b6f259eb92..dd09011c7ee5 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -55,6 +55,11 @@ config BROADCOM_PHY ---help--- Currently supports the BCM5411, BCM5421 and BCM5461 PHYs. +config ICPLUS_PHY + tristate "Drivers for ICPlus PHYs" + ---help--- + Currently supports the IP175C PHY. + config FIXED_PHY tristate "Drivers for PHY emulation on fixed speed/link" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index bcd1efbd2a18..8885650647ff 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -11,4 +11,5 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o obj-$(CONFIG_BROADCOM_PHY) += broadcom.o +obj-$(CONFIG_ICPLUS_PHY) += icplus.o obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index b87f8d2a888b..d2ede5ff9fff 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -60,6 +60,7 @@ #define MII_M1111_PHY_EXT_SR 0x1b #define MII_M1111_HWCFG_MODE_MASK 0xf #define MII_M1111_HWCFG_MODE_RGMII 0xb +#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 MODULE_DESCRIPTION("Marvell PHY driver"); MODULE_AUTHOR("Andy Fleming"); @@ -169,6 +170,21 @@ static int m88e1111_config_init(struct phy_device *phydev) return err; } + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + int temp; + + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); + if (temp < 0) + return temp; + + temp &= ~(MII_M1111_HWCFG_MODE_MASK); + temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; + + err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); + if (err < 0) + return err; + } + err = phy_write(phydev, MII_BMCR, BMCR_RESET); if (err < 0) return err; @@ -238,77 +254,84 @@ static int m88e1145_config_init(struct phy_device *phydev) return 0; } -static struct phy_driver m88e1101_driver = { - .phy_id = 0x01410c60, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1101", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, -}; - -static struct phy_driver m88e1111_driver = { - .phy_id = 0x01410cc0, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1111", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .config_init = &m88e1111_config_init, - .driver = {.owner = THIS_MODULE,}, -}; - -static struct phy_driver m88e1145_driver = { - .phy_id = 0x01410cd0, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1145", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_init = &m88e1145_config_init, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, +static struct phy_driver marvell_drivers[] = { + { + .phy_id = 0x01410c60, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1101", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + }, + { + .phy_id = 0x01410c90, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1112", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1111_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + }, + { + .phy_id = 0x01410cc0, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1111", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1111_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + }, + { + .phy_id = 0x01410cd0, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1145", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1145_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + } }; static int __init marvell_init(void) { int ret; + int i; - ret = phy_driver_register(&m88e1101_driver); - if (ret) - return ret; + for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { + ret = phy_driver_register(&marvell_drivers[i]); - ret = phy_driver_register(&m88e1111_driver); - if (ret) - goto err1111; - - ret = phy_driver_register(&m88e1145_driver); - if (ret) - goto err1145; + if (ret) { + while (i-- > 0) + phy_driver_unregister(&marvell_drivers[i]); + return ret; + } + } return 0; - -err1145: - phy_driver_unregister(&m88e1111_driver); -err1111: - phy_driver_unregister(&m88e1101_driver); - return ret; } static void __exit marvell_exit(void) { - phy_driver_unregister(&m88e1101_driver); - phy_driver_unregister(&m88e1111_driver); - phy_driver_unregister(&m88e1145_driver); + int i; + + for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) + phy_driver_unregister(&marvell_drivers[i]); } module_init(marvell_init); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f71dab347667..cb230f44d6fc 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -261,7 +261,7 @@ void phy_sanitize_settings(struct phy_device *phydev) /* Sanitize settings based on PHY capabilities */ if ((features & SUPPORTED_Autoneg) == 0) - phydev->autoneg = 0; + phydev->autoneg = AUTONEG_DISABLE; idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex), features); @@ -374,7 +374,7 @@ int phy_mii_ioctl(struct phy_device *phydev, if (mii_data->phy_id == phydev->addr) { switch(mii_data->reg_num) { case MII_BMCR: - if (val & (BMCR_RESET|BMCR_ANENABLE)) + if ((val & (BMCR_RESET|BMCR_ANENABLE)) == 0) phydev->autoneg = AUTONEG_DISABLE; else phydev->autoneg = AUTONEG_ENABLE; @@ -409,6 +409,7 @@ int phy_mii_ioctl(struct phy_device *phydev, return 0; } +EXPORT_SYMBOL(phy_mii_ioctl); /** * phy_start_aneg - start auto-negotiation for this PHY device @@ -755,7 +756,7 @@ out_unlock: */ void phy_start(struct phy_device *phydev) { - spin_lock(&phydev->lock); + spin_lock_bh(&phydev->lock); switch (phydev->state) { case PHY_STARTING: @@ -769,7 +770,7 @@ void phy_start(struct phy_device *phydev) default: break; } - spin_unlock(&phydev->lock); + spin_unlock_bh(&phydev->lock); } EXPORT_SYMBOL(phy_stop); EXPORT_SYMBOL(phy_start); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index a8b74cdab1ea..49328e050505 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -364,7 +364,7 @@ EXPORT_SYMBOL(genphy_config_advert); */ int genphy_setup_forced(struct phy_device *phydev) { - int ctl = BMCR_RESET; + int ctl = 0; phydev->pause = phydev->asym_pause = 0; @@ -644,7 +644,7 @@ static int phy_probe(struct device *dev) if (!(phydrv->flags & PHY_HAS_INTERRUPT)) phydev->irq = PHY_POLL; - spin_lock(&phydev->lock); + spin_lock_bh(&phydev->lock); /* Start out supporting everything. Eventually, * a controller will attach, and may modify one @@ -658,7 +658,7 @@ static int phy_probe(struct device *dev) if (phydev->drv->probe) err = phydev->drv->probe(phydev); - spin_unlock(&phydev->lock); + spin_unlock_bh(&phydev->lock); return err; diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 596222b260d6..8874497b6bbf 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -21,6 +21,10 @@ /* Vitesse Extended Control Register 1 */ #define MII_VSC8244_EXT_CON1 0x17 #define MII_VSC8244_EXTCON1_INIT 0x0000 +#define MII_VSC8244_EXTCON1_TX_SKEW_MASK 0x0c00 +#define MII_VSC8244_EXTCON1_RX_SKEW_MASK 0x0300 +#define MII_VSC8244_EXTCON1_TX_SKEW 0x0800 +#define MII_VSC8244_EXTCON1_RX_SKEW 0x0200 /* Vitesse Interrupt Mask Register */ #define MII_VSC8244_IMASK 0x19 @@ -39,7 +43,7 @@ /* Vitesse Auxiliary Control/Status Register */ #define MII_VSC8244_AUX_CONSTAT 0x1c -#define MII_VSC8244_AUXCONSTAT_INIT 0x0004 +#define MII_VSC8244_AUXCONSTAT_INIT 0x0000 #define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 #define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 #define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 @@ -51,6 +55,7 @@ MODULE_LICENSE("GPL"); static int vsc824x_config_init(struct phy_device *phydev) { + int extcon; int err; err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, @@ -58,14 +63,34 @@ static int vsc824x_config_init(struct phy_device *phydev) if (err < 0) return err; - err = phy_write(phydev, MII_VSC8244_EXT_CON1, - MII_VSC8244_EXTCON1_INIT); + extcon = phy_read(phydev, MII_VSC8244_EXT_CON1); + + if (extcon < 0) + return err; + + extcon &= ~(MII_VSC8244_EXTCON1_TX_SKEW_MASK | + MII_VSC8244_EXTCON1_RX_SKEW_MASK); + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + extcon |= (MII_VSC8244_EXTCON1_TX_SKEW | + MII_VSC8244_EXTCON1_RX_SKEW); + + err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon); + return err; } static int vsc824x_ack_interrupt(struct phy_device *phydev) { - int err = phy_read(phydev, MII_VSC8244_ISTAT); + int err = 0; + + /* + * Don't bother to ACK the interrupts if interrupts + * are disabled. The 824x cannot clear the interrupts + * if they are disabled. + */ + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_read(phydev, MII_VSC8244_ISTAT); return (err < 0) ? err : 0; } @@ -77,8 +102,19 @@ static int vsc824x_config_intr(struct phy_device *phydev) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, MII_VSC8244_IMASK, MII_VSC8244_IMASK_MASK); - else + else { + /* + * The Vitesse PHY cannot clear the interrupt + * once it has disabled them, so we clear them first + */ + err = phy_read(phydev, MII_VSC8244_ISTAT); + + if (err < 0) + return err; + err = phy_write(phydev, MII_VSC8244_IMASK, 0); + } + return err; } diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index caabbc408c34..27f5b904f48e 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -159,12 +159,11 @@ ppp_asynctty_open(struct tty_struct *tty) int err; err = -ENOMEM; - ap = kmalloc(sizeof(*ap), GFP_KERNEL); + ap = kzalloc(sizeof(*ap), GFP_KERNEL); if (ap == 0) goto out; /* initialize the asyncppp structure */ - memset(ap, 0, sizeof(*ap)); ap->tty = tty; ap->mru = PPP_MRU; spin_lock_init(&ap->xmit_lock); diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c index 72c8d6628f58..eb98b661efba 100644 --- a/drivers/net/ppp_deflate.c +++ b/drivers/net/ppp_deflate.c @@ -121,12 +121,11 @@ static void *z_comp_alloc(unsigned char *options, int opt_len) if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) return NULL; - state = kmalloc(sizeof(*state), + state = kzalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) return NULL; - memset (state, 0, sizeof (struct ppp_deflate_state)); state->strm.next_in = NULL; state->w_size = w_size; state->strm.workspace = vmalloc(zlib_deflate_workspacesize()); @@ -341,11 +340,10 @@ static void *z_decomp_alloc(unsigned char *options, int opt_len) if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) return NULL; - state = kmalloc(sizeof(*state), GFP_KERNEL); + state = kzalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) return NULL; - memset (state, 0, sizeof (struct ppp_deflate_state)); state->w_size = w_size; state->strm.next_out = NULL; state->strm.workspace = kmalloc(zlib_inflate_workspacesize(), diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 9a81fed5aa6e..4b49d0e8c7eb 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -899,17 +899,9 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Put the 2-byte PPP protocol number on the front, making sure there is room for the address and control fields. */ - if (skb_headroom(skb) < PPP_HDRLEN) { - struct sk_buff *ns; - - ns = alloc_skb(skb->len + dev->hard_header_len, GFP_ATOMIC); - if (ns == 0) - goto outf; - skb_reserve(ns, dev->hard_header_len); - skb_copy_bits(skb, 0, skb_put(ns, skb->len), skb->len); - kfree_skb(skb); - skb = ns; - } + if (skb_cow_head(skb, PPP_HDRLEN)) + goto outf; + pp = skb_push(skb, 2); proto = npindex_to_proto[npi]; pp[0] = proto >> 8; @@ -1533,7 +1525,7 @@ ppp_input_error(struct ppp_channel *chan, int code) static void ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) { - if (skb->len >= 2) { + if (pskb_may_pull(skb, 2)) { #ifdef CONFIG_PPP_MULTILINK /* XXX do channel-level decompression here */ if (PPP_PROTO(skb) == PPP_MP) @@ -1585,7 +1577,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) goto err; - if (skb_tailroom(skb) < 124) { + if (skb_tailroom(skb) < 124 || skb_cloned(skb)) { /* copy to a new sk_buff with more tailroom */ ns = dev_alloc_skb(skb->len + 128); if (ns == 0) { @@ -1656,23 +1648,29 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) /* check if the packet passes the pass and active filters */ /* the filter instructions are constructed assuming a four-byte PPP header on each packet */ - *skb_push(skb, 2) = 0; - if (ppp->pass_filter - && sk_run_filter(skb, ppp->pass_filter, - ppp->pass_len) == 0) { - if (ppp->debug & 1) - printk(KERN_DEBUG "PPP: inbound frame not passed\n"); - kfree_skb(skb); - return; - } - if (!(ppp->active_filter - && sk_run_filter(skb, ppp->active_filter, - ppp->active_len) == 0)) - ppp->last_recv = jiffies; - skb_pull(skb, 2); -#else - ppp->last_recv = jiffies; + if (ppp->pass_filter || ppp->active_filter) { + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto err; + + *skb_push(skb, 2) = 0; + if (ppp->pass_filter + && sk_run_filter(skb, ppp->pass_filter, + ppp->pass_len) == 0) { + if (ppp->debug & 1) + printk(KERN_DEBUG "PPP: inbound frame " + "not passed\n"); + kfree_skb(skb); + return; + } + if (!(ppp->active_filter + && sk_run_filter(skb, ppp->active_filter, + ppp->active_len) == 0)) + ppp->last_recv = jiffies; + __skb_pull(skb, 2); + } else #endif /* CONFIG_PPP_FILTER */ + ppp->last_recv = jiffies; if ((ppp->dev->flags & IFF_UP) == 0 || ppp->npmode[npi] != NPMODE_PASS) { @@ -1770,7 +1768,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) struct channel *ch; int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; - if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0) + if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0) goto err; /* no good, throw it away */ /* Decode sequence number and begin/end bits */ @@ -2684,8 +2682,7 @@ static void __exit ppp_cleanup(void) if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count)) printk(KERN_ERR "PPP: removing module but units remain!\n"); cardmap_destroy(&all_ppp_units); - if (unregister_chrdev(PPP_MAJOR, "ppp") != 0) - printk(KERN_ERR "PPP: failed to unregister PPP device\n"); + unregister_chrdev(PPP_MAJOR, "ppp"); device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); class_destroy(ppp_class); } diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c index d5bdd2574659..c0b6d19d1457 100644 --- a/drivers/net/ppp_mppe.c +++ b/drivers/net/ppp_mppe.c @@ -136,7 +136,7 @@ struct ppp_mppe_state { * Key Derivation, from RFC 3078, RFC 3079. * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. */ -static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey) +static void get_new_key_from_sha(struct ppp_mppe_state * state) { struct hash_desc desc; struct scatterlist sg[4]; @@ -153,8 +153,6 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *I desc.flags = 0; crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest); - - memcpy(InterimKey, state->sha1_digest, state->keylen); } /* @@ -163,21 +161,21 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *I */ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) { - unsigned char InterimKey[MPPE_MAX_KEY_LEN]; struct scatterlist sg_in[1], sg_out[1]; struct blkcipher_desc desc = { .tfm = state->arc4 }; - get_new_key_from_sha(state, InterimKey); + get_new_key_from_sha(state); if (!initial_key) { - crypto_blkcipher_setkey(state->arc4, InterimKey, state->keylen); - setup_sg(sg_in, InterimKey, state->keylen); + crypto_blkcipher_setkey(state->arc4, state->sha1_digest, + state->keylen); + setup_sg(sg_in, state->sha1_digest, state->keylen); setup_sg(sg_out, state->session_key, state->keylen); if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, state->keylen) != 0) { printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); } } else { - memcpy(state->session_key, InterimKey, state->keylen); + memcpy(state->session_key, state->sha1_digest, state->keylen); } if (state->keylen == 8) { /* See RFC 3078 */ @@ -200,11 +198,10 @@ static void *mppe_alloc(unsigned char *options, int optlen) || options[0] != CI_MPPE || options[1] != CILEN_MPPE) goto out; - state = kmalloc(sizeof(*state), GFP_KERNEL); + state = kzalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) goto out; - memset(state, 0, sizeof(*state)); state->arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(state->arc4)) { diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 5918fab38349..ce64032a465a 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -207,13 +207,12 @@ ppp_sync_open(struct tty_struct *tty) struct syncppp *ap; int err; - ap = kmalloc(sizeof(*ap), GFP_KERNEL); + ap = kzalloc(sizeof(*ap), GFP_KERNEL); err = -ENOMEM; if (ap == 0) goto out; /* initialize the syncppp structure */ - memset(ap, 0, sizeof(*ap)); ap->tty = tty; ap->mru = PPP_MRU; spin_lock_init(&ap->xmit_lock); diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 6f98834e6ace..9b30cd600a64 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -108,19 +108,24 @@ static inline int cmp_addr(struct pppoe_addr *a, unsigned long sid, char *addr) (memcmp(a->remote,addr,ETH_ALEN) == 0)); } -static int hash_item(unsigned long sid, unsigned char *addr) +#if 8%PPPOE_HASH_BITS +#error 8 must be a multiple of PPPOE_HASH_BITS +#endif + +static int hash_item(unsigned int sid, unsigned char *addr) { - char hash = 0; - int i, j; + unsigned char hash = 0; + unsigned int i; - for (i = 0; i < ETH_ALEN ; ++i) { - for (j = 0; j < 8/PPPOE_HASH_BITS ; ++j) { - hash ^= addr[i] >> ( j * PPPOE_HASH_BITS ); - } + for (i = 0 ; i < ETH_ALEN ; i++) { + hash ^= addr[i]; + } + for (i = 0 ; i < sizeof(sid_t)*8 ; i += 8 ){ + hash ^= sid>>i; + } + for (i = 8 ; (i>>=1) >= PPPOE_HASH_BITS ; ) { + hash ^= hash>>i; } - - for (i = 0; i < (sizeof(unsigned long)*8) / PPPOE_HASH_BITS ; ++i) - hash ^= sid >> (i*PPPOE_HASH_BITS); return hash & ( PPPOE_HASH_SIZE - 1 ); } @@ -380,12 +385,12 @@ static int pppoe_rcv(struct sk_buff *skb, struct pppoe_hdr *ph; struct pppox_sock *po; - if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) - goto drop; - if (!(skb = skb_share_check(skb, GFP_ATOMIC))) goto out; + if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) + goto drop; + ph = pppoe_hdr(skb); po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex); @@ -664,8 +669,8 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, { struct sock *sk = sock->sk; struct pppox_sock *po = pppox_sk(sk); - int val = 0; - int err = 0; + int val; + int err; switch (cmd) { case PPPIOCGMRU: @@ -754,8 +759,9 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, err = 0; break; - default:; - }; + default: + err = -ENOTTY; + } return err; } @@ -773,6 +779,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct net_device *dev; char *start; + lock_sock(sk); if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) { error = -ENOTCONN; goto end; @@ -783,8 +790,6 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, hdr.code = 0; hdr.sid = po->num; - lock_sock(sk); - dev = po->pppoe_dev; error = -EMSGSIZE; @@ -843,71 +848,44 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) { struct pppox_sock *po = pppox_sk(sk); struct net_device *dev = po->pppoe_dev; - struct pppoe_hdr hdr; struct pppoe_hdr *ph; - int headroom = skb_headroom(skb); int data_len = skb->len; - struct sk_buff *skb2; if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) goto abort; - hdr.ver = 1; - hdr.type = 1; - hdr.code = 0; - hdr.sid = po->num; - hdr.length = htons(skb->len); - if (!dev) goto abort; - /* Copy the skb if there is no space for the header. */ - if (headroom < (sizeof(struct pppoe_hdr) + dev->hard_header_len)) { - skb2 = dev_alloc_skb(32+skb->len + - sizeof(struct pppoe_hdr) + - dev->hard_header_len); - - if (skb2 == NULL) - goto abort; - - skb_reserve(skb2, dev->hard_header_len + sizeof(struct pppoe_hdr)); - skb_copy_from_linear_data(skb, skb_put(skb2, skb->len), - skb->len); - } else { - /* Make a clone so as to not disturb the original skb, - * give dev_queue_xmit something it can free. - */ - skb2 = skb_clone(skb, GFP_ATOMIC); - - if (skb2 == NULL) - goto abort; - } + /* Copy the data if there is no space for the header or if it's + * read-only. + */ + if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) + goto abort; - ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr)); - memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); - skb2->protocol = __constant_htons(ETH_P_PPP_SES); + __skb_push(skb, sizeof(*ph)); + skb_reset_network_header(skb); - skb_reset_network_header(skb2); + ph = pppoe_hdr(skb); + ph->ver = 1; + ph->type = 1; + ph->code = 0; + ph->sid = po->num; + ph->length = htons(data_len); - skb2->dev = dev; + skb->protocol = __constant_htons(ETH_P_PPP_SES); + skb->dev = dev; - dev->hard_header(skb2, dev, ETH_P_PPP_SES, + dev->hard_header(skb, dev, ETH_P_PPP_SES, po->pppoe_pa.remote, NULL, data_len); - /* We're transmitting skb2, and assuming that dev_queue_xmit - * will free it. The generic ppp layer however, is expecting - * that we give back 'skb' (not 'skb2') in case of failure, - * but free it in case of success. - */ - - if (dev_queue_xmit(skb2) < 0) - goto abort; + dev_queue_xmit(skb); - kfree_skb(skb); return 1; abort: - return 0; + kfree_skb(skb); + return 1; } diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c index f3e47d0c2b3c..25c52b55c38f 100644 --- a/drivers/net/pppox.c +++ b/drivers/net/pppox.c @@ -73,7 +73,7 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; struct pppox_sock *po = pppox_sk(sk); - int rc = 0; + int rc; lock_sock(sk); @@ -94,12 +94,9 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; } default: - if (pppox_protos[sk->sk_protocol]->ioctl) - rc = pppox_protos[sk->sk_protocol]->ioctl(sock, cmd, - arg); - - break; - }; + rc = pppox_protos[sk->sk_protocol]->ioctl ? + pppox_protos[sk->sk_protocol]->ioctl(sock, cmd, arg) : -ENOTTY; + } release_sock(sk); return rc; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 585be044ebbb..ea151315050c 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1904,7 +1904,6 @@ static void ql_get_pauseparam(struct net_device *ndev, static const struct ethtool_ops ql3xxx_ethtool_ops = { .get_settings = ql_get_settings, .get_drvinfo = ql_get_drvinfo, - .get_perm_addr = ethtool_op_get_perm_addr, .get_link = ethtool_op_get_link, .get_msglevel = ql_get_msglevel, .set_msglevel = ql_set_msglevel, @@ -2249,6 +2248,13 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, qdev->rsp_consumer_index) && (work_done < work_to_do)) { net_rsp = qdev->rsp_current; + rmb(); + /* + * Fix 4032 chipe undocumented "feature" where bit-8 is set if the + * inbound completion is for a VLAN. + */ + if (qdev->device_id == QL3032_DEVICE_ID) + net_rsp->opcode &= 0x7f; switch (net_rsp->opcode) { case OPCODE_OB_MAC_IOCB_FN0: @@ -2433,37 +2439,22 @@ static int ql_get_seg_count(struct ql3_adapter *qdev, return -1; } -static void ql_hw_csum_setup(struct sk_buff *skb, +static void ql_hw_csum_setup(const struct sk_buff *skb, struct ob_mac_iocb_req *mac_iocb_ptr) { - struct ethhdr *eth; - struct iphdr *ip = NULL; - u8 offset = ETH_HLEN; + const struct iphdr *ip = ip_hdr(skb); - eth = (struct ethhdr *)(skb->data); - - if (eth->h_proto == __constant_htons(ETH_P_IP)) { - ip = (struct iphdr *)&skb->data[ETH_HLEN]; - } else if (eth->h_proto == htons(ETH_P_8021Q) && - ((struct vlan_ethhdr *)skb->data)-> - h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) { - ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN]; - offset = VLAN_ETH_HLEN; - } + mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb); + mac_iocb_ptr->ip_hdr_len = ip->ihl; - if (ip) { - if (ip->protocol == IPPROTO_TCP) { - mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | + if (ip->protocol == IPPROTO_TCP) { + mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | OB_3032MAC_IOCB_REQ_IC; - mac_iocb_ptr->ip_hdr_off = offset; - mac_iocb_ptr->ip_hdr_len = ip->ihl; - } else if (ip->protocol == IPPROTO_UDP) { - mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | + } else { + mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | OB_3032MAC_IOCB_REQ_IC; - mac_iocb_ptr->ip_hdr_off = offset; - mac_iocb_ptr->ip_hdr_len = ip->ihl; - } } + } /* diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 84958c8d0e69..c76dd29c8e9a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1,53 +1,11 @@ /* -========================================================================= - r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x. - -------------------------------------------------------------------- - - History: - Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>. - May 20 2002 - Add link status force-mode and TBI mode support. - 2004 - Massive updates. See kernel SCM system for details. -========================================================================= - 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. - Command: 'insmod r8169 media = SET_MEDIA' - Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. - - SET_MEDIA can be: - _10_Half = 0x01 - _10_Full = 0x02 - _100_Half = 0x04 - _100_Full = 0x08 - _1000_Full = 0x10 - - 2. Support TBI mode. -========================================================================= -VERSION 1.1 <2002/10/4> - - The bit4:0 of MII register 4 is called "selector field", and have to be - 00001b to indicate support of IEEE std 802.3 during NWay process of - exchanging Link Code Word (FLP). - -VERSION 1.2 <2002/11/30> - - - Large style cleanup - - Use ether_crc in stock kernel (linux/crc32.h) - - Copy mc_filter setup code from 8139cp - (includes an optimization, and avoids set_bit use) - -VERSION 1.6LK <2004/04/14> - - - Merge of Realtek's version 1.6 - - Conversion to DMA API - - Suspend/resume - - Endianness - - Misc Rx/Tx bugs - -VERSION 2.2LK <2005/01/25> - - - RX csum, TX csum/SG, TSO - - VLAN - - baby (< 7200) Jumbo frames support - - Merge of Realtek's version 2.2 (new phy) + * r8169.c: RealTek 8169/8168/8101 ethernet driver. + * + * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw> + * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com> + * Copyright (c) a lot of people too. Please respect their work. + * + * See MAINTAINERS file for support contact information. */ #include <linux/module.h> @@ -108,11 +66,6 @@ VERSION 2.2LK <2005/01/25> #define rtl8169_rx_quota(count, quota) count #endif -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -static int num_media = 0; - /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static const int max_interrupt_work = 20; @@ -126,7 +79,7 @@ static const int multicast_filter_limit = 32; #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ +#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ #define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ @@ -151,16 +104,17 @@ static const int multicast_filter_limit = 32; #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x00, - RTL_GIGA_MAC_VER_02 = 0x01, - RTL_GIGA_MAC_VER_03 = 0x02, - RTL_GIGA_MAC_VER_04 = 0x03, - RTL_GIGA_MAC_VER_05 = 0x04, - RTL_GIGA_MAC_VER_11 = 0x0b, - RTL_GIGA_MAC_VER_12 = 0x0c, - RTL_GIGA_MAC_VER_13 = 0x0d, - RTL_GIGA_MAC_VER_14 = 0x0e, - RTL_GIGA_MAC_VER_15 = 0x0f + RTL_GIGA_MAC_VER_01 = 0x01, // 8169 + RTL_GIGA_MAC_VER_02 = 0x02, // 8169S + RTL_GIGA_MAC_VER_03 = 0x03, // 8110S + RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB + RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd + RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe + RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb + RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf + RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec + RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 + RTL_GIGA_MAC_VER_15 = 0x0f // 8101 }; enum phy_version { @@ -180,11 +134,12 @@ static const struct { u8 mac_version; u32 RxConfigMask; /* Clears the bits supported by this chip */ } rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), - _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_02, 0xff7e1880), - _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), + _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 + _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S + _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S + _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB + _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd + _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 @@ -199,20 +154,15 @@ enum cfg_version { RTL_CFG_2 }; -static const struct { - unsigned int region; - unsigned int align; -} rtl_cfg_info[] = { - [RTL_CFG_0] = { 1, NET_IP_ALIGN }, - [RTL_CFG_1] = { 2, NET_IP_ALIGN }, - [RTL_CFG_2] = { 2, 8 } -}; +static void rtl_hw_start_8169(struct net_device *); +static void rtl_hw_start_8168(struct net_device *); +static void rtl_hw_start_8101(struct net_device *); static struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_2 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 }, @@ -230,62 +180,63 @@ static struct { u32 msg_enable; } debug = { -1 }; -enum RTL8169_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4C, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5C, - PHYAR = 0x60, - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6A, - PHYstatus = 0x6C, - RxMaxSize = 0xDA, - CPlusCmd = 0xE0, - IntrMitigate = 0xE2, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - EarlyTxThres = 0xEC, - FuncEvent = 0xF0, - FuncEventMask = 0xF4, - FuncPresetState = 0xF8, - FuncForceEvent = 0xFC, +enum rtl_registers { + MAC0 = 0, /* Ethernet hardware address. */ + MAC4 = 4, + MAR0 = 8, /* Multicast filter. */ + CounterAddrLow = 0x10, + CounterAddrHigh = 0x14, + TxDescStartAddrLow = 0x20, + TxDescStartAddrHigh = 0x24, + TxHDescStartAddrLow = 0x28, + TxHDescStartAddrHigh = 0x2c, + FLASH = 0x30, + ERSR = 0x36, + ChipCmd = 0x37, + TxPoll = 0x38, + IntrMask = 0x3c, + IntrStatus = 0x3e, + TxConfig = 0x40, + RxConfig = 0x44, + RxMissed = 0x4c, + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + Config2 = 0x53, + Config3 = 0x54, + Config4 = 0x55, + Config5 = 0x56, + MultiIntr = 0x5c, + PHYAR = 0x60, + TBICSR = 0x64, + TBI_ANAR = 0x68, + TBI_LPAR = 0x6a, + PHYstatus = 0x6c, + RxMaxSize = 0xda, + CPlusCmd = 0xe0, + IntrMitigate = 0xe2, + RxDescAddrLow = 0xe4, + RxDescAddrHigh = 0xe8, + EarlyTxThres = 0xec, + FuncEvent = 0xf0, + FuncEventMask = 0xf4, + FuncPresetState = 0xf8, + FuncForceEvent = 0xfc, }; -enum RTL8169_register_content { +enum rtl_register_content { /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x80, - RxFIFOOver = 0x40, - LinkChg = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, + SYSErr = 0x8000, + PCSTimeout = 0x4000, + SWInt = 0x0100, + TxDescUnavail = 0x0080, + RxFIFOOver = 0x0040, + LinkChg = 0x0020, + RxOverflow = 0x0010, + TxErr = 0x0008, + TxOK = 0x0004, + RxErr = 0x0002, + RxOK = 0x0001, /* RxStatusDesc */ RxFOVF = (1 << 23), @@ -295,26 +246,31 @@ enum RTL8169_register_content { RxCRC = (1 << 19), /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, + RxBufEmpty = 0x01, + + /* TXPoll register p.5 */ + HPQ = 0x80, /* Poll cmd on the high prio queue */ + NPQ = 0x40, /* Poll cmd on the low prio queue */ + FSWInt = 0x01, /* Forced software interrupt */ /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, + Cfg9346_Lock = 0x00, + Cfg9346_Unlock = 0xc0, /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0x08, + AcceptMulticast = 0x04, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, + RxCfgFIFOShift = 13, + RxCfgDMAShift = 8, /* TxConfigBits */ TxInterFrameGapShift = 24, @@ -323,6 +279,10 @@ enum RTL8169_register_content { /* Config1 register p.24 */ PMEnable = (1 << 0), /* Power Management Enable */ + /* Config2 register p. 25 */ + PCI_Clock_66MHz = 0x01, + PCI_Clock_33MHz = 0x00, + /* Config3 register p.25 */ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ @@ -343,36 +303,34 @@ enum RTL8169_register_content { TBINwComplete = 0x01000000, /* CPlusCmd p.31 */ + PktCntrDisable = (1 << 7), // 8168 RxVlan = (1 << 6), RxChkSum = (1 << 5), PCIDAC = (1 << 4), PCIMulRW = (1 << 3), + INTT_0 = 0x0000, // 8168 + INTT_1 = 0x0001, // 8168 + INTT_2 = 0x0002, // 8168 + INTT_3 = 0x0003, // 8168 /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _MediaType */ - _10_Half = 0x01, - _10_Full = 0x02, - _100_Half = 0x04, - _100_Full = 0x08, - _1000_Full = 0x10, + TBI_Enable = 0x80, + TxFlowCtrl = 0x40, + RxFlowCtrl = 0x20, + _1000bpsF = 0x10, + _100bps = 0x08, + _10bps = 0x04, + LinkStatus = 0x02, + FullDup = 0x01, /* _TBICSRBit */ - TBILinkOK = 0x02000000, + TBILinkOK = 0x02000000, /* DumpCounterCommand */ - CounterDump = 0x8, + CounterDump = 0x8, }; -enum _DescStatusBit { +enum desc_status_bit { DescOwn = (1 << 31), /* Descriptor is owned by NIC */ RingEnd = (1 << 30), /* End of descriptor ring */ FirstFrag = (1 << 29), /* First segment of a packet */ @@ -405,15 +363,15 @@ enum _DescStatusBit { #define RsvdMask 0x3fffc000 struct TxDesc { - u32 opts1; - u32 opts2; - u64 addr; + __le32 opts1; + __le32 opts2; + __le64 addr; }; struct RxDesc { - u32 opts1; - u32 opts2; - u64 addr; + __le32 opts1; + __le32 opts2; + __le64 addr; }; struct ring_info { @@ -446,6 +404,8 @@ struct rtl8169_private { unsigned rx_buf_sz; struct timer_list timer; u16 cp_cmd; + u16 intr_event; + u16 napi_event; u16 intr_mask; int phy_auto_nego_reg; int phy_1000_ctrl_reg; @@ -455,6 +415,7 @@ struct rtl8169_private { int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); void (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(void __iomem *); + void (*hw_start)(struct net_device *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); struct delayed_work task; @@ -463,8 +424,6 @@ struct rtl8169_private { MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param_array(media, int, &num_media, 0); -MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8)."); module_param(rx_copybreak, int, 0); MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); module_param(use_dac, int, 0); @@ -478,9 +437,9 @@ static int rtl8169_open(struct net_device *dev); static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); static int rtl8169_init_ring(struct net_device *dev); -static void rtl8169_hw_start(struct net_device *dev); +static void rtl_hw_start(struct net_device *dev); static int rtl8169_close(struct net_device *dev); -static void rtl8169_set_rx_mode(struct net_device *dev); +static void rtl_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, @@ -493,35 +452,37 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp); static int rtl8169_poll(struct net_device *dev, int *budget); #endif -static const u16 rtl8169_intr_mask = - SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; -static const u16 rtl8169_napi_event = - RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); -static void mdio_write(void __iomem *ioaddr, int RegAddr, int value) +static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) { int i; - RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); + RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value); for (i = 20; i > 0; i--) { - /* Check if the RTL8169 has completed writing to the specified MII register */ + /* + * Check if the RTL8169 has completed writing to the specified + * MII register. + */ if (!(RTL_R32(PHYAR) & 0x80000000)) break; udelay(25); } } -static int mdio_read(void __iomem *ioaddr, int RegAddr) +static int mdio_read(void __iomem *ioaddr, int reg_addr) { int i, value = -1; - RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); + RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16); for (i = 20; i > 0; i--) { - /* Check if the RTL8169 has completed retrieving data from the specified MII register */ + /* + * Check if the RTL8169 has completed retrieving data from + * the specified MII register. + */ if (RTL_R32(PHYAR) & 0x80000000) { value = (int) (RTL_R32(PHYAR) & 0xFFFF); break; @@ -579,7 +540,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) } static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, void __iomem *ioaddr) + struct rtl8169_private *tp, + void __iomem *ioaddr) { unsigned long flags; @@ -596,38 +558,6 @@ static void rtl8169_check_link_status(struct net_device *dev, spin_unlock_irqrestore(&tp->lock, flags); } -static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) -{ - struct { - u16 speed; - u8 duplex; - u8 autoneg; - u8 media; - } link_settings[] = { - { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half }, - { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full }, - { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half }, - { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full }, - { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full }, - /* Make TBI happy */ - { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff } - }, *p; - unsigned char option; - - option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; - - if ((option != 0xff) && !idx && netif_msg_drv(&debug)) - printk(KERN_WARNING PFX "media option is deprecated.\n"); - - for (p = link_settings; p->media != 0xff; p++) { - if (p->media == option) - break; - } - *autoneg = p->autoneg; - *speed = p->speed; - *duplex = p->duplex; -} - static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8169_private *tp = netdev_priv(dev); @@ -667,7 +597,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - int i; + unsigned int i; static struct { u32 opt; u16 reg; @@ -795,6 +725,12 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + if (tp->mac_version == RTL_GIGA_MAC_VER_12) { + /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */ + mdio_write(ioaddr, 0x1f, 0x0000); + mdio_write(ioaddr, 0x0e, 0x0000); + } + tp->phy_auto_nego_reg = auto_nego; tp->phy_1000_ctrl_reg = giga_ctrl; @@ -893,8 +829,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, int ret; if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, - swab16(opts2 & 0xffff)); + rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff)); ret = 0; } else ret = -1; @@ -1115,7 +1050,6 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) } } - static const struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, .get_regs_len = rtl8169_get_regs_len, @@ -1138,11 +1072,10 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { .get_strings = rtl8169_get_strings, .get_stats_count = rtl8169_get_stats_count, .get_ethtool_stats = rtl8169_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum, - int bitval) +static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, + int bitnum, int bitval) { int val; @@ -1152,8 +1085,20 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum mdio_write(ioaddr, reg, val & 0xffff); } -static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr) +static void rtl8169_get_mac_version(struct rtl8169_private *tp, + void __iomem *ioaddr) { + /* + * The driver currently handles the 8168Bf and the 8168Be identically + * but they can be identified more specifically through the test below + * if needed: + * + * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be + * + * Same thing for the 8101Eb and the 8101Ec: + * + * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec + */ const struct { u32 mask; int mac_version; @@ -1163,6 +1108,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io { 0x34000000, RTL_GIGA_MAC_VER_13 }, { 0x30800000, RTL_GIGA_MAC_VER_14 }, { 0x30000000, RTL_GIGA_MAC_VER_11 }, + { 0x98000000, RTL_GIGA_MAC_VER_06 }, { 0x18000000, RTL_GIGA_MAC_VER_05 }, { 0x10000000, RTL_GIGA_MAC_VER_04 }, { 0x04000000, RTL_GIGA_MAC_VER_03 }, @@ -1171,7 +1117,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io }, *p = mac_info; u32 reg; - reg = RTL_R32(TxConfig) & 0x7c800000; + reg = RTL_R32(TxConfig) & 0xfc800000; while ((reg & p->mask) != p->mask) p++; tp->mac_version = p->mac_version; @@ -1182,7 +1128,8 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp) dprintk("mac_version = 0x%02x\n", tp->mac_version); } -static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr) +static void rtl8169_get_phy_version(struct rtl8169_private *tp, + void __iomem *ioaddr) { const struct { u16 mask; @@ -1259,7 +1206,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) 0xbf00 } //w 0 15 0 bf00 } }, *p = phy_magic; - int i; + unsigned int i; rtl8169_print_mac_version(tp); rtl8169_print_phy_version(tp); @@ -1281,7 +1228,10 @@ static void rtl8169_hw_phy_config(struct net_device *dev) return; } - /* phy config for RTL8169s mac_version C chip */ + if ((tp->mac_version != RTL_GIGA_MAC_VER_02) && + (tp->mac_version != RTL_GIGA_MAC_VER_03)) + return; + mdio_write(ioaddr, 31, 0x0001); //w 31 2 0 1 mdio_write(ioaddr, 21, 0x1000); //w 21 15 0 1000 mdio_write(ioaddr, 24, 0x65c7); //w 24 15 0 65c7 @@ -1393,7 +1343,7 @@ static void rtl8169_phy_reset(struct net_device *dev, struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - int i; + unsigned int i; tp->phy_reset_enable(ioaddr); for (i = 0; i < 100; i++) { @@ -1408,21 +1358,16 @@ static void rtl8169_phy_reset(struct net_device *dev, static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - static int board_idx = -1; - u8 autoneg, duplex; - u16 speed; - - board_idx++; rtl8169_hw_phy_config(dev); dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); RTL_W8(0x82, 0x01); - if (tp->mac_version < RTL_GIGA_MAC_VER_03) { - dprintk("Set PCI Latency=0x40\n"); - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - } + pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); + + if (tp->mac_version <= RTL_GIGA_MAC_VER_06) + pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); if (tp->mac_version == RTL_GIGA_MAC_VER_02) { dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); @@ -1431,16 +1376,52 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 } - rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); - rtl8169_phy_reset(dev, tp); - rtl8169_set_speed(dev, autoneg, speed, duplex); + /* + * rtl8169_set_speed_xmii takes good care of the Fast Ethernet + * only 8101. Don't panic. + */ + rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); } +static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) +{ + void __iomem *ioaddr = tp->mmio_addr; + u32 high; + u32 low; + + low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); + high = addr[4] | (addr[5] << 8); + + spin_lock_irq(&tp->lock); + + RTL_W8(Cfg9346, Cfg9346_Unlock); + RTL_W32(MAC0, low); + RTL_W32(MAC4, high); + RTL_W8(Cfg9346, Cfg9346_Lock); + + spin_unlock_irq(&tp->lock); +} + +static int rtl_set_mac_address(struct net_device *dev, void *p) +{ + struct rtl8169_private *tp = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + rtl_rar_set(tp, dev->dev_addr); + + return 0; +} + static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct rtl8169_private *tp = netdev_priv(dev); @@ -1467,15 +1448,49 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EOPNOTSUPP; } +static const struct rtl_cfg_info { + void (*hw_start)(struct net_device *); + unsigned int region; + unsigned int align; + u16 intr_event; + u16 napi_event; +} rtl_cfg_infos [] = { + [RTL_CFG_0] = { + .hw_start = rtl_hw_start_8169, + .region = 1, + .align = 0, + .intr_event = SYSErr | LinkChg | RxOverflow | + RxFIFOOver | TxErr | TxOK | RxOK | RxErr, + .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow + }, + [RTL_CFG_1] = { + .hw_start = rtl_hw_start_8168, + .region = 2, + .align = 8, + .intr_event = SYSErr | LinkChg | RxOverflow | + TxErr | TxOK | RxOK | RxErr, + .napi_event = TxErr | TxOK | RxOK | RxOverflow + }, + [RTL_CFG_2] = { + .hw_start = rtl_hw_start_8101, + .region = 2, + .align = 8, + .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | + RxFIFOOver | TxErr | TxOK | RxOK | RxErr, + .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow + } +}; + static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - const unsigned int region = rtl_cfg_info[ent->driver_data].region; + const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; + const unsigned int region = cfg->region; struct rtl8169_private *tp; struct net_device *dev; void __iomem *ioaddr; - unsigned int pm_cap; - int i, rc; + unsigned int i; + int rc; if (netif_msg_drv(&debug)) { printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", @@ -1508,20 +1523,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc < 0) goto err_out_disable_2; - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command, acpi_idle_state; - - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; - } else { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "PowerManagement capability not found.\n"); - } - } - /* make sure PCI base addr 1 is MMIO */ if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { if (netif_msg_probe(tp)) { @@ -1585,7 +1586,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) RTL_W8(ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { + for (i = 0; i < 100; i++) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; msleep_interruptible(1); @@ -1647,11 +1648,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); dev->stop = rtl8169_close; dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl8169_set_rx_mode; + dev->set_multicast_list = rtl_set_rx_mode; dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; dev->change_mtu = rtl8169_change_mtu; + dev->set_mac_address = rtl_set_mac_address; #ifdef CONFIG_R8169_NAPI dev->poll = rtl8169_poll; @@ -1670,7 +1672,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; - tp->align = rtl_cfg_info[ent->driver_data].align; + tp->align = cfg->align; + tp->hw_start = cfg->hw_start; + tp->intr_event = cfg->intr_event; + tp->napi_event = cfg->napi_event; init_timer(&tp->timer); tp->timer.data = (unsigned long) dev; @@ -1685,15 +1690,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, dev); if (netif_msg_probe(tp)) { + u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; + printk(KERN_INFO "%s: %s at 0x%lx, " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", + "XID %08x IRQ %d\n", dev->name, rtl_chip_info[tp->chipset].name, dev->base_addr, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); + dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); } rtl8169_init_phy(dev, tp); @@ -1714,15 +1721,11 @@ err_out_free_dev_1: goto out; } -static void __devexit -rtl8169_remove_one(struct pci_dev *pdev) +static void __devexit rtl8169_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); - assert(dev != NULL); - assert(tp != NULL); - flush_scheduled_work(); unregister_netdev(dev); @@ -1774,7 +1777,7 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_release_ring_2; - rtl8169_hw_start(dev); + rtl_hw_start(dev); rtl8169_request_timer(dev); @@ -1805,7 +1808,7 @@ static void rtl8169_hw_reset(void __iomem *ioaddr) RTL_R8(ChipCmd); } -static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp) +static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; u32 cfg = rtl8169_rx_config; @@ -1818,45 +1821,90 @@ static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp) (InterFrameGap << TxInterFrameGapShift)); } -static void rtl8169_hw_start(struct net_device *dev) +static void rtl_hw_start(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - u16 cmd; - u32 i; + unsigned int i; /* Soft reset the chip. */ RTL_W8(ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { + for (i = 0; i < 100; i++) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; msleep_interruptible(1); } - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } + tp->hw_start(dev); - if (tp->mac_version == RTL_GIGA_MAC_VER_13) { - pci_write_config_word(pdev, 0x68, 0x00); - pci_write_config_word(pdev, 0x69, 0x08); - } + netif_start_queue(dev); +} - /* Undocumented stuff. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */ - if ((RTL_R8(Config2) & 0x07) & 0x01) - RTL_W32(0x7c, 0x0007ffff); - RTL_W32(0x7c, 0x0007ff00); +static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, + void __iomem *ioaddr) +{ + /* + * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh + * register to be written before TxDescAddrLow to work. + * Switching from MMIO to I/O access fixes the issue as well. + */ + RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); + RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); + RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); + RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); +} + +static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) +{ + u16 cmd; + + cmd = RTL_R16(CPlusCmd); + RTL_W16(CPlusCmd, cmd); + return cmd; +} + +static void rtl_set_rx_max_size(void __iomem *ioaddr) +{ + /* Low hurts. Let's disable the filtering. */ + RTL_W16(RxMaxSize, 16383); +} + +static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) +{ + struct { + u32 mac_version; + u32 clk; + u32 val; + } cfg2_info [] = { + { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd + { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, + { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe + { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } + }, *p = cfg2_info; + unsigned int i; + u32 clk; - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd = cmd & 0xef; - pci_write_config_word(pdev, PCI_COMMAND, cmd); + clk = RTL_R8(Config2) & PCI_Clock_66MHz; + for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) { + if ((p->mac_version == mac_version) && (p->clk == clk)) { + RTL_W32(0x7c, p->val); + break; + } + } +} + +static void rtl_hw_start_8169(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + + if (tp->mac_version == RTL_GIGA_MAC_VER_05) { + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); } RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -1868,19 +1916,15 @@ static void rtl8169_hw_start(struct net_device *dev) RTL_W8(EarlyTxThres, EarlyTxThld); - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); + rtl_set_rx_max_size(ioaddr); if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || (tp->mac_version == RTL_GIGA_MAC_VER_02) || (tp->mac_version == RTL_GIGA_MAC_VER_03) || (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl8169_set_rx_tx_config_registers(tp); - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); + rtl_set_rx_tx_config_registers(tp); - tp->cp_cmd |= cmd | PCIMulRW; + tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || (tp->mac_version == RTL_GIGA_MAC_VER_03)) { @@ -1891,28 +1935,22 @@ static void rtl8169_hw_start(struct net_device *dev) RTL_W16(CPlusCmd, tp->cp_cmd); + rtl8169_set_magic_reg(ioaddr, tp->mac_version); + /* * Undocumented corner. Supposedly: * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets */ RTL_W16(IntrMitigate, 0x0000); - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32)); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK)); + rtl_set_rx_tx_desc_registers(tp, ioaddr); if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && (tp->mac_version != RTL_GIGA_MAC_VER_02) && (tp->mac_version != RTL_GIGA_MAC_VER_03) && (tp->mac_version != RTL_GIGA_MAC_VER_04)) { RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl8169_set_rx_tx_config_registers(tp); + rtl_set_rx_tx_config_registers(tp); } RTL_W8(Cfg9346, Cfg9346_Lock); @@ -1922,15 +1960,105 @@ static void rtl8169_hw_start(struct net_device *dev) RTL_W32(RxMissed, 0); - rtl8169_set_rx_mode(dev); + rtl_set_rx_mode(dev); /* no early-rx interrupts */ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, rtl8169_intr_mask); + RTL_W16(IntrMask, tp->intr_event); +} - netif_start_queue(dev); +static void rtl_hw_start_8168(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + u8 ctl; + + RTL_W8(Cfg9346, Cfg9346_Unlock); + + RTL_W8(EarlyTxThres, EarlyTxThld); + + rtl_set_rx_max_size(ioaddr); + + rtl_set_rx_tx_config_registers(tp); + + tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; + + RTL_W16(CPlusCmd, tp->cp_cmd); + + /* Tx performance tweak. */ + pci_read_config_byte(pdev, 0x69, &ctl); + ctl = (ctl & ~0x70) | 0x50; + pci_write_config_byte(pdev, 0x69, ctl); + + RTL_W16(IntrMitigate, 0x5151); + + /* Work around for RxFIFO overflow. */ + if (tp->mac_version == RTL_GIGA_MAC_VER_11) { + tp->intr_event |= RxFIFOOver | PCSTimeout; + tp->intr_event &= ~RxOverflow; + } + + rtl_set_rx_tx_desc_registers(tp, ioaddr); + + RTL_W8(Cfg9346, Cfg9346_Lock); + + RTL_R8(IntrMask); + + RTL_W32(RxMissed, 0); + + rtl_set_rx_mode(dev); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + + RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); + + RTL_W16(IntrMask, tp->intr_event); +} + +static void rtl_hw_start_8101(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + + if (tp->mac_version == RTL_GIGA_MAC_VER_13) { + pci_write_config_word(pdev, 0x68, 0x00); + pci_write_config_word(pdev, 0x69, 0x08); + } + + RTL_W8(Cfg9346, Cfg9346_Unlock); + + RTL_W8(EarlyTxThres, EarlyTxThld); + + rtl_set_rx_max_size(ioaddr); + + tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; + + RTL_W16(CPlusCmd, tp->cp_cmd); + + RTL_W16(IntrMitigate, 0x0000); + + rtl_set_rx_tx_desc_registers(tp, ioaddr); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + rtl_set_rx_tx_config_registers(tp); + + RTL_W8(Cfg9346, Cfg9346_Lock); + + RTL_R8(IntrMask); + + RTL_W32(RxMissed, 0); + + rtl_set_rx_mode(dev); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + + RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); + + RTL_W16(IntrMask, tp->intr_event); } static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) @@ -1956,7 +2084,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) netif_poll_enable(dev); - rtl8169_hw_start(dev); + rtl_hw_start(dev); rtl8169_request_timer(dev); @@ -1997,38 +2125,38 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, rtl8169_mark_to_asic(desc, rx_buf_sz); } -static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) +static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, + struct net_device *dev, + struct RxDesc *desc, int rx_buf_sz, + unsigned int align) { struct sk_buff *skb; dma_addr_t mapping; - int ret = 0; + unsigned int pad; + + pad = align ? align : NET_IP_ALIGN; - skb = dev_alloc_skb(rx_buf_sz + align); + skb = netdev_alloc_skb(dev, rx_buf_sz + pad); if (!skb) goto err_out; - skb_reserve(skb, (align - 1) & (unsigned long)skb->data); - *sk_buff = skb; + skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); mapping = pci_map_single(pdev, skb->data, rx_buf_sz, PCI_DMA_FROMDEVICE); rtl8169_map_to_asic(desc, mapping, rx_buf_sz); - out: - return ret; + return skb; err_out: - ret = -ENOMEM; rtl8169_make_unusable_by_asic(desc); goto out; } static void rtl8169_rx_clear(struct rtl8169_private *tp) { - int i; + unsigned int i; for (i = 0; i < NUM_RX_DESC; i++) { if (tp->Rx_skbuff[i]) { @@ -2043,16 +2171,22 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, { u32 cur; - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % NUM_RX_DESC; + for (cur = start; end - cur != 0; cur++) { + struct sk_buff *skb; + unsigned int i = cur % NUM_RX_DESC; + + WARN_ON((s32)(end - cur) < 0); if (tp->Rx_skbuff[i]) continue; - ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, - tp->RxDescArray + i, tp->rx_buf_sz, tp->align); - if (ret < 0) + skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, + tp->RxDescArray + i, + tp->rx_buf_sz, tp->align); + if (!skb) break; + + tp->Rx_skbuff[i] = skb; } return cur - start; } @@ -2164,14 +2298,9 @@ static void rtl8169_reinit_task(struct work_struct *work) ret = rtl8169_open(dev); if (unlikely(ret < 0)) { - if (net_ratelimit()) { - struct rtl8169_private *tp = netdev_priv(dev); - - if (netif_msg_drv(tp)) { - printk(PFX KERN_ERR - "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } + if (net_ratelimit() && netif_msg_drv(tp)) { + printk(PFX KERN_ERR "%s: reinit failure (status = %d)." + " Rescheduling.\n", dev->name, ret); } rtl8169_schedule_work(dev, rtl8169_reinit_task); } @@ -2198,16 +2327,12 @@ static void rtl8169_reset_task(struct work_struct *work) if (tp->dirty_rx == tp->cur_rx) { rtl8169_init_ring_indexes(tp); - rtl8169_hw_start(dev); + rtl_hw_start(dev); netif_wake_queue(dev); } else { - if (net_ratelimit()) { - struct rtl8169_private *tp = netdev_priv(dev); - - if (netif_msg_intr(tp)) { - printk(PFX KERN_EMERG - "%s: Rx buffers shortage\n", dev->name); - } + if (net_ratelimit() && netif_msg_intr(tp)) { + printk(PFX KERN_EMERG "%s: Rx buffers shortage\n", + dev->name); } rtl8169_schedule_work(dev, rtl8169_reset_task); } @@ -2231,7 +2356,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, { struct skb_shared_info *info = skb_shinfo(skb); unsigned int cur_frag, entry; - struct TxDesc *txd; + struct TxDesc * uninitialized_var(txd); entry = tp->cur_tx; for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { @@ -2344,7 +2469,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) smp_wmb(); - RTL_W8(TxPoll, 0x40); /* set polling bit */ + RTL_W8(TxPoll, NPQ); /* set polling bit */ if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { netif_stop_queue(dev); @@ -2414,16 +2539,12 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) rtl8169_schedule_work(dev, rtl8169_reinit_task); } -static void -rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, - void __iomem *ioaddr) +static void rtl8169_tx_interrupt(struct net_device *dev, + struct rtl8169_private *tp, + void __iomem *ioaddr) { unsigned int dirty_tx, tx_left; - assert(dev != NULL); - assert(tp != NULL); - assert(ioaddr != NULL); - dirty_tx = tp->dirty_tx; smp_rmb(); tx_left = tp->cur_tx - dirty_tx; @@ -2459,6 +2580,15 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { netif_wake_queue(dev); } + /* + * 8168 hack: TxPoll requests are lost when the Tx packets are + * too close. Let's kick an extra TxPoll request when a burst + * of start_xmit activity is detected (if it is not detected, + * it is slow enough). -- FR + */ + smp_rmb(); + if (tp->cur_tx != dirty_tx) + RTL_W8(TxPoll, NPQ); } } @@ -2480,38 +2610,37 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) skb->ip_summed = CHECKSUM_NONE; } -static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) +static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, + struct rtl8169_private *tp, int pkt_size, + dma_addr_t addr) { - int ret = -1; + struct sk_buff *skb; + bool done = false; - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; + if (pkt_size >= rx_copybreak) + goto out; - skb = dev_alloc_skb(pkt_size + align); - if (skb) { - skb_reserve(skb, (align - 1) & (unsigned long)skb->data); - eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0); - *sk_buff = skb; - rtl8169_mark_to_asic(desc, rx_buf_sz); - ret = 0; - } - } - return ret; + skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); + if (!skb) + goto out; + + pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, + PCI_DMA_FROMDEVICE); + skb_reserve(skb, NET_IP_ALIGN); + skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); + *sk_buff = skb; + done = true; +out: + return done; } -static int -rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, - void __iomem *ioaddr) +static int rtl8169_rx_interrupt(struct net_device *dev, + struct rtl8169_private *tp, + void __iomem *ioaddr) { unsigned int cur_rx, rx_left; unsigned int delta, count; - assert(dev != NULL); - assert(tp != NULL); - assert(ioaddr != NULL); - cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); @@ -2544,9 +2673,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { struct sk_buff *skb = tp->Rx_skbuff[entry]; + dma_addr_t addr = le64_to_cpu(desc->addr); int pkt_size = (status & 0x00001FFF) - 4; - void (*pci_action)(struct pci_dev *, dma_addr_t, - size_t, int) = pci_dma_sync_single_for_device; + struct pci_dev *pdev = tp->pci_dev; /* * The driver does not support incoming fragmented @@ -2562,19 +2691,16 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, rtl8169_rx_csum(skb, desc); - pci_dma_sync_single_for_cpu(tp->pci_dev, - le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - - if (rtl8169_try_rx_copy(&skb, pkt_size, desc, - tp->rx_buf_sz, tp->align)) { - pci_action = pci_unmap_single; + if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { + pci_dma_sync_single_for_device(pdev, addr, + pkt_size, PCI_DMA_FROMDEVICE); + rtl8169_mark_to_asic(desc, tp->rx_buf_sz); + } else { + pci_unmap_single(pdev, addr, pkt_size, + PCI_DMA_FROMDEVICE); tp->Rx_skbuff[entry] = NULL; } - pci_action(tp->pci_dev, le64_to_cpu(desc->addr), - tp->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); @@ -2585,6 +2711,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, tp->stats.rx_bytes += pkt_size; tp->stats.rx_packets++; } + + /* Work around for AMD plateform. */ + if ((desc->opts2 & 0xfffe000) && + (tp->mac_version == RTL_GIGA_MAC_VER_05)) { + desc->opts2 = 0; + cur_rx++; + } } count = cur_rx - tp->cur_rx; @@ -2608,11 +2741,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, return count; } -/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static irqreturn_t -rtl8169_interrupt(int irq, void *dev_instance) +static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) { - struct net_device *dev = (struct net_device *) dev_instance; + struct net_device *dev = dev_instance; struct rtl8169_private *tp = netdev_priv(dev); int boguscnt = max_interrupt_work; void __iomem *ioaddr = tp->mmio_addr; @@ -2637,9 +2768,17 @@ rtl8169_interrupt(int irq, void *dev_instance) RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); - if (!(status & rtl8169_intr_mask)) + if (!(status & tp->intr_event)) break; + /* Work around for rx fifo overflow */ + if (unlikely(status & RxFIFOOver) && + (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + netif_stop_queue(dev); + rtl8169_tx_timeout(dev); + break; + } + if (unlikely(status & SYSErr)) { rtl8169_pcierr_interrupt(dev); break; @@ -2649,9 +2788,9 @@ rtl8169_interrupt(int irq, void *dev_instance) rtl8169_check_link_status(dev, tp, ioaddr); #ifdef CONFIG_R8169_NAPI - if (status & rtl8169_napi_event) { - RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); - tp->intr_mask = ~rtl8169_napi_event; + if (status & tp->napi_event) { + RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); + tp->intr_mask = ~tp->napi_event; if (likely(netif_rx_schedule_prep(dev))) __netif_rx_schedule(dev); @@ -2663,9 +2802,9 @@ rtl8169_interrupt(int irq, void *dev_instance) break; #else /* Rx interrupt */ - if (status & (RxOK | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | RxOverflow | RxFIFOOver)) rtl8169_rx_interrupt(dev, tp, ioaddr); - } + /* Tx interrupt */ if (status & (TxOK | TxErr)) rtl8169_tx_interrupt(dev, tp, ioaddr); @@ -2709,7 +2848,7 @@ static int rtl8169_poll(struct net_device *dev, int *budget) * write is safe - FR */ smp_wmb(); - RTL_W16(IntrMask, rtl8169_intr_mask); + RTL_W16(IntrMask, tp->intr_event); } return (work_done >= work_to_do); @@ -2791,14 +2930,13 @@ static int rtl8169_close(struct net_device *dev) return 0; } -static void -rtl8169_set_rx_mode(struct net_device *dev) +static void rtl_set_rx_mode(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; + int rx_mode; u32 tmp = 0; if (dev->flags & IFF_PROMISC) { @@ -2818,6 +2956,8 @@ rtl8169_set_rx_mode(struct net_device *dev) mc_filter[1] = mc_filter[0] = 0xffffffff; } else { struct dev_mc_list *mclist; + unsigned int i; + rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; @@ -2842,10 +2982,11 @@ rtl8169_set_rx_mode(struct net_device *dev) mc_filter[1] = 0xffffffff; } - RTL_W32(RxConfig, tmp); RTL_W32(MAR0 + 0, mc_filter[0]); RTL_W32(MAR0 + 4, mc_filter[1]); + RTL_W32(RxConfig, tmp); + spin_unlock_irqrestore(&tp->lock, flags); } @@ -2933,14 +3074,12 @@ static struct pci_driver rtl8169_pci_driver = { #endif }; -static int __init -rtl8169_init_module(void) +static int __init rtl8169_init_module(void) { return pci_register_driver(&rtl8169_pci_driver); } -static void __exit -rtl8169_cleanup_module(void) +static void __exit rtl8169_cleanup_module(void) { pci_unregister_driver(&rtl8169_pci_driver); } diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index 25c73d47daad..5c2e41fac6d2 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -516,7 +516,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv, } -static int __init rr_init(struct net_device *dev) +static int __devinit rr_init(struct net_device *dev) { struct rr_private *rrpriv; struct rr_regs __iomem *regs; diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index 4cb710bbe729..cfa267914476 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h @@ -747,10 +747,9 @@ struct XENA_dev_config { #define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23) #define MC_ERR_REG_SM_ERR BIT(31) #define MC_ERR_REG_ECC_ALL_SNG (BIT(2) | BIT(3) | BIT(4) | BIT(5) |\ - BIT(6) | BIT(7) | BIT(17) | BIT(19)) + BIT(17) | BIT(19)) #define MC_ERR_REG_ECC_ALL_DBL (BIT(10) | BIT(11) | BIT(12) |\ - BIT(13) | BIT(14) | BIT(15) |\ - BIT(18) | BIT(20)) + BIT(13) | BIT(18) | BIT(20)) u64 mc_err_mask; u64 mc_err_alarm; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 09078ff84cd2..24feb00600ee 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -32,12 +32,12 @@ * rx_ring_sz: This defines the number of receive blocks each ring can have. * This is also an array of size 8. * rx_ring_mode: This defines the operation mode of all 8 rings. The valid - * values are 1, 2 and 3. + * values are 1, 2. * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver. * tx_fifo_len: This too is an array of 8. Each element defines the number of * Tx descriptors that can be associated with each corresponding FIFO. * intr_type: This defines the type of interrupt. The values can be 0(INTA), - * 1(MSI), 2(MSI_X). Default value is '0(INTA)' + * 2(MSI_X). Default value is '0(INTA)' * lro: Specifies whether to enable Large Receive Offload (LRO) or not. * Possible values '1' for enable '0' for disable. Default is '0' * lro_max_pkts: This parameter defines maximum number of packets can be @@ -84,14 +84,14 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.23.1" +#define DRV_VERSION "2.0.25.1" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; static char s2io_driver_version[] = DRV_VERSION; -static int rxd_size[4] = {32,48,48,64}; -static int rxd_count[4] = {127,85,85,63}; +static int rxd_size[2] = {32,48}; +static int rxd_count[2] = {127,85}; static inline int RXD_IS_UP2DT(struct RxD_t *rxdp) { @@ -282,6 +282,7 @@ static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = { ("lro_flush_due_to_max_pkts"), ("lro_avg_aggr_pkts"), ("mem_alloc_fail_cnt"), + ("pci_map_fail_cnt"), ("watchdog_timer_cnt"), ("mem_allocated"), ("mem_freed"), @@ -426,7 +427,7 @@ S2IO_PARM_INT(bimodal, 0); S2IO_PARM_INT(l3l4hdr_size, 128); /* Frequency of Rx desc syncs expressed as power of 2 */ S2IO_PARM_INT(rxsync_frequency, 3); -/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ +/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */ S2IO_PARM_INT(intr_type, 0); /* Large receive offload feature */ S2IO_PARM_INT(lro, 0); @@ -469,11 +470,18 @@ static struct pci_device_id s2io_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, s2io_tbl); +static struct pci_error_handlers s2io_err_handler = { + .error_detected = s2io_io_error_detected, + .slot_reset = s2io_io_slot_reset, + .resume = s2io_io_resume, +}; + static struct pci_driver s2io_driver = { .name = "S2IO", .id_table = s2io_tbl, .probe = s2io_init_nic, .remove = __devexit_p(s2io_rem_nic), + .err_handler = &s2io_err_handler, }; /* A simplifier macro used both by init and free shared_mem Fns(). */ @@ -694,7 +702,7 @@ static int init_shared_mem(struct s2io_nic *nic) (u64) tmp_p_addr_next; } } - if (nic->rxd_mode >= RXD_MODE_3A) { + if (nic->rxd_mode == RXD_MODE_3B) { /* * Allocation of Storages for buffer addresses in 2BUFF mode * and the buffers as well. @@ -789,12 +797,14 @@ static void free_shared_mem(struct s2io_nic *nic) struct mac_info *mac_control; struct config_param *config; int lst_size, lst_per_page; - struct net_device *dev = nic->dev; + struct net_device *dev; int page_num = 0; if (!nic) return; + dev = nic->dev; + mac_control = &nic->mac_control; config = &nic->config; @@ -861,7 +871,7 @@ static void free_shared_mem(struct s2io_nic *nic) } } - if (nic->rxd_mode >= RXD_MODE_3A) { + if (nic->rxd_mode == RXD_MODE_3B) { /* Freeing buffer storage addresses in 2BUFF mode. */ for (i = 0; i < config->rx_ring_num; i++) { blk_cnt = config->rx_cfg[i].num_rxd / @@ -1128,7 +1138,7 @@ static int init_nic(struct s2io_nic *nic) * SXE-008 TRANSMIT DMA ARBITRATION ISSUE. */ if ((nic->device_type == XFRAME_I_DEVICE) && - (get_xena_rev_id(nic->pdev) < 4)) + (nic->pdev->revision < 4)) writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable); val64 = readq(&bar0->tx_fifo_partition_0); @@ -1866,7 +1876,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) herc = (sp->device_type == XFRAME_II_DEVICE); if (flag == FALSE) { - if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) { + if ((!herc && (sp->pdev->revision >= 4)) || herc) { if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE)) ret = 1; } else { @@ -1874,7 +1884,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) ret = 1; } } else { - if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) { + if ((!herc && (sp->pdev->revision >= 4)) || herc) { if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == ADAPTER_STATUS_RMAC_PCC_IDLE)) ret = 1; @@ -2224,44 +2234,6 @@ static void stop_nic(struct s2io_nic *nic) writeq(val64, &bar0->adapter_control); } -static int fill_rxd_3buf(struct s2io_nic *nic, struct RxD_t *rxdp, struct \ - sk_buff *skb) -{ - struct net_device *dev = nic->dev; - struct sk_buff *frag_list; - void *tmp; - - /* Buffer-1 receives L3/L4 headers */ - ((struct RxD3*)rxdp)->Buffer1_ptr = pci_map_single - (nic->pdev, skb->data, l3l4hdr_size + 4, - PCI_DMA_FROMDEVICE); - - /* skb_shinfo(skb)->frag_list will have L4 data payload */ - skb_shinfo(skb)->frag_list = dev_alloc_skb(dev->mtu + ALIGN_SIZE); - if (skb_shinfo(skb)->frag_list == NULL) { - nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; - DBG_PRINT(INFO_DBG, "%s: dev_alloc_skb failed\n ", dev->name); - return -ENOMEM ; - } - frag_list = skb_shinfo(skb)->frag_list; - skb->truesize += frag_list->truesize; - nic->mac_control.stats_info->sw_stat.mem_allocated - += frag_list->truesize; - frag_list->next = NULL; - tmp = (void *)ALIGN((long)frag_list->data, ALIGN_SIZE + 1); - frag_list->data = tmp; - skb_reset_tail_pointer(frag_list); - - /* Buffer-2 receives L4 data payload */ - ((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single(nic->pdev, - frag_list->data, dev->mtu, - PCI_DMA_FROMDEVICE); - rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4); - rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu); - - return SUCCESS; -} - /** * fill_rx_buffers - Allocates the Rx side skbs * @nic: device private variable @@ -2298,6 +2270,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) unsigned long flags; struct RxD_t *first_rxdp = NULL; u64 Buffer0_ptr = 0, Buffer1_ptr = 0; + struct RxD1 *rxdp1; + struct RxD3 *rxdp3; + struct swStat *stats = &nic->mac_control.stats_info->sw_stat; mac_control = &nic->mac_control; config = &nic->config; @@ -2350,7 +2325,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) (block_no * (rxd_count[nic->rxd_mode] + 1)) + off; } if ((rxdp->Control_1 & RXD_OWN_XENA) && - ((nic->rxd_mode >= RXD_MODE_3A) && + ((nic->rxd_mode == RXD_MODE_3B) && (rxdp->Control_2 & BIT(0)))) { mac_control->rings[ring_no].rx_curr_put_info. offset = off; @@ -2361,10 +2336,8 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) HEADER_802_2_SIZE + HEADER_SNAP_SIZE; if (nic->rxd_mode == RXD_MODE_1) size += NET_IP_ALIGN; - else if (nic->rxd_mode == RXD_MODE_3B) - size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; else - size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4; + size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; /* allocate skb */ skb = dev_alloc_skb(size); @@ -2383,33 +2356,35 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) += skb->truesize; if (nic->rxd_mode == RXD_MODE_1) { /* 1 buffer mode - normal operation mode */ + rxdp1 = (struct RxD1*)rxdp; memset(rxdp, 0, sizeof(struct RxD1)); skb_reserve(skb, NET_IP_ALIGN); - ((struct RxD1*)rxdp)->Buffer0_ptr = pci_map_single + rxdp1->Buffer0_ptr = pci_map_single (nic->pdev, skb->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); + if( (rxdp1->Buffer0_ptr == 0) || + (rxdp1->Buffer0_ptr == + DMA_ERROR_CODE)) + goto pci_map_failed; + rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN); - } else if (nic->rxd_mode >= RXD_MODE_3A) { + } else if (nic->rxd_mode == RXD_MODE_3B) { /* - * 2 or 3 buffer mode - - * Both 2 buffer mode and 3 buffer mode provides 128 + * 2 buffer mode - + * 2 buffer mode provides 128 * byte aligned receive buffers. - * - * 3 buffer mode provides header separation where in - * skb->data will have L3/L4 headers where as - * skb_shinfo(skb)->frag_list will have the L4 data - * payload */ + rxdp3 = (struct RxD3*)rxdp; /* save buffer pointers to avoid frequent dma mapping */ - Buffer0_ptr = ((struct RxD3*)rxdp)->Buffer0_ptr; - Buffer1_ptr = ((struct RxD3*)rxdp)->Buffer1_ptr; + Buffer0_ptr = rxdp3->Buffer0_ptr; + Buffer1_ptr = rxdp3->Buffer1_ptr; memset(rxdp, 0, sizeof(struct RxD3)); /* restore the buffer pointers for dma sync*/ - ((struct RxD3*)rxdp)->Buffer0_ptr = Buffer0_ptr; - ((struct RxD3*)rxdp)->Buffer1_ptr = Buffer1_ptr; + rxdp3->Buffer0_ptr = Buffer0_ptr; + rxdp3->Buffer1_ptr = Buffer1_ptr; ba = &mac_control->rings[ring_no].ba[block_no][off]; skb_reserve(skb, BUF0_LEN); @@ -2419,14 +2394,18 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) skb->data = (void *) (unsigned long)tmp; skb_reset_tail_pointer(skb); - if (!(((struct RxD3*)rxdp)->Buffer0_ptr)) - ((struct RxD3*)rxdp)->Buffer0_ptr = + if (!(rxdp3->Buffer0_ptr)) + rxdp3->Buffer0_ptr = pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); else pci_dma_sync_single_for_device(nic->pdev, - (dma_addr_t) ((struct RxD3*)rxdp)->Buffer0_ptr, + (dma_addr_t) rxdp3->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); + if( (rxdp3->Buffer0_ptr == 0) || + (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) + goto pci_map_failed; + rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { /* Two buffer mode */ @@ -2435,33 +2414,30 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) * Buffer2 will have L3/L4 header plus * L4 payload */ - ((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single + rxdp3->Buffer2_ptr = pci_map_single (nic->pdev, skb->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - /* Buffer-1 will be dummy buffer. Not used */ - if (!(((struct RxD3*)rxdp)->Buffer1_ptr)) { - ((struct RxD3*)rxdp)->Buffer1_ptr = + if( (rxdp3->Buffer2_ptr == 0) || + (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) + goto pci_map_failed; + + rxdp3->Buffer1_ptr = pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); + if( (rxdp3->Buffer1_ptr == 0) || + (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { + pci_unmap_single + (nic->pdev, + (dma_addr_t)rxdp3->Buffer2_ptr, + dev->mtu + 4, + PCI_DMA_FROMDEVICE); + goto pci_map_failed; } rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3 (dev->mtu + 4); - } else { - /* 3 buffer mode */ - if (fill_rxd_3buf(nic, rxdp, skb) == -ENOMEM) { - nic->mac_control.stats_info->sw_stat.\ - mem_freed += skb->truesize; - dev_kfree_skb_irq(skb); - if (first_rxdp) { - wmb(); - first_rxdp->Control_1 |= - RXD_OWN_XENA; - } - return -ENOMEM ; - } } rxdp->Control_2 |= BIT(0); } @@ -2496,6 +2472,11 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) } return SUCCESS; +pci_map_failed: + stats->pci_map_fail_cnt++; + stats->mem_freed += skb->truesize; + dev_kfree_skb_irq(skb); + return -ENOMEM; } static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) @@ -2506,6 +2487,8 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) struct RxD_t *rxdp; struct mac_info *mac_control; struct buffAdd *ba; + struct RxD1 *rxdp1; + struct RxD3 *rxdp3; mac_control = &sp->mac_control; for (j = 0 ; j < rxd_count[sp->rxd_mode]; j++) { @@ -2517,40 +2500,30 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) continue; } if (sp->rxd_mode == RXD_MODE_1) { + rxdp1 = (struct RxD1*)rxdp; pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD1*)rxdp)->Buffer0_ptr, - dev->mtu + - HEADER_ETHERNET_II_802_3_SIZE - + HEADER_802_2_SIZE + - HEADER_SNAP_SIZE, - PCI_DMA_FROMDEVICE); + rxdp1->Buffer0_ptr, + dev->mtu + + HEADER_ETHERNET_II_802_3_SIZE + + HEADER_802_2_SIZE + + HEADER_SNAP_SIZE, + PCI_DMA_FROMDEVICE); memset(rxdp, 0, sizeof(struct RxD1)); } else if(sp->rxd_mode == RXD_MODE_3B) { + rxdp3 = (struct RxD3*)rxdp; ba = &mac_control->rings[ring_no]. ba[blk][j]; pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, - BUF0_LEN, - PCI_DMA_FROMDEVICE); - pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, - BUF1_LEN, - PCI_DMA_FROMDEVICE); - pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, - dev->mtu + 4, - PCI_DMA_FROMDEVICE); - memset(rxdp, 0, sizeof(struct RxD3)); - } else { - pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN, + rxdp3->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, - l3l4hdr_size + 4, + rxdp3->Buffer1_ptr, + BUF1_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, dev->mtu, + rxdp3->Buffer2_ptr, + dev->mtu + 4, PCI_DMA_FROMDEVICE); memset(rxdp, 0, sizeof(struct RxD3)); } @@ -2689,6 +2662,9 @@ static void s2io_netpoll(struct net_device *dev) u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; + if (pci_channel_offline(nic->pdev)) + return; + disable_irq(dev->irq); atomic_inc(&nic->isr_cnt); @@ -2744,6 +2720,8 @@ static void rx_intr_handler(struct ring_info *ring_data) struct sk_buff *skb; int pkt_cnt = 0; int i; + struct RxD1* rxdp1; + struct RxD3* rxdp3; spin_lock(&nic->rx_lock); if (atomic_read(&nic->card_state) == CARD_DOWN) { @@ -2784,32 +2762,23 @@ static void rx_intr_handler(struct ring_info *ring_data) return; } if (nic->rxd_mode == RXD_MODE_1) { + rxdp1 = (struct RxD1*)rxdp; pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD1*)rxdp)->Buffer0_ptr, - dev->mtu + - HEADER_ETHERNET_II_802_3_SIZE + - HEADER_802_2_SIZE + - HEADER_SNAP_SIZE, - PCI_DMA_FROMDEVICE); + rxdp1->Buffer0_ptr, + dev->mtu + + HEADER_ETHERNET_II_802_3_SIZE + + HEADER_802_2_SIZE + + HEADER_SNAP_SIZE, + PCI_DMA_FROMDEVICE); } else if (nic->rxd_mode == RXD_MODE_3B) { + rxdp3 = (struct RxD3*)rxdp; pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, - BUF0_LEN, PCI_DMA_FROMDEVICE); + rxdp3->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, - dev->mtu + 4, - PCI_DMA_FROMDEVICE); - } else { - pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN, - PCI_DMA_FROMDEVICE); - pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, - l3l4hdr_size + 4, - PCI_DMA_FROMDEVICE); - pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, - dev->mtu, PCI_DMA_FROMDEVICE); + rxdp3->Buffer2_ptr, + dev->mtu + 4, + PCI_DMA_FROMDEVICE); } prefetch(skb->data); rx_osm_handler(ring_data, rxdp); @@ -3215,6 +3184,8 @@ static void alarm_intr_handler(struct s2io_nic *nic) int i; if (atomic_read(&nic->card_state) == CARD_DOWN) return; + if (pci_channel_offline(nic->pdev)) + return; nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0; /* Handling the XPAK counters update */ if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) { @@ -3411,23 +3382,8 @@ static void s2io_reset(struct s2io_nic * sp) /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd)); - if (sp->device_type == XFRAME_II_DEVICE) { - int ret; - ret = pci_set_power_state(sp->pdev, 3); - if (!ret) - ret = pci_set_power_state(sp->pdev, 0); - else { - DBG_PRINT(ERR_DBG,"%s PME based SW_Reset failed!\n", - __FUNCTION__); - goto old_way; - } - msleep(20); - goto new_way; - } -old_way: val64 = SW_RESET_ALL; writeq(val64, &bar0->sw_reset); -new_way: if (strstr(sp->product_name, "CX4")) { msleep(750); } @@ -3717,56 +3673,6 @@ static void store_xmsi_data(struct s2io_nic *nic) } } -int s2io_enable_msi(struct s2io_nic *nic) -{ - struct XENA_dev_config __iomem *bar0 = nic->bar0; - u16 msi_ctrl, msg_val; - struct config_param *config = &nic->config; - struct net_device *dev = nic->dev; - u64 val64, tx_mat, rx_mat; - int i, err; - - val64 = readq(&bar0->pic_control); - val64 &= ~BIT(1); - writeq(val64, &bar0->pic_control); - - err = pci_enable_msi(nic->pdev); - if (err) { - DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n", - nic->dev->name); - return err; - } - - /* - * Enable MSI and use MSI-1 in stead of the standard MSI-0 - * for interrupt handling. - */ - pci_read_config_word(nic->pdev, 0x4c, &msg_val); - msg_val ^= 0x1; - pci_write_config_word(nic->pdev, 0x4c, msg_val); - pci_read_config_word(nic->pdev, 0x4c, &msg_val); - - pci_read_config_word(nic->pdev, 0x42, &msi_ctrl); - msi_ctrl |= 0x10; - pci_write_config_word(nic->pdev, 0x42, msi_ctrl); - - /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */ - tx_mat = readq(&bar0->tx_mat0_n[0]); - for (i=0; i<config->tx_fifo_num; i++) { - tx_mat |= TX_MAT_SET(i, 1); - } - writeq(tx_mat, &bar0->tx_mat0_n[0]); - - rx_mat = readq(&bar0->rx_mat); - for (i=0; i<config->rx_ring_num; i++) { - rx_mat |= RX_MAT_SET(i, 1); - } - writeq(rx_mat, &bar0->rx_mat); - - dev->irq = nic->pdev->irq; - return 0; -} - static int s2io_enable_msi_x(struct s2io_nic *nic) { struct XENA_dev_config __iomem *bar0 = nic->bar0; @@ -3958,7 +3864,6 @@ static int s2io_close(struct net_device *dev) /* Reset card, kill tasklet and free Tx and Rx buffers. */ s2io_card_down(sp); - sp->device_close_flag = TRUE; /* Device is shut down. */ return 0; } @@ -3988,6 +3893,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) struct mac_info *mac_control; struct config_param *config; int offload_type; + struct swStat *stats = &sp->mac_control.stats_info->sw_stat; mac_control = &sp->mac_control; config = &sp->config; @@ -4072,11 +3978,18 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Buffer_Pointer = pci_map_single(sp->pdev, sp->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); + if((txdp->Buffer_Pointer == 0) || + (txdp->Buffer_Pointer == DMA_ERROR_CODE)) + goto pci_map_failed; txdp++; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); + if((txdp->Buffer_Pointer == 0) || + (txdp->Buffer_Pointer == DMA_ERROR_CODE)) + goto pci_map_failed; + txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); if (offload_type == SKB_GSO_UDP) @@ -4133,6 +4046,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&sp->tx_lock, flags); return 0; +pci_map_failed: + stats->pci_map_fail_cnt++; + netif_stop_queue(dev); + stats->mem_freed += skb->truesize; + dev_kfree_skb(skb); + spin_unlock_irqrestore(&sp->tx_lock, flags); + return 0; } static void @@ -4173,39 +4093,6 @@ static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n) return 0; } -static irqreturn_t s2io_msi_handle(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct s2io_nic *sp = dev->priv; - int i; - struct mac_info *mac_control; - struct config_param *config; - - atomic_inc(&sp->isr_cnt); - mac_control = &sp->mac_control; - config = &sp->config; - DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__); - - /* If Intr is because of Rx Traffic */ - for (i = 0; i < config->rx_ring_num; i++) - rx_intr_handler(&mac_control->rings[i]); - - /* If Intr is because of Tx Traffic */ - for (i = 0; i < config->tx_fifo_num; i++) - tx_intr_handler(&mac_control->fifos[i]); - - /* - * If the Rx buffer count is below the panic threshold then - * reallocate the buffers from the interrupt handler itself, - * else schedule a tasklet to reallocate the buffers. - */ - for (i = 0; i < config->rx_ring_num; i++) - s2io_chk_rx_buffers(sp, i); - - atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; -} - static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) { struct ring_info *ring = (struct ring_info *)dev_id; @@ -4314,6 +4201,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) struct mac_info *mac_control; struct config_param *config; + /* Pretend we handled any irq's from a disconnected card */ + if (pci_channel_offline(sp->pdev)) + return IRQ_NONE; + atomic_inc(&sp->isr_cnt); mac_control = &sp->mac_control; config = &sp->config; @@ -4910,19 +4801,17 @@ static void s2io_ethtool_gringparam(struct net_device *dev, ering->rx_max_pending = MAX_RX_DESC_1; else if (sp->rxd_mode == RXD_MODE_3B) ering->rx_max_pending = MAX_RX_DESC_2; - else if (sp->rxd_mode == RXD_MODE_3A) - ering->rx_max_pending = MAX_RX_DESC_3; ering->tx_max_pending = MAX_TX_DESC; - for (i = 0 ; i < sp->config.tx_fifo_num ; i++) { + for (i = 0 ; i < sp->config.tx_fifo_num ; i++) tx_desc_count += sp->config.tx_cfg[i].fifo_len; - } + DBG_PRINT(INFO_DBG,"\nmax txds : %d\n",sp->config.max_txds); ering->tx_pending = tx_desc_count; rx_desc_count = 0; - for (i = 0 ; i < sp->config.rx_ring_num ; i++) { + for (i = 0 ; i < sp->config.rx_ring_num ; i++) rx_desc_count += sp->config.rx_cfg[i].num_rxd; - } + ering->rx_pending = rx_desc_count; ering->rx_mini_max_pending = 0; @@ -5906,6 +5795,7 @@ static void s2io_get_ethtool_stats(struct net_device *dev, else tmp_stats[i++] = 0; tmp_stats[i++] = stat_info->sw_stat.mem_alloc_fail_cnt; + tmp_stats[i++] = stat_info->sw_stat.pci_map_fail_cnt; tmp_stats[i++] = stat_info->sw_stat.watchdog_timer_cnt; tmp_stats[i++] = stat_info->sw_stat.mem_allocated; tmp_stats[i++] = stat_info->sw_stat.mem_freed; @@ -6249,9 +6139,10 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, u64 *temp2, int size) { struct net_device *dev = sp->dev; - struct sk_buff *frag_list; + struct swStat *stats = &sp->mac_control.stats_info->sw_stat; if ((sp->rxd_mode == RXD_MODE_1) && (rxdp->Host_Control == 0)) { + struct RxD1 *rxdp1 = (struct RxD1 *)rxdp; /* allocate skb */ if (*skb) { DBG_PRINT(INFO_DBG, "SKB is not NULL\n"); @@ -6260,7 +6151,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, * using same mapped address for the Rxd * buffer pointer */ - ((struct RxD1*)rxdp)->Buffer0_ptr = *temp0; + rxdp1->Buffer0_ptr = *temp0; } else { *skb = dev_alloc_skb(size); if (!(*skb)) { @@ -6277,18 +6168,23 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, * such it will be used for next rxd whose * Host Control is NULL */ - ((struct RxD1*)rxdp)->Buffer0_ptr = *temp0 = + rxdp1->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, (*skb)->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); + if( (rxdp1->Buffer0_ptr == 0) || + (rxdp1->Buffer0_ptr == DMA_ERROR_CODE)) { + goto memalloc_failed; + } rxdp->Host_Control = (unsigned long) (*skb); } } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { + struct RxD3 *rxdp3 = (struct RxD3 *)rxdp; /* Two buffer Mode */ if (*skb) { - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2; - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0; - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1; + rxdp3->Buffer2_ptr = *temp2; + rxdp3->Buffer0_ptr = *temp0; + rxdp3->Buffer1_ptr = *temp1; } else { *skb = dev_alloc_skb(size); if (!(*skb)) { @@ -6301,73 +6197,50 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, } sp->mac_control.stats_info->sw_stat.mem_allocated += (*skb)->truesize; - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2 = + rxdp3->Buffer2_ptr = *temp2 = pci_map_single(sp->pdev, (*skb)->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0 = + if( (rxdp3->Buffer2_ptr == 0) || + (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) { + goto memalloc_failed; + } + rxdp3->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); + if( (rxdp3->Buffer0_ptr == 0) || + (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) { + pci_unmap_single (sp->pdev, + (dma_addr_t)rxdp3->Buffer2_ptr, + dev->mtu + 4, PCI_DMA_FROMDEVICE); + goto memalloc_failed; + } rxdp->Host_Control = (unsigned long) (*skb); /* Buffer-1 will be dummy buffer not used */ - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1 = + rxdp3->Buffer1_ptr = *temp1 = pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN, - PCI_DMA_FROMDEVICE); - } - } else if ((rxdp->Host_Control == 0)) { - /* Three buffer mode */ - if (*skb) { - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0; - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1; - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2; - } else { - *skb = dev_alloc_skb(size); - if (!(*skb)) { - DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name); - DBG_PRINT(INFO_DBG, "memory to allocate "); - DBG_PRINT(INFO_DBG, "3 buf mode SKBs\n"); - sp->mac_control.stats_info->sw_stat. \ - mem_alloc_fail_cnt++; - return -ENOMEM; - } - sp->mac_control.stats_info->sw_stat.mem_allocated - += (*skb)->truesize; - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0 = - pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN, - PCI_DMA_FROMDEVICE); - /* Buffer-1 receives L3/L4 headers */ - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1 = - pci_map_single( sp->pdev, (*skb)->data, - l3l4hdr_size + 4, PCI_DMA_FROMDEVICE); - /* - * skb_shinfo(skb)->frag_list will have L4 - * data payload - */ - skb_shinfo(*skb)->frag_list = dev_alloc_skb(dev->mtu + - ALIGN_SIZE); - if (skb_shinfo(*skb)->frag_list == NULL) { - DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \ - failed\n ", dev->name); - sp->mac_control.stats_info->sw_stat. \ - mem_alloc_fail_cnt++; - return -ENOMEM ; + if( (rxdp3->Buffer1_ptr == 0) || + (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { + pci_unmap_single (sp->pdev, + (dma_addr_t)rxdp3->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); + pci_unmap_single (sp->pdev, + (dma_addr_t)rxdp3->Buffer2_ptr, + dev->mtu + 4, PCI_DMA_FROMDEVICE); + goto memalloc_failed; } - frag_list = skb_shinfo(*skb)->frag_list; - frag_list->next = NULL; - sp->mac_control.stats_info->sw_stat.mem_allocated - += frag_list->truesize; - /* - * Buffer-2 receives L4 data payload - */ - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2 = - pci_map_single( sp->pdev, frag_list->data, - dev->mtu, PCI_DMA_FROMDEVICE); } } return 0; + memalloc_failed: + stats->pci_map_fail_cnt++; + stats->mem_freed += (*skb)->truesize; + dev_kfree_skb(*skb); + return -ENOMEM; } + static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp, int size) { @@ -6378,10 +6251,6 @@ static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp, rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4); - } else { - rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); - rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4); - rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu); } } @@ -6403,8 +6272,6 @@ static int rxd_owner_bit_reset(struct s2io_nic *sp) size += NET_IP_ALIGN; else if (sp->rxd_mode == RXD_MODE_3B) size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; - else - size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4; for (i = 0; i < config->rx_ring_num; i++) { blk_cnt = config->rx_cfg[i].num_rxd / @@ -6414,7 +6281,7 @@ static int rxd_owner_bit_reset(struct s2io_nic *sp) for (k = 0; k < rxd_count[sp->rxd_mode]; k++) { rxdp = mac_control->rings[i]. rx_blocks[j].rxds[k].virt_addr; - if(sp->rxd_mode >= RXD_MODE_3A) + if(sp->rxd_mode == RXD_MODE_3B) ba = &mac_control->rings[i].ba[j][k]; if (set_rxd_buffer_pointer(sp, rxdp, ba, &skb,(u64 *)&temp0_64, @@ -6441,9 +6308,7 @@ static int s2io_add_isr(struct s2io_nic * sp) struct net_device *dev = sp->dev; int err = 0; - if (sp->intr_type == MSI) - ret = s2io_enable_msi(sp); - else if (sp->intr_type == MSI_X) + if (sp->intr_type == MSI_X) ret = s2io_enable_msi_x(sp); if (ret) { DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name); @@ -6454,16 +6319,6 @@ static int s2io_add_isr(struct s2io_nic * sp) store_xmsi_data(sp); /* After proper initialization of H/W, register ISR */ - if (sp->intr_type == MSI) { - err = request_irq((int) sp->pdev->irq, s2io_msi_handle, - IRQF_SHARED, sp->name, dev); - if (err) { - pci_disable_msi(sp->pdev); - DBG_PRINT(ERR_DBG, "%s: MSI registration failed\n", - dev->name); - return -1; - } - } if (sp->intr_type == MSI_X) { int i, msix_tx_cnt=0,msix_rx_cnt=0; @@ -6550,14 +6405,6 @@ static void s2io_rem_isr(struct s2io_nic * sp) pci_disable_msix(sp->pdev); } else { free_irq(sp->pdev->irq, dev); - if (sp->intr_type == MSI) { - u16 val; - - pci_disable_msi(sp->pdev); - pci_read_config_word(sp->pdev, 0x4c, &val); - val ^= 0x1; - pci_write_config_word(sp->pdev, 0x4c, val); - } } /* Waiting till all Interrupt handlers are complete */ cnt = 0; @@ -6569,7 +6416,7 @@ static void s2io_rem_isr(struct s2io_nic * sp) } while(cnt < 5); } -static void s2io_card_down(struct s2io_nic * sp) +static void do_s2io_card_down(struct s2io_nic * sp, int do_io) { int cnt = 0; struct XENA_dev_config __iomem *bar0 = sp->bar0; @@ -6584,7 +6431,8 @@ static void s2io_card_down(struct s2io_nic * sp) atomic_set(&sp->card_state, CARD_DOWN); /* disable Tx and Rx traffic on the NIC */ - stop_nic(sp); + if (do_io) + stop_nic(sp); s2io_rem_isr(sp); @@ -6592,7 +6440,7 @@ static void s2io_card_down(struct s2io_nic * sp) tasklet_kill(&sp->task); /* Check if the device is Quiescent and then Reset the NIC */ - do { + while(do_io) { /* As per the HW requirement we need to replenish the * receive buffer to avoid the ring bump. Since there is * no intention of processing the Rx frame at this pointwe are @@ -6617,8 +6465,9 @@ static void s2io_card_down(struct s2io_nic * sp) (unsigned long long) val64); break; } - } while (1); - s2io_reset(sp); + } + if (do_io) + s2io_reset(sp); spin_lock_irqsave(&sp->tx_lock, flags); /* Free all Tx buffers */ @@ -6633,6 +6482,11 @@ static void s2io_card_down(struct s2io_nic * sp) clear_bit(0, &(sp->link_state)); } +static void s2io_card_down(struct s2io_nic * sp) +{ + do_s2io_card_down(sp, 1); +} + static int s2io_card_up(struct s2io_nic * sp) { int i, ret = 0; @@ -6883,6 +6737,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) } /* Updating statistics */ + sp->stats.rx_packets++; rxdp->Host_Control = 0; if (sp->rxd_mode == RXD_MODE_1) { int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2); @@ -6890,7 +6745,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) sp->stats.rx_bytes += len; skb_put(skb, len); - } else if (sp->rxd_mode >= RXD_MODE_3A) { + } else if (sp->rxd_mode == RXD_MODE_3B) { int get_block = ring_data->rx_curr_get_info.block_index; int get_off = ring_data->rx_curr_get_info.offset; int buf0_len = RXD_GET_BUFFER0_SIZE_3(rxdp->Control_2); @@ -6900,18 +6755,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) struct buffAdd *ba = &ring_data->ba[get_block][get_off]; sp->stats.rx_bytes += buf0_len + buf2_len; memcpy(buff, ba->ba_0, buf0_len); - - if (sp->rxd_mode == RXD_MODE_3A) { - int buf1_len = RXD_GET_BUFFER1_SIZE_3(rxdp->Control_2); - - skb_put(skb, buf1_len); - skb->len += buf2_len; - skb->data_len += buf2_len; - skb_put(skb_shinfo(skb)->frag_list, buf2_len); - sp->stats.rx_bytes += buf1_len; - - } else - skb_put(skb, buf2_len); + skb_put(skb, buf2_len); } if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) || @@ -7054,23 +6898,6 @@ static void s2io_link(struct s2io_nic * sp, int link) } /** - * get_xena_rev_id - to identify revision ID of xena. - * @pdev : PCI Dev structure - * Description: - * Function to identify the Revision ID of xena. - * Return value: - * returns the revision ID of the device. - */ - -static int get_xena_rev_id(struct pci_dev *pdev) -{ - u8 id = 0; - int ret; - ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id); - return id; -} - -/** * s2io_init_pci -Initialization of PCI and PCI-X configuration registers . * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure. @@ -7124,7 +6951,7 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) *dev_intr_type = INTA; } #else - if (*dev_intr_type > MSI_X) { + if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) { DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " "Defaulting to INTA\n"); *dev_intr_type = INTA; @@ -7138,10 +6965,10 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) *dev_intr_type = INTA; } - if (rx_ring_mode > 3) { + if ((rx_ring_mode != 1) && (rx_ring_mode != 2)) { DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n"); - DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n"); - rx_ring_mode = 3; + DBG_PRINT(ERR_DBG, "s2io: Defaulting to 1-buffer mode\n"); + rx_ring_mode = 1; } return SUCCESS; } @@ -7233,28 +7060,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) pci_disable_device(pdev); return -ENOMEM; } - if (dev_intr_type != MSI_X) { - if (pci_request_regions(pdev, s2io_driver_name)) { - DBG_PRINT(ERR_DBG, "Request Regions failed\n"); - pci_disable_device(pdev); - return -ENODEV; - } - } - else { - if (!(request_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0), s2io_driver_name))) { - DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n"); - pci_disable_device(pdev); - return -ENODEV; - } - if (!(request_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2), s2io_driver_name))) { - DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n"); - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - pci_disable_device(pdev); - return -ENODEV; - } + if ((ret = pci_request_regions(pdev, s2io_driver_name))) { + DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x \n", __FUNCTION__, ret); + pci_disable_device(pdev); + return -ENODEV; } dev = alloc_etherdev(sizeof(struct s2io_nic)); @@ -7281,8 +7090,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) sp->rxd_mode = RXD_MODE_1; if (rx_ring_mode == 2) sp->rxd_mode = RXD_MODE_3B; - if (rx_ring_mode == 3) - sp->rxd_mode = RXD_MODE_3A; sp->intr_type = dev_intr_type; @@ -7528,7 +7335,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) s2io_vpd_read(sp); DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2007 Neterion Inc.\n"); DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name, - sp->product_name, get_xena_rev_id(sp->pdev)); + sp->product_name, pdev->revision); DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, s2io_driver_version); DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " @@ -7558,10 +7365,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n", dev->name); break; - case RXD_MODE_3A: - DBG_PRINT(ERR_DBG, "%s: 3-Buffer receive mode enabled\n", - dev->name); - break; } if (napi) @@ -7570,9 +7373,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) case INTA: DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name); break; - case MSI: - DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI\n", dev->name); - break; case MSI_X: DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name); break; @@ -7612,14 +7412,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) mem_alloc_failed: free_shared_mem(sp); pci_disable_device(pdev); - if (dev_intr_type != MSI_X) - pci_release_regions(pdev); - else { - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); - } + pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev); @@ -7654,14 +7447,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) free_shared_mem(sp); iounmap(sp->bar0); iounmap(sp->bar1); - if (sp->intr_type != MSI_X) - pci_release_regions(pdev); - else { - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); - } + pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev); pci_disable_device(pdev); @@ -8010,3 +7796,85 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; return; } + +/** + * s2io_io_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * This function is called after a PCI bus error affecting + * this device has been detected. + */ +static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct s2io_nic *sp = netdev->priv; + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + /* Bring down the card, while avoiding PCI I/O */ + do_s2io_card_down(sp, 0); + } + pci_disable_device(pdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * s2io_io_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + * At this point, the card has exprienced a hard reset, + * followed by fixups by BIOS, and has its config space + * set up identically to what it was at cold boot. + */ +static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct s2io_nic *sp = netdev->priv; + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "s2io: " + "Cannot re-enable PCI device after reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_set_master(pdev); + s2io_reset(sp); + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * s2io_io_resume - called when traffic can start flowing again. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells + * us that its OK to resume normal operation. + */ +static void s2io_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct s2io_nic *sp = netdev->priv; + + if (netif_running(netdev)) { + if (s2io_card_up(sp)) { + printk(KERN_ERR "s2io: " + "Can't bring device back up after reset.\n"); + return; + } + + if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) { + s2io_card_down(sp); + printk(KERN_ERR "s2io: " + "Can't resetore mac addr after reset.\n"); + return; + } + } + + netif_device_attach(netdev); + netif_wake_queue(netdev); +} diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 54baa0b8ec7c..92983ee7df8c 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -74,6 +74,10 @@ static int debug_level = ERR_DBG; /* DEBUG message print. */ #define DBG_PRINT(dbg_level, args...) if(!(debug_level<dbg_level)) printk(args) +#ifndef DMA_ERROR_CODE +#define DMA_ERROR_CODE (~(dma_addr_t)0x0) +#endif + /* Protocol assist features of the NIC */ #define L3_CKSUM_OK 0xFFFF #define L4_CKSUM_OK 0xFFFF @@ -97,6 +101,7 @@ struct swStat { unsigned long long num_aggregations; /* Other statistics */ unsigned long long mem_alloc_fail_cnt; + unsigned long long pci_map_fail_cnt; unsigned long long watchdog_timer_cnt; unsigned long long mem_allocated; unsigned long long mem_freed; @@ -575,8 +580,7 @@ struct RxD_block { #define SIZE_OF_BLOCK 4096 #define RXD_MODE_1 0 /* One Buffer mode */ -#define RXD_MODE_3A 1 /* Three Buffer mode */ -#define RXD_MODE_3B 2 /* Two Buffer mode */ +#define RXD_MODE_3B 1 /* Two Buffer mode */ /* Structure to hold virtual addresses of Buf0 and Buf1 in * 2buf mode. */ @@ -794,7 +798,6 @@ struct s2io_nic { struct net_device_stats stats; int high_dma_flag; - int device_close_flag; int device_enabled_once; char name[60]; @@ -877,7 +880,6 @@ struct s2io_nic { u16 lro_max_aggr_per_sess; #define INTA 0 -#define MSI 1 #define MSI_X 2 u8 intr_type; @@ -1021,8 +1023,6 @@ static int s2io_poll(struct net_device *dev, int *budget); static void s2io_init_pci(struct s2io_nic * sp); static int s2io_set_mac_addr(struct net_device *dev, u8 * addr); static void s2io_alarm_handle(unsigned long data); -static int s2io_enable_msi(struct s2io_nic *nic); -static irqreturn_t s2io_msi_handle(int irq, void *dev_id); static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id); static irqreturn_t @@ -1034,7 +1034,6 @@ static void s2io_set_link(struct work_struct *work); static int s2io_set_swapper(struct s2io_nic * sp); static void s2io_card_down(struct s2io_nic *nic); static int s2io_card_up(struct s2io_nic *nic); -static int get_xena_rev_id(struct pci_dev *pdev); static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit, int bit_state); static int s2io_add_isr(struct s2io_nic * sp); @@ -1052,6 +1051,11 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, struct sk_buff *skb, u32 tcp_len); static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring); +static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state); +static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev); +static void s2io_io_resume(struct pci_dev *pdev); + #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_offload_type(skb) skb_shinfo(skb)->gso_type diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c index ad94358ece89..7dae4d404978 100644 --- a/drivers/net/saa9730.c +++ b/drivers/net/saa9730.c @@ -690,9 +690,9 @@ static int lan_saa9730_rx(struct net_device *dev) lp->stats.rx_packets++; skb_reserve(skb, 2); /* 16 byte align */ skb_put(skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *) pData, - len, 0); + len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; @@ -940,15 +940,14 @@ static void lan_saa9730_set_multicast(struct net_device *dev) CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC, &lp->lan_saa9730_regs->CamCtl); } else { - if (dev->flags & IFF_ALLMULTI) { + if (dev->flags & IFF_ALLMULTI || dev->mc_count) { /* accept all multicast packets */ - writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | - CAM_CONTROL_BROAD_ACC, - &lp->lan_saa9730_regs->CamCtl); - } else { /* * Will handle the multicast stuff later. -carstenl */ + writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | + CAM_CONTROL_BROAD_ACC, + &lp->lan_saa9730_regs->CamCtl); } } diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 5b7284c955dc..872cb1cc9c41 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1402,7 +1402,6 @@ static struct ethtool_ops sc92031_ethtool_ops = { .get_strings = sc92031_ethtool_get_strings, .get_stats_count = sc92031_ethtool_get_stats_count, .get_ethtool_stats = sc92031_ethtool_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, .get_ufo = ethtool_op_get_ufo, }; diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 2106becf6990..0fb74cb51c4b 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -320,7 +320,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp skb_put(skb, len); /* Copy out of kseg1 to avoid silly cache flush. */ - eth_copy_and_sum(skb, pkt_pointer + 2, len, 0); + skb_copy_to_linear_data(skb, pkt_pointer + 2, len); skb->protocol = eth_type_trans(skb, dev); /* We don't want to receive our own packets */ @@ -726,7 +726,7 @@ err_out: return err; } -static void __exit sgiseeq_remove(struct platform_device *pdev) +static int __exit sgiseeq_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct sgiseeq_private *sp = netdev_priv(dev); @@ -735,6 +735,8 @@ static void __exit sgiseeq_remove(struct platform_device *pdev) free_page((unsigned long) sp->srings); free_netdev(dev); platform_set_drvdata(pdev, NULL); + + return 0; } static struct platform_driver sgiseeq_driver = { diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c index e886e8d7cfdf..4c3d98ff4cd4 100644 --- a/drivers/net/shaper.c +++ b/drivers/net/shaper.c @@ -600,10 +600,9 @@ static int __init shaper_init(void) return -ENODEV; alloc_size = sizeof(*dev) * shapers; - devs = kmalloc(alloc_size, GFP_KERNEL); + devs = kzalloc(alloc_size, GFP_KERNEL); if (!devs) return -ENOMEM; - memset(devs, 0, alloc_size); for (i = 0; i < shapers; i++) { diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index bc8de48da313..d470b19c0810 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -548,7 +548,7 @@ static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN); if (skb) { skb_reserve(skb, NET_IP_ALIGN); - eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0); + skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size); *sk_buff = skb; sis190_give_to_asic(desc, rx_buf_sz); ret = 0; @@ -1593,6 +1593,9 @@ static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, pci_name(pdev)); isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0965, NULL); + if (!isa_bridge) + isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0966, NULL); + if (!isa_bridge) { net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n", pci_name(pdev)); diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 2cb2e156c758..7c6e4808399a 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -573,7 +573,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, * return error if it failed to found. */ -static int __init sis900_mii_probe(struct net_device * net_dev) +static int __devinit sis900_mii_probe(struct net_device * net_dev) { struct sis900_private * sis_priv = net_dev->priv; const char *dev_name = pci_name(sis_priv->pci_dev); diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c index 36460694eb82..5a6da8950faa 100644 --- a/drivers/net/sk98lin/skethtool.c +++ b/drivers/net/sk98lin/skethtool.c @@ -616,7 +616,6 @@ const struct ethtool_ops SkGeEthtoolOps = { .get_pauseparam = getPauseParams, .set_pauseparam = setPauseParams, .get_link = ethtool_op_get_link, - .get_perm_addr = ethtool_op_get_perm_addr, .get_sg = ethtool_op_get_sg, .set_sg = setScatterGather, .get_tx_csum = ethtool_op_get_tx_csum, diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index bf218621db16..7dc9c9ebf5e7 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -5168,10 +5168,17 @@ err_out: #endif static struct pci_device_id skge_pci_tbl[] = { +#ifdef SK98LIN_ALL_DEVICES { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif +#ifdef GENESIS + /* Generic SysKonnect SK-98xx Gigabit Ethernet Server Adapter */ { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + /* Generic SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter */ { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#ifdef SK98LIN_ALL_DEVICES /* DLink card does not have valid VPD so this driver gags * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */ @@ -5180,6 +5187,7 @@ static struct pci_device_id skge_pci_tbl[] = { { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, }, { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif { 0 } }; diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c index efc639c013fd..ea85de918233 100644 --- a/drivers/net/skfp/pmf.c +++ b/drivers/net/skfp/pmf.c @@ -575,7 +575,7 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, int sp_len ; /* - * skip if errror + * skip if error */ if (pcon->pc_err) return ; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 776692946562..e3d8520209b8 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -821,7 +821,6 @@ static const struct ethtool_ops skge_ethtool_ops = { .phys_id = skge_phys_id, .get_stats_count = skge_get_stats_count, .get_ethtool_stats = skge_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; /* diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2e76c4afaf98..ea117fc3d5e3 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -39,6 +39,7 @@ #include <linux/workqueue.h> #include <linux/if_vlan.h> #include <linux/prefetch.h> +#include <linux/debugfs.h> #include <linux/mii.h> #include <asm/irq.h> @@ -50,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.14" +#define DRV_VERSION "1.18" #define PFX DRV_NAME " " /* @@ -64,7 +65,6 @@ #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) #define RX_DEF_PENDING RX_MAX_PENDING #define RX_SKB_ALIGN 8 -#define RX_BUF_WRITE 16 #define TX_RING_SIZE 512 #define TX_DEF_PENDING (TX_RING_SIZE - 1) @@ -77,6 +77,9 @@ #define NAPI_WEIGHT 64 #define PHY_RETRIES 1000 +#define SKY2_EEPROM_MAGIC 0x9955aabb + + #define RING_NEXT(x,s) (((x)+1) & ((s)-1)) static const u32 default_msg = @@ -96,10 +99,6 @@ static int disable_msi = 0; module_param(disable_msi, int, 0); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); -static int idle_timeout = 100; -module_param(idle_timeout, int, 0); -MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); - static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ @@ -119,18 +118,21 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ -// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ { 0 } }; @@ -148,8 +150,11 @@ static const char *yukon2_name[] = { "Extreme", /* 0xb5 */ "EC", /* 0xb6 */ "FE", /* 0xb7 */ + "FE+", /* 0xb8 */ }; +static void sky2_set_multicast(struct net_device *dev); + /* Access to external PHY */ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) { @@ -216,14 +221,29 @@ static void sky2_power_on(struct sky2_hw *hw) else sky2_write8(hw, B2_Y2_CLK_GATE, 0); - if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { - u32 reg1; + if (hw->flags & SKY2_HW_ADV_POWER_CTL) { + u32 reg; sky2_pci_write32(hw, PCI_DEV_REG3, 0); - reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); - reg1 &= P_ASPM_CONTROL_MSK; - sky2_pci_write32(hw, PCI_DEV_REG4, reg1); - sky2_pci_write32(hw, PCI_DEV_REG5, 0); + + reg = sky2_pci_read32(hw, PCI_DEV_REG4); + /* set all bits to 0 except bits 15..12 and 8 */ + reg &= P_ASPM_CONTROL_MSK; + sky2_pci_write32(hw, PCI_DEV_REG4, reg); + + reg = sky2_pci_read32(hw, PCI_DEV_REG5); + /* set all bits to 0 except bits 28 & 27 */ + reg &= P_CTL_TIM_VMAIN_AV_MSK; + sky2_pci_write32(hw, PCI_DEV_REG5, reg); + + sky2_pci_write32(hw, PCI_CFG_REG_1, 0); + + /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */ + reg = sky2_read32(hw, B2_GP_IO); + reg |= GLB_GPIO_STAT_RACE_DIS; + sky2_write32(hw, B2_GP_IO, reg); + + sky2_read32(hw, B2_GP_IO); } } @@ -294,10 +314,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) struct sky2_port *sky2 = netdev_priv(hw->dev[port]); u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; - if (sky2->autoneg == AUTONEG_ENABLE - && !(hw->chip_id == CHIP_ID_YUKON_XL - || hw->chip_id == CHIP_ID_YUKON_EC_U - || hw->chip_id == CHIP_ID_YUKON_EX)) { + if (sky2->autoneg == AUTONEG_ENABLE && + !(hw->flags & SKY2_HW_NEWER_PHY)) { u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | @@ -317,9 +335,19 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); if (sky2_is_copper(hw)) { - if (hw->chip_id == CHIP_ID_YUKON_FE) { + if (!(hw->flags & SKY2_HW_GIGABIT)) { /* enable automatic crossover */ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; + + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) { + u16 spec; + + /* Enable Class A driver for FE+ A0 */ + spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2); + spec |= PHY_M_FESC_SEL_CL_A; + gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); + } } else { /* disable energy detect */ ctrl &= ~PHY_M_PC_EN_DET_MSK; @@ -329,9 +357,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* downshift on PHY 88E1112 and 88E1149 is changed */ if (sky2->autoneg == AUTONEG_ENABLE - && (hw->chip_id == CHIP_ID_YUKON_XL - || hw->chip_id == CHIP_ID_YUKON_EC_U - || hw->chip_id == CHIP_ID_YUKON_EX)) { + && (hw->flags & SKY2_HW_NEWER_PHY)) { /* set downshift counter to 3x and enable downshift */ ctrl &= ~PHY_M_PC_DSC_MSK; ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; @@ -347,7 +373,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); /* special setup for PHY 88E1112 Fiber */ - if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) { + if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) { pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ @@ -438,7 +464,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gma_write16(hw, port, GM_GP_CTRL, reg); - if (hw->chip_id != CHIP_ID_YUKON_FE) + if (hw->flags & SKY2_HW_GIGABIT) gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); @@ -462,6 +488,23 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); break; + case CHIP_ID_YUKON_FE_P: + /* Enable Link Partner Next Page */ + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + ctrl |= PHY_M_PC_ENA_LIP_NP; + + /* disable Energy Detect and enable scrambler */ + ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB); + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */ + ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) | + PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) | + PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED); + + gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); + break; + case CHIP_ID_YUKON_XL: pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); @@ -531,7 +574,13 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* set page register to 0 */ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); + } else if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) { + /* apply workaround for integrated resistors calibration */ + gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17); + gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60); } else if (hw->chip_id != CHIP_ID_YUKON_EX) { + /* no effect on Yukon-XL */ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { @@ -650,10 +699,35 @@ static void sky2_wol_init(struct sky2_port *sky2) } +static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) +{ + struct net_device *dev = hw->dev[port]; + + if (dev->mtu <= ETH_DATA_LEN) + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); + + else if (hw->chip_id != CHIP_ID_YUKON_EC_U) + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_STFW_ENA | TX_JUMBO_ENA); + else { + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); + + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_DIS); + + /* Can't do offload because of lack of store/forward */ + dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM); + } +} + static void sky2_mac_init(struct sky2_hw *hw, unsigned port) { struct sky2_port *sky2 = netdev_priv(hw->dev[port]); u16 reg; + u32 rx_reg; int i; const u8 *addr = hw->dev[port]->dev_addr; @@ -730,33 +804,34 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) /* Configure Rx MAC FIFO */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); - sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), - GMF_OPER_ON | GMF_RX_F_FL_ON); + rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON; + if (hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_FE_P) + rx_reg |= GMF_RX_OVER_ON; + + sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); /* Flush Rx MAC FIFO on any flow control or error */ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ - sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); + reg = RX_GMF_FL_THR_DEF + 1; + /* Another magic mystery workaround from sk98lin */ + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) + reg = 0x178; + sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg); /* Configure Tx MAC FIFO */ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); - if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { + /* On chips without ram buffer, pause is controled by MAC level */ + if (sky2_read8(hw, B2_E_0) == 0) { sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); - /* set Tx GMAC FIFO Almost Empty Threshold */ - sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), - (ECU_JUMBO_WM << 16) | ECU_AE_THR); - - if (hw->dev[port]->mtu > ETH_DATA_LEN) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); - else - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); + sky2_set_tx_stfwd(hw, port); } } @@ -835,6 +910,20 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) return le; } +static void tx_init(struct sky2_port *sky2) +{ + struct sky2_tx_le *le; + + sky2->tx_prod = sky2->tx_cons = 0; + sky2->tx_tcpsum = 0; + sky2->tx_last_mss = 0; + + le = get_tx_le(sky2); + le->addr = 0; + le->opcode = OP_ADDR64 | HW_OWNER; + sky2->tx_addr64 = 0; +} + static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, struct sky2_tx_le *le) { @@ -861,24 +950,18 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) return le; } -/* Return high part of DMA address (could be 32 or 64 bit) */ -static inline u32 high32(dma_addr_t a) -{ - return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0; -} - /* Build description to hardware for one receive segment */ static void sky2_rx_add(struct sky2_port *sky2, u8 op, dma_addr_t map, unsigned len) { struct sky2_rx_le *le; - u32 hi = high32(map); + u32 hi = upper_32_bits(map); if (sky2->rx_addr64 != hi) { le = sky2_next_rx(sky2); le->addr = cpu_to_le32(hi); le->opcode = OP_ADDR64 | HW_OWNER; - sky2->rx_addr64 = high32(map + len); + sky2->rx_addr64 = upper_32_bits(map + len); } le = sky2_next_rx(sky2); @@ -937,9 +1020,8 @@ static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) */ static void rx_set_checksum(struct sky2_port *sky2) { - struct sky2_rx_le *le; + struct sky2_rx_le *le = sky2_next_rx(sky2); - le = sky2_next_rx(sky2); le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); le->ctrl = 0; le->opcode = OP_TCPSTART | HW_OWNER; @@ -947,7 +1029,6 @@ static void rx_set_checksum(struct sky2_port *sky2) sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); - } /* @@ -1106,6 +1187,11 @@ nomem: return NULL; } +static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq) +{ + sky2_put_idx(sky2->hw, rxq, sky2->rx_put); +} + /* * Allocate and setup receiver buffer pool. * Normal case this ends up creating one list element for skb @@ -1134,15 +1220,15 @@ static int sky2_rx_start(struct sky2_port *sky2) if (hw->chip_id == CHIP_ID_YUKON_EC_U && (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) - sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS); + sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS); sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); - rx_set_checksum(sky2); + if (!(hw->flags & SKY2_HW_NEW_LE)) + rx_set_checksum(sky2); /* Space needed for frame data + headers rounded up */ - size = ALIGN(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8) - + 8; + size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); /* Stopping point for hardware truncation */ thresh = (size - 8) / sizeof(u32); @@ -1197,7 +1283,7 @@ static int sky2_rx_start(struct sky2_port *sky2) } /* Tell chip about available buffers */ - sky2_put_idx(hw, rxq, sky2->rx_put); + sky2_rx_update(sky2, rxq); return 0; nomem: sky2_rx_clean(sky2); @@ -1210,7 +1296,7 @@ static int sky2_up(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u32 ramsize, imask; + u32 imask, ramsize; int cap, err = -ENOMEM; struct net_device *otherdev = hw->dev[sky2->port^1]; @@ -1248,7 +1334,8 @@ static int sky2_up(struct net_device *dev) GFP_KERNEL); if (!sky2->tx_ring) goto err_out; - sky2->tx_prod = sky2->tx_cons = 0; + + tx_init(sky2); sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, &sky2->rx_le_map); @@ -1267,11 +1354,10 @@ static int sky2_up(struct net_device *dev) /* Register is number of 4K blocks on internal RAM buffer. */ ramsize = sky2_read8(hw, B2_E_0) * 4; - printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize); - if (ramsize > 0) { u32 rxspace; + pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); if (ramsize < 16) rxspace = ramsize / 2; else @@ -1287,6 +1373,10 @@ static int sky2_up(struct net_device *dev) sky2_qset(hw, txqaddr[port]); + /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */ + if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0) + sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF); + /* Set almost empty threshold */ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_U_A0) @@ -1382,27 +1472,32 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); - addr64 = high32(mapping); + addr64 = upper_32_bits(mapping); /* Send high bits if changed or crosses boundary */ - if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) { + if (addr64 != sky2->tx_addr64 || + upper_32_bits(mapping + len) != sky2->tx_addr64) { le = get_tx_le(sky2); le->addr = cpu_to_le32(addr64); le->opcode = OP_ADDR64 | HW_OWNER; - sky2->tx_addr64 = high32(mapping + len); + sky2->tx_addr64 = upper_32_bits(mapping + len); } /* Check for TCP Segmentation Offload */ mss = skb_shinfo(skb)->gso_size; if (mss != 0) { - mss += tcp_optlen(skb); /* TCP options */ - mss += ip_hdrlen(skb) + sizeof(struct tcphdr); - mss += ETH_HLEN; - if (mss != sky2->tx_last_mss) { - le = get_tx_le(sky2); - le->addr = cpu_to_le32(mss); - le->opcode = OP_LRGLEN | HW_OWNER; + if (!(hw->flags & SKY2_HW_NEW_LE)) + mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); + + if (mss != sky2->tx_last_mss) { + le = get_tx_le(sky2); + le->addr = cpu_to_le32(mss); + + if (hw->flags & SKY2_HW_NEW_LE) + le->opcode = OP_MSS | HW_OWNER; + else + le->opcode = OP_LRGLEN | HW_OWNER; sky2->tx_last_mss = mss; } } @@ -1424,24 +1519,29 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* Handle TCP checksum offload */ if (skb->ip_summed == CHECKSUM_PARTIAL) { - const unsigned offset = skb_transport_offset(skb); - u32 tcpsum; - - tcpsum = offset << 16; /* sum start */ - tcpsum |= offset + skb->csum_offset; /* sum write */ - - ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; - if (ip_hdr(skb)->protocol == IPPROTO_UDP) - ctrl |= UDPTCP; - - if (tcpsum != sky2->tx_tcpsum) { - sky2->tx_tcpsum = tcpsum; - - le = get_tx_le(sky2); - le->addr = cpu_to_le32(tcpsum); - le->length = 0; /* initial checksum value */ - le->ctrl = 1; /* one packet */ - le->opcode = OP_TCPLISW | HW_OWNER; + /* On Yukon EX (some versions) encoding change. */ + if (hw->flags & SKY2_HW_AUTO_TX_SUM) + ctrl |= CALSUM; /* auto checksum */ + else { + const unsigned offset = skb_transport_offset(skb); + u32 tcpsum; + + tcpsum = offset << 16; /* sum start */ + tcpsum |= offset + skb->csum_offset; /* sum write */ + + ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; + if (ip_hdr(skb)->protocol == IPPROTO_UDP) + ctrl |= UDPTCP; + + if (tcpsum != sky2->tx_tcpsum) { + sky2->tx_tcpsum = tcpsum; + + le = get_tx_le(sky2); + le->addr = cpu_to_le32(tcpsum); + le->length = 0; /* initial checksum value */ + le->ctrl = 1; /* one packet */ + le->opcode = OP_TCPLISW | HW_OWNER; + } } } @@ -1461,7 +1561,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); - addr64 = high32(mapping); + addr64 = upper_32_bits(mapping); if (addr64 != sky2->tx_addr64) { le = get_tx_le(sky2); le->addr = cpu_to_le32(addr64); @@ -1531,13 +1631,13 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) if (unlikely(netif_msg_tx_done(sky2))) printk(KERN_DEBUG "%s: tx done %u\n", dev->name, idx); + sky2->net_stats.tx_packets++; sky2->net_stats.tx_bytes += re->skb->len; dev_kfree_skb_any(re->skb); + sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE); } - - le->opcode = 0; /* paranoia */ } sky2->tx_cons = idx; @@ -1656,11 +1756,15 @@ static int sky2_down(struct net_device *dev) static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) { - if (!sky2_is_copper(hw)) + if (hw->flags & SKY2_HW_FIBRE_PHY) return SPEED_1000; - if (hw->chip_id == CHIP_ID_YUKON_FE) - return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10; + if (!(hw->flags & SKY2_HW_GIGABIT)) { + if (aux & PHY_M_PS_SPEED_100) + return SPEED_100; + else + return SPEED_10; + } switch (aux & PHY_M_PS_SPEED_MSK) { case PHY_M_PS_SPEED_1000: @@ -1693,13 +1797,13 @@ static void sky2_link_up(struct sky2_port *sky2) netif_carrier_on(sky2->netdev); + mod_timer(&hw->watchdog_timer, jiffies + 1); + /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); - if (hw->chip_id == CHIP_ID_YUKON_XL - || hw->chip_id == CHIP_ID_YUKON_EC_U - || hw->chip_id == CHIP_ID_YUKON_EX) { + if (hw->flags & SKY2_HW_NEWER_PHY) { u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ @@ -1786,7 +1890,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) /* Since the pause result bits seem to in different positions on * different chips. look at registers. */ - if (!sky2_is_copper(hw)) { + if (hw->flags & SKY2_HW_FIBRE_PHY) { /* Shift for bits in fiber PHY */ advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM); lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM); @@ -1897,7 +2001,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; - if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE) + if (new_mtu > ETH_DATA_LEN && + (hw->chip_id == CHIP_ID_YUKON_FE || + hw->chip_id == CHIP_ID_YUKON_FE_P)) return -EINVAL; if (!netif_running(dev)) { @@ -1914,15 +2020,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) synchronize_irq(hw->pdev->irq); - if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { - if (new_mtu > ETH_DATA_LEN) { - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); - dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; - } else - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); - } + if (sky2_read8(hw, B2_E_0) == 0) + sky2_set_tx_stfwd(hw, port); ctl = gma_read16(hw, port, GM_GP_CTRL); gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); @@ -2020,8 +2119,6 @@ static struct sk_buff *receive_new(struct sky2_port *sky2, struct sk_buff *skb, *nskb; unsigned hdr_space = sky2->rx_data_size; - pr_debug(PFX "receive new length=%d\n", length); - /* Don't be tricky about reusing pages (yet) */ nskb = sky2_rx_alloc(sky2); if (unlikely(!nskb)) @@ -2051,6 +2148,13 @@ static struct sk_buff *sky2_receive(struct net_device *dev, struct sky2_port *sky2 = netdev_priv(dev); struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next; struct sk_buff *skb = NULL; + u16 count = (status & GMR_FS_LEN) >> 16; + +#ifdef SKY2_VLAN_TAG_USED + /* Account for vlan tag */ + if (sky2->vlgrp && (status & GMR_FS_VLAN)) + count -= VLAN_HLEN; +#endif if (unlikely(netif_msg_rx_status(sky2))) printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", @@ -2059,15 +2163,26 @@ static struct sk_buff *sky2_receive(struct net_device *dev, sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; prefetch(sky2->rx_ring + sky2->rx_next); + /* This chip has hardware problems that generates bogus status. + * So do only marginal checking and expect higher level protocols + * to handle crap frames. + */ + if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && + sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 && + length != count) + goto okay; + if (status & GMR_FS_ANY_ERR) goto error; if (!(status & GMR_FS_RX_OK)) goto resubmit; - if (status >> 16 != length) - goto len_mismatch; + /* if length reported by DMA does not match PHY, packet was truncated */ + if (length != count) + goto len_error; +okay: if (length < copybreak) skb = receive_copy(sky2, re, length); else @@ -2077,10 +2192,14 @@ resubmit: return skb; -len_mismatch: +len_error: /* Truncation of overlength packets causes PHY length to not match MAC length */ ++sky2->net_stats.rx_length_errors; + if (netif_msg_rx_err(sky2) && net_ratelimit()) + pr_info(PFX "%s: rx length error: status %#x length %d\n", + dev->name, status, length); + goto resubmit; error: ++sky2->net_stats.rx_errors; @@ -2118,15 +2237,16 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) /* Process status response ring */ static int sky2_status_intr(struct sky2_hw *hw, int to_do) { - struct sky2_port *sky2; int work_done = 0; - unsigned buf_write[2] = { 0, 0 }; + unsigned rx[2] = { 0, 0 }; u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); rmb(); while (hw->st_idx != hwidx) { + struct sky2_port *sky2; struct sky2_status_le *le = hw->st_le + hw->st_idx; + unsigned port = le->css & CSS_LINK_BIT; struct net_device *dev; struct sk_buff *skb; u32 status; @@ -2134,19 +2254,28 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); - BUG_ON(le->link >= 2); - dev = hw->dev[le->link]; - + dev = hw->dev[port]; sky2 = netdev_priv(dev); length = le16_to_cpu(le->length); status = le32_to_cpu(le->status); switch (le->opcode & ~HW_OWNER) { case OP_RXSTAT: + ++rx[port]; skb = sky2_receive(dev, length, status); if (unlikely(!skb)) { sky2->net_stats.rx_dropped++; - goto force_update; + break; + } + + /* This chip reports checksum status differently */ + if (hw->flags & SKY2_HW_NEW_LE) { + if (sky2->rx_csum && + (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && + (le->css & CSS_TCPUDPCSOK)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; } skb->protocol = eth_type_trans(skb, dev); @@ -2163,13 +2292,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) #endif netif_receive_skb(skb); - /* Update receiver after 16 frames */ - if (++buf_write[le->link] == RX_BUF_WRITE) { -force_update: - sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put); - buf_write[le->link] = 0; - } - /* Stop after net poll weight */ if (++work_done >= to_do) goto exit_loop; @@ -2188,6 +2310,15 @@ force_update: if (!sky2->rx_csum) break; + /* If this happens then driver assuming wrong format */ + if (unlikely(hw->flags & SKY2_HW_NEW_LE)) { + if (net_ratelimit()) + printk(KERN_NOTICE "%s: unexpected" + " checksum status\n", + dev->name); + break; + } + /* Both checksum counters are programmed to start at * the same offset, so unless there is a problem they * should match. This failure is an early indication that @@ -2203,7 +2334,7 @@ force_update: dev->name, status); sky2->rx_csum = 0; sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[le->link], Q_CSR), + Q_ADDR(rxqaddr[port], Q_CSR), BMU_DIS_RX_CHKSUM); } break; @@ -2222,24 +2353,18 @@ force_update: if (net_ratelimit()) printk(KERN_WARNING PFX "unknown status opcode 0x%x\n", le->opcode); - goto exit_loop; } } /* Fully processed status ring so clear irq */ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); - mmiowb(); exit_loop: - if (buf_write[0]) { - sky2 = netdev_priv(hw->dev[0]); - sky2_put_idx(hw, Q_R1, sky2->rx_put); - } + if (rx[0]) + sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1); - if (buf_write[1]) { - sky2 = netdev_priv(hw->dev[1]); - sky2_put_idx(hw, Q_R2, sky2->rx_put); - } + if (rx[1]) + sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2); return work_done; } @@ -2384,25 +2509,72 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port, sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); } -/* If idle then force a fake soft NAPI poll once a second - * to work around cases where sharing an edge triggered interrupt. - */ -static inline void sky2_idle_start(struct sky2_hw *hw) +static int sky2_rx_hung(struct net_device *dev) { - if (idle_timeout > 0) - mod_timer(&hw->idle_timer, - jiffies + msecs_to_jiffies(idle_timeout)); + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + unsigned rxq = rxqaddr[port]; + u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP)); + u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV)); + u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP)); + u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL)); + + /* If idle and MAC or PCI is stuck */ + if (sky2->check.last == dev->last_rx && + ((mac_rp == sky2->check.mac_rp && + mac_lev != 0 && mac_lev >= sky2->check.mac_lev) || + /* Check if the PCI RX hang */ + (fifo_rp == sky2->check.fifo_rp && + fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) { + printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n", + dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp, + sky2_read8(hw, Q_ADDR(rxq, Q_WP))); + return 1; + } else { + sky2->check.last = dev->last_rx; + sky2->check.mac_rp = mac_rp; + sky2->check.mac_lev = mac_lev; + sky2->check.fifo_rp = fifo_rp; + sky2->check.fifo_lev = fifo_lev; + return 0; + } } -static void sky2_idle(unsigned long arg) +static void sky2_watchdog(unsigned long arg) { struct sky2_hw *hw = (struct sky2_hw *) arg; - struct net_device *dev = hw->dev[0]; + struct net_device *dev; - if (__netif_rx_schedule_prep(dev)) - __netif_rx_schedule(dev); + /* Check for lost IRQ once a second */ + if (sky2_read32(hw, B0_ISRC)) { + dev = hw->dev[0]; + if (__netif_rx_schedule_prep(dev)) + __netif_rx_schedule(dev); + } else { + int i, active = 0; + + for (i = 0; i < hw->ports; i++) { + dev = hw->dev[i]; + if (!netif_running(dev)) + continue; + ++active; + + /* For chips with Rx FIFO, check if stuck */ + if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) && + sky2_rx_hung(dev)) { + pr_info(PFX "%s: receiver hang detected\n", + dev->name); + schedule_work(&hw->restart_work); + return; + } + } + + if (active == 0) + return; + } - mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); + mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); } /* Hardware/software error handling */ @@ -2499,17 +2671,25 @@ static void sky2_netpoll(struct net_device *dev) #endif /* Chip internal frequency for clock calculations */ -static inline u32 sky2_mhz(const struct sky2_hw *hw) +static u32 sky2_mhz(const struct sky2_hw *hw) { switch (hw->chip_id) { case CHIP_ID_YUKON_EC: case CHIP_ID_YUKON_EC_U: case CHIP_ID_YUKON_EX: - return 125; /* 125 Mhz */ + return 125; + case CHIP_ID_YUKON_FE: - return 100; /* 100 Mhz */ - default: /* YUKON_XL */ - return 156; /* 156 Mhz */ + return 100; + + case CHIP_ID_YUKON_FE_P: + return 50; + + case CHIP_ID_YUKON_XL: + return 156; + + default: + BUG(); } } @@ -2528,34 +2708,69 @@ static int __devinit sky2_init(struct sky2_hw *hw) { u8 t8; + /* Enable all clocks */ + sky2_pci_write32(hw, PCI_DEV_REG3, 0); + sky2_write8(hw, B0_CTST, CS_RST_CLR); hw->chip_id = sky2_read8(hw, B2_CHIP_ID); - if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { - dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", - hw->chip_id); - return -EOPNOTSUPP; - } + hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; - if (hw->chip_id == CHIP_ID_YUKON_EX) - dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n" - "Please report success or failure to <netdev@vger.kernel.org>\n"); + switch(hw->chip_id) { + case CHIP_ID_YUKON_XL: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEWER_PHY; + if (hw->chip_rev < 3) + hw->flags |= SKY2_HW_FIFO_HANG_CHECK; - /* Make sure and enable all clocks */ - if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) - sky2_pci_write32(hw, PCI_DEV_REG3, 0); + break; - hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; + case CHIP_ID_YUKON_EC_U: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEWER_PHY + | SKY2_HW_ADV_POWER_CTL; + break; + + case CHIP_ID_YUKON_EX: + hw->flags = SKY2_HW_GIGABIT + | SKY2_HW_NEWER_PHY + | SKY2_HW_NEW_LE + | SKY2_HW_ADV_POWER_CTL; + + /* New transmit checksum */ + if (hw->chip_rev != CHIP_REV_YU_EX_B0) + hw->flags |= SKY2_HW_AUTO_TX_SUM; + break; + + case CHIP_ID_YUKON_EC: + /* This rev is really old, and requires untested workarounds */ + if (hw->chip_rev == CHIP_REV_YU_EC_A1) { + dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); + return -EOPNOTSUPP; + } + hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK; + break; + + case CHIP_ID_YUKON_FE: + break; - /* This rev is really old, and requires untested workarounds */ - if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { - dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n", - yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], - hw->chip_id, hw->chip_rev); + case CHIP_ID_YUKON_FE_P: + hw->flags = SKY2_HW_NEWER_PHY + | SKY2_HW_NEW_LE + | SKY2_HW_AUTO_TX_SUM + | SKY2_HW_ADV_POWER_CTL; + break; + default: + dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", + hw->chip_id); return -EOPNOTSUPP; } hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); + if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') + hw->flags |= SKY2_HW_FIBRE_PHY; + + hw->ports = 1; t8 = sky2_read8(hw, B2_Y2_HW_RES); if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { @@ -2604,6 +2819,11 @@ static void sky2_reset(struct sky2_hw *hw) for (i = 0; i < hw->ports; i++) { sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); + + if (hw->chip_id == CHIP_ID_YUKON_EX) + sky2_write16(hw, SK_REG(i, GMAC_CTRL), + GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON + | GMC_BYP_RETR_ON); } sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); @@ -2690,10 +2910,6 @@ static void sky2_restart(struct work_struct *work) struct net_device *dev; int i, err; - dev_dbg(&hw->pdev->dev, "restarting\n"); - - del_timer_sync(&hw->idle_timer); - rtnl_lock(); sky2_write32(hw, B0_IMSK, 0); sky2_read32(hw, B0_IMSK); @@ -2722,8 +2938,6 @@ static void sky2_restart(struct work_struct *work) } } - sky2_idle_start(hw); - rtnl_unlock(); } @@ -2750,7 +2964,9 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) sky2->wol = wol->wolopts; - if (hw->chip_id == CHIP_ID_YUKON_EC_U) + if (hw->chip_id == CHIP_ID_YUKON_EC_U || + hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_FE_P) sky2_write32(hw, B0_CTST, sky2->wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); @@ -2768,7 +2984,7 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw) | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP; - if (hw->chip_id != CHIP_ID_YUKON_FE) + if (hw->flags & SKY2_HW_GIGABIT) modes |= SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; return modes; @@ -2788,13 +3004,6 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->supported = sky2_supported_modes(hw); ecmd->phy_address = PHY_ADDR_MARV; if (sky2_is_copper(hw)) { - ecmd->supported = SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full - | SUPPORTED_1000baseT_Half - | SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_TP; ecmd->port = PORT_TP; ecmd->speed = sky2->speed; } else { @@ -2861,8 +3070,10 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) sky2->autoneg = ecmd->autoneg; sky2->advertising = ecmd->advertising; - if (netif_running(dev)) + if (netif_running(dev)) { sky2_phy_reinit(sky2); + sky2_set_multicast(dev); + } return 0; } @@ -2955,6 +3166,7 @@ static int sky2_nway_reset(struct net_device *dev) return -EINVAL; sky2_phy_reinit(sky2); + sky2_set_multicast(dev); return 0; } @@ -3345,7 +3557,7 @@ static int sky2_get_regs_len(struct net_device *dev) /* * Returns copy of control register region - * Note: access to the RAM address register set will cause timeouts. + * Note: ethtool_get_regs always provides full size (16k) buffer */ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) @@ -3353,15 +3565,19 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, const struct sky2_port *sky2 = netdev_priv(dev); const void __iomem *io = sky2->hw->regs; - BUG_ON(regs->len < B3_RI_WTO_R1); regs->version = 1; memset(p, 0, regs->len); memcpy_fromio(p, io, B3_RAM_ADDR); - memcpy_fromio(p + B3_RI_WTO_R1, - io + B3_RI_WTO_R1, - regs->len - B3_RI_WTO_R1); + /* skip diagnostic ram region */ + memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1); + + /* copy GMAC registers */ + memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000); + if (sky2->hw->ports > 1) + memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000); + } /* In order to do Jumbo packets on these chips, need to turn off the @@ -3372,9 +3588,7 @@ static int no_tx_offload(struct net_device *dev) const struct sky2_port *sky2 = netdev_priv(dev); const struct sky2_hw *hw = sky2->hw; - return dev->mtu > ETH_DATA_LEN && - (hw->chip_id == CHIP_ID_YUKON_EX - || hw->chip_id == CHIP_ID_YUKON_EC_U); + return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U; } static int sky2_set_tx_csum(struct net_device *dev, u32 data) @@ -3394,39 +3608,314 @@ static int sky2_set_tso(struct net_device *dev, u32 data) return ethtool_op_set_tso(dev, data); } +static int sky2_get_eeprom_len(struct net_device *dev) +{ + struct sky2_port *sky2 = netdev_priv(dev); + u16 reg2; + + reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2); + return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); +} + +static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset) +{ + sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); + + while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F)) + cpu_relax(); + return sky2_pci_read32(hw, cap + PCI_VPD_DATA); +} + +static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val) +{ + sky2_pci_write32(hw, cap + PCI_VPD_DATA, val); + sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); + do { + cpu_relax(); + } while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F); +} + +static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *data) +{ + struct sky2_port *sky2 = netdev_priv(dev); + int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); + int length = eeprom->len; + u16 offset = eeprom->offset; + + if (!cap) + return -EINVAL; + + eeprom->magic = SKY2_EEPROM_MAGIC; + + while (length > 0) { + u32 val = sky2_vpd_read(sky2->hw, cap, offset); + int n = min_t(int, length, sizeof(val)); + + memcpy(data, &val, n); + length -= n; + data += n; + offset += n; + } + return 0; +} + +static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *data) +{ + struct sky2_port *sky2 = netdev_priv(dev); + int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); + int length = eeprom->len; + u16 offset = eeprom->offset; + + if (!cap) + return -EINVAL; + + if (eeprom->magic != SKY2_EEPROM_MAGIC) + return -EINVAL; + + while (length > 0) { + u32 val; + int n = min_t(int, length, sizeof(val)); + + if (n < sizeof(val)) + val = sky2_vpd_read(sky2->hw, cap, offset); + memcpy(&val, data, n); + + sky2_vpd_write(sky2->hw, cap, offset, val); + + length -= n; + data += n; + offset += n; + } + return 0; +} + + static const struct ethtool_ops sky2_ethtool_ops = { - .get_settings = sky2_get_settings, - .set_settings = sky2_set_settings, - .get_drvinfo = sky2_get_drvinfo, - .get_wol = sky2_get_wol, - .set_wol = sky2_set_wol, - .get_msglevel = sky2_get_msglevel, - .set_msglevel = sky2_set_msglevel, - .nway_reset = sky2_nway_reset, - .get_regs_len = sky2_get_regs_len, - .get_regs = sky2_get_regs, - .get_link = ethtool_op_get_link, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = sky2_set_tx_csum, - .get_tso = ethtool_op_get_tso, - .set_tso = sky2_set_tso, - .get_rx_csum = sky2_get_rx_csum, - .set_rx_csum = sky2_set_rx_csum, - .get_strings = sky2_get_strings, - .get_coalesce = sky2_get_coalesce, - .set_coalesce = sky2_set_coalesce, - .get_ringparam = sky2_get_ringparam, - .set_ringparam = sky2_set_ringparam, + .get_settings = sky2_get_settings, + .set_settings = sky2_set_settings, + .get_drvinfo = sky2_get_drvinfo, + .get_wol = sky2_get_wol, + .set_wol = sky2_set_wol, + .get_msglevel = sky2_get_msglevel, + .set_msglevel = sky2_set_msglevel, + .nway_reset = sky2_nway_reset, + .get_regs_len = sky2_get_regs_len, + .get_regs = sky2_get_regs, + .get_link = ethtool_op_get_link, + .get_eeprom_len = sky2_get_eeprom_len, + .get_eeprom = sky2_get_eeprom, + .set_eeprom = sky2_set_eeprom, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = sky2_set_tx_csum, + .get_tso = ethtool_op_get_tso, + .set_tso = sky2_set_tso, + .get_rx_csum = sky2_get_rx_csum, + .set_rx_csum = sky2_set_rx_csum, + .get_strings = sky2_get_strings, + .get_coalesce = sky2_get_coalesce, + .set_coalesce = sky2_set_coalesce, + .get_ringparam = sky2_get_ringparam, + .set_ringparam = sky2_set_ringparam, .get_pauseparam = sky2_get_pauseparam, .set_pauseparam = sky2_set_pauseparam, - .phys_id = sky2_phys_id, + .phys_id = sky2_phys_id, .get_stats_count = sky2_get_stats_count, .get_ethtool_stats = sky2_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; +#ifdef CONFIG_SKY2_DEBUG + +static struct dentry *sky2_debug; + +static int sky2_debug_show(struct seq_file *seq, void *v) +{ + struct net_device *dev = seq->private; + const struct sky2_port *sky2 = netdev_priv(dev); + const struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + unsigned idx, last; + int sop; + + if (!netif_running(dev)) + return -ENETDOWN; + + seq_printf(seq, "IRQ src=%x mask=%x control=%x\n", + sky2_read32(hw, B0_ISRC), + sky2_read32(hw, B0_IMSK), + sky2_read32(hw, B0_Y2_SP_ICR)); + + netif_poll_disable(hw->dev[0]); + last = sky2_read16(hw, STAT_PUT_IDX); + + if (hw->st_idx == last) + seq_puts(seq, "Status ring (empty)\n"); + else { + seq_puts(seq, "Status ring\n"); + for (idx = hw->st_idx; idx != last && idx < STATUS_RING_SIZE; + idx = RING_NEXT(idx, STATUS_RING_SIZE)) { + const struct sky2_status_le *le = hw->st_le + idx; + seq_printf(seq, "[%d] %#x %d %#x\n", + idx, le->opcode, le->length, le->status); + } + seq_puts(seq, "\n"); + } + + seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n", + sky2->tx_cons, sky2->tx_prod, + sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), + sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE))); + + /* Dump contents of tx ring */ + sop = 1; + for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE; + idx = RING_NEXT(idx, TX_RING_SIZE)) { + const struct sky2_tx_le *le = sky2->tx_le + idx; + u32 a = le32_to_cpu(le->addr); + + if (sop) + seq_printf(seq, "%u:", idx); + sop = 0; + + switch(le->opcode & ~HW_OWNER) { + case OP_ADDR64: + seq_printf(seq, " %#x:", a); + break; + case OP_LRGLEN: + seq_printf(seq, " mtu=%d", a); + break; + case OP_VLAN: + seq_printf(seq, " vlan=%d", be16_to_cpu(le->length)); + break; + case OP_TCPLISW: + seq_printf(seq, " csum=%#x", a); + break; + case OP_LARGESEND: + seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length)); + break; + case OP_PACKET: + seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length)); + break; + case OP_BUFFER: + seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length)); + break; + default: + seq_printf(seq, " op=%#x,%#x(%d)", le->opcode, + a, le16_to_cpu(le->length)); + } + + if (le->ctrl & EOP) { + seq_putc(seq, '\n'); + sop = 1; + } + } + + seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n", + sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)), + last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), + sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); + + netif_poll_enable(hw->dev[0]); + return 0; +} + +static int sky2_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, sky2_debug_show, inode->i_private); +} + +static const struct file_operations sky2_debug_fops = { + .owner = THIS_MODULE, + .open = sky2_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * Use network device events to create/remove/rename + * debugfs file entries + */ +static int sky2_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + + if (dev->open == sky2_up) { + struct sky2_port *sky2 = netdev_priv(dev); + + switch(event) { + case NETDEV_CHANGENAME: + if (!netif_running(dev)) + break; + /* fallthrough */ + case NETDEV_DOWN: + case NETDEV_GOING_DOWN: + if (sky2->debugfs) { + printk(KERN_DEBUG PFX "%s: remove debugfs\n", + dev->name); + debugfs_remove(sky2->debugfs); + sky2->debugfs = NULL; + } + + if (event != NETDEV_CHANGENAME) + break; + /* fallthrough for changename */ + case NETDEV_UP: + if (sky2_debug) { + struct dentry *d; + d = debugfs_create_file(dev->name, S_IRUGO, + sky2_debug, dev, + &sky2_debug_fops); + if (d == NULL || IS_ERR(d)) + printk(KERN_INFO PFX + "%s: debugfs create failed\n", + dev->name); + else + sky2->debugfs = d; + } + break; + } + } + + return NOTIFY_DONE; +} + +static struct notifier_block sky2_notifier = { + .notifier_call = sky2_device_event, +}; + + +static __init void sky2_debug_init(void) +{ + struct dentry *ent; + + ent = debugfs_create_dir("sky2", NULL); + if (!ent || IS_ERR(ent)) + return; + + sky2_debug = ent; + register_netdevice_notifier(&sky2_notifier); +} + +static __exit void sky2_debug_cleanup(void) +{ + if (sky2_debug) { + unregister_netdevice_notifier(&sky2_notifier); + debugfs_remove(sky2_debug); + sky2_debug = NULL; + } +} + +#else +#define sky2_debug_init() +#define sky2_debug_cleanup() +#endif + + /* Initialize network device */ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, @@ -3493,8 +3982,12 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, dev->features |= NETIF_F_HIGHDMA; #ifdef SKY2_VLAN_TAG_USED - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = sky2_vlan_rx_register; + /* The workaround for FE+ status conflicts with VLAN tag detection. */ + if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && + sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) { + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_rx_register = sky2_vlan_rx_register; + } #endif /* read the mac address */ @@ -3525,7 +4018,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) return IRQ_NONE; if (status & Y2_IS_IRQ_SW) { - hw->msi = 1; + hw->flags |= SKY2_HW_USE_MSI; wake_up(&hw->msi_wait); sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); } @@ -3553,9 +4046,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); sky2_read8(hw, B0_CTST); - wait_event_timeout(hw->msi_wait, hw->msi, HZ/10); + wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10); - if (!hw->msi) { + if (!(hw->flags & SKY2_HW_USE_MSI)) { /* MSI test failed, go back to INTx mode */ dev_info(&pdev->dev, "No interrupt generated using MSI, " "switching to INTx mode.\n"); @@ -3688,7 +4181,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_netdev; } - err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, + err = request_irq(pdev->irq, sky2_intr, + (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED, dev->name, hw); if (err) { dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); @@ -3713,17 +4207,15 @@ static int __devinit sky2_probe(struct pci_dev *pdev, sky2_show_addr(dev1); } - setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); + setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw); INIT_WORK(&hw->restart_work, sky2_restart); - sky2_idle_start(hw); - pci_set_drvdata(pdev, hw); return 0; err_out_unregister: - if (hw->msi) + if (hw->flags & SKY2_HW_USE_MSI) pci_disable_msi(pdev); unregister_netdev(dev); err_out_free_netdev: @@ -3752,7 +4244,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) if (!hw) return; - del_timer_sync(&hw->idle_timer); + del_timer_sync(&hw->watchdog_timer); flush_scheduled_work(); @@ -3772,7 +4264,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) sky2_read8(hw, B0_CTST); free_irq(pdev->irq, hw); - if (hw->msi) + if (hw->flags & SKY2_HW_USE_MSI) pci_disable_msi(pdev); pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); pci_release_regions(pdev); @@ -3796,7 +4288,6 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) if (!hw) return 0; - del_timer_sync(&hw->idle_timer); netif_poll_disable(hw->dev[0]); for (i = 0; i < hw->ports; i++) { @@ -3841,7 +4332,9 @@ static int sky2_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D0, 0); /* Re-enable all clocks */ - if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) + if (hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_EC_U || + hw->chip_id == CHIP_ID_YUKON_FE_P) sky2_pci_write32(hw, PCI_DEV_REG3, 0); sky2_reset(hw); @@ -3858,11 +4351,13 @@ static int sky2_resume(struct pci_dev *pdev) dev_close(dev); goto out; } + + sky2_set_multicast(dev); } } netif_poll_enable(hw->dev[0]); - sky2_idle_start(hw); + return 0; out: dev_err(&pdev->dev, "resume failed (%d)\n", err); @@ -3879,7 +4374,6 @@ static void sky2_shutdown(struct pci_dev *pdev) if (!hw) return; - del_timer_sync(&hw->idle_timer); netif_poll_disable(hw->dev[0]); for (i = 0; i < hw->ports; i++) { @@ -3917,12 +4411,14 @@ static struct pci_driver sky2_driver = { static int __init sky2_init_module(void) { + sky2_debug_init(); return pci_register_driver(&sky2_driver); } static void __exit sky2_cleanup_module(void) { pci_unregister_driver(&sky2_driver); + sky2_debug_cleanup(); } module_init(sky2_init_module); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index b8c4a3b5eadf..8bc5c54e3efa 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -14,6 +14,8 @@ enum { PCI_DEV_REG3 = 0x80, PCI_DEV_REG4 = 0x84, PCI_DEV_REG5 = 0x88, + PCI_CFG_REG_0 = 0x90, + PCI_CFG_REG_1 = 0x94, }; enum { @@ -28,6 +30,7 @@ enum { enum pci_dev_reg_1 { PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */ PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */ + PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */ PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */ PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */ PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */ @@ -67,6 +70,80 @@ enum pci_dev_reg_4 { | P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY, }; +/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */ +enum pci_dev_reg_5 { + /* Bit 31..27: for A3 & later */ + P_CTL_DIV_CORE_CLK_ENA = 1<<31, /* Divide Core Clock Enable */ + P_CTL_SRESET_VMAIN_AV = 1<<30, /* Soft Reset for Vmain_av De-Glitch */ + P_CTL_BYPASS_VMAIN_AV = 1<<29, /* Bypass En. for Vmain_av De-Glitch */ + P_CTL_TIM_VMAIN_AV_MSK = 3<<27, /* Bit 28..27: Timer Vmain_av Mask */ + /* Bit 26..16: Release Clock on Event */ + P_REL_PCIE_RST_DE_ASS = 1<<26, /* PCIe Reset De-Asserted */ + P_REL_GPHY_REC_PACKET = 1<<25, /* GPHY Received Packet */ + P_REL_INT_FIFO_N_EMPTY = 1<<24, /* Internal FIFO Not Empty */ + P_REL_MAIN_PWR_AVAIL = 1<<23, /* Main Power Available */ + P_REL_CLKRUN_REQ_REL = 1<<22, /* CLKRUN Request Release */ + P_REL_PCIE_RESET_ASS = 1<<21, /* PCIe Reset Asserted */ + P_REL_PME_ASSERTED = 1<<20, /* PME Asserted */ + P_REL_PCIE_EXIT_L1_ST = 1<<19, /* PCIe Exit L1 State */ + P_REL_LOADER_NOT_FIN = 1<<18, /* EPROM Loader Not Finished */ + P_REL_PCIE_RX_EX_IDLE = 1<<17, /* PCIe Rx Exit Electrical Idle State */ + P_REL_GPHY_LINK_UP = 1<<16, /* GPHY Link Up */ + + /* Bit 10.. 0: Mask for Gate Clock */ + P_GAT_PCIE_RST_ASSERTED = 1<<10,/* PCIe Reset Asserted */ + P_GAT_GPHY_N_REC_PACKET = 1<<9, /* GPHY Not Received Packet */ + P_GAT_INT_FIFO_EMPTY = 1<<8, /* Internal FIFO Empty */ + P_GAT_MAIN_PWR_N_AVAIL = 1<<7, /* Main Power Not Available */ + P_GAT_CLKRUN_REQ_REL = 1<<6, /* CLKRUN Not Requested */ + P_GAT_PCIE_RESET_ASS = 1<<5, /* PCIe Reset Asserted */ + P_GAT_PME_DE_ASSERTED = 1<<4, /* PME De-Asserted */ + P_GAT_PCIE_ENTER_L1_ST = 1<<3, /* PCIe Enter L1 State */ + P_GAT_LOADER_FINISHED = 1<<2, /* EPROM Loader Finished */ + P_GAT_PCIE_RX_EL_IDLE = 1<<1, /* PCIe Rx Electrical Idle State */ + P_GAT_GPHY_LINK_DOWN = 1<<0, /* GPHY Link Down */ + + PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET | + P_REL_INT_FIFO_N_EMPTY | + P_REL_PCIE_EXIT_L1_ST | + P_REL_PCIE_RX_EX_IDLE | + P_GAT_GPHY_N_REC_PACKET | + P_GAT_INT_FIFO_EMPTY | + P_GAT_PCIE_ENTER_L1_ST | + P_GAT_PCIE_RX_EL_IDLE, +}; + +#/* PCI_CFG_REG_1 32 bit Config Register 1 (Yukon-Ext only) */ +enum pci_cfg_reg1 { + P_CF1_DIS_REL_EVT_RST = 1<<24, /* Dis. Rel. Event during PCIE reset */ + /* Bit 23..21: Release Clock on Event */ + P_CF1_REL_LDR_NOT_FIN = 1<<23, /* EEPROM Loader Not Finished */ + P_CF1_REL_VMAIN_AVLBL = 1<<22, /* Vmain available */ + P_CF1_REL_PCIE_RESET = 1<<21, /* PCI-E reset */ + /* Bit 20..18: Gate Clock on Event */ + P_CF1_GAT_LDR_NOT_FIN = 1<<20, /* EEPROM Loader Finished */ + P_CF1_GAT_PCIE_RX_IDLE = 1<<19, /* PCI-E Rx Electrical idle */ + P_CF1_GAT_PCIE_RESET = 1<<18, /* PCI-E Reset */ + P_CF1_PRST_PHY_CLKREQ = 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */ + P_CF1_PCIE_RST_CLKREQ = 1<<16, /* Enable PCI-E rst generate CLKREQ */ + + P_CF1_ENA_CFG_LDR_DONE = 1<<8, /* Enable core level Config loader done */ + + P_CF1_ENA_TXBMU_RD_IDLE = 1<<1, /* Enable TX BMU Read IDLE for ASPM */ + P_CF1_ENA_TXBMU_WR_IDLE = 1<<0, /* Enable TX BMU Write IDLE for ASPM */ + + PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST | + P_CF1_REL_LDR_NOT_FIN | + P_CF1_REL_VMAIN_AVLBL | + P_CF1_REL_PCIE_RESET | + P_CF1_GAT_LDR_NOT_FIN | + P_CF1_GAT_PCIE_RESET | + P_CF1_PRST_PHY_CLKREQ | + P_CF1_ENA_CFG_LDR_DONE | + P_CF1_ENA_TXBMU_RD_IDLE | + P_CF1_ENA_TXBMU_WR_IDLE, +}; + #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ PCI_STATUS_SIG_SYSTEM_ERROR | \ @@ -364,6 +441,20 @@ enum { TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */ }; +/* B2_GPIO */ +enum { + GLB_GPIO_CLK_DEB_ENA = 1<<31, /* Clock Debug Enable */ + GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */ + + GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */ + GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */ + GLB_GPIO_STAT_RACE_DIS = 1<<13, /* Status Race Disable */ + GLB_GPIO_TEST_SEL_MSK = 3<<11, /* Testmode Select */ + GLB_GPIO_TEST_SEL_BASE = 1<<11, + GLB_GPIO_RAND_ENA = 1<<10, /* Random Enable */ + GLB_GPIO_RAND_BIT_1 = 1<<9, /* Random Bit 1 */ +}; + /* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ enum { CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */ @@ -379,19 +470,30 @@ enum { CHIP_ID_YUKON_EX = 0xb5, /* Chip ID for YUKON-2 Extreme */ CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ - + CHIP_ID_YUKON_FE_P = 0xb8, /* Chip ID for YUKON-2 FE+ */ +}; +enum yukon_ec_rev { CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */ CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */ CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */ - +}; +enum yukon_ec_u_rev { CHIP_REV_YU_EC_U_A0 = 1, CHIP_REV_YU_EC_U_A1 = 2, CHIP_REV_YU_EC_U_B0 = 3, - +}; +enum yukon_fe_rev { CHIP_REV_YU_FE_A1 = 1, CHIP_REV_YU_FE_A2 = 2, - }; +enum yukon_fe_p_rev { + CHIP_REV_YU_FE2_A0 = 0, +}; +enum yukon_ex_rev { + CHIP_REV_YU_EX_A0 = 1, + CHIP_REV_YU_EX_B0 = 2, +}; + /* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ enum { @@ -515,23 +617,15 @@ enum { enum { B8_Q_REGS = 0x0400, /* base of Queue registers */ Q_D = 0x00, /* 8*32 bit Current Descriptor */ - Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */ - Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */ + Q_VLAN = 0x20, /* 16 bit Current VLAN Tag */ + Q_DONE = 0x24, /* 16 bit Done Index */ Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */ Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */ Q_BC = 0x30, /* 32 bit Current Byte Counter */ Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */ - Q_F = 0x38, /* 32 bit Flag Register */ - Q_T1 = 0x3c, /* 32 bit Test Register 1 */ - Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */ - Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */ - Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */ - Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */ - Q_T2 = 0x40, /* 32 bit Test Register 2 */ - Q_T3 = 0x44, /* 32 bit Test Register 3 */ + Q_TEST = 0x38, /* 32 bit Test/Control Register */ /* Yukon-2 */ - Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */ Q_WM = 0x40, /* 16 bit FIFO Watermark */ Q_AL = 0x42, /* 8 bit FIFO Alignment */ Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */ @@ -545,15 +639,16 @@ enum { }; #define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs)) -/* Q_F 32 bit Flag Register */ +/* Q_TEST 32 bit Test Register */ enum { - F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */ - F_EMPTY = 1<<27, /* Tx FIFO: empty flag */ - F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */ - F_WM_REACHED = 1<<25, /* Watermark reached */ + /* Transmit */ + F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */ + F_TX_CHK_AUTO_ON = 1<<30, /* Tx checksum auto calc off (Yukon EX) */ + + /* Receive */ F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */ - F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */ - F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */ + + /* Hardware testbits not used */ }; /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/ @@ -1579,7 +1674,7 @@ enum { /* Receive Frame Status Encoding */ enum { - GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ + GMR_FS_LEN = 0x7fff<<16, /* Bit 30..16: Rx Frame Length */ GMR_FS_VLAN = 1<<13, /* VLAN Packet */ GMR_FS_JABBER = 1<<12, /* Jabber Packet */ GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */ @@ -1608,6 +1703,16 @@ enum { RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */ RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */ + RX_MACSEC_FLUSH_ON = 1<<23, + RX_MACSEC_FLUSH_OFF = 1<<22, + RX_MACSEC_ASF_FLUSH_ON = 1<<21, + RX_MACSEC_ASF_FLUSH_OFF = 1<<20, + + GMF_RX_OVER_ON = 1<<19, /* enable flushing on receive overrun */ + GMF_RX_OVER_OFF = 1<<18, /* disable flushing on receive overrun */ + GMF_ASF_RX_OVER_ON = 1<<17, /* enable flushing of ASF when overrun */ + GMF_ASF_RX_OVER_OFF = 1<<16, /* disable flushing of ASF when overrun */ + GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */ GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */ GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */ @@ -1630,6 +1735,10 @@ enum { GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON, }; +/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ +enum { + TX_DYN_WM_ENA = 3, /* Yukon-FE+ specific */ +}; /* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ enum { @@ -1720,6 +1829,15 @@ enum { /* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ enum { + GMC_SET_RST = 1<<15,/* MAC SEC RST */ + GMC_SEC_RST_OFF = 1<<14,/* MAC SEC RSt OFF */ + GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */ + GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */ + GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */ + GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX off*/ + GMC_BYP_RETR_ON = 1<<9, /* Bypass retransmit FIFO On */ + GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */ + GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */ GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */ GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */ @@ -1805,9 +1923,13 @@ enum { OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN, OP_LRGLEN = 0x24, OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN, + OP_MSS = 0x28, + OP_MSSVLAN = OP_MSS | OP_VLAN, + OP_BUFFER = 0x40, OP_PACKET = 0x41, OP_LARGESEND = 0x43, + OP_LSOV2 = 0x45, /* YUKON-2 STATUS opcodes defines */ OP_RXSTAT = 0x60, @@ -1818,6 +1940,19 @@ enum { OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN, OP_RSS_HASH = 0x65, OP_TXINDEXLE = 0x68, + OP_MACSEC = 0x6c, + OP_PUTIDX = 0x70, +}; + +enum status_css { + CSS_TCPUDPCSOK = 1<<7, /* TCP / UDP checksum is ok */ + CSS_ISUDP = 1<<6, /* packet is a UDP packet */ + CSS_ISTCP = 1<<5, /* packet is a TCP packet */ + CSS_ISIPFRAG = 1<<4, /* packet is a TCP/UDP frag, CS calc not done */ + CSS_ISIPV6 = 1<<3, /* packet is a IPv6 packet */ + CSS_IPV4CSUMOK = 1<<2, /* IP v4: TCP header checksum is ok */ + CSS_ISIPV4 = 1<<1, /* packet is a IPv4 packet */ + CSS_LINK_BIT = 1<<0, /* port number (legacy) */ }; /* Yukon 2 hardware interface */ @@ -1838,7 +1973,7 @@ struct sky2_rx_le { struct sky2_status_le { __le32 status; /* also checksum */ __le16 length; /* also vlan tag */ - u8 link; + u8 css; u8 opcode; } __attribute((packed)); @@ -1873,6 +2008,7 @@ struct sky2_port { struct sky2_tx_le *tx_le; u16 tx_cons; /* next le to check */ u16 tx_prod; /* next le to use */ + u16 tx_next; /* debug only */ u32 tx_addr64; u16 tx_pending; u16 tx_last_mss; @@ -1891,6 +2027,14 @@ struct sky2_port { u16 rx_tag; struct vlan_group *vlgrp; #endif + struct { + unsigned long last; + u32 mac_rp; + u8 mac_lev; + u8 fifo_rp; + u8 fifo_lev; + } check; + dma_addr_t rx_le_map; dma_addr_t tx_le_map; @@ -1903,6 +2047,9 @@ struct sky2_port { enum flow_control flow_mode; enum flow_control flow_status; +#ifdef CONFIG_SKY2_DEBUG + struct dentry *debugfs; +#endif struct net_device_stats net_stats; }; @@ -1911,6 +2058,15 @@ struct sky2_hw { void __iomem *regs; struct pci_dev *pdev; struct net_device *dev[2]; + unsigned long flags; +#define SKY2_HW_USE_MSI 0x00000001 +#define SKY2_HW_FIBRE_PHY 0x00000002 +#define SKY2_HW_GIGABIT 0x00000004 +#define SKY2_HW_NEWER_PHY 0x00000008 +#define SKY2_HW_FIFO_HANG_CHECK 0x00000010 +#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ +#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ +#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ u8 chip_id; u8 chip_rev; @@ -1921,15 +2077,14 @@ struct sky2_hw { u32 st_idx; dma_addr_t st_dma; - struct timer_list idle_timer; + struct timer_list watchdog_timer; struct work_struct restart_work; - int msi; wait_queue_head_t msi_wait; }; static inline int sky2_is_copper(const struct sky2_hw *hw) { - return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P'); + return !(hw->flags & SKY2_HW_FIBRE_PHY); } /* Register accessor for memory mapped device */ diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 65bd20fac820..3fd4735006f5 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -957,7 +957,7 @@ slip_close(struct tty_struct *tty) * STANDARD SLIP ENCAPSULATION * ************************************************************************/ -int +static int slip_esc(unsigned char *s, unsigned char *d, int len) { unsigned char *ptr = d; diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index f8429449dc1e..6ff3a1627af8 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -299,7 +299,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_CAN_USE_8BIT 1 #define SMC_CAN_USE_16BIT 1 -#define SMC_CAN_USE_32BIT 1 +#define SMC_CAN_USE_32BIT 0 #define SMC_inb(a, r) inb((a) + (r)) #define SMC_inw(a, r) inw((a) + (r)) @@ -310,8 +310,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #endif /* BOARDS */ -#define set_irq_type(irq, type) do {} while (0) - #elif defined(CONFIG_M32R) #define SMC_CAN_USE_8BIT 0 diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 7a4aa6a9f949..82d837ab4db9 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -434,7 +434,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card, bufsize + SPIDER_NET_RXBUF_ALIGN - 1); if (!descr->skb) { if (netif_msg_rx_err(card) && net_ratelimit()) - pr_err("Not enough memory to allocate rx buffer\n"); + dev_err(&card->netdev->dev, + "Not enough memory to allocate rx buffer\n"); card->spider_stats.alloc_rx_skb_error++; return -ENOMEM; } @@ -455,7 +456,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card, dev_kfree_skb_any(descr->skb); descr->skb = NULL; if (netif_msg_rx_err(card) && net_ratelimit()) - pr_err("Could not iommu-map rx buffer\n"); + dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n"); card->spider_stats.rx_iommu_map_error++; hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; } else { @@ -500,6 +501,20 @@ spider_net_enable_rxdmac(struct spider_net_card *card) } /** + * spider_net_disable_rxdmac - disables the receive DMA controller + * @card: card structure + * + * spider_net_disable_rxdmac terminates processing on the DMA controller + * by turing off the DMA controller, with the force-end flag set. + */ +static inline void +spider_net_disable_rxdmac(struct spider_net_card *card) +{ + spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR, + SPIDER_NET_DMA_RX_FEND_VALUE); +} + +/** * spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains * @card: card structure * @@ -655,20 +670,6 @@ write_hash: } /** - * spider_net_disable_rxdmac - disables the receive DMA controller - * @card: card structure - * - * spider_net_disable_rxdmac terminates processing on the DMA controller by - * turing off DMA and issueing a force end - */ -static void -spider_net_disable_rxdmac(struct spider_net_card *card) -{ - spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR, - SPIDER_NET_DMA_RX_FEND_VALUE); -} - -/** * spider_net_prepare_tx_descr - fill tx descriptor with skb data * @card: card structure * @descr: descriptor structure to fill out @@ -692,7 +693,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(buf)) { if (netif_msg_tx_err(card) && net_ratelimit()) - pr_err("could not iommu-map packet (%p, %i). " + dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). " "Dropping packet\n", skb->data, skb->len); card->spider_stats.tx_iommu_map_error++; return -ENOMEM; @@ -715,7 +716,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, hwdescr->data_status = 0; hwdescr->dmac_cmd_status = - SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS; + SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL; spin_unlock_irqrestore(&chain->lock, flags); if (skb->ip_summed == CHECKSUM_PARTIAL) @@ -832,9 +833,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal) case SPIDER_NET_DESCR_PROTECTION_ERROR: case SPIDER_NET_DESCR_FORCE_END: if (netif_msg_tx_err(card)) - pr_err("%s: forcing end of tx descriptor " - "with status x%02x\n", - card->netdev->name, status); + dev_err(&card->netdev->dev, "forcing end of tx descriptor " + "with status x%02x\n", status); card->netdev_stats.tx_errors++; break; @@ -1022,34 +1022,94 @@ spider_net_pass_skb_up(struct spider_net_descr *descr, netif_receive_skb(skb); } -#ifdef DEBUG static void show_rx_chain(struct spider_net_card *card) { struct spider_net_descr_chain *chain = &card->rx_chain; struct spider_net_descr *start= chain->tail; struct spider_net_descr *descr= start; + struct spider_net_hw_descr *hwd = start->hwdescr; + struct device *dev = &card->netdev->dev; + u32 curr_desc, next_desc; int status; + int tot = 0; int cnt = 0; - int cstat = spider_net_get_descr_status(descr); - printk(KERN_INFO "RX chain tail at descr=%ld\n", - (start - card->descr) - card->tx_chain.num_desc); + int off = start - chain->ring; + int cstat = hwd->dmac_cmd_status; + + dev_info(dev, "Total number of descrs=%d\n", + chain->num_desc); + dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n", + off, cstat); + + curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA); + next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA); + status = cstat; do { - status = spider_net_get_descr_status(descr); + hwd = descr->hwdescr; + off = descr - chain->ring; + status = hwd->dmac_cmd_status; + + if (descr == chain->head) + dev_info(dev, "Chain head is at %d, head status=0x%x\n", + off, status); + + if (curr_desc == descr->bus_addr) + dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n", + off, status); + + if (next_desc == descr->bus_addr) + dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n", + off, status); + + if (hwd->next_descr_addr == 0) + dev_info(dev, "chain is cut at %d\n", off); + if (cstat != status) { - printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat); + int from = (chain->num_desc + off - cnt) % chain->num_desc; + int to = (chain->num_desc + off - 1) % chain->num_desc; + dev_info(dev, "Have %d (from %d to %d) descrs " + "with stat=0x%08x\n", cnt, from, to, cstat); cstat = status; cnt = 0; } + cnt ++; + tot ++; + descr = descr->next; + } while (descr != start); + + dev_info(dev, "Last %d descrs with stat=0x%08x " + "for a total of %d descrs\n", cnt, cstat, tot); + +#ifdef DEBUG + /* Now dump the whole ring */ + descr = start; + do + { + struct spider_net_hw_descr *hwd = descr->hwdescr; + status = spider_net_get_descr_status(hwd); + cnt = descr - chain->ring; + dev_info(dev, "Descr %d stat=0x%08x skb=%p\n", + cnt, status, descr->skb); + dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n", + descr->bus_addr, hwd->buf_addr, hwd->buf_size); + dev_info(dev, "next=%08x result sz=%d valid sz=%d\n", + hwd->next_descr_addr, hwd->result_size, + hwd->valid_size); + dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n", + hwd->dmac_cmd_status, hwd->data_status, + hwd->data_error); + dev_info(dev, "\n"); + descr = descr->next; } while (descr != start); - printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat); -} #endif +} + /** * spider_net_resync_head_ptr - Advance head ptr past empty descrs * @@ -1127,6 +1187,7 @@ spider_net_decode_one_descr(struct spider_net_card *card) struct spider_net_descr_chain *chain = &card->rx_chain; struct spider_net_descr *descr = chain->tail; struct spider_net_hw_descr *hwdescr = descr->hwdescr; + u32 hw_buf_addr; int status; status = spider_net_get_descr_status(hwdescr); @@ -1140,15 +1201,17 @@ spider_net_decode_one_descr(struct spider_net_card *card) chain->tail = descr->next; /* unmap descriptor */ - pci_unmap_single(card->pdev, hwdescr->buf_addr, + hw_buf_addr = hwdescr->buf_addr; + hwdescr->buf_addr = 0xffffffff; + pci_unmap_single(card->pdev, hw_buf_addr, SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE); if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) || (status == SPIDER_NET_DESCR_PROTECTION_ERROR) || (status == SPIDER_NET_DESCR_FORCE_END) ) { if (netif_msg_rx_err(card)) - pr_err("%s: dropping RX descriptor with state %d\n", - card->netdev->name, status); + dev_err(&card->netdev->dev, + "dropping RX descriptor with state %d\n", status); card->netdev_stats.rx_dropped++; goto bad_desc; } @@ -1156,8 +1219,8 @@ spider_net_decode_one_descr(struct spider_net_card *card) if ( (status != SPIDER_NET_DESCR_COMPLETE) && (status != SPIDER_NET_DESCR_FRAME_END) ) { if (netif_msg_rx_err(card)) - pr_err("%s: RX descriptor with unknown state %d\n", - card->netdev->name, status); + dev_err(&card->netdev->dev, + "RX descriptor with unknown state %d\n", status); card->spider_stats.rx_desc_unk_state++; goto bad_desc; } @@ -1165,18 +1228,17 @@ spider_net_decode_one_descr(struct spider_net_card *card) /* The cases we'll throw away the packet immediately */ if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) { if (netif_msg_rx_err(card)) - pr_err("%s: error in received descriptor found, " + dev_err(&card->netdev->dev, + "error in received descriptor found, " "data_status=x%08x, data_error=x%08x\n", - card->netdev->name, hwdescr->data_status, hwdescr->data_error); goto bad_desc; } - if (hwdescr->dmac_cmd_status & 0xfcf4) { - pr_err("%s: bad status, cmd_status=x%08x\n", - card->netdev->name, + if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) { + dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n", hwdescr->dmac_cmd_status); - pr_err("buf_addr=x%08x\n", hwdescr->buf_addr); + pr_err("buf_addr=x%08x\n", hw_buf_addr); pr_err("buf_size=x%08x\n", hwdescr->buf_size); pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr); pr_err("result_size=x%08x\n", hwdescr->result_size); @@ -1196,6 +1258,8 @@ spider_net_decode_one_descr(struct spider_net_card *card) return 1; bad_desc: + if (netif_msg_rx_err(card)) + show_rx_chain(card); dev_kfree_skb_irq(descr->skb); descr->skb = NULL; hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; @@ -1221,7 +1285,6 @@ spider_net_poll(struct net_device *netdev, int *budget) int packets_to_do, packets_done = 0; int no_more_packets = 0; - spider_net_cleanup_tx_ring(card); packets_to_do = min(*budget, netdev->quota); while (packets_to_do) { @@ -1246,6 +1309,8 @@ spider_net_poll(struct net_device *netdev, int *budget) spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); + spider_net_cleanup_tx_ring(card); + /* if all packets are in the stack, enable interrupts and return 0 */ /* if not, return 1 */ if (no_more_packets) { @@ -1382,6 +1447,9 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS); error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS); + error_reg1 &= SPIDER_NET_INT1_MASK_VALUE; + error_reg2 &= SPIDER_NET_INT2_MASK_VALUE; + /* check GHIINT0STS ************************************/ if (status_reg) for (i = 0; i < 32; i++) @@ -1415,7 +1483,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GPWFFINT: /* PHY command queue full */ if (netif_msg_intr(card)) - pr_err("PHY write queue full\n"); + dev_err(&card->netdev->dev, "PHY write queue full\n"); show_error = 0; break; @@ -1582,9 +1650,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) } if ((show_error) && (netif_msg_intr(card)) && net_ratelimit()) - pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, " + dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, " "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n", - card->netdev->name, status_reg, error_reg1, error_reg2); /* clear interrupt sources */ @@ -1612,6 +1679,7 @@ spider_net_interrupt(int irq, void *ptr) u32 status_reg; status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS); + status_reg &= SPIDER_NET_INT0_MASK_VALUE; if (!status_reg) return IRQ_NONE; @@ -1653,6 +1721,38 @@ spider_net_poll_controller(struct net_device *netdev) #endif /* CONFIG_NET_POLL_CONTROLLER */ /** + * spider_net_enable_interrupts - enable interrupts + * @card: card structure + * + * spider_net_enable_interrupt enables several interrupts + */ +static void +spider_net_enable_interrupts(struct spider_net_card *card) +{ + spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, + SPIDER_NET_INT0_MASK_VALUE); + spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, + SPIDER_NET_INT1_MASK_VALUE); + spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, + SPIDER_NET_INT2_MASK_VALUE); +} + +/** + * spider_net_disable_interrupts - disable interrupts + * @card: card structure + * + * spider_net_disable_interrupts disables all the interrupts + */ +static void +spider_net_disable_interrupts(struct spider_net_card *card) +{ + spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); + spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); + spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); + spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); +} + +/** * spider_net_init_card - initializes the card * @card: card structure * @@ -1672,6 +1772,7 @@ spider_net_init_card(struct spider_net_card *card) spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); + spider_net_disable_interrupts(card); } /** @@ -1759,14 +1860,6 @@ spider_net_enable_card(struct spider_net_card *card) spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, SPIDER_NET_OPMODE_VALUE); - /* set interrupt mask registers */ - spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, - SPIDER_NET_INT0_MASK_VALUE); - spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, - SPIDER_NET_INT1_MASK_VALUE); - spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, - SPIDER_NET_INT2_MASK_VALUE); - spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, SPIDER_NET_GDTBSTA); } @@ -1849,7 +1942,8 @@ spider_net_init_firmware(struct spider_net_card *card) SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) { if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) && netif_msg_probe(card) ) { - pr_err("Incorrect size of spidernet firmware in " \ + dev_err(&card->netdev->dev, + "Incorrect size of spidernet firmware in " \ "filesystem. Looking in host firmware...\n"); goto try_host_fw; } @@ -1873,8 +1967,8 @@ try_host_fw: if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) && netif_msg_probe(card) ) { - pr_err("Incorrect size of spidernet firmware in " \ - "host firmware\n"); + dev_err(&card->netdev->dev, + "Incorrect size of spidernet firmware in host firmware\n"); goto done; } @@ -1884,7 +1978,8 @@ done: return err; out_err: if (netif_msg_probe(card)) - pr_err("Couldn't find spidernet firmware in filesystem " \ + dev_err(&card->netdev->dev, + "Couldn't find spidernet firmware in filesystem " \ "or host firmware\n"); return err; } @@ -1941,6 +2036,8 @@ spider_net_open(struct net_device *netdev) netif_carrier_on(netdev); netif_poll_enable(netdev); + spider_net_enable_interrupts(card); + return 0; register_int_failed: @@ -2113,11 +2210,7 @@ spider_net_stop(struct net_device *netdev) del_timer_sync(&card->tx_timer); del_timer_sync(&card->aneg_timer); - /* disable/mask all interrupts */ - spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); - spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); - spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); - spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); + spider_net_disable_interrupts(card); free_irq(netdev->irq, netdev); @@ -2279,13 +2372,14 @@ spider_net_setup_netdev(struct spider_net_card *card) result = spider_net_set_mac(netdev, &addr); if ((result) && (netif_msg_probe(card))) - pr_err("Failed to set MAC address: %i\n", result); + dev_err(&card->netdev->dev, + "Failed to set MAC address: %i\n", result); result = register_netdev(netdev); if (result) { if (netif_msg_probe(card)) - pr_err("Couldn't register net_device: %i\n", - result); + dev_err(&card->netdev->dev, + "Couldn't register net_device: %i\n", result); return result; } @@ -2363,17 +2457,19 @@ spider_net_setup_pci_dev(struct pci_dev *pdev) unsigned long mmio_start, mmio_len; if (pci_enable_device(pdev)) { - pr_err("Couldn't enable PCI device\n"); + dev_err(&pdev->dev, "Couldn't enable PCI device\n"); return NULL; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - pr_err("Couldn't find proper PCI device base address.\n"); + dev_err(&pdev->dev, + "Couldn't find proper PCI device base address.\n"); goto out_disable_dev; } if (pci_request_regions(pdev, spider_net_driver_name)) { - pr_err("Couldn't obtain PCI resources, aborting.\n"); + dev_err(&pdev->dev, + "Couldn't obtain PCI resources, aborting.\n"); goto out_disable_dev; } @@ -2381,8 +2477,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev) card = spider_net_alloc_card(); if (!card) { - pr_err("Couldn't allocate net_device structure, " - "aborting.\n"); + dev_err(&pdev->dev, + "Couldn't allocate net_device structure, aborting.\n"); goto out_release_regions; } card->pdev = pdev; @@ -2396,7 +2492,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev) card->regs = ioremap(mmio_start, mmio_len); if (!card->regs) { - pr_err("Couldn't obtain PCI resources, aborting.\n"); + dev_err(&pdev->dev, + "Couldn't obtain PCI resources, aborting.\n"); goto out_release_regions; } diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h index 1d054aa71504..dbbdb8cee3c6 100644 --- a/drivers/net/spider_net.h +++ b/drivers/net/spider_net.h @@ -349,11 +349,23 @@ enum spider_net_int2_status { #define SPIDER_NET_GPRDAT_MASK 0x0000ffff #define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000 -#define SPIDER_NET_DMAC_NOCS 0x00040000 +#define SPIDER_NET_DMAC_TXFRMTL 0x00040000 #define SPIDER_NET_DMAC_TCP 0x00020000 #define SPIDER_NET_DMAC_UDP 0x00030000 #define SPIDER_NET_TXDCEST 0x08000000 +#define SPIDER_NET_DESCR_RXFDIS 0x00000001 +#define SPIDER_NET_DESCR_RXDCEIS 0x00000002 +#define SPIDER_NET_DESCR_RXDEN0IS 0x00000004 +#define SPIDER_NET_DESCR_RXINVDIS 0x00000008 +#define SPIDER_NET_DESCR_RXRERRIS 0x00000010 +#define SPIDER_NET_DESCR_RXFDCIMS 0x00000100 +#define SPIDER_NET_DESCR_RXDCEIMS 0x00000200 +#define SPIDER_NET_DESCR_RXDEN0IMS 0x00000400 +#define SPIDER_NET_DESCR_RXINVDIMS 0x00000800 +#define SPIDER_NET_DESCR_RXRERRMIS 0x00001000 +#define SPIDER_NET_DESCR_UNUSED 0x077fe0e0 + #define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000 #define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */ #define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */ @@ -364,6 +376,13 @@ enum spider_net_int2_status { #define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000 #define SPIDER_NET_DESCR_TXDESFLG 0x00800000 +#define SPIDER_NET_DESCR_BAD_STATUS (SPIDER_NET_DESCR_RXDEN0IS | \ + SPIDER_NET_DESCR_RXRERRIS | \ + SPIDER_NET_DESCR_RXDEN0IMS | \ + SPIDER_NET_DESCR_RXINVDIMS | \ + SPIDER_NET_DESCR_RXRERRMIS | \ + SPIDER_NET_DESCR_UNUSED) + /* Descriptor, as defined by the hardware */ struct spider_net_hw_descr { u32 buf_addr; diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 786d4b9c07ec..8b6478663a56 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -740,7 +740,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, pci_set_master(pdev); /* enable MWI -- it vastly improves Rx performance on sparc64 */ - pci_set_mwi(pdev); + pci_try_set_mwi(pdev); #ifdef ZEROCOPY /* Starfire can do TCP/UDP checksumming */ @@ -1456,7 +1456,7 @@ static int __netdev_rx(struct net_device *dev, int *quota) pci_dma_sync_single_for_cpu(np->pci_dev, np->rx_info[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0); + skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, np->rx_info[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index a123ea87893b..b77ab6e8fd35 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -777,7 +777,7 @@ static void sun3_82586_rcv_int(struct net_device *dev) { skb_reserve(skb,2); skb_put(skb,totlen); - eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0); + skb_copy_to_linear_data(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); p->stats.rx_packets++; diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 791e081fdc15..f1548c033327 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -853,10 +853,9 @@ static int lance_rx( struct net_device *dev ) skb_reserve( skb, 2 ); /* 16 byte align */ skb_put( skb, pkt_len ); /* Make room */ -// skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), pkt_len); - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), - pkt_len, 0); + pkt_len); skb->protocol = eth_type_trans( skb, dev ); netif_rx( skb ); diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 2ad8d58dee3b..b3e0158def4f 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -860,7 +860,7 @@ static void bigmac_rx(struct bigmac *bp) sbus_dma_sync_single_for_cpu(bp->bigmac_sdev, this->rx_addr, len, SBUS_DMA_FROMDEVICE); - eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0); + skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len); sbus_dma_sync_single_for_device(bp->bigmac_sdev, this->rx_addr, len, SBUS_DMA_FROMDEVICE); diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index e1f912d04043..a8f2af8f778a 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -397,7 +397,6 @@ struct netdev_private { unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */ struct pci_dev *pci_dev; void __iomem *base; - unsigned char pci_rev_id; }; /* The station address location in the EEPROM. */ @@ -544,8 +543,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, dev->change_mtu = &change_mtu; pci_set_drvdata(pdev, dev); - pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id); - i = register_netdev(dev); if (i) goto err_out_unmap_rx; @@ -828,7 +825,7 @@ static int netdev_open(struct net_device *dev) iowrite8(100, ioaddr + RxDMAPollPeriod); iowrite8(127, ioaddr + TxDMAPollPeriod); /* Fix DFE-580TX packet drop issue */ - if (np->pci_rev_id >= 0x14) + if (np->pci_dev->revision >= 0x14) iowrite8(0x01, ioaddr + DebugCtrl1); netif_start_queue(dev); @@ -1194,7 +1191,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) hw_frame_id = ioread8(ioaddr + TxFrameId); } - if (np->pci_rev_id >= 0x14) { + if (np->pci_dev->revision >= 0x14) { spin_lock(&np->lock); for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { int entry = np->dirty_tx % TX_RING_SIZE; @@ -1313,7 +1310,7 @@ static void rx_poll(unsigned long data) np->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, desc->frag[0].addr, np->rx_buf_sz, @@ -1589,7 +1586,6 @@ static const struct ethtool_ops ethtool_ops = { .get_link = get_link, .get_msglevel = get_msglevel, .set_msglevel = set_msglevel, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 51c3fe2108a3..8b35f13318ea 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2625,7 +2625,7 @@ static void quattro_sbus_free_irqs(void) #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI -static struct quattro * __init quattro_pci_find(struct pci_dev *pdev) +static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev) { struct pci_dev *bdev = pdev->bus->self; struct quattro *qp; @@ -3095,12 +3095,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, #ifdef CONFIG_SPARC hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff); - if (hp->hm_revision == 0xff) { - unsigned char prev; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &prev); - hp->hm_revision = 0xc0 | (prev & 0x0f); - } + if (hp->hm_revision == 0xff) + hp->hm_revision = 0xc0 | (pdev->revision & 0x0f); #else /* works with this on non-sparc hosts */ hp->hm_revision = 0x20; diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 42722530ab24..68e4f660367d 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -99,8 +99,7 @@ static char lancestr[] = "LANCE"; #include <asm/byteorder.h> /* Used by the checksum routines */ #include <asm/idprom.h> #include <asm/sbus.h> -#include <asm/openprom.h> -#include <asm/oplib.h> +#include <asm/prom.h> #include <asm/auxio.h> /* For tpe-link-test? setting */ #include <asm/irq.h> @@ -549,9 +548,9 @@ static void lance_rx_dvma(struct net_device *dev) skb_reserve(skb, 2); /* 16 byte align */ skb_put(skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)&(ib->rx_buf [entry][0]), - len, 0); + len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; @@ -1326,6 +1325,7 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, struct sbus_dev *lebuffer) { static unsigned version_printed; + struct device_node *dp = sdev->ofdev.node; struct net_device *dev; struct lance_private *lp; int i; @@ -1389,54 +1389,46 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, lp->rx = lance_rx_dvma; lp->tx = lance_tx_dvma; } - lp->busmaster_regval = prom_getintdefault(sdev->prom_node, - "busmaster-regval", - (LE_C3_BSWP | LE_C3_ACON | - LE_C3_BCON)); + lp->busmaster_regval = of_getintprop_default(dp, "busmaster-regval", + (LE_C3_BSWP | + LE_C3_ACON | + LE_C3_BCON)); lp->name = lancestr; lp->ledma = ledma; lp->burst_sizes = 0; if (lp->ledma) { - char prop[6]; + struct device_node *ledma_dp = ledma->sdev->ofdev.node; + const char *prop; unsigned int sbmask; u32 csr; /* Find burst-size property for ledma */ - lp->burst_sizes = prom_getintdefault(ledma->sdev->prom_node, - "burst-sizes", 0); + lp->burst_sizes = of_getintprop_default(ledma_dp, + "burst-sizes", 0); /* ledma may be capable of fast bursts, but sbus may not. */ - sbmask = prom_getintdefault(ledma->sdev->bus->prom_node, - "burst-sizes", DMA_BURSTBITS); + sbmask = of_getintprop_default(ledma_dp, "burst-sizes", + DMA_BURSTBITS); lp->burst_sizes &= sbmask; /* Get the cable-selection property */ - memset(prop, 0, sizeof(prop)); - prom_getstring(ledma->sdev->prom_node, "cable-selection", - prop, sizeof(prop)); - if (prop[0] == 0) { - int topnd, nd; + prop = of_get_property(ledma_dp, "cable-selection", NULL); + if (!prop || prop[0] == '\0') { + struct device_node *nd; - printk(KERN_INFO "SunLance: using auto-carrier-detection.\n"); + printk(KERN_INFO "SunLance: using " + "auto-carrier-detection.\n"); - /* Is this found at /options .attributes in all - * Prom versions? XXX - */ - topnd = prom_getchild(prom_root_node); - - nd = prom_searchsiblings(topnd, "options"); + nd = of_find_node_by_path("/options"); if (!nd) goto no_link_test; - if (!prom_node_has_property(nd, "tpe-link-test?")) + prop = of_get_property(nd, "tpe-link-test?", NULL); + if (!prop) goto no_link_test; - memset(prop, 0, sizeof(prop)); - prom_getstring(nd, "tpe-link-test?", prop, - sizeof(prop)); - if (strcmp(prop, "true")) { printk(KERN_NOTICE "SunLance: warning: overriding option " "'tpe-link-test?'\n"); diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index fa70e0b78af7..1b65ae8a1c7c 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -439,8 +439,8 @@ static void qe_rx(struct sunqe *qep) } else { skb_reserve(skb, 2); skb_put(skb, len); - eth_copy_and_sum(skb, (unsigned char *) this_qbuf, - len, 0); + skb_copy_to_linear_data(skb, (unsigned char *) this_qbuf, + len); skb->protocol = eth_type_trans(skb, qep->dev); netif_rx(skb); qep->dev->last_rx = jiffies; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 463d600ed83d..ec41469eee82 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -23,9 +23,9 @@ */ #ifdef TC35815_NAPI -#define DRV_VERSION "1.35-NAPI" +#define DRV_VERSION "1.36-NAPI" #else -#define DRV_VERSION "1.35" +#define DRV_VERSION "1.36" #endif static const char *version = "tc35815.c:v" DRV_VERSION "\n"; #define MODNAME "tc35815" @@ -49,6 +49,7 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n"; #include <linux/pci.h> #include <linux/mii.h> #include <linux/ethtool.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <asm/byteorder.h> @@ -597,13 +598,46 @@ static int tc_mdio_read(struct net_device *dev, int phy_id, int location); static void tc_mdio_write(struct net_device *dev, int phy_id, int location, int val); -static void __devinit tc35815_init_dev_addr (struct net_device *dev) +#ifdef CONFIG_CPU_TX49XX +/* + * Find a platform_device providing a MAC address. The platform code + * should provide a "tc35815-mac" device with a MAC address in its + * platform_data. + */ +static int __devinit tc35815_mac_match(struct device *dev, void *data) +{ + struct platform_device *plat_dev = to_platform_device(dev); + struct pci_dev *pci_dev = data; + unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn; + return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id; +} + +static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev) +{ + struct tc35815_local *lp = dev->priv; + struct device *pd = bus_find_device(&platform_bus_type, NULL, + lp->pci_dev, tc35815_mac_match); + if (pd) { + if (pd->platform_data) + memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN); + put_device(pd); + return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV; + } + return -ENODEV; +} +#else +static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev) +{ + return -ENODEV; +} +#endif + +static int __devinit tc35815_init_dev_addr (struct net_device *dev) { struct tc35815_regs __iomem *tr = (struct tc35815_regs __iomem *)dev->base_addr; int i; - /* dev_addr will be overwritten on NETDEV_REGISTER event */ while (tc_readl(&tr->PROM_Ctl) & PROM_Busy) ; for (i = 0; i < 6; i += 2) { @@ -615,6 +649,9 @@ static void __devinit tc35815_init_dev_addr (struct net_device *dev) dev->dev_addr[i] = data & 0xff; dev->dev_addr[i+1] = data >> 8; } + if (!is_valid_ether_addr(dev->dev_addr)) + return tc35815_read_plat_dev_addr(dev); + return 0; } static int __devinit tc35815_init_one (struct pci_dev *pdev, @@ -724,7 +761,10 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev, tc35815_chip_reset(dev); /* Retrieve the ethernet address. */ - tc35815_init_dev_addr(dev); + if (tc35815_init_dev_addr(dev)) { + dev_warn(&pdev->dev, "not valid ether addr\n"); + random_ether_addr(dev->dev_addr); + } rc = register_netdev (dev); if (rc) @@ -2158,7 +2198,6 @@ static const struct ethtool_ops tc35815_ethtool_ops = { .get_strings = tc35815_get_strings, .get_stats_count = tc35815_get_stats_count, .get_ethtool_stats = tc35815_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 2f3184184ad9..9034a05734ef 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.77" -#define DRV_MODULE_RELDATE "May 31, 2007" +#define DRV_MODULE_VERSION "3.81" +#define DRV_MODULE_RELDATE "September 5, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -721,6 +721,44 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) return ret; } +static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) +{ + u32 phy; + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) + return; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 ephy; + + if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) { + tg3_writephy(tp, MII_TG3_EPHY_TEST, + ephy | MII_TG3_EPHY_SHADOW_EN); + if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) { + if (enable) + phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX; + else + phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX; + tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy); + } + tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy); + } + } else { + phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC | + MII_TG3_AUXCTL_SHDWSEL_MISC; + if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) && + !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) { + if (enable) + phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX; + else + phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX; + phy |= MII_TG3_AUXCTL_MISC_WREN; + tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); + } + } +} + static void tg3_phy_set_wirespeed(struct tg3 *tp) { u32 val; @@ -1045,23 +1083,11 @@ out: } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u32 phy_reg; - /* adjust output voltage */ tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12); - - if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) { - u32 phy_reg2; - - tg3_writephy(tp, MII_TG3_EPHY_TEST, - phy_reg | MII_TG3_EPHY_SHADOW_EN); - /* Enable auto-MDIX */ - if (!tg3_readphy(tp, 0x10, &phy_reg2)) - tg3_writephy(tp, 0x10, phy_reg2 | 0x4000); - tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg); - } } + tg3_phy_toggle_automdix(tp, 1); tg3_phy_set_wirespeed(tp); return 0; } @@ -1162,6 +1188,19 @@ static void tg3_frob_aux_power(struct tg3 *tp) } } +static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed) +{ + if (tp->led_ctrl == LED_CTRL_MODE_PHY_2) + return 1; + else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) { + if (speed != SPEED_10) + return 1; + } else if (speed == SPEED_10) + return 1; + + return 0; +} + static int tg3_setup_phy(struct tg3 *, int); #define RESET_KIND_SHUTDOWN 0 @@ -1320,9 +1359,17 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) else mac_mode = MAC_MODE_PORT_MODE_MII; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 || - !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)) - mac_mode |= MAC_MODE_LINK_POLARITY; + mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == + ASIC_REV_5700) { + u32 speed = (tp->tg3_flags & + TG3_FLAG_WOL_SPEED_100MB) ? + SPEED_100 : SPEED_10; + if (tg3_5700_link_polarity(tp, speed)) + mac_mode |= MAC_MODE_LINK_POLARITY; + else + mac_mode &= ~MAC_MODE_LINK_POLARITY; + } } else { mac_mode = MAC_MODE_PORT_MODE_TBI; } @@ -1990,15 +2037,12 @@ relink: if (tp->link_config.active_duplex == DUPLEX_HALF) tp->mac_mode |= MAC_MODE_HALF_DUPLEX; - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { - if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) || - (current_link_up == 1 && - tp->link_config.active_speed == SPEED_10)) - tp->mac_mode |= MAC_MODE_LINK_POLARITY; - } else { - if (current_link_up == 1) + if (current_link_up == 1 && + tg3_5700_link_polarity(tp, tp->link_config.active_speed)) tp->mac_mode |= MAC_MODE_LINK_POLARITY; + else + tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; } /* ??? Without this setting Netgear GA302T PHY does not @@ -2639,6 +2683,9 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); udelay(40); + + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); } out: @@ -2698,10 +2745,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) else current_link_up = tg3_setup_fiber_by_hand(tp, mac_status); - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); - tp->hw_status->status = (SD_STATUS_UPDATED | (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); @@ -3512,9 +3555,9 @@ static inline int tg3_irq_sync(struct tg3 *tp) */ static inline void tg3_full_lock(struct tg3 *tp, int irq_sync) { + spin_lock_bh(&tp->lock); if (irq_sync) tg3_irq_quiesce(tp); - spin_lock_bh(&tp->lock); } static inline void tg3_full_unlock(struct tg3 *tp) @@ -4804,6 +4847,59 @@ static int tg3_poll_fw(struct tg3 *tp) return 0; } +/* Save PCI command register before chip reset */ +static void tg3_save_pci_state(struct tg3 *tp) +{ + u32 val; + + pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val); + tp->pci_cmd = val; +} + +/* Restore PCI state after chip reset */ +static void tg3_restore_pci_state(struct tg3 *tp) +{ + u32 val; + + /* Re-enable indirect register accesses. */ + pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, + tp->misc_host_ctrl); + + /* Set MAX PCI retry to zero. */ + val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); + if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && + (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) + val |= PCISTATE_RETRY_SAME_DMA; + pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); + + pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd); + + /* Make sure PCI-X relaxed ordering bit is clear. */ + pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); + val &= ~PCIX_CAPS_RELAXED_ORDERING; + pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val); + + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { + u32 val; + + /* Chip reset on 5780 will reset MSI enable bit, + * so need to restore it. + */ + if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + u16 ctrl; + + pci_read_config_word(tp->pdev, + tp->msi_cap + PCI_MSI_FLAGS, + &ctrl); + pci_write_config_word(tp->pdev, + tp->msi_cap + PCI_MSI_FLAGS, + ctrl | PCI_MSI_FLAGS_ENABLE); + val = tr32(MSGINT_MODE); + tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE); + } + } +} + static void tg3_stop_fw(struct tg3 *); /* tp->lock is held. */ @@ -4820,6 +4916,12 @@ static int tg3_chip_reset(struct tg3 *tp) */ tp->nvram_lock_cnt = 0; + /* GRC_MISC_CFG core clock reset will clear the memory + * enable bit in PCI register 4 and the MSI enable bit + * on some chips, so we save relevant registers here. + */ + tg3_save_pci_state(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) @@ -4918,50 +5020,14 @@ static int tg3_chip_reset(struct tg3 *tp) pci_write_config_dword(tp->pdev, 0xd8, 0xf5000); } - /* Re-enable indirect register accesses. */ - pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, - tp->misc_host_ctrl); - - /* Set MAX PCI retry to zero. */ - val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) - val |= PCISTATE_RETRY_SAME_DMA; - pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); - - pci_restore_state(tp->pdev); + tg3_restore_pci_state(tp); tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING; - /* Make sure PCI-X relaxed ordering bit is clear. */ - pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); - val &= ~PCIX_CAPS_RELAXED_ORDERING; - pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val); - - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { - u32 val; - - /* Chip reset on 5780 will reset MSI enable bit, - * so need to restore it. - */ - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { - u16 ctrl; - - pci_read_config_word(tp->pdev, - tp->msi_cap + PCI_MSI_FLAGS, - &ctrl); - pci_write_config_word(tp->pdev, - tp->msi_cap + PCI_MSI_FLAGS, - ctrl | PCI_MSI_FLAGS_ENABLE); - val = tr32(MSGINT_MODE); - tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE); - } - + val = 0; + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) val = tr32(MEMARB_MODE); - tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); - - } else - tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { tg3_stop_fw(tp); @@ -6444,6 +6510,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) + tp->mac_mode |= MAC_MODE_LINK_POLARITY; tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); udelay(40); @@ -7057,6 +7127,10 @@ static int tg3_open(struct net_device *dev) } else if (pci_enable_msi(tp->pdev) == 0) { u32 msi_mode; + /* Hardware bug - MSI won't work if INTX disabled. */ + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + pci_intx(tp->pdev, 1); + msi_mode = tr32(MSGINT_MODE); tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); tp->tg3_flags2 |= TG3_FLG2_USING_MSI; @@ -8271,7 +8345,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) 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); + ethtool_op_set_tx_ipv6_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8805,7 +8879,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) return 0; mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY; + MAC_MODE_PORT_INT_LPBACK; + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + mac_mode |= MAC_MODE_LINK_POLARITY; if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) mac_mode |= MAC_MODE_PORT_MODE_MII; else @@ -8824,19 +8900,18 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) phytest | MII_TG3_EPHY_SHADOW_EN); if (!tg3_readphy(tp, 0x1b, &phy)) tg3_writephy(tp, 0x1b, phy & ~0x20); - if (!tg3_readphy(tp, 0x10, &phy)) - tg3_writephy(tp, 0x10, phy & ~0x4000); tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest); } val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100; } else val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000; + tg3_phy_toggle_automdix(tp, 0); + tg3_writephy(tp, MII_BMCR, val); udelay(40); - mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_LINK_POLARITY; + mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800); mac_mode |= MAC_MODE_PORT_MODE_MII; @@ -8849,8 +8924,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) udelay(10); tw32_f(MAC_RX_MODE, tp->rx_mode); } - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { - mac_mode &= ~MAC_MODE_LINK_POLARITY; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) + mac_mode &= ~MAC_MODE_LINK_POLARITY; + else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) + mac_mode |= MAC_MODE_LINK_POLARITY; tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_LNK3_LED_MODE); } @@ -9116,10 +9194,10 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) /* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */ __tg3_set_rx_mode(dev); - tg3_full_unlock(tp); - if (netif_running(dev)) tg3_netif_start(tp); + + tg3_full_unlock(tp); } #endif @@ -9220,7 +9298,6 @@ static const struct ethtool_ops tg3_ethtool_ops = { .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, - .get_perm_addr = ethtool_op_get_perm_addr, }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) @@ -9410,11 +9487,13 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) case FLASH_5755VENDOR_ATMEL_FLASH_1: case FLASH_5755VENDOR_ATMEL_FLASH_2: case FLASH_5755VENDOR_ATMEL_FLASH_3: + case FLASH_5755VENDOR_ATMEL_FLASH_5: tp->nvram_jedecnum = JEDEC_ATMEL; tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; tp->tg3_flags2 |= TG3_FLG2_FLASH; tp->nvram_pagesize = 264; - if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1) + if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 || + nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5) tp->nvram_size = (protect ? 0x3e200 : 0x80000); else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2) tp->nvram_size = (protect ? 0x1f200 : 0x40000); @@ -10498,11 +10577,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) continue; } if (pci_id->rev != PCI_ANY_ID) { - u8 rev; - - pci_read_config_byte(bridge, PCI_REVISION_ID, - &rev); - if (rev > pci_id->rev) + if (bridge->revision > pci_id->rev) continue; } if (bridge->subordinate && @@ -11929,7 +12004,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, */ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - pci_save_state(tp->pdev); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); } @@ -11944,12 +12018,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; 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; - dev->features |= NETIF_F_SG; + dev->features |= NETIF_F_IPV6_CSUM; + tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; } else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; @@ -11959,12 +12032,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_coal(tp); - /* Now that we have fully setup the chip, save away a snapshot - * of the PCI config space. We need to restore this after - * GRC_MISC_CFG core clock resets and some resume events. - */ - pci_save_state(tp->pdev); - pci_set_drvdata(pdev, dev); err = register_netdev(dev); @@ -12048,6 +12115,12 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) struct tg3 *tp = netdev_priv(dev); int err; + /* PCI register 4 needs to be saved whether netif_running() or not. + * MSI address and data need to be saved if using MSI and + * netif_running(). + */ + pci_save_state(pdev); + if (!netif_running(dev)) return 0; @@ -12067,9 +12140,6 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; tg3_full_unlock(tp); - /* Save MSI address and data for resume. */ - pci_save_state(pdev); - err = tg3_set_power_state(tp, pci_choose_state(pdev, state)); if (err) { tg3_full_lock(tp, 0); @@ -12097,15 +12167,20 @@ static int tg3_resume(struct pci_dev *pdev) struct tg3 *tp = netdev_priv(dev); int err; + pci_restore_state(tp->pdev); + if (!netif_running(dev)) return 0; - pci_restore_state(tp->pdev); - err = tg3_set_power_state(tp, PCI_D0); if (err) return err; + /* Hardware bug - MSI won't work if INTX disabled. */ + if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) && + (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) + pci_intx(tp->pdev, 1); + netif_device_attach(dev); tg3_full_lock(tp, 0); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index bd9f4f428e5b..5c21f49026c9 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1467,6 +1467,7 @@ #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_FLASH_5 0x02000003 #define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003 #define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002 #define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003 @@ -1642,6 +1643,11 @@ #define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ +#define MII_TG3_AUXCTL_MISC_WREN 0x8000 +#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200 +#define MII_TG3_AUXCTL_MISC_RDSEL_MISC 0x7000 +#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 + #define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */ #define MII_TG3_AUX_STAT_LPASS 0x0004 #define MII_TG3_AUX_STAT_SPDMASK 0x0700 @@ -1667,6 +1673,9 @@ #define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */ #define MII_TG3_EPHY_SHADOW_EN 0x80 +#define MII_TG3_EPHYTST_MISCCTRL 0x10 /* 5906 EPHY misc ctrl shadow register */ +#define MII_TG3_EPHYTST_MISCCTRL_MDIX 0x4000 + #define MII_TG3_TEST1 0x1e #define MII_TG3_TEST1_TRIM_EN 0x0010 #define MII_TG3_TEST1_CRC_EN 0x8000 @@ -2336,6 +2345,7 @@ struct tg3 { #define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */ u32 led_ctrl; + u32 pci_cmd; char board_part_number[24]; char fw_ver[16]; diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 106dc1ef0acb..74eb12107e68 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -533,7 +533,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, struct net_device *dev; TLanPrivateInfo *priv; - u8 pci_rev; u16 device_id; int reg, rc = -ENODEV; @@ -577,8 +576,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, goto err_out_free_dev; } - pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev); - for ( reg= 0; reg <= 5; reg ++ ) { if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) { pci_io_base = pci_resource_start(pdev, reg); @@ -595,7 +592,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, dev->base_addr = pci_io_base; dev->irq = pdev->irq; - priv->adapterRev = pci_rev; + priv->adapterRev = pdev->revision; pci_set_master(pdev); pci_set_drvdata(pdev, dev); diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index e22a3f5333ef..9f1b6ab9c228 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -363,7 +363,7 @@ static int __devinit xl_probe(struct pci_dev *pdev, } -static int __init xl_init(struct net_device *dev) +static int __devinit xl_init(struct net_device *dev) { struct xl_private *xl_priv = (struct xl_private *)dev->priv ; diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 58d7e5d452fa..f83bb5cb0d3d 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -3692,7 +3692,6 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size, __u16 rcode, correlator; int err = 0; __u8 xframe = 1; - __u16 tx_fstatus; rmf->vl = SWAP_BYTES(rmf->vl); if(rx_status & FCB_RX_STATUS_DA_MATCHED) @@ -3783,7 +3782,9 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size, } break; - case TX_FORWARD: + case TX_FORWARD: { + __u16 uninitialized_var(tx_fstatus); + if((rcode = smctr_rcv_tx_forward(dev, rmf)) != POSITIVE_ACK) { @@ -3811,6 +3812,7 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size, } } break; + } /* Received MAC Frames Processed by CRS/REM/RPS. */ case RSP: diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index 8c9634a98c11..1c537d5a3062 100644 --- a/drivers/net/tulip/Kconfig +++ b/drivers/net/tulip/Kconfig @@ -2,17 +2,17 @@ # Tulip family network device configuration # -menu "Tulip family network device support" - depends on NET_ETHERNET && (PCI || EISA || CARDBUS) - -config NET_TULIP +menuconfig NET_TULIP bool "\"Tulip\" family network device support" + depends on PCI || EISA || CARDBUS help This selects the "Tulip" family of EISA/PCI network cards. +if NET_TULIP + config DE2104X tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)" - depends on NET_TULIP && PCI && EXPERIMENTAL + depends on PCI && EXPERIMENTAL select CRC32 ---help--- This driver is developed for the SMC EtherPower series Ethernet @@ -30,7 +30,7 @@ config DE2104X config TULIP tristate "DECchip Tulip (dc2114x) PCI support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 ---help--- This driver is developed for the SMC EtherPower series Ethernet @@ -95,7 +95,7 @@ config TULIP_NAPI_HW_MITIGATION config DE4X5 tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA" - depends on NET_TULIP && (PCI || EISA) + depends on PCI || EISA select CRC32 ---help--- This is support for the DIGITAL series of PCI/EISA Ethernet cards. @@ -112,7 +112,7 @@ config DE4X5 config WINBOND_840 tristate "Winbond W89c840 Ethernet support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 select MII help @@ -123,7 +123,7 @@ config WINBOND_840 config DM9102 tristate "Davicom DM910x/DM980x support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 ---help--- This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from @@ -137,7 +137,7 @@ config DM9102 config ULI526X tristate "ULi M526x controller support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 ---help--- This driver is for ULi M5261/M5263 10/100M Ethernet Controller @@ -149,7 +149,7 @@ config ULI526X config PCMCIA_XIRCOM tristate "Xircom CardBus support (new driver)" - depends on NET_TULIP && CARDBUS + depends on CARDBUS ---help--- This driver is for the Digital "Tulip" Ethernet CardBus adapters. It should work with most DEC 21*4*-based chips/ethercards, as well @@ -162,7 +162,7 @@ config PCMCIA_XIRCOM config PCMCIA_XIRTULIP tristate "Xircom Tulip-like CardBus support (old driver)" - depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP + depends on CARDBUS && BROKEN_ON_SMP select CRC32 ---help--- This driver is for the Digital "Tulip" Ethernet CardBus adapters. @@ -174,5 +174,4 @@ config PCMCIA_XIRTULIP <file:Documentation/networking/net-modules.txt>. The module will be called xircom_tulip_cb. If unsure, say N. -endmenu - +endif # NET_TULIP diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 861729806dc1..d380e0b3f05a 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -785,7 +785,6 @@ static void __de_set_rx_mode (struct net_device *dev) de->tx_head = NEXT_TX(entry); - BUG_ON(TX_BUFFS_AVAIL(de) < 0); if (TX_BUFFS_AVAIL(de) == 0) netif_stop_queue(dev); diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 62143f92c231..09902891a6e6 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -597,7 +597,7 @@ static char *args; #endif struct parameters { - int fdx; + bool fdx; int autosense; }; @@ -809,10 +809,10 @@ struct de4x5_private { s32 irq_en; /* Summary interrupt bits */ int media; /* Media (eg TP), mode (eg 100B)*/ int c_media; /* Remember the last media conn */ - int fdx; /* media full duplex flag */ + bool fdx; /* media full duplex flag */ int linkOK; /* Link is OK */ int autosense; /* Allow/disallow autosensing */ - int tx_enable; /* Enable descriptor polling */ + bool tx_enable; /* Enable descriptor polling */ int setup_f; /* Setup frame filtering type */ int local_state; /* State within a 'media' state */ struct mii_phy phy[DE4X5_MAX_PHY]; /* List of attached PHY devices */ @@ -838,8 +838,8 @@ struct de4x5_private { struct de4x5_srom srom; /* A copy of the SROM */ int cfrv; /* Card CFRV copy */ int rx_ovf; /* Check for 'RX overflow' tag */ - int useSROM; /* For non-DEC card use SROM */ - int useMII; /* Infoblock using the MII */ + bool useSROM; /* For non-DEC card use SROM */ + bool useMII; /* Infoblock using the MII */ int asBitValid; /* Autosense bits in GEP? */ int asPolarity; /* 0 => asserted high */ int asBit; /* Autosense bit number in GEP */ @@ -928,7 +928,7 @@ static int dc21040_state(struct net_device *dev, int csr13, int csr14, int c static int test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec); static int test_for_100Mb(struct net_device *dev, int msec); static int wait_for_link(struct net_device *dev); -static int test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec); +static int test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec); static int is_spd_100(struct net_device *dev); static int is_100_up(struct net_device *dev); static int is_10_up(struct net_device *dev); @@ -1109,7 +1109,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) /* ** Now find out what kind of DC21040/DC21041/DC21140 board we have. */ - lp->useSROM = FALSE; + lp->useSROM = false; if (lp->bus == PCI) { PCI_signature(name, lp); } else { @@ -1137,7 +1137,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) lp->cache.gepc = GEP_INIT; lp->asBit = GEP_SLNK; lp->asPolarity = GEP_SLNK; - lp->asBitValid = TRUE; + lp->asBitValid = ~0; lp->timeout = -1; lp->gendev = gendev; spin_lock_init(&lp->lock); @@ -1463,7 +1463,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) u_long flags = 0; netif_stop_queue(dev); - if (lp->tx_enable == NO) { /* Cannot send for now */ + if (!lp->tx_enable) { /* Cannot send for now */ return -1; } @@ -2134,7 +2134,7 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) u_short vendor, status; u_int irq = 0, device; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ - int i, j, cfrv; + int i, j; struct de4x5_private *lp = netdev_priv(dev); struct list_head *walk; @@ -2150,7 +2150,6 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) /* Get the chip configuration revision register */ pb = this_dev->bus->number; - pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv); /* Set the device number information */ lp->device = PCI_SLOT(this_dev->devfn); @@ -2158,7 +2157,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) /* Set the chipset information */ if (is_DC2114x) { - device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); + device = ((this_dev->revision & CFRV_RN) < DC2114x_BRK + ? DC21142 : DC21143); } lp->chipset = device; @@ -2254,7 +2254,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev, } /* Get the chip configuration revision register */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &lp->cfrv); + lp->cfrv = pdev->revision; /* Set the device number information */ lp->device = dev_num; @@ -2424,7 +2424,7 @@ dc21040_autoconf(struct net_device *dev) switch (lp->media) { case INIT: DISABLE_IRQs; - lp->tx_enable = NO; + lp->tx_enable = false; lp->timeout = -1; de4x5_save_skbs(dev); if ((lp->autosense == AUTO) || (lp->autosense == TP)) { @@ -2477,7 +2477,7 @@ dc21040_autoconf(struct net_device *dev) lp->c_media = lp->media; } lp->media = INIT; - lp->tx_enable = NO; + lp->tx_enable = false; break; } @@ -2578,7 +2578,7 @@ dc21041_autoconf(struct net_device *dev) switch (lp->media) { case INIT: DISABLE_IRQs; - lp->tx_enable = NO; + lp->tx_enable = false; lp->timeout = -1; de4x5_save_skbs(dev); /* Save non transmitted skb's */ if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) { @@ -2757,7 +2757,7 @@ dc21041_autoconf(struct net_device *dev) lp->c_media = lp->media; } lp->media = INIT; - lp->tx_enable = NO; + lp->tx_enable = false; break; } @@ -2781,7 +2781,7 @@ dc21140m_autoconf(struct net_device *dev) case INIT: if (lp->timeout < 0) { DISABLE_IRQs; - lp->tx_enable = FALSE; + lp->tx_enable = false; lp->linkOK = 0; de4x5_save_skbs(dev); /* Save non transmitted skb's */ } @@ -2830,7 +2830,7 @@ dc21140m_autoconf(struct net_device *dev) if (lp->timeout < 0) { mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII); } - cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500); + cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500); if (cr < 0) { next_tick = cr & ~TIMER_CB; } else { @@ -2845,7 +2845,7 @@ dc21140m_autoconf(struct net_device *dev) break; case 1: - if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) { + if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) { next_tick = sr & ~TIMER_CB; } else { lp->media = SPD_DET; @@ -2857,10 +2857,10 @@ dc21140m_autoconf(struct net_device *dev) if (!(anlpa & MII_ANLPA_RF) && (cap = anlpa & MII_ANLPA_TAF & ana)) { if (cap & MII_ANA_100M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0; lp->media = _100Mb; } else if (cap & MII_ANA_10M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0; lp->media = _10Mb; } @@ -2932,7 +2932,7 @@ dc21140m_autoconf(struct net_device *dev) lp->c_media = lp->media; } lp->media = INIT; - lp->tx_enable = FALSE; + lp->tx_enable = false; break; } @@ -2965,7 +2965,7 @@ dc2114x_autoconf(struct net_device *dev) case INIT: if (lp->timeout < 0) { DISABLE_IRQs; - lp->tx_enable = FALSE; + lp->tx_enable = false; lp->linkOK = 0; lp->timeout = -1; de4x5_save_skbs(dev); /* Save non transmitted skb's */ @@ -3013,7 +3013,7 @@ dc2114x_autoconf(struct net_device *dev) if (lp->timeout < 0) { mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII); } - cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500); + cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500); if (cr < 0) { next_tick = cr & ~TIMER_CB; } else { @@ -3028,7 +3028,8 @@ dc2114x_autoconf(struct net_device *dev) break; case 1: - if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) { + sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000); + if (sr < 0) { next_tick = sr & ~TIMER_CB; } else { lp->media = SPD_DET; @@ -3040,10 +3041,10 @@ dc2114x_autoconf(struct net_device *dev) if (!(anlpa & MII_ANLPA_RF) && (cap = anlpa & MII_ANLPA_TAF & ana)) { if (cap & MII_ANA_100M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0; lp->media = _100Mb; } else if (cap & MII_ANA_10M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0; lp->media = _10Mb; } } @@ -3222,14 +3223,14 @@ srom_map_media(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); - lp->fdx = 0; + lp->fdx = false; if (lp->infoblock_media == lp->media) return 0; switch(lp->infoblock_media) { case SROM_10BASETF: if (!lp->params.fdx) return -1; - lp->fdx = TRUE; + lp->fdx = true; case SROM_10BASET: if (lp->params.fdx && !lp->fdx) return -1; if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) { @@ -3249,7 +3250,7 @@ srom_map_media(struct net_device *dev) case SROM_100BASETF: if (!lp->params.fdx) return -1; - lp->fdx = TRUE; + lp->fdx = true; case SROM_100BASET: if (lp->params.fdx && !lp->fdx) return -1; lp->media = _100Mb; @@ -3261,7 +3262,7 @@ srom_map_media(struct net_device *dev) case SROM_100BASEFF: if (!lp->params.fdx) return -1; - lp->fdx = TRUE; + lp->fdx = true; case SROM_100BASEF: if (lp->params.fdx && !lp->fdx) return -1; lp->media = _100Mb; @@ -3297,7 +3298,7 @@ de4x5_init_connection(struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); de4x5_rst_desc_ring(dev); de4x5_setup_intr(dev); - lp->tx_enable = YES; + lp->tx_enable = true; spin_unlock_irqrestore(&lp->lock, flags); outl(POLL_DEMAND, DE4X5_TPD); @@ -3336,7 +3337,7 @@ de4x5_reset_phy(struct net_device *dev) } } if (lp->useMII) { - next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500); + next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500); } } else if (lp->chipset == DC21140) { PHY_HARD_RESET; @@ -3466,7 +3467,7 @@ wait_for_link(struct net_device *dev) ** */ static int -test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec) +test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec) { struct de4x5_private *lp = netdev_priv(dev); int test; @@ -3476,9 +3477,8 @@ test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec) lp->timeout = msec/100; } - if (pol) pol = ~0; reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask; - test = (reg ^ pol) & mask; + test = (reg ^ (pol ? ~0 : 0)) & mask; if (test && --lp->timeout) { reg = 100 | TIMER_CB; @@ -3992,10 +3992,10 @@ PCI_signature(char *name, struct de4x5_private *lp) ))))))); } if (lp->chipset != DC21041) { - lp->useSROM = TRUE; /* card is not recognisably DEC */ + lp->useSROM = true; /* card is not recognisably DEC */ } } else if ((lp->chipset & ~0x00ff) == DC2114x) { - lp->useSROM = TRUE; + lp->useSROM = true; } return status; @@ -4216,7 +4216,7 @@ srom_repair(struct net_device *dev, int card) memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom)); memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN); memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100); - lp->useSROM = TRUE; + lp->useSROM = true; break; } @@ -4392,7 +4392,7 @@ srom_infoleaf_info(struct net_device *dev) if (lp->chipset == infoleaf_array[i].chipset) break; } if (i == INFOLEAF_SIZE) { - lp->useSROM = FALSE; + lp->useSROM = false; printk("%s: Cannot find correct chipset for SROM decoding!\n", dev->name); return -ENXIO; @@ -4409,7 +4409,7 @@ srom_infoleaf_info(struct net_device *dev) if (lp->device == *p) break; } if (i == 0) { - lp->useSROM = FALSE; + lp->useSROM = false; printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n", dev->name, lp->device); return -ENXIO; @@ -4542,7 +4542,7 @@ dc21140_infoleaf(struct net_device *dev) } lp->media = INIT; lp->tcount = 0; - lp->tx_enable = FALSE; + lp->tx_enable = false; } return next_tick & ~TIMER_CB; @@ -4577,7 +4577,7 @@ dc21142_infoleaf(struct net_device *dev) } lp->media = INIT; lp->tcount = 0; - lp->tx_enable = FALSE; + lp->tx_enable = false; } return next_tick & ~TIMER_CB; @@ -4611,7 +4611,7 @@ dc21143_infoleaf(struct net_device *dev) } lp->media = INIT; lp->tcount = 0; - lp->tx_enable = FALSE; + lp->tx_enable = false; } return next_tick & ~TIMER_CB; @@ -4650,7 +4650,7 @@ compact_infoblock(struct net_device *dev, u_char count, u_char *p) lp->asBit = 1 << ((csr6 >> 1) & 0x07); lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit; lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18); - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -4691,7 +4691,7 @@ type0_infoblock(struct net_device *dev, u_char count, u_char *p) lp->asBit = 1 << ((csr6 >> 1) & 0x07); lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit; lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18); - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -4731,7 +4731,7 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p) lp->ibn = 1; lp->active = *p; lp->infoblock_csr6 = OMR_MII_100; - lp->useMII = TRUE; + lp->useMII = true; lp->infoblock_media = ANS; de4x5_switch_mac_port(dev); @@ -4773,7 +4773,7 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p) lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2; lp->cache.gep = ((s32)(TWIDDLE(p)) << 16); lp->infoblock_csr6 = OMR_SIA; - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -4814,7 +4814,7 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p) lp->active = *p; if (MOTO_SROM_BUG) lp->active = 0; lp->infoblock_csr6 = OMR_MII_100; - lp->useMII = TRUE; + lp->useMII = true; lp->infoblock_media = ANS; de4x5_switch_mac_port(dev); @@ -4856,7 +4856,7 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p) lp->asBit = 1 << ((csr6 >> 1) & 0x07); lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit; lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18); - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -5077,7 +5077,7 @@ mii_get_phy(struct net_device *dev) int id; lp->active = 0; - lp->useMII = TRUE; + lp->useMII = true; /* Search the MII address space for possible PHY devices */ for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) { @@ -5127,7 +5127,7 @@ mii_get_phy(struct net_device *dev) de4x5_dbg_mii(dev, k); } } - if (!lp->mii_cnt) lp->useMII = FALSE; + if (!lp->mii_cnt) lp->useMII = false; return lp->mii_cnt; } diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h index 57226e5eb8a6..12af0cc037fb 100644 --- a/drivers/net/tulip/de4x5.h +++ b/drivers/net/tulip/de4x5.h @@ -893,15 +893,6 @@ #define PHYS_ADDR_ONLY 1 /* Update the physical address only */ /* -** Booleans -*/ -#define NO 0 -#define FALSE 0 - -#define YES ~0 -#define TRUE ~0 - -/* ** Adapter state */ #define INITIALISED 0 /* After h/w initialised and mem alloc'd */ diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 4ed67ff0e81e..dab74feb44bc 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -181,11 +181,12 @@ udelay(5); #define __CHK_IO_SIZE(pci_id, dev_rev) \ - (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \ + (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x30) ) ? \ DM9102A_IO_SIZE: DM9102_IO_SIZE) -#define CHK_IO_SIZE(pci_dev, dev_rev) \ - (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)) +#define CHK_IO_SIZE(pci_dev) \ + (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, \ + (pci_dev)->revision)) /* Sten Check */ #define DEVICE net_device @@ -205,7 +206,7 @@ struct rx_desc { struct dmfe_board_info { u32 chip_id; /* Chip vendor/Device ID */ - u32 chip_revision; /* Chip revision */ + u8 chip_revision; /* Chip revision */ struct DEVICE *next_dev; /* next device */ struct pci_dev *pdev; /* PCI device */ spinlock_t lock; @@ -359,7 +360,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, { struct dmfe_board_info *db; /* board information structure */ struct net_device *dev; - u32 dev_rev, pci_pmr; + u32 pci_pmr; int i, err; DMFE_DBUG(0, "dmfe_init_one()", 0); @@ -392,10 +393,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, goto err_out_disable; } - /* Read Chip revision */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev); - - if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) { + if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev)) ) { printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n"); err = -ENODEV; goto err_out_disable; @@ -433,7 +431,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, db->chip_id = ent->driver_data; db->ioaddr = pci_resource_start(pdev, 0); - db->chip_revision = dev_rev; + db->chip_revision = pdev->revision; db->wol_mode = 0; db->pdev = pdev; @@ -455,7 +453,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, pci_read_config_dword(pdev, 0x50, &pci_pmr); pci_pmr &= 0x70000; - if ( (pci_pmr == 0x10000) && (dev_rev == 0x02000031) ) + if ( (pci_pmr == 0x10000) && (db->chip_revision == 0x31) ) db->chip_type = 1; /* DM9102A E3 */ else db->chip_type = 0; @@ -553,7 +551,7 @@ static int dmfe_open(struct DEVICE *dev) /* CR6 operation mode decision */ if ( !chkmode || (db->chip_id == PCI_DM9132_ID) || - (db->chip_revision >= 0x02000030) ) { + (db->chip_revision >= 0x30) ) { db->cr6_data |= DMFE_TXTH_256; db->cr0_data = CR0_DEFAULT; db->dm910x_chk_mode=4; /* Enter the normal mode */ @@ -1199,9 +1197,9 @@ static void dmfe_timer(unsigned long data) tmp_cr12 = inb(db->ioaddr + DCR12); /* DM9102/DM9102A */ if ( ((db->chip_id == PCI_DM9102_ID) && - (db->chip_revision == 0x02000030)) || + (db->chip_revision == 0x30)) || ((db->chip_id == PCI_DM9132_ID) && - (db->chip_revision == 0x02000010)) ) { + (db->chip_revision == 0x10)) ) { /* DM9102A Chip */ if (tmp_cr12 & 2) link_ok = 0; diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index ea896777bcaf..53efd6694e75 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -197,8 +197,8 @@ int tulip_poll(struct net_device *dev, int *budget) tp->rx_buffers[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) - eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data, - pkt_len, 0); + skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data, + pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), @@ -420,8 +420,8 @@ static int tulip_rx(struct net_device *dev) tp->rx_buffers[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) - eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data, - pkt_len, 0); + skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data, + pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 041af63f2811..eca984f89bbf 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1155,7 +1155,7 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev, /* set or disable MWI in the standard PCI command bit. * Check for the case where mwi is desired but not available */ - if (csr0 & MWI) pci_set_mwi(pdev); + if (csr0 & MWI) pci_try_set_mwi(pdev); else pci_clear_mwi(pdev); /* read result from hardware (in case bit refused to enable) */ @@ -1238,7 +1238,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, }; static int last_irq; static int multiport_cnt; /* For four-port boards w/one EEPROM */ - u8 chip_rev; int i, irq; unsigned short sum; unsigned char *ee_data; @@ -1274,10 +1273,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (pdev->vendor == 0x1282 && pdev->device == 0x9100) { - u32 dev_rev; /* Read Chip revision */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev); - if(dev_rev < 0x02000030) + if (pdev->revision < 0x30) { printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n"); return -ENODEV; @@ -1360,8 +1357,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (!ioaddr) goto err_out_free_res; - pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev); - /* * initialize private data structure 'tp' * it is zeroed and aligned in alloc_etherdev @@ -1382,7 +1377,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->flags = tulip_tbl[chip_idx].flags; tp->pdev = pdev; tp->base_addr = ioaddr; - tp->revision = chip_rev; + tp->revision = pdev->revision; tp->csr0 = csr0; spin_lock_init(&tp->lock); spin_lock_init(&tp->mii_lock); @@ -1399,7 +1394,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tulip_mwi_config (pdev, dev); #else /* MWI is broken for DC21143 rev 65... */ - if (chip_idx == DC21143 && chip_rev == 65) + if (chip_idx == DC21143 && pdev->revision == 65) tp->csr0 &= ~MWI; #endif @@ -1476,14 +1471,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, sa_offset = 2; /* Grrr, damn Matrox boards. */ multiport_cnt = 4; } -#ifdef CONFIG_DDB5477 - if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) { - /* DDB5477 MAC address in first EEPROM locations. */ - sa_offset = 0; - /* No media table either */ - tp->flags &= ~HAS_MEDIA_TABLE; - } -#endif #ifdef CONFIG_MIPS_COBALT if ((pdev->bus->number == 0) && ((PCI_SLOT(pdev->devfn) == 7) || @@ -1640,7 +1627,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, #else "Port" #endif - " %#llx,", dev->name, chip_name, chip_rev, + " %#llx,", dev->name, chip_name, pdev->revision, (unsigned long long) pci_resource_start(pdev, TULIP_BAR)); pci_set_drvdata(pdev, dev); diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 38f3b99716b8..5824f6a35495 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1232,7 +1232,7 @@ static int netdev_rx(struct net_device *dev) pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 2470b1ee33c0..16a54e6b8d4f 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -205,7 +205,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ { struct net_device *dev = NULL; struct xircom_private *private; - unsigned char chip_rev; unsigned long flags; unsigned short tmp16; enter("xircom_probe"); @@ -224,8 +223,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ pci_read_config_word (pdev,PCI_STATUS, &tmp16); pci_write_config_word (pdev, PCI_STATUS,tmp16); - pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev); - if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) { printk(KERN_ERR "xircom_probe: failed to allocate io-region\n"); return -ENODEV; @@ -286,7 +283,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ goto reg_fail; } - printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq); + printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, pdev->revision, pdev->irq); /* start the transmitter to get a heartbeat */ /* TODO: send 2 dummy packets here */ transceiver_voodoo(private); @@ -1208,7 +1205,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri goto out; } skb_reserve(skb, 2); - eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0); + skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c index f64172927377..fc439f333350 100644 --- a/drivers/net/tulip/xircom_tulip_cb.c +++ b/drivers/net/tulip/xircom_tulip_cb.c @@ -524,7 +524,6 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi int chip_idx = id->driver_data; long ioaddr; int i; - u8 chip_rev; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -620,9 +619,8 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi if (register_netdev(dev)) goto err_out_cleardev; - pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev); printk(KERN_INFO "%s: %s rev %d at %#3lx,", - dev->name, xircom_tbl[chip_idx].chip_name, chip_rev, ioaddr); + dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr); for (i = 0; i < 6; i++) printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]); printk(", IRQ %d.\n", dev->irq); @@ -1242,8 +1240,8 @@ xircom_rx(struct net_device *dev) && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ #if ! defined(__alpha__) - eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1), - pkt_len, 0); + skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1), + pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a2c6caaaae93..62b2b3005019 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -432,6 +432,7 @@ static void tun_setup(struct net_device *dev) init_waitqueue_head(&tun->read_wait); tun->owner = -1; + tun->group = -1; SET_MODULE_OWNER(dev); dev->open = tun_net_open; @@ -467,8 +468,11 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) return -EBUSY; /* Check permissions */ - if (tun->owner != -1 && - current->euid != tun->owner && !capable(CAP_NET_ADMIN)) + if (((tun->owner != -1 && + current->euid != tun->owner) || + (tun->group != -1 && + current->egid != tun->group)) && + !capable(CAP_NET_ADMIN)) return -EPERM; } else if (__dev_get_by_name(ifr->ifr_name)) @@ -610,6 +614,13 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner); break; + case TUNSETGROUP: + /* Set group of the device */ + tun->group= (gid_t) arg; + + DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group); + break; + case TUNSETLINK: /* Only allow setting the type when the interface is down */ if (tun->dev->flags & IFF_UP) { diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 15b2fb8aa492..03587205546e 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1703,7 +1703,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready, pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(new_skb, skb->data, pkt_len, 0); + skb_copy_to_linear_data(new_skb, skb->data, pkt_len); pci_dma_sync_single_for_device(tp->pdev, dma_addr, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); @@ -2267,12 +2267,6 @@ need_resume: typhoon_resume(pdev); return -EBUSY; } - -static int -typhoon_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable) -{ - return pci_enable_wake(pdev, state, enable); -} #endif static int __devinit @@ -2636,7 +2630,6 @@ static struct pci_driver typhoon_driver = { #ifdef CONFIG_PM .suspend = typhoon_suspend, .resume = typhoon_resume, - .enable_wake = typhoon_enable_wake, #endif }; diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 953ecde43013..13bf3e98ed94 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -43,10 +43,6 @@ #undef DEBUG -#define DRV_DESC "QE UCC Gigabit Ethernet Controller" -#define DRV_NAME "ucc_geth" -#define DRV_VERSION "1.1" - #define ugeth_printk(level, format, arg...) \ printk(level format "\n", ## arg) @@ -64,9 +60,19 @@ #else #define ugeth_vdbg(fmt, args...) do { } while (0) #endif /* UGETH_VERBOSE_DEBUG */ +#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 +void uec_set_ethtool_ops(struct net_device *netdev); + static DEFINE_SPINLOCK(ugeth_lock); +static struct { + u32 msg_enable; +} debug = { -1 }; + +module_param_named(debug, debug.msg_enable, int, 0); +MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)"); + static struct ucc_geth_info ugeth_primary_info = { .uf_info = { .bd_mem_part = MEM_PART_SYSTEM, @@ -104,6 +110,7 @@ static struct ucc_geth_info ugeth_primary_info = { .maxRetransmission = 0xf, .collisionWindow = 0x37, .receiveFlowControl = 1, + .transmitFlowControl = 1, .maxGroupAddrInHash = 4, .maxIndAddrInHash = 4, .prel = 7, @@ -139,7 +146,9 @@ static struct ucc_geth_info ugeth_primary_info = { .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1, .largestexternallookupkeysize = QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE, - .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE, + .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE | + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX | + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX, .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP, .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP, .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT, @@ -281,7 +290,8 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth, for (i = 0; i < num_entries; i++) { if ((snum = qe_get_snum()) < 0) { - ugeth_err("fill_init_enet_entries: Can not get SNUM."); + if (netif_msg_ifup(ugeth)) + ugeth_err("fill_init_enet_entries: Can not get SNUM."); return snum; } if ((i == 0) && skip_page_for_first_entry) @@ -291,8 +301,8 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth, init_enet_offset = qe_muram_alloc(thread_size, thread_alignment); if (IS_ERR_VALUE(init_enet_offset)) { - ugeth_err - ("fill_init_enet_entries: Can not allocate DPRAM memory."); + if (netif_msg_ifup(ugeth)) + ugeth_err("fill_init_enet_entries: Can not allocate DPRAM memory."); qe_put_snum((u8) snum); return -ENOMEM; } @@ -1200,7 +1210,7 @@ static int init_inter_frame_gap_params(u8 non_btb_cs_ipg, return 0; } -static int init_flow_control_params(u32 automatic_flow_control_mode, +int init_flow_control_params(u32 automatic_flow_control_mode, int rx_flow_control_enable, int tx_flow_control_enable, u16 pause_period, @@ -1486,9 +1496,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2); if (ret_val != 0) { - ugeth_err - ("%s: Preamble length must be between 3 and 7 inclusive.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Preamble length must be between 3 and 7 inclusive.", + __FUNCTION__); return ret_val; } @@ -1726,7 +1736,8 @@ static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) /* check if the UCC number is in range. */ if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: ucc_num out of range.", __FUNCTION__); return -EINVAL; } @@ -1754,7 +1765,8 @@ static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode) /* check if the UCC number is in range. */ if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: ucc_num out of range.", __FUNCTION__); return -EINVAL; } @@ -2136,7 +2148,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { if (ugeth->tx_skbuff[i][j]) { dma_unmap_single(NULL, - ((qe_bd_t *)bd)->buf, + ((struct qe_bd *)bd)->buf, (in_be32((u32 *)bd) & BD_LENGTH_MASK), DMA_TO_DEVICE); @@ -2276,7 +2288,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) phy_stop(phydev); /* Mask all interrupts */ - out_be32(ugeth->uccf->p_ucce, 0x00000000); + out_be32(ugeth->uccf->p_uccm, 0x00000000); /* Clear all interrupts */ out_be32(ugeth->uccf->p_ucce, 0xffffffff); @@ -2306,7 +2318,9 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || (uf_info->bd_mem_part == MEM_PART_MURAM))) { - ugeth_err("%s: Bad memory partition value.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Bad memory partition value.", + __FUNCTION__); return -EINVAL; } @@ -2315,9 +2329,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) || (ug_info->bdRingLenRx[i] % UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) { - ugeth_err - ("%s: Rx BD ring length must be multiple of 4," - " no smaller than 8.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: Rx BD ring length must be multiple of 4, no smaller than 8.", + __FUNCTION__); return -EINVAL; } } @@ -2325,9 +2340,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* Tx BD lengths */ for (i = 0; i < ug_info->numQueuesTx; i++) { if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) { - ugeth_err - ("%s: Tx BD ring length must be no smaller than 2.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: Tx BD ring length must be no smaller than 2.", + __FUNCTION__); return -EINVAL; } } @@ -2335,31 +2351,35 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* mrblr */ if ((uf_info->max_rx_buf_length == 0) || (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) { - ugeth_err - ("%s: max_rx_buf_length must be non-zero multiple of 128.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: max_rx_buf_length must be non-zero multiple of 128.", + __FUNCTION__); return -EINVAL; } /* num Tx queues */ if (ug_info->numQueuesTx > NUM_TX_QUEUES) { - ugeth_err("%s: number of tx queues too large.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: number of tx queues too large.", __FUNCTION__); return -EINVAL; } /* num Rx queues */ if (ug_info->numQueuesRx > NUM_RX_QUEUES) { - ugeth_err("%s: number of rx queues too large.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: number of rx queues too large.", __FUNCTION__); return -EINVAL; } /* l2qt */ for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) { if (ug_info->l2qt[i] >= ug_info->numQueuesRx) { - ugeth_err - ("%s: VLAN priority table entry must not be" - " larger than number of Rx queues.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: VLAN priority table entry must not be" + " larger than number of Rx queues.", + __FUNCTION__); return -EINVAL; } } @@ -2367,26 +2387,29 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* l3qt */ for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) { if (ug_info->l3qt[i] >= ug_info->numQueuesRx) { - ugeth_err - ("%s: IP priority table entry must not be" - " larger than number of Rx queues.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: IP priority table entry must not be" + " larger than number of Rx queues.", + __FUNCTION__); return -EINVAL; } } if (ug_info->cam && !ug_info->ecamptr) { - ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", + __FUNCTION__); return -EINVAL; } if ((ug_info->numStationAddresses != UCC_GETH_NUM_OF_STATION_ADDRESSES_1) && ug_info->rxExtendedFiltering) { - ugeth_err("%s: Number of station addresses greater than 1 " - "not allowed in extended parsing mode.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Number of station addresses greater than 1 " + "not allowed in extended parsing mode.", + __FUNCTION__); return -EINVAL; } @@ -2399,7 +2422,8 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); /* Initialize the general fast UCC block. */ if (ucc_fast_init(uf_info, &ugeth->uccf)) { - ugeth_err("%s: Failed to init uccf.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Failed to init uccf.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2452,7 +2476,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) numThreadsRxNumerical = 8; break; default: - ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Bad number of Rx threads value.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; break; @@ -2475,7 +2501,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) numThreadsTxNumerical = 8; break; default: - ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Bad number of Tx threads value.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; break; @@ -2507,7 +2535,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* For more details see the hardware spec. */ init_flow_control_params(ug_info->aufc, ug_info->receiveFlowControl, - 1, + ug_info->transmitFlowControl, ug_info->pausePeriod, ug_info->extensionField, &uf_regs->upsmr, @@ -2527,8 +2555,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ug_info->backToBackInterFrameGap, &ug_regs->ipgifg); if (ret_val != 0) { - ugeth_err("%s: IPGIFG initialization parameter too large.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: IPGIFG initialization parameter too large.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -2544,7 +2573,8 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ug_info->collisionWindow, &ug_regs->hafdup); if (ret_val != 0) { - ugeth_err("%s: Half Duplex initialization parameter too large.", + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Half Duplex initialization parameter too large.", __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; @@ -2597,9 +2627,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) tx_bd_ring_offset[j]); } if (!ugeth->p_tx_bd_ring[j]) { - ugeth_err - ("%s: Can not allocate memory for Tx bd rings.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate memory for Tx bd rings.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2632,9 +2663,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) rx_bd_ring_offset[j]); } if (!ugeth->p_rx_bd_ring[j]) { - ugeth_err - ("%s: Can not allocate memory for Rx bd rings.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate memory for Rx bd rings.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2648,8 +2680,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) GFP_KERNEL); if (ugeth->tx_skbuff[j] == NULL) { - ugeth_err("%s: Could not allocate tx_skbuff", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Could not allocate tx_skbuff", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2679,8 +2712,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) GFP_KERNEL); if (ugeth->rx_skbuff[j] == NULL) { - ugeth_err("%s: Could not allocate rx_skbuff", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Could not allocate rx_skbuff", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2711,9 +2745,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram), UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); if (IS_ERR_VALUE(ugeth->tx_glbl_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2733,9 +2768,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) 32 * (numThreadsTxNumerical == 1), UCC_GETH_THREAD_DATA_ALIGNMENT); if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2761,9 +2797,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_send_queue_qd), UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2804,9 +2841,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_scheduler), UCC_GETH_SCHEDULER_ALIGNMENT); if (IS_ERR_VALUE(ugeth->scheduler_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_scheduler.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_scheduler.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2852,9 +2890,11 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) (struct ucc_geth_tx_firmware_statistics_pram), UCC_GETH_TX_STATISTICS_ALIGNMENT); if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_tx_fw_statistics_pram.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_tx_fw_statistics_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2891,9 +2931,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram), UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_glbl_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2912,9 +2953,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_thread_data_rx), UCC_GETH_THREAD_DATA_ALIGNMENT); if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2935,9 +2977,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) (struct ucc_geth_rx_firmware_statistics_pram), UCC_GETH_RX_STATISTICS_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_fw_statistics_pram.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_rx_fw_statistics_pram.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2957,9 +3000,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_rx_interrupt_coalescing_entry) + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_irq_coalescing_tbl.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_rx_irq_coalescing_tbl.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3025,9 +3069,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_rx_prefetched_bds)), UCC_GETH_RX_BD_QUEUES_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3102,8 +3147,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* initialize extended filtering */ if (ug_info->rxExtendedFiltering) { if (!ug_info->extendedFilteringChainPointer) { - ugeth_err("%s: Null Extended Filtering Chain Pointer.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Null Extended Filtering Chain Pointer.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; } @@ -3114,9 +3160,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram), UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_exf_glbl_param.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_exf_glbl_param.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3161,9 +3208,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) */ if (!(ugeth->p_init_enet_param_shadow = kmalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) { - ugeth_err - ("%s: Can not allocate memory for" - " p_UccInitEnetParamShadows.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate memory for" + " p_UccInitEnetParamShadows.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3196,8 +3244,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) && (ug_info->largestexternallookupkeysize != QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) { - ugeth_err("%s: Invalid largest External Lookup Key Size.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Invalid largest External Lookup Key Size.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; } @@ -3222,8 +3271,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Rx needs one extra for terminator */ , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT, ug_info->riscRx, 1)) != 0) { - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Can not fill p_init_enet_param_shadow.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3237,8 +3287,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_thread_tx_pram), UCC_GETH_THREAD_TX_PRAM_ALIGNMENT, ug_info->riscTx, 0)) != 0) { - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Can not fill p_init_enet_param_shadow.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3246,8 +3297,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Load Rx bds with buffers */ for (i = 0; i < ug_info->numQueuesRx; i++) { if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) { - ugeth_err("%s: Can not fill Rx bds with buffers.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Can not fill Rx bds with buffers.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3256,9 +3308,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Allocate InitEnet command parameter structure */ init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4); if (IS_ERR_VALUE(init_enet_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3428,8 +3481,9 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit if (!skb || (!(bd_status & (R_F | R_L))) || (bd_status & R_ERRORS_FATAL)) { - ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x", - __FUNCTION__, __LINE__, (u32) skb); + if (netif_msg_rx_err(ugeth)) + ugeth_err("%s, %d: ERROR!!! skb - 0x%08x", + __FUNCTION__, __LINE__, (u32) skb); if (skb) dev_kfree_skb_any(skb); @@ -3458,7 +3512,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit skb = get_new_skb(ugeth, bd); if (!skb) { - ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); + if (netif_msg_rx_err(ugeth)) + ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); ugeth->stats.rx_dropped++; break; } @@ -3649,28 +3704,32 @@ static int ucc_geth_open(struct net_device *dev) /* Test station address */ if (dev->dev_addr[0] & ENET_GROUP_ADDR) { - ugeth_err("%s: Multicast address used for station address" - " - is this what you wanted?", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Multicast address used for station address" + " - is this what you wanted?", __FUNCTION__); return -EINVAL; } err = ucc_struct_init(ugeth); if (err) { - ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); return err; } err = ucc_geth_startup(ugeth); if (err) { - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot configure net device, aborting.", + dev->name); return err; } err = adjust_enet_interface(ugeth); if (err) { - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot configure net device, aborting.", + dev->name); return err; } @@ -3687,7 +3746,8 @@ static int ucc_geth_open(struct net_device *dev) err = init_phy(dev); if (err) { - ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); return err; } @@ -3697,15 +3757,17 @@ static int ucc_geth_open(struct net_device *dev) request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, "UCC Geth", dev); if (err) { - ugeth_err("%s: Cannot get IRQ for net device, aborting.", - dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot get IRQ for net device, aborting.", + dev->name); ucc_geth_stop(ugeth); return err; } err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); if (err) { - ugeth_err("%s: Cannot enable net device, aborting.", dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot enable net device, aborting.", dev->name); ucc_geth_stop(ugeth); return err; } @@ -3732,8 +3794,6 @@ static int ucc_geth_close(struct net_device *dev) return 0; } -const struct ethtool_ops ucc_geth_ethtool_ops = { }; - static phy_interface_t to_phy_interface(const char *phy_connection_type) { if (strcasecmp(phy_connection_type, "mii") == 0) @@ -3790,6 +3850,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma return -ENODEV; ug_info = &ugeth_info[ucc_num]; + if (ug_info == NULL) { + if (netif_msg_probe(&debug)) + ugeth_err("%s: [%d] Missing additional data!", + __FUNCTION__, ucc_num); + return -ENODEV; + } + ug_info->uf_info.ucc_num = ucc_num; prop = of_get_property(np, "rx-clock", NULL); @@ -3868,15 +3935,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->mdio_bus = res.start; - printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", - ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, - ug_info->uf_info.irq); - - if (ug_info == NULL) { - ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__, - ucc_num); - return -ENODEV; - } + if (netif_msg_probe(&debug)) + printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", + ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, + ug_info->uf_info.irq); /* Create an ethernet device instance */ dev = alloc_etherdev(sizeof(*ugeth)); @@ -3896,6 +3958,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma SET_NETDEV_DEV(dev, device); /* Fill in the dev structure */ + uec_set_ethtool_ops(dev); dev->open = ucc_geth_open; dev->hard_start_xmit = ucc_geth_start_xmit; dev->tx_timeout = ucc_geth_timeout; @@ -3909,16 +3972,16 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma // dev->change_mtu = ucc_geth_change_mtu; dev->mtu = 1500; dev->set_multicast_list = ucc_geth_set_multi; - dev->ethtool_ops = &ucc_geth_ethtool_ops; - ugeth->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; + ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); ugeth->phy_interface = phy_interface; ugeth->max_speed = max_speed; err = register_netdev(dev); if (err) { - ugeth_err("%s: Cannot register net device, aborting.", - dev->name); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Cannot register net device, aborting.", + dev->name); free_netdev(dev); return err; } @@ -3972,7 +4035,8 @@ static int __init ucc_geth_init(void) if (ret) return ret; - printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); + if (netif_msg_drv(&debug)) + printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); for (i = 0; i < 8; i++) memcpy(&(ugeth_info[i]), &ugeth_primary_info, sizeof(ugeth_primary_info)); diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index a29e1c3ca4b7..bb4dac8c0c65 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -30,6 +30,10 @@ #include "ucc_geth_mii.h" +#define DRV_DESC "QE UCC Gigabit Ethernet Controller" +#define DRV_NAME "ucc_geth" +#define DRV_VERSION "1.1" + #define NUM_TX_QUEUES 8 #define NUM_RX_QUEUES 8 #define NUM_BDS_IN_PREFETCHED_BDS 4 @@ -896,6 +900,7 @@ struct ucc_geth_hardware_statistics { #define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX 8 #define UCC_GETH_RX_BD_RING_SIZE_MIN 8 #define UCC_GETH_TX_BD_RING_SIZE_MIN 2 +#define UCC_GETH_BD_RING_SIZE_MAX 0xffff #define UCC_GETH_SIZE_OF_BD QE_SIZEOF_BD @@ -1135,6 +1140,7 @@ struct ucc_geth_info { int bro; int ecm; int receiveFlowControl; + int transmitFlowControl; u8 maxGroupAddrInHash; u8 maxIndAddrInHash; u8 prel; diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c index 7bcb82f50cf7..6c257b88ce51 100644 --- a/drivers/net/ucc_geth_mii.c +++ b/drivers/net/ucc_geth_mii.c @@ -54,8 +54,8 @@ #define vdbg(format, arg...) do {} while(0) #endif -#define DRV_DESC "QE UCC Ethernet Controller MII Bus" -#define DRV_NAME "fsl-uec_mdio" +#define MII_DRV_DESC "QE UCC Ethernet Controller MII Bus" +#define MII_DRV_NAME "fsl-uec_mdio" /* Write value to the PHY for this device to the register at regnum, */ /* waiting until the write is done before it returns. All PHY */ @@ -261,7 +261,7 @@ static struct of_device_id uec_mdio_match[] = { }; static struct of_platform_driver uec_mdio_driver = { - .name = DRV_NAME, + .name = MII_DRV_NAME, .probe = uec_mdio_probe, .remove = uec_mdio_remove, .match_table = uec_mdio_match, @@ -272,7 +272,8 @@ int __init uec_mdio_init(void) return of_register_platform_driver(&uec_mdio_driver); } -void __exit uec_mdio_exit(void) +/* called from __init ucc_geth_init, therefore can not be __exit */ +void uec_mdio_exit(void) { of_unregister_platform_driver(&uec_mdio_driver); } diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 86e90c59d551..76752d84a30f 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -255,7 +255,7 @@ static void catc_rx_done(struct urb *urb) if (!(skb = dev_alloc_skb(pkt_len))) return; - eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0); + skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, catc->netdev); diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c index bc62b012602b..943988ed01d8 100644 --- a/drivers/net/usb/cdc_subset.c +++ b/drivers/net/usb/cdc_subset.c @@ -305,6 +305,9 @@ static const struct usb_device_id products [] = { USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader .driver_info = (unsigned long) &blob_info, }, { + USB_DEVICE (0x1286, 0x8001), // "blob" bootloader + .driver_info = (unsigned long) &blob_info, +}, { // Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config // e.g. Gumstix, current OpenZaurus, ... USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203), diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 16c7a0e87850..a2de32fabc17 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -405,7 +405,7 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &dm9601_ethtool_ops; dev->net->hard_header_len += DM_TX_OVERHEAD; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; - dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD; + dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD; dev->mii.dev = dev->net; dev->mii.mdio_read = dm9601_mdio_read; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 60d29440f316..524dc5f5e46d 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -635,7 +635,7 @@ static void kaweth_usb_receive(struct urb *urb) skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0); + skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len); skb_put(skb, pkt_len); diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index a05fd97e5bc2..04cba6bf3d54 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -768,11 +768,13 @@ done: static void write_bulk_callback(struct urb *urb) { pegasus_t *pegasus = urb->context; - struct net_device *net = pegasus->net; + struct net_device *net; if (!pegasus) return; + net = pegasus->net; + if (!netif_device_present(net) || !netif_running(net)) return; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index a12f576391cf..37bf4f2c0a44 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -192,7 +192,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf) usb_pipeendpoint(pipe), maxp, period); } } - return 0; + return 0; } /* Passes this packet up the stack, updating its accounting. @@ -326,7 +326,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) if (netif_running (dev->net) && netif_device_present (dev->net) && !test_bit (EVENT_RX_HALT, &dev->flags)) { - switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ + switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { case -EPIPE: usbnet_defer_kevent (dev, EVENT_RX_HALT); break; @@ -393,8 +393,8 @@ static void rx_complete (struct urb *urb) entry->urb = NULL; switch (urb_status) { - // success - case 0: + /* success */ + case 0: if (skb->len < dev->net->hard_header_len) { entry->state = rx_cleanup; dev->stats.rx_errors++; @@ -404,28 +404,30 @@ static void rx_complete (struct urb *urb) } break; - // stalls need manual reset. this is rare ... except that - // when going through USB 2.0 TTs, unplug appears this way. - // we avoid the highspeed version of the ETIMEOUT/EILSEQ - // storm, recovering as needed. - case -EPIPE: + /* stalls need manual reset. this is rare ... except that + * when going through USB 2.0 TTs, unplug appears this way. + * we avoid the highspeed version of the ETIMEOUT/EILSEQ + * storm, recovering as needed. + */ + case -EPIPE: dev->stats.rx_errors++; usbnet_defer_kevent (dev, EVENT_RX_HALT); // FALLTHROUGH - // software-driven interface shutdown - case -ECONNRESET: // async unlink - case -ESHUTDOWN: // hardware gone + /* software-driven interface shutdown */ + case -ECONNRESET: /* async unlink */ + case -ESHUTDOWN: /* hardware gone */ if (netif_msg_ifdown (dev)) devdbg (dev, "rx shutdown, code %d", urb_status); goto block; - // we get controller i/o faults during khubd disconnect() delays. - // throttle down resubmits, to avoid log floods; just temporarily, - // so we still recover when the fault isn't a khubd delay. - case -EPROTO: - case -ETIME: - case -EILSEQ: + /* we get controller i/o faults during khubd disconnect() delays. + * throttle down resubmits, to avoid log floods; just temporarily, + * so we still recover when the fault isn't a khubd delay. + */ + case -EPROTO: + case -ETIME: + case -EILSEQ: dev->stats.rx_errors++; if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); @@ -438,12 +440,12 @@ block: urb = NULL; break; - // data overrun ... flush fifo? - case -EOVERFLOW: + /* data overrun ... flush fifo? */ + case -EOVERFLOW: dev->stats.rx_over_errors++; // FALLTHROUGH - default: + default: entry->state = rx_cleanup; dev->stats.rx_errors++; if (netif_msg_rx_err (dev)) @@ -471,22 +473,22 @@ static void intr_complete (struct urb *urb) int status = urb->status; switch (status) { - /* success */ - case 0: + /* success */ + case 0: dev->driver_info->status(dev, urb); break; - /* software-driven interface shutdown */ - case -ENOENT: // urb killed - case -ESHUTDOWN: // hardware gone + /* software-driven interface shutdown */ + case -ENOENT: /* urb killed */ + case -ESHUTDOWN: /* hardware gone */ if (netif_msg_ifdown (dev)) devdbg (dev, "intr shutdown, code %d", status); return; - /* NOTE: not throttling like RX/TX, since this endpoint - * already polls infrequently - */ - default: + /* NOTE: not throttling like RX/TX, since this endpoint + * already polls infrequently + */ + default: devdbg (dev, "intr status %d", status); break; } @@ -569,9 +571,9 @@ static int usbnet_stop (struct net_device *net) temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq); // maybe wait for deletions to finish. - while (!skb_queue_empty(&dev->rxq) && - !skb_queue_empty(&dev->txq) && - !skb_queue_empty(&dev->done)) { + while (!skb_queue_empty(&dev->rxq) + && !skb_queue_empty(&dev->txq) + && !skb_queue_empty(&dev->done)) { msleep(UNLINK_TIMEOUT_MS); if (netif_msg_ifdown (dev)) devdbg (dev, "waited for %d urb completions", temp); @@ -1011,16 +1013,16 @@ static void usbnet_bh (unsigned long param) while ((skb = skb_dequeue (&dev->done))) { entry = (struct skb_data *) skb->cb; switch (entry->state) { - case rx_done: + case rx_done: entry->state = rx_cleanup; rx_process (dev, skb); continue; - case tx_done: - case rx_cleanup: + case tx_done: + case rx_cleanup: usb_free_urb (entry->urb); dev_kfree_skb (skb); continue; - default: + default: devdbg (dev, "bogus skb state %d", entry->state); } } @@ -1211,7 +1213,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) status = 0; } - if (status == 0 && dev->status) + if (status >= 0 && dev->status) status = init_status (dev, udev); if (status < 0) goto out3; diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h index a3f8b9e7bc00..a6c5820767de 100644 --- a/drivers/net/usb/usbnet.h +++ b/drivers/net/usb/usbnet.h @@ -47,7 +47,7 @@ struct usbnet { unsigned long data [5]; u32 xid; u32 hard_mtu; /* count any extra framing */ - size_t rx_urb_size; /* size for rx urbs */ + size_t rx_urb_size; /* size for rx urbs */ struct mii_if_info mii; /* various kinds of pending driver work */ @@ -85,7 +85,7 @@ struct driver_info { #define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */ #define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */ -#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ +#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ /* init device ... can sleep, or cause probe() failure */ int (*bind)(struct usbnet *, struct usb_interface *); @@ -146,9 +146,9 @@ extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *); /* CDC and RNDIS support the same host-chosen packet filters for IN transfers */ #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ - |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ - |USB_CDC_PACKET_TYPE_PROMISCUOUS \ - |USB_CDC_PACKET_TYPE_DIRECTED) + |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ + |USB_CDC_PACKET_TYPE_PROMISCUOUS \ + |USB_CDC_PACKET_TYPE_DIRECTED) /* we record the state for each of our queued skbs */ diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index adea290a9d5e..b56dff26772d 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -42,7 +42,13 @@ static int max_interrupt_work = 20; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ +#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ + || defined(CONFIG_SPARC) || defined(__ia64__) \ + || defined(__sh__) || defined(__mips__) +static int rx_copybreak = 1518; +#else static int rx_copybreak; +#endif /* Work-around for broken BIOSes: they are unable to get the chip back out of power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */ @@ -622,7 +628,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, struct net_device *dev; struct rhine_private *rp; int i, rc; - u8 pci_rev; u32 quirks; long pioaddr; long memaddr; @@ -642,27 +647,25 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, printk(version); #endif - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - io_size = 256; phy_id = 0; quirks = 0; name = "Rhine"; - if (pci_rev < VTunknown0) { + if (pdev->revision < VTunknown0) { quirks = rqRhineI; io_size = 128; } - else if (pci_rev >= VT6102) { + else if (pdev->revision >= VT6102) { quirks = rqWOL | rqForceReset; - if (pci_rev < VT6105) { + if (pdev->revision < VT6105) { name = "Rhine II"; quirks |= rqStatusWBRace; /* Rhine-II exclusive */ } else { phy_id = 1; /* Integrated PHY, phy_id fixed to 1 */ - if (pci_rev >= VT6105_B0) + if (pdev->revision >= VT6105_B0) quirks |= rq6patterns; - if (pci_rev < VT6105M) + if (pdev->revision < VT6105M) name = "Rhine III"; else name = "Rhine III (Management Adapter)"; @@ -1492,9 +1495,9 @@ static int rhine_rx(struct net_device *dev, int limit) rp->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, rp->rx_skbuff[entry]->data, - pkt_len, 0); + pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(rp->pdev, rp->rx_skbuff_dma[entry], @@ -1808,7 +1811,6 @@ static const struct ethtool_ops netdev_ethtool_ops = { .set_wol = rhine_set_wol, .get_sg = ethtool_op_get_sg, .get_tx_csum = ethtool_op_get_tx_csum, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index b670b97bcfde..93574add4063 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -890,8 +890,7 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev) { - if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0) - return -EIO; + vptr->rev_id = pdev->revision; pci_set_master(pdev); @@ -1614,7 +1613,7 @@ static void velocity_error(struct velocity_info *vptr, int status) if (status & ISR_TXSTLI) { struct mac_regs __iomem * regs = vptr->mac_regs; - printk(KERN_ERR "TD structure errror TDindex=%hx\n", readw(®s->TDIdx[0])); + printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(®s->TDIdx[0])); BYTE_REG_BITS_ON(TXESR_TDSTR, ®s->TXESR); writew(TRDCSR_RUN, ®s->TDCSRClr); netif_stop_queue(vptr->dev); diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 4fc8681bc110..a3df09ee729f 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -61,7 +61,7 @@ config COSA # config LANMEDIA tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards" - depends on PCI + depends on PCI && VIRT_TO_BUS ---help--- Driver for the following Lan Media family of serial boards: diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index 6b63b350cd52..8ead774d14c8 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -315,12 +315,11 @@ static int __init c101_run(unsigned long irq, unsigned long winbase) return -ENODEV; } - card = kmalloc(sizeof(card_t), GFP_KERNEL); + card = kzalloc(sizeof(card_t), GFP_KERNEL); if (card == NULL) { printk(KERN_ERR "c101: unable to allocate memory\n"); return -ENOBUFS; } - memset(card, 0, sizeof(card_t)); card->dev = alloc_hdlcdev(card); if (!card->dev) { diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 9ef49ce148b2..26058b4f8f36 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -572,13 +572,11 @@ static int cosa_probe(int base, int irq, int dma) sprintf(cosa->name, "cosa%d", cosa->num); /* Initialize the per-channel data */ - cosa->chan = kmalloc(sizeof(struct channel_data)*cosa->nchannels, - GFP_KERNEL); + cosa->chan = kcalloc(cosa->nchannels, sizeof(struct channel_data), GFP_KERNEL); if (!cosa->chan) { err = -ENOMEM; goto err_out3; } - memset(cosa->chan, 0, sizeof(struct channel_data)*cosa->nchannels); for (i=0; i<cosa->nchannels; i++) { cosa->chan[i].cosa = cosa; cosa->chan[i].num = i; diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c index 6e5f1c898517..a0e8611ad8e8 100644 --- a/drivers/net/wan/cycx_main.c +++ b/drivers/net/wan/cycx_main.c @@ -113,12 +113,10 @@ static int __init cycx_init(void) /* Verify number of cards and allocate adapter data space */ cycx_ncards = min_t(int, cycx_ncards, CYCX_MAX_CARDS); cycx_ncards = max_t(int, cycx_ncards, 1); - cycx_card_array = kmalloc(sizeof(struct cycx_device) * cycx_ncards, - GFP_KERNEL); + cycx_card_array = kcalloc(cycx_ncards, sizeof(struct cycx_device), GFP_KERNEL); if (!cycx_card_array) goto out; - memset(cycx_card_array, 0, sizeof(struct cycx_device) * cycx_ncards); /* Register adapters with WAN router */ for (cnt = 0; cnt < cycx_ncards; ++cnt) { diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c index 016b3ff3ea5e..a8af28b273d3 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -376,11 +376,10 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev, } /* allocate and initialize private data */ - chan = kmalloc(sizeof(struct cycx_x25_channel), GFP_KERNEL); + chan = kzalloc(sizeof(struct cycx_x25_channel), GFP_KERNEL); if (!chan) return -ENOMEM; - memset(chan, 0, sizeof(*chan)); strcpy(chan->name, conf->name); chan->card = card; chan->link = conf->port; diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index dca024471455..50d2f9108dca 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -890,12 +890,11 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) struct dscc4_dev_priv *root; int i, ret = -ENOMEM; - root = kmalloc(dev_per_card*sizeof(*root), GFP_KERNEL); + root = kcalloc(dev_per_card, sizeof(*root), GFP_KERNEL); if (!root) { printk(KERN_ERR "%s: can't allocate data\n", DRV_NAME); goto err_out; } - memset(root, 0, dev_per_card*sizeof(*root)); for (i = 0; i < dev_per_card; i++) { root[i].dev = alloc_hdlcdev(root + i); @@ -903,12 +902,11 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) goto err_free_dev; } - ppriv = kmalloc(sizeof(*ppriv), GFP_KERNEL); + ppriv = kzalloc(sizeof(*ppriv), GFP_KERNEL); if (!ppriv) { printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME); goto err_free_dev; } - memset(ppriv, 0, sizeof(struct dscc4_pci_priv)); ppriv->root = root; spin_lock_init(&ppriv->lock); diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 58a53b6d9b42..12dae8e24844 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2476,13 +2476,12 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Allocate driver private data */ - card = kmalloc(sizeof (struct fst_card_info), GFP_KERNEL); + card = kzalloc(sizeof (struct fst_card_info), GFP_KERNEL); if (card == NULL) { printk_err("FarSync card found but insufficient memory for" " driver storage\n"); return -ENOMEM; } - memset(card, 0, sizeof (struct fst_card_info)); /* Try to enable the device */ if ((err = pci_enable_device(pdev)) != 0) { diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 15b6e07a4382..071a64cacd5c 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -212,14 +212,13 @@ static pvc_device* add_pvc(struct net_device *dev, u16 dlci) pvc_p = &(*pvc_p)->next; } - pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); + pvc = kzalloc(sizeof(pvc_device), GFP_ATOMIC); #ifdef DEBUG_PVC printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev); #endif if (!pvc) return NULL; - memset(pvc, 0, sizeof(pvc_device)); pvc->dlci = dlci; pvc->frad = dev; pvc->next = *pvc_p; /* Put it in the chain */ diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c index 9ba3e4ee6ec7..bf5f8d9b5c83 100644 --- a/drivers/net/wan/hostess_sv11.c +++ b/drivers/net/wan/hostess_sv11.c @@ -231,11 +231,10 @@ static struct sv11_device *sv11_init(int iobase, int irq) return NULL; } - sv = kmalloc(sizeof(struct sv11_device), GFP_KERNEL); + sv = kzalloc(sizeof(struct sv11_device), GFP_KERNEL); if(!sv) goto fail3; - memset(sv, 0, sizeof(*sv)); sv->if_ptr=&sv->netdev; sv->netdev.dev = alloc_netdev(0, "hdlc%d", sv11_setup); diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index 5c322dfb79f6..cbdf0b748bde 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -351,12 +351,11 @@ static int __init n2_run(unsigned long io, unsigned long irq, return -ENODEV; } - card = kmalloc(sizeof(card_t), GFP_KERNEL); + card = kzalloc(sizeof(card_t), GFP_KERNEL); if (card == NULL) { printk(KERN_ERR "n2: unable to allocate memory\n"); return -ENOBUFS; } - memset(card, 0, sizeof(card_t)); card->ports[0].dev = alloc_hdlcdev(&card->ports[0]); card->ports[1].dev = alloc_hdlcdev(&card->ports[1]); diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 999bf71937ca..99fee2f1d019 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -2833,6 +2833,8 @@ static int clock_rate_calc(uclong rate, uclong clock, int *br_io) int br, tc; int br_pwr, error; + *br_io = 0; + if (rate == 0) return (0); @@ -3439,7 +3441,6 @@ static int __devinit cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int first_time = 1; - ucchar cpc_rev_id; int err, eeprom_outdated = 0; ucshort device_id; pc300_t *card; @@ -3455,7 +3456,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if ((err = pci_enable_device(pdev)) < 0) return err; - card = kmalloc(sizeof(pc300_t), GFP_KERNEL); + card = kzalloc(sizeof(pc300_t), GFP_KERNEL); if (card == NULL) { printk("PC300 found at RAM 0x%016llx, " "but could not allocate card structure.\n", @@ -3463,7 +3464,6 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENOMEM; goto err_disable_dev; } - memset(card, 0, sizeof(pc300_t)); err = -ENODEV; @@ -3480,7 +3480,6 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) card->hw.falcsize = pci_resource_len(pdev, 4); card->hw.plxphys = pci_resource_start(pdev, 5); card->hw.plxsize = pci_resource_len(pdev, 5); - pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id); switch (device_id) { case PCI_DEVICE_ID_PC300_RX_1: @@ -3498,7 +3497,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } #ifdef PC300_DEBUG_PCI printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", cpc_rev_id, card->hw.irq); + printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq); printk("cpc:found ramaddr=0x%08lx plxaddr=0x%08lx " "ctladdr=0x%08lx falcaddr=0x%08lx\n", card->hw.ramphys, card->hw.plxphys, card->hw.scaphys, diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index aff05dba720a..6353cb5c658d 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -311,7 +311,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { card_t *card; - u8 rev_id; u32 __iomem *p; int i; u32 ramsize; @@ -335,14 +334,13 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, return i; } - card = kmalloc(sizeof(card_t), GFP_KERNEL); + card = kzalloc(sizeof(card_t), GFP_KERNEL); if (card == NULL) { printk(KERN_ERR "pc300: unable to allocate memory\n"); pci_release_regions(pdev); pci_disable_device(pdev); return -ENOBUFS; } - memset(card, 0, sizeof(card_t)); pci_set_drvdata(pdev, card); if (pdev->device == PCI_DEVICE_ID_PC300_TE_1 || @@ -366,7 +364,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, return -ENOMEM; } - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE || pci_resource_len(pdev, 2) != PC300_SCA_SIZE || pci_resource_len(pdev, 3) < 16384) { diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index ca06a00d9d86..092e51d89036 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -289,7 +289,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { card_t *card; - u8 rev_id; u32 __iomem *p; int i; u32 ramsize; @@ -313,14 +312,13 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, return i; } - card = kmalloc(sizeof(card_t), GFP_KERNEL); + card = kzalloc(sizeof(card_t), GFP_KERNEL); if (card == NULL) { printk(KERN_ERR "pci200syn: unable to allocate memory\n"); pci_release_regions(pdev); pci_disable_device(pdev); return -ENOBUFS; } - memset(card, 0, sizeof(card_t)); pci_set_drvdata(pdev, card); card->ports[0].dev = alloc_hdlcdev(&card->ports[0]); card->ports[1].dev = alloc_hdlcdev(&card->ports[1]); @@ -330,7 +328,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, return -ENOMEM; } - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE || pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE || pci_resource_len(pdev, 3) < 16384) { diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 35eded7ffb2d..1cc18e787a65 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -595,8 +595,8 @@ recv_frame( struct net_device *dev ) u32 crc = CRC32_INITIAL; - unsigned framelen, frameno, ack; - unsigned is_first, frame_ok; + unsigned framelen = 0, frameno, ack; + unsigned is_first, frame_ok = 0; if( check_fhdr( ioaddr, &framelen, &frameno, &ack, &is_first, &crc ) ) { frame_ok = framelen > 4 @@ -604,8 +604,7 @@ recv_frame( struct net_device *dev ) : skip_tail( ioaddr, framelen, crc ); if( frame_ok ) interpret_ack( dev, ack ); - } else - frame_ok = 0; + } outb( inb( ioaddr + CSR0 ) ^ CT_ZER, ioaddr + CSR0 ); if( frame_ok ) { diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 6a485f0556f4..792e588d7d61 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -1196,10 +1196,9 @@ static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int r if (read) { - temp = kmalloc(mem.len, GFP_KERNEL); + temp = kzalloc(mem.len, GFP_KERNEL); if (!temp) return(-ENOMEM); - memset(temp, 0, mem.len); sdla_read(dev, mem.addr, temp, mem.len); if(copy_to_user(mem.data, temp, mem.len)) { diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c index 131358108c5a..11276bf3149f 100644 --- a/drivers/net/wan/sealevel.c +++ b/drivers/net/wan/sealevel.c @@ -270,11 +270,10 @@ static __init struct slvl_board *slvl_init(int iobase, int irq, return NULL; } - b = kmalloc(sizeof(struct slvl_board), GFP_KERNEL); + b = kzalloc(sizeof(struct slvl_board), GFP_KERNEL); if(!b) goto fail3; - memset(b, 0, sizeof(*b)); if (!(b->dev[0]= slvl_alloc(iobase, irq))) goto fail2; diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index c73601574334..3c78f9856380 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -599,7 +599,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, } alloc_size = sizeof(card_t) + ports * sizeof(port_t); - card = kmalloc(alloc_size, GFP_KERNEL); + card = kzalloc(alloc_size, GFP_KERNEL); if (card == NULL) { printk(KERN_ERR "wanXL %s: unable to allocate memory\n", pci_name(pdev)); @@ -607,7 +607,6 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, pci_disable_device(pdev); return -ENOBUFS; } - memset(card, 0, alloc_size); pci_set_drvdata(pdev, card); card->pdev = pdev; diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 1c9edd97accd..c48b1cc63fd5 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -786,14 +786,12 @@ static int __init init_x25_asy(void) printk(KERN_INFO "X.25 async: version 0.00 ALPHA " "(dynamic channels, max=%d).\n", x25_asy_maxdev ); - x25_asy_devs = kmalloc(sizeof(struct net_device *)*x25_asy_maxdev, - GFP_KERNEL); + x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device*), GFP_KERNEL); if (!x25_asy_devs) { printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] " "array! Uaargh! (-> No X.25 available)\n"); return -ENOMEM; } - memset(x25_asy_devs, 0, sizeof(struct net_device *)*x25_asy_maxdev); return tty_register_ldisc(N_X25, &x25_ldisc); } diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index fa2399cbd5ca..ae27af0141c0 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -546,6 +546,18 @@ config USB_ZD1201 To compile this driver as a module, choose M here: the module will be called zd1201. +config RTL8187 + tristate "Realtek 8187 USB support" + depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL + select EEPROM_93CX6 + ---help--- + This is a driver for RTL8187 based cards. + These are USB based chips found in cards such as: + + Netgear WG111v2 + + Thanks to Realtek for their support! + source "drivers/net/wireless/hostap/Kconfig" source "drivers/net/wireless/bcm43xx/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index d2124602263b..4eb6d9752881 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -43,4 +43,7 @@ obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o obj-$(CONFIG_USB_ZD1201) += zd1201.o -obj-$(CONFIG_LIBERTAS_USB) += libertas/ +obj-$(CONFIG_LIBERTAS) += libertas/ + +rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o +obj-$(CONFIG_RTL8187) += rtl8187.o diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2d3a180dada0..ee1cc14db389 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -52,6 +52,8 @@ #include "airo.h" +#define DRV_NAME "airo" + #ifdef CONFIG_PCI static struct pci_device_id card_ids[] = { { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, @@ -71,7 +73,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state); static int airo_pci_resume(struct pci_dev *pdev); static struct pci_driver airo_driver = { - .name = "airo", + .name = DRV_NAME, .id_table = card_ids, .probe = airo_pci_probe, .remove = __devexit_p(airo_pci_remove), @@ -1092,7 +1094,7 @@ static int get_dec_u16( char *buffer, int *start, int limit ); static void OUT4500( struct airo_info *, u16 register, u16 value ); static unsigned short IN4500( struct airo_info *, u16 register ); static u16 setup_card(struct airo_info*, u8 *mac, int lock); -static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ); +static int enable_MAC(struct airo_info *ai, int lock); static void disable_MAC(struct airo_info *ai, int lock); static void enable_interrupts(struct airo_info*); static void disable_interrupts(struct airo_info*); @@ -1250,7 +1252,7 @@ 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); } + printk(type DRV_NAME "(%s): " fmt "\n", name, ##args) #define airo_print_info(name, fmt, args...) \ airo_print(KERN_INFO, name, fmt, ##args) @@ -1926,28 +1928,54 @@ static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) { return rc; } +static void try_auto_wep(struct airo_info *ai) +{ + if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) { + ai->expires = RUN_AT(3*HZ); + wake_up_interruptible(&ai->thr_wait); + } +} + static int airo_open(struct net_device *dev) { - struct airo_info *info = dev->priv; - Resp rsp; + struct airo_info *ai = dev->priv; + int rc = 0; - if (test_bit(FLAG_FLASHING, &info->flags)) + if (test_bit(FLAG_FLASHING, &ai->flags)) return -EIO; /* Make sure the card is configured. * Wireless Extensions may postpone config changes until the card * is open (to pipeline changes and speed-up card setup). If * those changes are not yet commited, do it now - Jean II */ - if (test_bit (FLAG_COMMIT, &info->flags)) { - disable_MAC(info, 1); - writeConfigRid(info, 1); + if (test_bit(FLAG_COMMIT, &ai->flags)) { + disable_MAC(ai, 1); + writeConfigRid(ai, 1); } - if (info->wifidev != dev) { + if (ai->wifidev != dev) { + clear_bit(JOB_DIE, &ai->jobs); + ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name); + if (IS_ERR(ai->airo_thread_task)) + return (int)PTR_ERR(ai->airo_thread_task); + + rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED, + dev->name, dev); + if (rc) { + airo_print_err(dev->name, + "register interrupt %d failed, rc %d", + dev->irq, rc); + set_bit(JOB_DIE, &ai->jobs); + kthread_stop(ai->airo_thread_task); + return rc; + } + /* Power on the MAC controller (which may have been disabled) */ - clear_bit(FLAG_RADIO_DOWN, &info->flags); - enable_interrupts(info); + clear_bit(FLAG_RADIO_DOWN, &ai->flags); + enable_interrupts(ai); + + try_auto_wep(ai); } - enable_MAC(info, &rsp, 1); + enable_MAC(ai, 1); netif_start_queue(dev); return 0; @@ -2338,14 +2366,13 @@ static int airo_set_mac_address(struct net_device *dev, void *p) { struct airo_info *ai = dev->priv; struct sockaddr *addr = p; - Resp rsp; readConfigRid(ai, 1); memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len); set_bit (FLAG_COMMIT, &ai->flags); disable_MAC(ai, 1); writeConfigRid (ai, 1); - enable_MAC(ai, &rsp, 1); + enable_MAC(ai, 1); memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len); if (ai->wifidev) memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len); @@ -2392,6 +2419,11 @@ static int airo_close(struct net_device *dev) { disable_MAC(ai, 1); #endif disable_interrupts( ai ); + + free_irq(dev->irq, dev); + + set_bit(JOB_DIE, &ai->jobs); + kthread_stop(ai->airo_thread_task); } return 0; } @@ -2403,7 +2435,6 @@ void stop_airo_card( struct net_device *dev, int freeres ) set_bit(FLAG_RADIO_DOWN, &ai->flags); disable_MAC(ai, 1); disable_interrupts(ai); - free_irq( dev->irq, dev ); takedown_proc_entry( dev, ai ); if (test_bit(FLAG_REGISTERED, &ai->flags)) { unregister_netdev( dev ); @@ -2414,9 +2445,6 @@ void stop_airo_card( struct net_device *dev, int freeres ) } clear_bit(FLAG_REGISTERED, &ai->flags); } - set_bit(JOB_DIE, &ai->jobs); - kthread_stop(ai->airo_thread_task); - /* * Clean out tx queue */ @@ -2554,8 +2582,7 @@ static int mpi_init_descriptors (struct airo_info *ai) * 2) Map PCI memory for issueing commands. * 3) Allocate memory (shared) to send and receive ethernet frames. */ -static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, - const char *name) +static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci) { unsigned long mem_start, mem_len, aux_start, aux_len; int rc = -1; @@ -2569,35 +2596,35 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, aux_start = pci_resource_start(pci, 2); aux_len = AUXMEMSIZE; - if (!request_mem_region(mem_start, mem_len, name)) { - airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", - (int)mem_start, (int)mem_len, name); + if (!request_mem_region(mem_start, mem_len, DRV_NAME)) { + airo_print_err("", "Couldn't get region %x[%x]", + (int)mem_start, (int)mem_len); goto out; } - if (!request_mem_region(aux_start, aux_len, name)) { - airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", - (int)aux_start, (int)aux_len, name); + if (!request_mem_region(aux_start, aux_len, DRV_NAME)) { + airo_print_err("", "Couldn't get region %x[%x]", + (int)aux_start, (int)aux_len); goto free_region1; } ai->pcimem = ioremap(mem_start, mem_len); if (!ai->pcimem) { - airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", - (int)mem_start, (int)mem_len, name); + airo_print_err("", "Couldn't map region %x[%x]", + (int)mem_start, (int)mem_len); goto free_region2; } ai->pciaux = ioremap(aux_start, aux_len); if (!ai->pciaux) { - airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", - (int)aux_start, (int)aux_len, name); + airo_print_err("", "Couldn't map region %x[%x]", + (int)aux_start, (int)aux_len); goto free_memmap; } /* 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) { - airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d", - PCI_SHARED_LEN); + airo_print_err("", "Couldn't alloc_consistent %d", + PCI_SHARED_LEN); goto free_auxmap; } @@ -2742,7 +2769,7 @@ static int airo_networks_allocate(struct airo_info *ai) kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement), GFP_KERNEL); if (!ai->networks) { - airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); + airo_print_warn("", "Out of memory allocating beacons"); return -ENOMEM; } @@ -2770,7 +2797,6 @@ static int airo_test_wpa_capable(struct airo_info *ai) { int status; CapabilityRid cap_rid; - const char *name = ai->dev->name; status = readCapabilityRid(ai, &cap_rid, 1); if (status != SUCCESS) return 0; @@ -2778,12 +2804,12 @@ static int airo_test_wpa_capable(struct airo_info *ai) /* Only firmware versions 5.30.17 or better can do WPA */ if ((cap_rid.softVer > 0x530) || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { - airo_print_info(name, "WPA is supported."); + airo_print_info("", "WPA is supported."); return 1; } /* No WPA support */ - airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17" + airo_print_info("", "WPA unsupported (only firmware versions 5.30.17" " and greater support WPA. Detected %s)", cap_rid.prodVer); return 0; } @@ -2797,23 +2823,19 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, int i, rc; /* Create the network device object. */ - dev = alloc_etherdev(sizeof(*ai)); - if (!dev) { + dev = alloc_netdev(sizeof(*ai), "", ether_setup); + if (!dev) { airo_print_err("", "Couldn't alloc_etherdev"); return NULL; - } - if (dev_alloc_name(dev, dev->name) < 0) { - airo_print_err("", "Couldn't get name!"); - goto err_out_free; } ai = dev->priv; ai->wifidev = NULL; - ai->flags = 0; + ai->flags = 1 << FLAG_RADIO_DOWN; ai->jobs = 0; ai->dev = dev; if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { - airo_print_dbg(dev->name, "Found an MPI350 card"); + airo_print_dbg("", "Found an MPI350 card"); set_bit(FLAG_MPI, &ai->flags); } spin_lock_init(&ai->aux_lock); @@ -2821,14 +2843,11 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ai->config.len = 0; ai->pci = pci; init_waitqueue_head (&ai->thr_wait); - ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name); - if (IS_ERR(ai->airo_thread_task)) - goto err_out_free; ai->tfm = NULL; add_airo_dev(ai); if (airo_networks_allocate (ai)) - goto err_out_thr; + goto err_out_free; airo_networks_initialize (ai); /* The Airo-specific entries in the device structure. */ @@ -2851,27 +2870,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, dev->base_addr = port; SET_NETDEV_DEV(dev, dmdev); + SET_MODULE_OWNER(dev); reset_card (dev, 1); msleep(400); - rc = request_irq( dev->irq, airo_interrupt, IRQF_SHARED, dev->name, dev ); - if (rc) { - airo_print_err(dev->name, "register interrupt %d failed, rc %d", - irq, rc); - goto err_out_nets; - } if (!is_pcmcia) { - if (!request_region( dev->base_addr, 64, dev->name )) { + if (!request_region(dev->base_addr, 64, DRV_NAME)) { rc = -EBUSY; airo_print_err(dev->name, "Couldn't request region"); - goto err_out_irq; + goto err_out_nets; } } if (test_bit(FLAG_MPI,&ai->flags)) { - if (mpi_map_card(ai, pci, dev->name)) { - airo_print_err(dev->name, "Could not map memory"); + if (mpi_map_card(ai, pci)) { + airo_print_err("", "Could not map memory"); goto err_out_res; } } @@ -2899,6 +2913,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); } + strcpy(dev->name, "eth%d"); rc = register_netdev(dev); if (rc) { airo_print_err(dev->name, "Couldn't register_netdev"); @@ -2921,8 +2936,6 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, if (setup_proc_entry(dev, dev->priv) < 0) goto err_out_wifi; - netif_start_queue(dev); - SET_MODULE_OWNER(dev); return dev; err_out_wifi: @@ -2940,14 +2953,9 @@ err_out_map: err_out_res: if (!is_pcmcia) release_region( dev->base_addr, 64 ); -err_out_irq: - free_irq(dev->irq, dev); err_out_nets: airo_networks_free(ai); -err_out_thr: del_airo_dev(ai); - set_bit(JOB_DIE, &ai->jobs); - kthread_stop(ai->airo_thread_task); err_out_free: free_netdev(dev); return NULL; @@ -3078,7 +3086,8 @@ static int airo_thread(void *data) { struct net_device *dev = data; struct airo_info *ai = dev->priv; int locked; - + + set_freezable(); while(1) { /* make swsusp happy with our thread */ try_to_freeze(); @@ -3529,9 +3538,11 @@ static u16 IN4500( struct airo_info *ai, u16 reg ) { return rc; } -static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { +static int enable_MAC(struct airo_info *ai, int lock) +{ int rc; - Cmd cmd; + Cmd cmd; + Resp rsp; /* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down" @@ -3547,7 +3558,7 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { if (!test_bit(FLAG_ENABLED, &ai->flags)) { memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_ENABLE; - rc = issuecommand(ai, &cmd, rsp); + rc = issuecommand(ai, &cmd, &rsp); if (rc == SUCCESS) set_bit(FLAG_ENABLED, &ai->flags); } else @@ -3557,8 +3568,12 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { up(&ai->sem); if (rc) - airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d", - __FUNCTION__, rc); + airo_print_err(ai->dev->name, "Cannot enable MAC"); + else if ((rsp.status & 0xFF00) != 0) { + airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, " + "rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2); + rc = ERROR; + } return rc; } @@ -3902,12 +3917,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if ( status != SUCCESS ) return ERROR; } - status = enable_MAC(ai, &rsp, lock); - if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) { - airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x," - " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); + status = enable_MAC(ai, lock); + if (status != SUCCESS) return ERROR; - } /* Grab the initial wep key, we gotta save it for auto_wep */ rc = readWepKeyRid(ai, &wkr, 1, lock); @@ -3919,10 +3931,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) rc = readWepKeyRid(ai, &wkr, 0, lock); } while(lastindex != wkr.kindex); - if (auto_wep) { - ai->expires = RUN_AT(3*HZ); - wake_up_interruptible(&ai->thr_wait); - } + try_auto_wep(ai); return SUCCESS; } @@ -4004,7 +4013,7 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ) } if ( !(max_tries--) ) { airo_print_err(ai->dev->name, - "airo: BAP setup error too many retries\n"); + "BAP setup error too many retries\n"); return ERROR; } // -- PC4500 missed it, try again @@ -5152,7 +5161,6 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) { struct net_device *dev = dp->data; struct airo_info *ai = dev->priv; SsidRid SSID_rid; - Resp rsp; int i; int offset = 0; @@ -5177,7 +5185,7 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) { SSID_rid.len = sizeof(SSID_rid); disable_MAC(ai, 1); writeSsidRid(ai, &SSID_rid, 1); - enable_MAC(ai, &rsp, 1); + enable_MAC(ai, 1); } static inline u8 hexVal(char c) { @@ -5193,7 +5201,6 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { struct net_device *dev = dp->data; struct airo_info *ai = dev->priv; APListRid APList_rid; - Resp rsp; int i; if ( !data->writelen ) return; @@ -5218,18 +5225,17 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { } disable_MAC(ai, 1); writeAPListRid(ai, &APList_rid, 1); - enable_MAC(ai, &rsp, 1); + enable_MAC(ai, 1); } /* This function wraps PC4500_writerid with a MAC disable */ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, int len, int dummy ) { int rc; - Resp rsp; disable_MAC(ai, 1); rc = PC4500_writerid(ai, rid, rid_data, len, 1); - enable_MAC(ai, &rsp, 1); + enable_MAC(ai, 1); return rc; } @@ -5260,7 +5266,6 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key, u16 keylen, int perm, int lock ) { static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; WepKeyRid wkr; - Resp rsp; memset(&wkr, 0, sizeof(wkr)); if (keylen == 0) { @@ -5280,7 +5285,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, if (perm) disable_MAC(ai, lock); writeWepKeyRid(ai, &wkr, perm, lock); - if (perm) enable_MAC(ai, &rsp, lock); + if (perm) enable_MAC(ai, lock); return 0; } @@ -5548,7 +5553,6 @@ static int proc_close( struct inode *inode, struct file *file ) changed. */ static void timer_func( struct net_device *dev ) { struct airo_info *apriv = dev->priv; - Resp rsp; /* We don't have a link so try changing the authtype */ readConfigRid(apriv, 0); @@ -5575,7 +5579,7 @@ static void timer_func( struct net_device *dev ) { } set_bit (FLAG_COMMIT, &apriv->flags); writeConfigRid(apriv, 0); - enable_MAC(apriv, &rsp, 0); + enable_MAC(apriv, 0); up(&apriv->sem); /* Schedule check to see if the change worked */ @@ -5597,8 +5601,10 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev, dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev); else dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev); - if (!dev) + if (!dev) { + pci_disable_device(pdev); return -ENODEV; + } pci_set_drvdata(pdev, dev); return 0; @@ -5610,6 +5616,8 @@ static void __devexit airo_pci_remove(struct pci_dev *pdev) airo_print_info(dev->name, "Unregistering..."); stop_airo_card(dev, 1); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); } static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) @@ -5646,7 +5654,6 @@ static int airo_pci_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct airo_info *ai = dev->priv; - Resp rsp; pci_power_t prev_state = pdev->current_state; pci_set_power_state(pdev, PCI_D0); @@ -5679,7 +5686,7 @@ static int airo_pci_resume(struct pci_dev *pdev) ai->APList = NULL; } writeConfigRid(ai, 0); - enable_MAC(ai, &rsp, 0); + enable_MAC(ai, 0); ai->power = PMSG_ON; netif_device_attach(dev); netif_wake_queue(dev); @@ -5903,7 +5910,6 @@ static int airo_set_essid(struct net_device *dev, char *extra) { struct airo_info *local = dev->priv; - Resp rsp; SsidRid SSID_rid; /* SSIDs */ /* Reload the list of current SSID */ @@ -5935,7 +5941,7 @@ static int airo_set_essid(struct net_device *dev, /* Write it to the card */ disable_MAC(local, 1); writeSsidRid(local, &SSID_rid, 1); - enable_MAC(local, &rsp, 1); + enable_MAC(local, 1); return 0; } @@ -6000,7 +6006,7 @@ static int airo_set_wap(struct net_device *dev, memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); disable_MAC(local, 1); writeAPListRid(local, &APList_rid, 1); - enable_MAC(local, &rsp, 1); + enable_MAC(local, 1); } return 0; } @@ -7454,7 +7460,6 @@ static int airo_config_commit(struct net_device *dev, char *extra) /* NULL */ { struct airo_info *local = dev->priv; - Resp rsp; if (!test_bit (FLAG_COMMIT, &local->flags)) return 0; @@ -7479,7 +7484,7 @@ static int airo_config_commit(struct net_device *dev, if (down_interruptible(&local->sem)) return -ERESTARTSYS; writeConfigRid(local, 0); - enable_MAC(local, &rsp, 0); + enable_MAC(local, 0); if (test_bit (FLAG_RESET, &local->flags)) airo_set_promisc(local); else @@ -7746,7 +7751,6 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { unsigned char *iobuf; int len; struct airo_info *ai = dev->priv; - Resp rsp; if (test_bit(FLAG_FLASHING, &ai->flags)) return -EIO; @@ -7758,7 +7762,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { if (test_bit(FLAG_COMMIT, &ai->flags)) { disable_MAC (ai, 1); writeConfigRid (ai, 1); - enable_MAC (ai, &rsp, 1); + enable_MAC(ai, 1); } break; case AIROGSLIST: ridcode = RID_SSID; break; @@ -7815,7 +7819,6 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { struct airo_info *ai = dev->priv; int ridcode; int enabled; - Resp rsp; static int (* writer)(struct airo_info *, u16 rid, const void *, int, int); unsigned char *iobuf; @@ -7849,7 +7852,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { * same with MAC off */ case AIROPMACON: - if (enable_MAC(ai, &rsp, 1) != 0) + if (enable_MAC(ai, 1) != 0) return -EIO; return 0; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index ef6b253a92ce..dfbd01eaaf34 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3183,6 +3183,9 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) unsigned long orig_trans_start = 0; mutex_lock(&bcm->mutex); + /* keep from doing and rearming periodic work if shutting down */ + if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT) + goto unlock_mutex; if (unlikely(bcm->periodic_state % 60 == 0)) { /* Periodic work will take a long time, so we want it to * be preemtible. @@ -3228,14 +3231,10 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) mmiowb(); bcm->periodic_state++; spin_unlock_irqrestore(&bcm->irq_lock, flags); +unlock_mutex: mutex_unlock(&bcm->mutex); } -void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) -{ - cancel_rearming_delayed_work(&bcm->periodic_work); -} - void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { struct delayed_work *work = &bcm->periodic_work; @@ -3285,6 +3284,14 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm) return err; } +void bcm43xx_cancel_work(struct bcm43xx_private *bcm) +{ + /* The system must be unlocked when this routine is entered. + * If not, the next 2 steps may deadlock */ + cancel_work_sync(&bcm->restart_work); + cancel_delayed_work_sync(&bcm->periodic_work); +} + static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) { int ret = 0; @@ -3321,7 +3328,12 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) { bcm43xx_rng_exit(bcm); bcm43xx_sysfs_unregister(bcm); - bcm43xx_periodic_tasks_delete(bcm); + + mutex_lock(&(bcm)->mutex); + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); + mutex_unlock(&(bcm)->mutex); + + bcm43xx_cancel_work(bcm); mutex_lock(&(bcm)->mutex); bcm43xx_shutdown_all_wireless_cores(bcm); @@ -3741,10 +3753,8 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) &bcm->board_type); if (err) goto err_iounmap; - err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID, - &bcm->board_revision); - if (err) - goto err_iounmap; + + bcm->board_revision = bcm->pci_dev->revision; err = bcm43xx_chipset_attach(bcm); if (err) @@ -4018,7 +4028,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev) err = bcm43xx_disable_interrupts_sync(bcm); assert(!err); bcm43xx_free_board(bcm); - flush_scheduled_work(); + bcm43xx_cancel_work(bcm); return 0; } @@ -4150,9 +4160,9 @@ static void bcm43xx_chip_reset(struct work_struct *work) struct bcm43xx_phyinfo *phy; int err = -ENODEV; + bcm43xx_cancel_work(bcm); mutex_lock(&(bcm)->mutex); if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - bcm43xx_periodic_tasks_delete(bcm); phy = bcm43xx_current_phy(bcm); err = bcm43xx_select_wireless_core(bcm, phy->type); if (!err) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index c8f3c532bab5..14cfbeb582ef 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_enable(struct bcm43xx_private *bcm); -void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm); +void bcm43xx_cancel_work(struct bcm43xx_private *bcm); void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index c71b998a3694..8ab5f93d192a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -327,7 +327,7 @@ static ssize_t bcm43xx_attr_phymode_store(struct device *dev, goto out; } - bcm43xx_periodic_tasks_delete(bcm); + bcm43xx_cancel_work(bcm); mutex_lock(&(bcm)->mutex); err = bcm43xx_select_wireless_core(bcm, phytype); if (!err) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index d6d9413d7f23..6acfdc49dccd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -444,7 +444,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, u16 maxpower; if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { - printk(PFX KERN_ERR "TX power not in dBm.\n"); + printk(KERN_ERR PFX "TX power not in dBm.\n"); return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 5b3abd54d0e5..90900525379c 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off, char *p = page; struct ap_data *ap = (struct ap_data *) data; char *policy_txt; - struct list_head *ptr; struct mac_entry *entry; if (off != 0) { @@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off, p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries); p += sprintf(p, "MAC list:\n"); spin_lock_bh(&ap->mac_restrictions.lock); - for (ptr = ap->mac_restrictions.mac_list.next; - ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) { + list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) { if (p - page > PAGE_SIZE - 80) { p += sprintf(p, "All entries did not fit one page.\n"); break; } - entry = list_entry(ptr, struct mac_entry, list); p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr)); } spin_unlock_bh(&ap->mac_restrictions.lock); @@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac) static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, u8 *mac) { - struct list_head *ptr; struct mac_entry *entry; int found = 0; @@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, return 0; spin_lock_bh(&mac_restrictions->lock); - for (ptr = mac_restrictions->mac_list.next; - ptr != &mac_restrictions->mac_list; ptr = ptr->next) { - entry = list_entry(ptr, struct mac_entry, list); - + list_for_each_entry(entry, &mac_restrictions->mac_list, list) { if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { found = 1; break; @@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off, { char *p = page; struct ap_data *ap = (struct ap_data *) data; - struct list_head *ptr; + struct sta_info *sta; int i; if (off > PROC_LIMIT) { @@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off, p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n"); spin_lock_bh(&ap->sta_table_lock); - for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { - struct sta_info *sta = (struct sta_info *) ptr; - + list_for_each_entry(sta, &ap->sta_list, list) { if (!sta->ap) continue; @@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local) void hostap_free_data(struct ap_data *ap) { - struct list_head *n, *ptr; + struct sta_info *n, *sta; if (ap == NULL || !ap->initialized) { printk(KERN_DEBUG "hostap_free_data: ap has not yet been " @@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap) ap->crypt = ap->crypt_priv = NULL; #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - list_for_each_safe(ptr, n, &ap->sta_list) { - struct sta_info *sta = list_entry(ptr, struct sta_info, list); + list_for_each_entry_safe(sta, n, &ap->sta_list, list) { ap_sta_hash_del(ap, sta); list_del(&sta->list); if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) @@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx) if (hdr->addr1[0] & 0x01) { /* broadcast/multicast frame - no AP related processing */ + if (local->ap->num_sta <= 0) + ret = AP_TX_DROP; goto out; } @@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap, void hostap_update_rates(local_info_t *local) { - struct list_head *ptr; + struct sta_info *sta; struct ap_data *ap = local->ap; if (!ap) return; spin_lock_bh(&ap->sta_table_lock); - for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { - struct sta_info *sta = (struct sta_info *) ptr; + list_for_each_entry(sta, &ap->sta_list, list) { prism2_check_tx_rates(sta); } spin_unlock_bh(&ap->sta_table_lock); @@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, void hostap_add_wds_links(local_info_t *local) { struct ap_data *ap = local->ap; - struct list_head *ptr; + struct sta_info *sta; spin_lock_bh(&ap->sta_table_lock); - list_for_each(ptr, &ap->sta_list) { - struct sta_info *sta = list_entry(ptr, struct sta_info, list); + list_for_each_entry(sta, &ap->sta_list, list) { if (sta->ap) hostap_wds_link_oper(local, sta->addr, WDS_ADD); } diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h index c090a5aebb58..30acd39d76a2 100644 --- a/drivers/net/wireless/hostap/hostap_config.h +++ b/drivers/net/wireless/hostap/hostap_config.h @@ -1,8 +1,6 @@ #ifndef HOSTAP_CONFIG_H #define HOSTAP_CONFIG_H -#define PRISM2_VERSION "0.4.4-kernel" - /* In the previous versions of Host AP driver, support for user space version * of IEEE 802.11 management (hostapd) used to be disabled in the default * configuration. From now on, support for hostapd is always included and it is diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index ee1532b62e42..30e723f65979 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -22,7 +22,6 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)"; static dev_info_t dev_info = "hostap_cs"; MODULE_AUTHOR("Jouni Malinen"); @@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " "cards (PC Card)."); MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); static int ignore_cis_vcc; @@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = { static int __init init_prism2_pccard(void) { - printk(KERN_INFO "%s: %s\n", dev_info, version); return pcmcia_register_driver(&hostap_driver); } static void __exit exit_prism2_pccard(void) { pcmcia_unregister_driver(&hostap_driver); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index cdea7f71b9eb..8c71077d653c 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev, local = iface->local; strncpy(info->driver, "hostap", sizeof(info->driver) - 1); - strncpy(info->version, PRISM2_VERSION, - sizeof(info->version) - 1); snprintf(info->fw_version, sizeof(info->fw_version) - 1, "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff, (local->sta_fw_ver >> 8) & 0xff, diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 4743426cf6ad..446de51bab74 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -37,7 +37,6 @@ MODULE_AUTHOR("Jouni Malinen"); MODULE_DESCRIPTION("Host AP common routines"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); #define TX_TIMEOUT (2 * HZ) diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index db4899ed4bb1..7da3664b8515 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -20,7 +20,6 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)"; static char *dev_info = "hostap_pci"; @@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN " "PCI cards."); MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); /* struct local_info::hw_priv */ @@ -455,15 +453,11 @@ static struct pci_driver prism2_pci_drv_id = { .suspend = prism2_pci_suspend, .resume = prism2_pci_resume, #endif /* CONFIG_PM */ - /* Linux 2.4.6 added save_state and enable_wake that are not used here - */ }; static int __init init_prism2_pci(void) { - printk(KERN_INFO "%s: %s\n", dev_info, version); - return pci_register_driver(&prism2_pci_drv_id); } @@ -471,7 +465,6 @@ static int __init init_prism2_pci(void) static void __exit exit_prism2_pci(void) { pci_unregister_driver(&prism2_pci_drv_id); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index f0fd5ecdb24d..040dc3e36410 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -23,7 +23,6 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)"; static char *dev_info = "hostap_plx"; @@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " "cards (PLX)."); MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); static int ignore_cis; @@ -615,16 +613,11 @@ static struct pci_driver prism2_plx_drv_id = { .id_table = prism2_plx_id_table, .probe = prism2_plx_probe, .remove = prism2_plx_remove, - .suspend = NULL, - .resume = NULL, - .enable_wake = NULL }; static int __init init_prism2_plx(void) { - printk(KERN_INFO "%s: %s\n", dev_info, version); - return pci_register_driver(&prism2_plx_drv_id); } @@ -632,7 +625,6 @@ static int __init init_prism2_plx(void) static void __exit exit_prism2_plx(void) { pci_unregister_driver(&prism2_plx_drv_id); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index d51daf87450f..8990585bd228 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1768,7 +1768,8 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) if (priv->stop_rf_kill) { priv->stop_rf_kill = 0; - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies(HZ)); } deferred = 1; @@ -2098,7 +2099,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) /* Make sure the RF Kill check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); } static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) @@ -4233,7 +4234,8 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies(HZ)); } else schedule_reset(priv); } @@ -5969,7 +5971,8 @@ static void ipw2100_rf_kill(struct work_struct *work) if (rf_kill_active(priv)) { IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n"); if (!priv->stop_rf_kill) - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies(HZ)); goto exit_unlock; } @@ -7865,10 +7868,10 @@ static int ipw2100_wx_set_powermode(struct net_device *dev, goto done; } - if ((mode < 1) || (mode > POWER_MODES)) + if ((mode < 0) || (mode > POWER_MODES)) mode = IPW_POWER_AUTO; - if (priv->power_mode != mode) + if (IPW_POWER_LEVEL(priv->power_mode) != mode) err = ipw2100_set_power_mode(priv, mode); done: mutex_unlock(&priv->action_mutex); @@ -7899,7 +7902,7 @@ static int ipw2100_wx_get_powermode(struct net_device *dev, break; case IPW_POWER_AUTO: snprintf(extra, MAX_POWER_STRING, - "Power save level: %d (Auto)", 0); + "Power save level: %d (Auto)", level); break; default: timeout = timeout_duration[level - 1] / 1000; diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 7cb2052a55a5..61497c467467 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -70,7 +70,7 @@ #define VQ #endif -#define IPW2200_VERSION "1.2.0" VK VD VM VP VR VQ +#define IPW2200_VERSION "1.2.2" VK VD VM VP VR VQ #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -1751,7 +1751,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ cancel_delayed_work(&priv->rf_kill); queue_delayed_work(priv->workqueue, &priv->rf_kill, - 2 * HZ); + round_jiffies(2 * HZ)); } else queue_work(priv->workqueue, &priv->up); } @@ -2506,7 +2506,7 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) break; } - param = cpu_to_le32(mode); + param = cpu_to_le32(param); return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), ¶m); } @@ -4690,7 +4690,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, else if (priv->config & CFG_BACKGROUND_SCAN && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, - &priv->request_scan, HZ); + &priv->request_scan, + round_jiffies(HZ)); /* Send an empty event to user space. * We don't send the received data on the event because @@ -9567,6 +9568,7 @@ static int ipw_wx_set_power(struct net_device *dev, priv->power_mode = IPW_POWER_ENABLED | IPW_POWER_BATTERY; else priv->power_mode = IPW_POWER_ENABLED | priv->power_mode; + err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); @@ -9603,22 +9605,19 @@ static int ipw_wx_set_powermode(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); int mode = *(int *)extra; int err; + mutex_lock(&priv->mutex); - if ((mode < 1) || (mode > IPW_POWER_LIMIT)) { + if ((mode < 1) || (mode > IPW_POWER_LIMIT)) mode = IPW_POWER_AC; - priv->power_mode = mode; - } else { - priv->power_mode = IPW_POWER_ENABLED | mode; - } - if (priv->power_mode != mode) { + if (IPW_POWER_LEVEL(priv->power_mode) != mode) { err = ipw_send_power_mode(priv, mode); - if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); mutex_unlock(&priv->mutex); return err; } + priv->power_mode = IPW_POWER_ENABLED | mode; } mutex_unlock(&priv->mutex); return 0; @@ -10554,7 +10553,7 @@ static irqreturn_t ipw_isr(int irq, void *data) spin_lock(&priv->irq_lock); if (!(priv->status & STATUS_INT_ENABLED)) { - /* Shared IRQ */ + /* IRQ is disabled */ goto none; } diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 13f6528abb00..4a8f5dc70239 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -240,7 +240,7 @@ static int wlan_cmd_802_11_enable_rsn(wlan_private * priv, if (*enable) penableRSN->enable = cpu_to_le16(cmd_enable_rsn); else - penableRSN->enable = cpu_to_le16(cmd_enable_rsn); + penableRSN->enable = cpu_to_le16(cmd_disable_rsn); } lbs_deb_leave(LBS_DEB_CMD); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4a59306a3f05..9f366242c392 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -613,6 +613,7 @@ static int wlan_service_main_thread(void *data) init_waitqueue_entry(&wait, current); + set_freezable(); for (;;) { lbs_deb_thread( "main-thread 111: intcounter=%d " "currenttxskb=%p dnld_sent=%d\n", diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 88d9d2d787d5..769c86fb9509 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -439,7 +439,6 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) ret = 0; done: - skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); return ret; } diff --git a/drivers/net/wireless/libertas/version.h b/drivers/net/wireless/libertas/version.h deleted file mode 100644 index 8b137891791f..000000000000 --- a/drivers/net/wireless/libertas/version.h +++ /dev/null @@ -1 +0,0 @@ - diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index f42b796b5e47..2fcc3bf21081 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1719,9 +1719,6 @@ static int wlan_set_encodeext(struct net_device *dev, pkey->type = KEY_TYPE_ID_TKIP; } else if (alg == IW_ENCODE_ALG_CCMP) { pkey->type = KEY_TYPE_ID_AES; - } else { - ret = -EINVAL; - goto out; } /* If WPA isn't enabled yet, do that now */ diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 283be4a70524..585f5996d292 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -1853,7 +1853,6 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info, islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; struct mac_entry *entry; - struct list_head *ptr; struct sockaddr *addr = (struct sockaddr *) extra; if (addr->sa_family != ARPHRD_ETHER) @@ -1861,11 +1860,9 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info, if (down_interruptible(&acl->sem)) return -ERESTARTSYS; - for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { - entry = list_entry(ptr, struct mac_entry, _list); - + list_for_each_entry(entry, &acl->mac_list, _list) { if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) { - list_del(ptr); + list_del(&entry->_list); acl->size--; kfree(entry); up(&acl->sem); @@ -1883,7 +1880,6 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; struct mac_entry *entry; - struct list_head *ptr; struct sockaddr *dst = (struct sockaddr *) extra; dwrq->length = 0; @@ -1891,9 +1887,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, if (down_interruptible(&acl->sem)) return -ERESTARTSYS; - for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { - entry = list_entry(ptr, struct mac_entry, _list); - + list_for_each_entry(entry, &acl->mac_list, _list) { memcpy(dst->sa_data, entry->addr, ETH_ALEN); dst->sa_family = ARPHRD_ETHER; dwrq->length++; @@ -1960,7 +1954,6 @@ prism54_get_policy(struct net_device *ndev, struct iw_request_info *info, static int prism54_mac_accept(struct islpci_acl *acl, char *mac) { - struct list_head *ptr; struct mac_entry *entry; int res = 0; @@ -1972,8 +1965,7 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac) return 1; } - for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { - entry = list_entry(ptr, struct mac_entry, _list); + list_for_each_entry(entry, &acl->mac_list, _list) { if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { res = 1; break; @@ -2216,11 +2208,9 @@ prism54_wpa_bss_ie_init(islpci_private *priv) void prism54_wpa_bss_ie_clean(islpci_private *priv) { - struct list_head *ptr, *n; + struct islpci_bss_wpa_ie *bss, *n; - list_for_each_safe(ptr, n, &priv->bss_wpa_list) { - struct islpci_bss_wpa_ie *bss; - bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); + list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) { kfree(bss); } } diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 3dcb13bb7d57..af2e4f2405f2 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -87,7 +87,6 @@ static struct pci_driver prism54_driver = { .remove = prism54_remove, .suspend = prism54_suspend, .resume = prism54_resume, - /* .enable_wake ; we don't support this yet */ }; /****************************************************************************** @@ -167,8 +166,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); /* enable MWI */ - if (!pci_set_mwi(pdev)) - printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME); + pci_try_set_mwi(pdev); /* setup the network device interface and its structure */ if (!(ndev = islpci_setup(pdev))) { diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index ce9230b2f630..c8b5c2271938 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1011,7 +1011,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev, } else { skb->dev = dev; skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */ - eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0); + skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12); wl3501_receive(this, skb->data, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, dev); diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile index 6603ad5be63d..4d505903352c 100644 --- a/drivers/net/wireless/zd1211rw/Makefile +++ b/drivers/net/wireless/zd1211rw/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o zd1211rw-objs := zd_chip.o zd_ieee80211.o \ zd_mac.o zd_netdev.o \ zd_rf_al2230.o zd_rf_rf2959.o \ - zd_rf_al7230b.o \ + zd_rf_al7230b.o zd_rf_uw2453.o \ zd_rf.o zd_usb.o zd_util.o ifeq ($(CONFIG_ZD1211RW_DEBUG),y) diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 95b4a2a26707..c39f1984b84d 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -49,8 +49,9 @@ void zd_chip_clear(struct zd_chip *chip) ZD_MEMCLEAR(chip, sizeof(*chip)); } -static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) +static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size) { + u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr; return scnprintf(buffer, size, "%02x-%02x-%02x", addr[0], addr[1], addr[2]); } @@ -61,10 +62,10 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) int i = 0; i = scnprintf(buffer, size, "zd1211%s chip ", - chip->is_zd1211b ? "b" : ""); + zd_chip_is_zd1211b(chip) ? "b" : ""); i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " "); - i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); + i += scnprint_mac_oui(chip, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " "); i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type, @@ -366,64 +367,9 @@ error: return r; } -static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr, - const zd_addr_t *addr) -{ - int r; - u32 parts[2]; - - r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2); - if (r) { - dev_dbg_f(zd_chip_dev(chip), - "error: couldn't read e2p macs. Error number %d\n", r); - return r; - } - - mac_addr[0] = parts[0]; - mac_addr[1] = parts[0] >> 8; - mac_addr[2] = parts[0] >> 16; - mac_addr[3] = parts[0] >> 24; - mac_addr[4] = parts[1]; - mac_addr[5] = parts[1] >> 8; - - return 0; -} - -static int read_e2p_mac_addr(struct zd_chip *chip) -{ - static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 }; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr); -} - /* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and * CR_MAC_ADDR_P2 must be overwritten */ -void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr) -{ - mutex_lock(&chip->mutex); - memcpy(mac_addr, chip->e2p_mac, ETH_ALEN); - mutex_unlock(&chip->mutex); -} - -static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr) -{ - static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 }; - return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr); -} - -int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr) -{ - int r; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - mutex_lock(&chip->mutex); - r = read_mac_addr(chip, mac_addr); - mutex_unlock(&chip->mutex); - return r; -} - int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) { int r; @@ -444,12 +390,6 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) mutex_lock(&chip->mutex); r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); -#ifdef DEBUG - { - u8 tmp[ETH_ALEN]; - read_mac_addr(chip, tmp); - } -#endif /* DEBUG */ mutex_unlock(&chip->mutex); return r; } @@ -809,7 +749,7 @@ out: static int hw_reset_phy(struct zd_chip *chip) { - return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) : + return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) : zd1211_hw_reset_phy(chip); } @@ -874,7 +814,7 @@ static int hw_init_hmac(struct zd_chip *chip) if (r) return r; - return chip->is_zd1211b ? + return zd_chip_is_zd1211b(chip) ? zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip); } @@ -1136,8 +1076,15 @@ static int read_fw_regs_offset(struct zd_chip *chip) return 0; } +/* Read mac address using pre-firmware interface */ +int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr) +{ + dev_dbg_f(zd_chip_dev(chip), "\n"); + return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr, + ETH_ALEN); +} -int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) +int zd_chip_init_hw(struct zd_chip *chip) { int r; u8 rf_type; @@ -1145,7 +1092,6 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) dev_dbg_f(zd_chip_dev(chip), "\n"); mutex_lock(&chip->mutex); - chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0; #ifdef DEBUG r = test_init(chip); @@ -1201,10 +1147,6 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) goto out; #endif /* DEBUG */ - r = read_e2p_mac_addr(chip); - if (r) - goto out; - r = read_cal_int_tables(chip); if (r) goto out; @@ -1253,10 +1195,13 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip, { int r; + if (!zd_rf_should_update_pwr_int(&chip->rf)) + return 0; + r = update_pwr_int(chip, channel); if (r) return r; - if (chip->is_zd1211b) { + if (zd_chip_is_zd1211b(chip)) { static const struct zd_ioreq16 ioreqs[] = { { CR69, 0x28 }, {}, @@ -1283,7 +1228,7 @@ static int patch_cck_gain(struct zd_chip *chip) int r; u32 value; - if (!chip->patch_cck_gain) + if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf)) return 0; ZD_ASSERT(mutex_is_locked(&chip->mutex)); diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index ce0a5f6da0d2..f4698576ab71 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -608,6 +608,9 @@ enum { #define CR_ZD1211B_TXOP CTL_REG(0x0b20) #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) +/* Used to detect PLL lock */ +#define UW2453_INTR_REG ((zd_addr_t)0x85c1) + #define CWIN_SIZE 0x007f043f @@ -701,7 +704,6 @@ struct zd_chip { struct mutex mutex; /* Base address of FW_REG_ registers */ zd_addr_t fw_regs_base; - u8 e2p_mac[ETH_ALEN]; /* EepSetPoint in the vendor driver */ u8 pwr_cal_values[E2P_CHANNEL_COUNT]; /* integration values in the vendor driver */ @@ -712,7 +714,7 @@ struct zd_chip { unsigned int pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, new_phy_layout:1, al2230s_bit:1, - is_zd1211b:1, supports_tx_led:1; + supports_tx_led:1; }; static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) @@ -731,9 +733,15 @@ void zd_chip_init(struct zd_chip *chip, struct net_device *netdev, struct usb_interface *intf); void zd_chip_clear(struct zd_chip *chip); -int zd_chip_init_hw(struct zd_chip *chip, u8 device_type); +int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr); +int zd_chip_init_hw(struct zd_chip *chip); int zd_chip_reset(struct zd_chip *chip); +static inline int zd_chip_is_zd1211b(struct zd_chip *chip) +{ + return chip->usb.is_zd1211b; +} + static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values, const zd_addr_t *addresses, unsigned int count) @@ -822,8 +830,6 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip) } u8 zd_chip_get_channel(struct zd_chip *chip); int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); -void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr); -int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr); int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); int zd_chip_switch_radio_on(struct zd_chip *chip); int zd_chip_switch_radio_off(struct zd_chip *chip); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6753d240c168..26869d107e52 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -86,38 +86,46 @@ out: return r; } -int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) +int zd_mac_preinit_hw(struct zd_mac *mac) { int r; - struct zd_chip *chip = &mac->chip; u8 addr[ETH_ALEN]; + + r = zd_chip_read_mac_addr_fw(&mac->chip, addr); + if (r) + return r; + + memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); + return 0; +} + +int zd_mac_init_hw(struct zd_mac *mac) +{ + int r; + struct zd_chip *chip = &mac->chip; u8 default_regdomain; r = zd_chip_enable_int(chip); if (r) goto out; - r = zd_chip_init_hw(chip, device_type); + r = zd_chip_init_hw(chip); if (r) goto disable_int; - zd_get_e2p_mac_addr(chip, addr); - r = zd_write_mac_addr(chip, addr); - if (r) - goto disable_int; ZD_ASSERT(!irqs_disabled()); - spin_lock_irq(&mac->lock); - memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); - spin_unlock_irq(&mac->lock); r = zd_read_regdomain(chip, &default_regdomain); if (r) goto disable_int; if (!zd_regdomain_supported(default_regdomain)) { - dev_dbg_f(zd_mac_dev(mac), - "Regulatory Domain %#04x is not supported.\n", - default_regdomain); - r = -EINVAL; - goto disable_int; + /* The vendor driver overrides the regulatory domain and + * allowed channel registers and unconditionally restricts + * available channels to 1-11 everywhere. Match their + * questionable behaviour only for regdomains which we don't + * recognise. */ + dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: " + "%#04x. Defaulting to FCC.\n", default_regdomain); + default_regdomain = ZD_REGDOMAIN_FCC; } spin_lock_irq(&mac->lock); mac->regdomain = mac->default_regdomain = default_regdomain; @@ -164,14 +172,25 @@ int zd_mac_open(struct net_device *netdev) { struct zd_mac *mac = zd_netdev_mac(netdev); struct zd_chip *chip = &mac->chip; + struct zd_usb *usb = &chip->usb; int r; + if (!usb->initialized) { + r = zd_usb_init_hw(usb); + if (r) + goto out; + } + tasklet_enable(&mac->rx_tasklet); r = zd_chip_enable_int(chip); if (r < 0) goto out; + r = zd_write_mac_addr(chip, netdev->dev_addr); + if (r) + goto disable_int; + r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G); if (r < 0) goto disable_int; @@ -251,9 +270,11 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p) dev_dbg_f(zd_mac_dev(mac), "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data)); - r = zd_write_mac_addr(chip, addr->sa_data); - if (r) - return r; + if (netdev->flags & IFF_UP) { + r = zd_write_mac_addr(chip, addr->sa_data); + if (r) + return r; + } spin_lock_irqsave(&mac->lock, flags); memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN); @@ -801,7 +822,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, cs->control |= ZD_CS_MULTICAST; /* PS-POLL */ - if (stype == IEEE80211_STYPE_PSPOLL) + if (ftype == IEEE80211_FTYPE_CTL && stype == IEEE80211_STYPE_PSPOLL) cs->control |= ZD_CS_PS_POLL_FRAME; /* Unicast data frames over the threshold should have RTS */ @@ -855,7 +876,7 @@ static int fill_ctrlset(struct zd_mac *mac, /* ZD1211B: Computing the length difference this way, gives us * flexibility to compute the packet length. */ - cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ? + cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ? packet_length - frag_len : packet_length); /* diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index faf4c7828d4e..9f9344eb50f9 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -189,7 +189,8 @@ int zd_mac_init(struct zd_mac *mac, struct usb_interface *intf); void zd_mac_clear(struct zd_mac *mac); -int zd_mac_init_hw(struct zd_mac *mac, u8 device_type); +int zd_mac_preinit_hw(struct zd_mac *mac); +int zd_mac_init_hw(struct zd_mac *mac); int zd_mac_open(struct net_device *netdev); int zd_mac_stop(struct net_device *netdev); diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c index 549c23bcd6cc..abe5d38f7f4d 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.c +++ b/drivers/net/wireless/zd1211rw/zd_rf.c @@ -34,7 +34,7 @@ static const char * const rfs[] = { [AL2210_RF] = "AL2210_RF", [MAXIM_NEW_RF] = "MAXIM_NEW_RF", [UW2453_RF] = "UW2453_RF", - [UNKNOWN_A_RF] = "UNKNOWN_A_RF", + [AL2230S_RF] = "AL2230S_RF", [RALINK_RF] = "RALINK_RF", [INTERSIL_RF] = "INTERSIL_RF", [RF2959_RF] = "RF2959_RF", @@ -52,34 +52,39 @@ const char *zd_rf_name(u8 type) void zd_rf_init(struct zd_rf *rf) { memset(rf, 0, sizeof(*rf)); + + /* default to update channel integration, as almost all RF's do want + * this */ + rf->update_channel_int = 1; } void zd_rf_clear(struct zd_rf *rf) { + if (rf->clear) + rf->clear(rf); ZD_MEMCLEAR(rf, sizeof(*rf)); } int zd_rf_init_hw(struct zd_rf *rf, u8 type) { - int r, t; + int r = 0; + int t; struct zd_chip *chip = zd_rf_to_chip(rf); ZD_ASSERT(mutex_is_locked(&chip->mutex)); switch (type) { case RF2959_RF: r = zd_rf_init_rf2959(rf); - if (r) - return r; break; case AL2230_RF: + case AL2230S_RF: r = zd_rf_init_al2230(rf); - if (r) - return r; break; case AL7230B_RF: r = zd_rf_init_al7230b(rf); - if (r) - return r; + break; + case UW2453_RF: + r = zd_rf_init_uw2453(rf); break; default: dev_err(zd_chip_dev(chip), @@ -88,6 +93,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type) return -ENODEV; } + if (r) + return r; + rf->type = type; r = zd_chip_lock_phy_regs(chip); diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h index aa9cc105ce60..30502f26b71c 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/drivers/net/wireless/zd1211rw/zd_rf.h @@ -26,7 +26,7 @@ #define AL2210_RF 0x7 #define MAXIM_NEW_RF 0x8 #define UW2453_RF 0x9 -#define UNKNOWN_A_RF 0xa +#define AL2230S_RF 0xa #define RALINK_RF 0xb #define INTERSIL_RF 0xc #define RF2959_RF 0xd @@ -48,12 +48,26 @@ struct zd_rf { u8 channel; + /* whether channel integration and calibration should be updated + * defaults to 1 (yes) */ + u8 update_channel_int:1; + + /* whether CR47 should be patched from the EEPROM, if the appropriate + * flag is set in the POD. The vendor driver suggests that this should + * be done for all RF's, but a bug in their code prevents but their + * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */ + u8 patch_cck_gain:1; + + /* private RF driver data */ + void *priv; + /* RF-specific functions */ int (*init_hw)(struct zd_rf *rf); int (*set_channel)(struct zd_rf *rf, u8 channel); int (*switch_radio_on)(struct zd_rf *rf); int (*switch_radio_off)(struct zd_rf *rf); int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel); + void (*clear)(struct zd_rf *rf); }; const char *zd_rf_name(u8 type); @@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf); int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel); int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel); +static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf) +{ + return rf->update_channel_int; +} + +static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf) +{ + return rf->patch_cck_gain; +} + +int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel); +int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel); + /* Functions for individual RF chips */ int zd_rf_init_rf2959(struct zd_rf *rf); int zd_rf_init_al2230(struct zd_rf *rf); int zd_rf_init_al7230b(struct zd_rf *rf); +int zd_rf_init_uw2453(struct zd_rf *rf); #endif /* _ZD_RF_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 511392acfedf..006774de3202 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -21,6 +21,8 @@ #include "zd_usb.h" #include "zd_chip.h" +#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF) + static const u32 zd1211_al2230_table[][3] = { RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, @@ -176,7 +178,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) if (r) return r; - if (chip->al2230s_bit) { + if (IS_AL2230S(chip)) { r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s, ARRAY_SIZE(ioreqs_init_al2230s)); if (r) @@ -188,7 +190,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) return r; /* improve band edge for AL2230S */ - if (chip->al2230s_bit) + if (IS_AL2230S(chip)) r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS); else r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS); @@ -314,7 +316,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) if (r) return r; - if (chip->al2230s_bit) { + if (IS_AL2230S(chip)) { r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s, ARRAY_SIZE(ioreqs_init_al2230s)); if (r) @@ -328,7 +330,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) if (r) return r; - if (chip->al2230s_bit) + if (IS_AL2230S(chip)) r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS); else r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS); @@ -422,7 +424,7 @@ int zd_rf_init_al2230(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); rf->switch_radio_off = al2230_switch_radio_off; - if (chip->is_zd1211b) { + if (zd_chip_is_zd1211b(chip)) { rf->init_hw = zd1211b_al2230_init_hw; rf->set_channel = zd1211b_al2230_set_channel; rf->switch_radio_on = zd1211b_al2230_switch_radio_on; @@ -432,5 +434,6 @@ int zd_rf_init_al2230(struct zd_rf *rf) rf->switch_radio_on = zd1211_al2230_switch_radio_on; } rf->patch_6m_band_edge = zd_rf_generic_patch_6m; + rf->patch_cck_gain = 1; return 0; } diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c index 5e5e9ddc6a74..73d0bb26f810 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c @@ -473,7 +473,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); - if (chip->is_zd1211b) { + if (zd_chip_is_zd1211b(chip)) { rf->init_hw = zd1211b_al7230b_init_hw; rf->switch_radio_on = zd1211b_al7230b_switch_radio_on; rf->set_channel = zd1211b_al7230b_set_channel; @@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf) rf->switch_radio_on = zd1211_al7230b_switch_radio_on; rf->set_channel = zd1211_al7230b_set_channel; rf->patch_6m_band_edge = zd_rf_generic_patch_6m; + rf->patch_cck_gain = 1; } rf->switch_radio_off = al7230b_switch_radio_off; diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c index 2d736bdf707c..cc70d40684ea 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c @@ -265,7 +265,7 @@ int zd_rf_init_rf2959(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); - if (chip->is_zd1211b) { + if (zd_chip_is_zd1211b(chip)) { dev_err(zd_chip_dev(chip), "RF2959 is currently not supported for ZD1211B" " devices\n"); diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 8459549d0cee..a9c339ef116a 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -15,7 +15,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <asm/unaligned.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> @@ -26,6 +25,7 @@ #include <linux/usb.h> #include <linux/workqueue.h> #include <net/ieee80211.h> +#include <asm/unaligned.h> #include "zd_def.h" #include "zd_netdev.h" @@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, @@ -70,6 +71,9 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x129b, 0x1667), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, @@ -194,26 +198,27 @@ static u16 get_word(const void *data, u16 offset) return le16_to_cpu(p[offset]); } -static char *get_fw_name(char *buffer, size_t size, u8 device_type, +static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size, const char* postfix) { scnprintf(buffer, size, "%s%s", - device_type == DEVICE_ZD1211B ? + usb->is_zd1211b ? FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, postfix); return buffer; } -static int handle_version_mismatch(struct usb_device *udev, u8 device_type, +static int handle_version_mismatch(struct zd_usb *usb, const struct firmware *ub_fw) { + struct usb_device *udev = zd_usb_to_usbdev(usb); const struct firmware *ur_fw = NULL; int offset; int r = 0; char fw_name[128]; r = request_fw_file(&ur_fw, - get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"), + get_fw_name(usb, fw_name, sizeof(fw_name), "ur"), &udev->dev); if (r) goto error; @@ -236,11 +241,12 @@ error: return r; } -static int upload_firmware(struct usb_device *udev, u8 device_type) +static int upload_firmware(struct zd_usb *usb) { int r; u16 fw_bcdDevice; u16 bcdDevice; + struct usb_device *udev = zd_usb_to_usbdev(usb); const struct firmware *ub_fw = NULL; const struct firmware *uph_fw = NULL; char fw_name[128]; @@ -248,7 +254,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) bcdDevice = get_bcdDevice(udev); r = request_fw_file(&ub_fw, - get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"), + get_fw_name(usb, fw_name, sizeof(fw_name), "ub"), &udev->dev); if (r) goto error; @@ -263,7 +269,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) dev_warn(&udev->dev, "device has old bootcode, please " "report success or failure\n"); - r = handle_version_mismatch(udev, device_type, ub_fw); + r = handle_version_mismatch(usb, ub_fw); if (r) goto error; } else { @@ -274,7 +280,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) r = request_fw_file(&uph_fw, - get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"), + get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"), &udev->dev); if (r) goto error; @@ -293,6 +299,30 @@ error: return r; } +/* Read data from device address space using "firmware interface" which does + * not require firmware to be loaded. */ +int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len) +{ + int r; + struct usb_device *udev = zd_usb_to_usbdev(usb); + + r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0, + data, len, 5000); + if (r < 0) { + dev_err(&udev->dev, + "read over firmware interface failed: %d\n", r); + return r; + } else if (r != len) { + dev_err(&udev->dev, + "incomplete read over firmware interface: %d/%d\n", + r, len); + return -EIO; + } + + return 0; +} + #define urb_dev(urb) (&(urb)->dev->dev) static inline void handle_regs_int(struct urb *urb) @@ -919,9 +949,42 @@ static int eject_installer(struct usb_interface *intf) return 0; } +int zd_usb_init_hw(struct zd_usb *usb) +{ + int r; + struct zd_mac *mac = zd_usb_to_mac(usb); + + dev_dbg_f(zd_usb_dev(usb), "\n"); + + r = upload_firmware(usb); + if (r) { + dev_err(zd_usb_dev(usb), + "couldn't load firmware. Error number %d\n", r); + return r; + } + + r = usb_reset_configuration(zd_usb_to_usbdev(usb)); + if (r) { + dev_dbg_f(zd_usb_dev(usb), + "couldn't reset configuration. Error number %d\n", r); + return r; + } + + r = zd_mac_init_hw(mac); + if (r) { + dev_dbg_f(zd_usb_dev(usb), + "couldn't initialize mac. Error number %d\n", r); + return r; + } + + usb->initialized = 1; + return 0; +} + static int probe(struct usb_interface *intf, const struct usb_device_id *id) { int r; + struct zd_usb *usb; struct usb_device *udev = interface_to_usbdev(intf); struct net_device *netdev = NULL; @@ -949,26 +1012,10 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id) goto error; } - r = upload_firmware(udev, id->driver_info); - if (r) { - dev_err(&intf->dev, - "couldn't load firmware. Error number %d\n", r); - goto error; - } + usb = &zd_netdev_mac(netdev)->chip.usb; + usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0; - r = usb_reset_configuration(udev); - if (r) { - dev_dbg_f(&intf->dev, - "couldn't reset configuration. Error number %d\n", r); - goto error; - } - - /* At this point the interrupt endpoint is not generally enabled. We - * save the USB bandwidth until the network device is opened. But - * notify that the initialization of the MAC will require the - * interrupts to be temporary enabled. - */ - r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info); + r = zd_mac_preinit_hw(zd_netdev_mac(netdev)); if (r) { dev_dbg_f(&intf->dev, "couldn't initialize mac. Error number %d\n", r); diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index 506ea6a74393..961a7a12ad68 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h @@ -188,6 +188,7 @@ struct zd_usb { struct zd_usb_rx rx; struct zd_usb_tx tx; struct usb_interface *intf; + u8 is_zd1211b:1, initialized:1; }; #define zd_usb_dev(usb) (&usb->intf->dev) @@ -236,6 +237,8 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits); +int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len); + extern struct workqueue_struct *zd_workqueue; #endif /* _ZD_USB_H */ diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index f2a90a7fa2d6..870c5393c21a 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -1137,7 +1137,7 @@ static int yellowfin_rx(struct net_device *dev) if (skb == NULL) break; skb_reserve(skb, 2); /* 16 byte align the IP header */ - eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0); + skb_copy_to_linear_data(skb, rx_skb->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(yp->pci_dev, desc->addr, yp->rx_buf_sz, |