diff options
Diffstat (limited to 'drivers/net/e100.c')
-rw-r--r-- | drivers/net/e100.c | 278 |
1 files changed, 237 insertions, 41 deletions
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 4a47df5a9ff9..25cc20e415da 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -143,6 +143,7 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/mii.h> @@ -155,7 +156,7 @@ #define DRV_NAME "e100" #define DRV_EXT "-NAPI" -#define DRV_VERSION "3.4.8-k2"DRV_EXT +#define DRV_VERSION "3.4.14-k2"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation" #define PFX DRV_NAME ": " @@ -784,6 +785,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) } #define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ +#define E100_WAIT_SCB_FAST 20 /* delay like the old code */ static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) { unsigned long flags; @@ -797,7 +799,7 @@ static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) if(likely(!readb(&nic->csr->scb.cmd_lo))) break; cpu_relax(); - if(unlikely(i > (E100_WAIT_SCB_TIMEOUT >> 1))) + if(unlikely(i > E100_WAIT_SCB_FAST)) udelay(5); } if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { @@ -901,8 +903,8 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data) static void e100_get_defaults(struct nic *nic) { - struct param_range rfds = { .min = 16, .max = 256, .count = 64 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 64 }; + struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; + struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ @@ -1005,25 +1007,213 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); } +/********************************************************/ +/* Micro code for 8086:1229 Rev 8 */ +/********************************************************/ + +/* Parameter values for the D101M B-step */ +#define D101M_CPUSAVER_TIMER_DWORD 78 +#define D101M_CPUSAVER_BUNDLE_DWORD 65 +#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 + +#define D101M_B_RCVBUNDLE_UCODE \ +{\ +0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ +0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ +0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ +0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ +0x00380438, 0x00000000, 0x00140000, 0x00380555, \ +0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ +0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ +0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ +0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ +0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ +0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ +0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ +0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ +0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ +0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ +0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ +0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ +0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ +0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ +0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ +0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ +0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ +0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ +0x00380559, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ +0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ +0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ +} + +/********************************************************/ +/* Micro code for 8086:1229 Rev 9 */ +/********************************************************/ + +/* Parameter values for the D101S */ +#define D101S_CPUSAVER_TIMER_DWORD 78 +#define D101S_CPUSAVER_BUNDLE_DWORD 67 +#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 + +#define D101S_RCVBUNDLE_UCODE \ +{\ +0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ +0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ +0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ +0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ +0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ +0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ +0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ +0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ +0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ +0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ +0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ +0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ +0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ +0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ +0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ +0x00101313, 0x00380700, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ +0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ +0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ +0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ +0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ +0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ +0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ +0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ +0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ +0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00130831, \ +0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ +0x00041000, 0x00010004, 0x00380700 \ +} + +/********************************************************/ +/* Micro code for the 8086:1229 Rev F/10 */ +/********************************************************/ + +/* Parameter values for the D102 E-step */ +#define D102_E_CPUSAVER_TIMER_DWORD 42 +#define D102_E_CPUSAVER_BUNDLE_DWORD 54 +#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 + +#define D102_E_RCVBUNDLE_UCODE \ +{\ +0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ +0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ +0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ +0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ +0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ +0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ +0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +0x00000000, 0x00000000, 0x00000000, 0x00000000, \ +} + static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) { - int i; - static const u32 ucode[UCODE_SIZE] = { - /* NFS packets are misinterpreted as TCO packets and - * incorrectly routed to the BMC over SMBus. This - * microcode patch checks the fragmented IP bit in the - * NFS/UDP header to distinguish between NFS and TCO. */ - 0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, - 0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, - 0x00906EFD, 0x00900EFD, 0x00E00EF8, - }; +/* *INDENT-OFF* */ + static struct { + u32 ucode[UCODE_SIZE + 1]; + u8 mac; + u8 timer_dword; + u8 bundle_dword; + u8 min_size_dword; + } ucode_opts[] = { + { D101M_B_RCVBUNDLE_UCODE, + mac_82559_D101M, + D101M_CPUSAVER_TIMER_DWORD, + D101M_CPUSAVER_BUNDLE_DWORD, + D101M_CPUSAVER_MIN_SIZE_DWORD }, + { D101S_RCVBUNDLE_UCODE, + mac_82559_D101S, + D101S_CPUSAVER_TIMER_DWORD, + D101S_CPUSAVER_BUNDLE_DWORD, + D101S_CPUSAVER_MIN_SIZE_DWORD }, + { D102_E_RCVBUNDLE_UCODE, + mac_82551_F, + D102_E_CPUSAVER_TIMER_DWORD, + D102_E_CPUSAVER_BUNDLE_DWORD, + D102_E_CPUSAVER_MIN_SIZE_DWORD }, + { D102_E_RCVBUNDLE_UCODE, + mac_82551_10, + D102_E_CPUSAVER_TIMER_DWORD, + D102_E_CPUSAVER_BUNDLE_DWORD, + D102_E_CPUSAVER_MIN_SIZE_DWORD }, + { {0}, 0, 0, 0, 0} + }, *opts; +/* *INDENT-ON* */ + +#define BUNDLESMALL 1 +#define BUNDLEMAX 50 +#define INTDELAY 15000 + + opts = ucode_opts; + + /* do not load u-code for ICH devices */ + if (nic->flags & ich) + return; + + /* Search for ucode match against h/w rev_id */ + while (opts->mac) { + if (nic->mac == opts->mac) { + int i; + u32 *ucode = opts->ucode; + + /* Insert user-tunable settings */ + ucode[opts->timer_dword] &= 0xFFFF0000; + ucode[opts->timer_dword] |= + (u16) INTDELAY; + ucode[opts->bundle_dword] &= 0xFFFF0000; + ucode[opts->bundle_dword] |= (u16) BUNDLEMAX; + ucode[opts->min_size_dword] &= 0xFFFF0000; + ucode[opts->min_size_dword] |= + (BUNDLESMALL) ? 0xFFFF : 0xFF80; + + for(i = 0; i < UCODE_SIZE; i++) + cb->u.ucode[i] = cpu_to_le32(ucode[i]); + cb->command = cpu_to_le16(cb_ucode); + return; + } + opts++; + } - if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) { - for(i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode); - } else - cb->command = cpu_to_le16(cb_nop); + cb->command = cpu_to_le16(cb_nop); } static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, @@ -1092,11 +1282,16 @@ static int e100_phy_init(struct nic *nic) } if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) - /* enable/disable MDI/MDI-X auto-switching */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); + (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) { + /* enable/disable MDI/MDI-X auto-switching. + MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */ + if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) || + (nic->mac == mac_82551_10) || (nic->mii.force_media) || + !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)) + mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0); + else + mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH); + } return 0; } @@ -1301,14 +1496,15 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, { cb->command = nic->tx_command; /* interrupt every 16 packets regardless of delay */ - if((nic->cbs_avail & ~15) == nic->cbs_avail) cb->command |= cb_i; + if((nic->cbs_avail & ~15) == nic->cbs_avail) + cb->command |= cpu_to_le16(cb_i); cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); cb->u.tcb.tcb_byte_count = 0; cb->u.tcb.threshold = nic->tx_threshold; cb->u.tcb.tbd_count = 1; cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); - // check for mapping failure? + /* check for mapping failure? */ cb->u.tcb.tbd.size = cpu_to_le16(skb->len); } @@ -1533,7 +1729,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, /* Don't indicate if hardware indicates errors */ nic->net_stats.rx_dropped++; dev_kfree_skb_any(skb); - } else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) { + } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { /* Don't indicate oversized frames */ nic->rx_over_length_errors++; nic->net_stats.rx_dropped++; @@ -1665,8 +1861,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs) if(stat_ack & stat_ack_rnr) nic->ru_running = RU_SUSPENDED; - e100_disable_irq(nic); - netif_rx_schedule(netdev); + if(likely(netif_rx_schedule_prep(netdev))) { + e100_disable_irq(nic); + __netif_rx_schedule(netdev); + } return IRQ_HANDLED; } @@ -1698,6 +1896,7 @@ static int e100_poll(struct net_device *netdev, int *budget) static void e100_netpoll(struct net_device *netdev) { struct nic *nic = netdev_priv(netdev); + e100_disable_irq(nic); e100_intr(nic->pdev->irq, netdev, NULL); e100_tx_clean(nic); @@ -2100,6 +2299,8 @@ static void e100_diag_test(struct net_device *netdev, } for(i = 0; i < E100_TEST_LEN; i++) test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; + + msleep_interruptible(4 * 1000); } static int e100_phys_id(struct net_device *netdev, u32 data) @@ -2286,7 +2487,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, goto err_out_disable_pdev; } - if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) { + if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); goto err_out_free_res; } @@ -2334,11 +2535,11 @@ static int __devinit e100_probe(struct pci_dev *pdev, goto err_out_iounmap; } - e100_phy_init(nic); - if((err = e100_eeprom_load(nic))) goto err_out_free; + e100_phy_init(nic); + memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); if(!is_valid_ether_addr(netdev->dev_addr)) { DPRINTK(PROBE, ERR, "Invalid MAC address from " @@ -2439,9 +2640,8 @@ static int e100_resume(struct pci_dev *pdev) #endif -static void e100_shutdown(struct device *dev) +static void e100_shutdown(struct pci_dev *pdev) { - struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); @@ -2462,11 +2662,7 @@ static struct pci_driver e100_driver = { .suspend = e100_suspend, .resume = e100_resume, #endif - - .driver = { - .shutdown = e100_shutdown, - } - + .shutdown = e100_shutdown, }; static int __init e100_init_module(void) |