diff options
Diffstat (limited to 'drivers/net/e1000')
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 86 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_hw.h | 88 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 228 |
3 files changed, 248 insertions, 154 deletions
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index b83ccce8a9b..d876787ce33 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -110,7 +110,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { "Interrupt test (offline)", "Loopback test (offline)", "Link test (on/offline)" }; -#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN +#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) static int e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) @@ -728,39 +728,65 @@ err_setup: return err; } -#define REG_PATTERN_TEST(R, M, W) \ -{ \ - uint32_t pat, val; \ - const uint32_t test[] = \ - {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ - for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \ - E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ - val = E1000_READ_REG(&adapter->hw, R); \ - if (val != (test[pat] & W & M)) { \ - DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ - "0x%08X expected 0x%08X\n", \ - E1000_##R, val, (test[pat] & W & M)); \ - *data = (adapter->hw.mac_type < e1000_82543) ? \ - E1000_82542_##R : E1000_##R; \ - return 1; \ - } \ - } \ +static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data, + int reg, uint32_t mask, uint32_t write) +{ + static const uint32_t test[] = + {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; + uint8_t __iomem *address = adapter->hw.hw_addr + reg; + uint32_t read; + int i; + + for (i = 0; i < ARRAY_SIZE(test); i++) { + writel(write & test[i], address); + read = readl(address); + if (read != (write & test[i] & mask)) { + DPRINTK(DRV, ERR, "pattern test reg %04X failed: " + "got 0x%08X expected 0x%08X\n", + reg, read, (write & test[i] & mask)); + *data = reg; + return true; + } + } + return false; } -#define REG_SET_AND_CHECK(R, M, W) \ -{ \ - uint32_t val; \ - E1000_WRITE_REG(&adapter->hw, R, W & M); \ - val = E1000_READ_REG(&adapter->hw, R); \ - if ((W & M) != (val & M)) { \ - DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ - "expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \ - *data = (adapter->hw.mac_type < e1000_82543) ? \ - E1000_82542_##R : E1000_##R; \ - return 1; \ - } \ +static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data, + int reg, uint32_t mask, uint32_t write) +{ + uint8_t __iomem *address = adapter->hw.hw_addr + reg; + uint32_t read; + + writel(write & mask, address); + read = readl(address); + if ((read & mask) != (write & mask)) { + DPRINTK(DRV, ERR, "set/check reg %04X test failed: " + "got 0x%08X expected 0x%08X\n", + reg, (read & mask), (write & mask)); + *data = reg; + return true; + } + return false; } +#define REG_PATTERN_TEST(reg, mask, write) \ + do { \ + if (reg_pattern_test(adapter, data, \ + (adapter->hw.mac_type >= e1000_82543) \ + ? E1000_##reg : E1000_82542_##reg, \ + mask, write)) \ + return 1; \ + } while (0) + +#define REG_SET_AND_CHECK(reg, mask, write) \ + do { \ + if (reg_set_and_check(adapter, data, \ + (adapter->hw.mac_type >= e1000_82543) \ + ? E1000_##reg : E1000_82542_##reg, \ + mask, write)) \ + return 1; \ + } while (0) + static int e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) { diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index a2a86c54a75..a6c3c34feb9 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -421,8 +421,6 @@ void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, u void e1000_get_bus_info(struct e1000_hw *hw); void e1000_pci_set_mwi(struct e1000_hw *hw); void e1000_pci_clear_mwi(struct e1000_hw *hw); -void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); -void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value); void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc); int e1000_pcix_get_mmrbc(struct e1000_hw *hw); @@ -595,35 +593,35 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); /* Receive Descriptor */ struct e1000_rx_desc { - uint64_t buffer_addr; /* Address of the descriptor's data buffer */ - uint16_t length; /* Length of data DMAed into data buffer */ - uint16_t csum; /* Packet checksum */ + __le64 buffer_addr; /* Address of the descriptor's data buffer */ + __le16 length; /* Length of data DMAed into data buffer */ + __le16 csum; /* Packet checksum */ uint8_t status; /* Descriptor status */ uint8_t errors; /* Descriptor Errors */ - uint16_t special; + __le16 special; }; /* Receive Descriptor - Extended */ union e1000_rx_desc_extended { struct { - uint64_t buffer_addr; - uint64_t reserved; + __le64 buffer_addr; + __le64 reserved; } read; struct { struct { - uint32_t mrq; /* Multiple Rx Queues */ + __le32 mrq; /* Multiple Rx Queues */ union { - uint32_t rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - uint16_t ip_id; /* IP id */ - uint16_t csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - uint32_t status_error; /* ext status/error */ - uint16_t length; - uint16_t vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length; + __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; @@ -633,29 +631,29 @@ union e1000_rx_desc_extended { union e1000_rx_desc_packet_split { struct { /* one buffer for protocol header(s), three data buffers */ - uint64_t buffer_addr[MAX_PS_BUFFERS]; + __le64 buffer_addr[MAX_PS_BUFFERS]; } read; struct { struct { - uint32_t mrq; /* Multiple Rx Queues */ + __le32 mrq; /* Multiple Rx Queues */ union { - uint32_t rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - uint16_t ip_id; /* IP id */ - uint16_t csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - uint32_t status_error; /* ext status/error */ - uint16_t length0; /* length of buffer 0 */ - uint16_t vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length0; /* length of buffer 0 */ + __le16 vlan; /* VLAN tag */ } middle; struct { - uint16_t header_status; - uint16_t length[3]; /* length of buffers 1-3 */ + __le16 header_status; + __le16 length[3]; /* length of buffers 1-3 */ } upper; - uint64_t reserved; + __le64 reserved; } wb; /* writeback */ }; @@ -715,21 +713,21 @@ union e1000_rx_desc_packet_split { /* Transmit Descriptor */ struct e1000_tx_desc { - uint64_t buffer_addr; /* Address of the descriptor's data buffer */ + __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { - uint32_t data; + __le32 data; struct { - uint16_t length; /* Data buffer length */ + __le16 length; /* Data buffer length */ uint8_t cso; /* Checksum offset */ uint8_t cmd; /* Descriptor control */ } flags; } lower; union { - uint32_t data; + __le32 data; struct { uint8_t status; /* Descriptor status */ uint8_t css; /* Checksum start */ - uint16_t special; + __le16 special; } fields; } upper; }; @@ -759,49 +757,49 @@ struct e1000_tx_desc { /* Offload Context Descriptor */ struct e1000_context_desc { union { - uint32_t ip_config; + __le32 ip_config; struct { uint8_t ipcss; /* IP checksum start */ uint8_t ipcso; /* IP checksum offset */ - uint16_t ipcse; /* IP checksum end */ + __le16 ipcse; /* IP checksum end */ } ip_fields; } lower_setup; union { - uint32_t tcp_config; + __le32 tcp_config; struct { uint8_t tucss; /* TCP checksum start */ uint8_t tucso; /* TCP checksum offset */ - uint16_t tucse; /* TCP checksum end */ + __le16 tucse; /* TCP checksum end */ } tcp_fields; } upper_setup; - uint32_t cmd_and_length; /* */ + __le32 cmd_and_length; /* */ union { - uint32_t data; + __le32 data; struct { uint8_t status; /* Descriptor status */ uint8_t hdr_len; /* Header length */ - uint16_t mss; /* Maximum segment size */ + __le16 mss; /* Maximum segment size */ } fields; } tcp_seg_setup; }; /* Offload data descriptor */ struct e1000_data_desc { - uint64_t buffer_addr; /* Address of the descriptor's buffer address */ + __le64 buffer_addr; /* Address of the descriptor's buffer address */ union { - uint32_t data; + __le32 data; struct { - uint16_t length; /* Data buffer length */ + __le16 length; /* Data buffer length */ uint8_t typ_len_ext; /* */ uint8_t cmd; /* */ } flags; } lower; union { - uint32_t data; + __le32 data; struct { uint8_t status; /* Descriptor status */ uint8_t popts; /* Packet Options */ - uint16_t special; /* */ + __le16 special; /* */ } fields; } upper; }; @@ -817,8 +815,8 @@ struct e1000_data_desc { /* Receive Address Register */ struct e1000_rar { - volatile uint32_t low; /* receive address low */ - volatile uint32_t high; /* receive address high */ + volatile __le32 low; /* receive address low */ + volatile __le32 high; /* receive address high */ }; /* Number of entries in the Multicast Table Array (MTA). */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 76c0fa690cc..8c87940a9ce 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -47,6 +47,12 @@ static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation * Macro expands to... * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} */ +#ifdef CONFIG_E1000E_ENABLED + #define PCIE(x) +#else + #define PCIE(x) x, +#endif + static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x1000), INTEL_E1000_ETHERNET_DEVICE(0x1001), @@ -73,14 +79,14 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x1026), INTEL_E1000_ETHERNET_DEVICE(0x1027), INTEL_E1000_ETHERNET_DEVICE(0x1028), - INTEL_E1000_ETHERNET_DEVICE(0x1049), - INTEL_E1000_ETHERNET_DEVICE(0x104A), - INTEL_E1000_ETHERNET_DEVICE(0x104B), - INTEL_E1000_ETHERNET_DEVICE(0x104C), - INTEL_E1000_ETHERNET_DEVICE(0x104D), - INTEL_E1000_ETHERNET_DEVICE(0x105E), - INTEL_E1000_ETHERNET_DEVICE(0x105F), - INTEL_E1000_ETHERNET_DEVICE(0x1060), +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x1049)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x104A)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x104B)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x104C)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x104D)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x105E)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x105F)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x1060)) INTEL_E1000_ETHERNET_DEVICE(0x1075), INTEL_E1000_ETHERNET_DEVICE(0x1076), INTEL_E1000_ETHERNET_DEVICE(0x1077), @@ -89,28 +95,28 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x107A), INTEL_E1000_ETHERNET_DEVICE(0x107B), INTEL_E1000_ETHERNET_DEVICE(0x107C), - INTEL_E1000_ETHERNET_DEVICE(0x107D), - INTEL_E1000_ETHERNET_DEVICE(0x107E), - INTEL_E1000_ETHERNET_DEVICE(0x107F), +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x107D)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x107E)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x107F)) INTEL_E1000_ETHERNET_DEVICE(0x108A), - INTEL_E1000_ETHERNET_DEVICE(0x108B), - INTEL_E1000_ETHERNET_DEVICE(0x108C), - INTEL_E1000_ETHERNET_DEVICE(0x1096), - INTEL_E1000_ETHERNET_DEVICE(0x1098), +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x108B)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x108C)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x1096)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x1098)) INTEL_E1000_ETHERNET_DEVICE(0x1099), - INTEL_E1000_ETHERNET_DEVICE(0x109A), - INTEL_E1000_ETHERNET_DEVICE(0x10A4), - INTEL_E1000_ETHERNET_DEVICE(0x10A5), +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x109A)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10A4)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10A5)) INTEL_E1000_ETHERNET_DEVICE(0x10B5), - INTEL_E1000_ETHERNET_DEVICE(0x10B9), - INTEL_E1000_ETHERNET_DEVICE(0x10BA), - INTEL_E1000_ETHERNET_DEVICE(0x10BB), - 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), +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10B9)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10BA)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10BB)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10BC)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10C4)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10C5)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10D5)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10D9)) +PCIE( INTEL_E1000_ETHERNET_DEVICE(0x10DA)) /* required last entry */ {0,} }; @@ -153,7 +159,7 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring); static void e1000_clean_rx_ring(struct e1000_adapter *adapter, struct e1000_rx_ring *rx_ring); -static void e1000_set_multi(struct net_device *netdev); +static void e1000_set_rx_mode(struct net_device *netdev); static void e1000_update_phy_info(unsigned long data); static void e1000_watchdog(unsigned long data); static void e1000_82547_tx_fifo_stall(unsigned long data); @@ -299,14 +305,14 @@ module_exit(e1000_exit_module); static int e1000_request_irq(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; - void (*handler) = &e1000_intr; + irq_handler_t handler = e1000_intr; int irq_flags = IRQF_SHARED; int err; if (adapter->hw.mac_type >= e1000_82571) { adapter->have_msi = !pci_enable_msi(adapter->pdev); if (adapter->have_msi) { - handler = &e1000_intr_msi; + handler = e1000_intr_msi; irq_flags = 0; } } @@ -514,7 +520,7 @@ static void e1000_configure(struct e1000_adapter *adapter) struct net_device *netdev = adapter->netdev; int i; - e1000_set_multi(netdev); + e1000_set_rx_mode(netdev); e1000_restore_vlan(adapter); e1000_init_manageability(adapter); @@ -845,6 +851,64 @@ e1000_reset(struct e1000_adapter *adapter) } /** + * Dump the eeprom for users having checksum issues + **/ +void e1000_dump_eeprom(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct ethtool_eeprom eeprom; + const struct ethtool_ops *ops = netdev->ethtool_ops; + u8 *data; + int i; + u16 csum_old, csum_new = 0; + + eeprom.len = ops->get_eeprom_len(netdev); + eeprom.offset = 0; + + data = kmalloc(eeprom.len, GFP_KERNEL); + if (!data) { + printk(KERN_ERR "Unable to allocate memory to dump EEPROM" + " data\n"); + return; + } + + ops->get_eeprom(netdev, &eeprom, data); + + csum_old = (data[EEPROM_CHECKSUM_REG * 2]) + + (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8); + for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2) + csum_new += data[i] + (data[i + 1] << 8); + csum_new = EEPROM_SUM - csum_new; + + printk(KERN_ERR "/*********************/\n"); + printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old); + printk(KERN_ERR "Calculated : 0x%04x\n", csum_new); + + printk(KERN_ERR "Offset Values\n"); + printk(KERN_ERR "======== ======\n"); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0); + + printk(KERN_ERR "Include this output when contacting your support " + "provider.\n"); + printk(KERN_ERR "This is not a software error! Something bad " + "happened to your hardware or\n"); + printk(KERN_ERR "EEPROM image. Ignoring this " + "problem could result in further problems,\n"); + printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n"); + printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, " + "which is invalid\n"); + printk(KERN_ERR "and requires you to set the proper MAC " + "address manually before continuing\n"); + printk(KERN_ERR "to enable this network device.\n"); + printk(KERN_ERR "Please inspect the EEPROM dump and report the issue " + "to your hardware vendor\n"); + printk(KERN_ERR "or Intel Customer Support: linux-nics@intel.com\n"); + printk(KERN_ERR "/*********************/\n"); + + kfree(data); +} + +/** * e1000_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in e1000_pci_tbl @@ -927,7 +991,7 @@ e1000_probe(struct pci_dev *pdev, netdev->stop = &e1000_close; netdev->hard_start_xmit = &e1000_xmit_frame; netdev->get_stats = &e1000_get_stats; - netdev->set_multicast_list = &e1000_set_multi; + netdev->set_rx_mode = &e1000_set_rx_mode; netdev->set_mac_address = &e1000_set_mac; netdev->change_mtu = &e1000_change_mtu; netdev->do_ioctl = &e1000_ioctl; @@ -995,7 +1059,6 @@ e1000_probe(struct pci_dev *pdev, adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); /* initialize eeprom parameters */ - if (e1000_init_eeprom_params(&adapter->hw)) { E1000_ERR("EEPROM initialization failed\n"); goto err_eeprom; @@ -1007,23 +1070,29 @@ e1000_probe(struct pci_dev *pdev, e1000_reset_hw(&adapter->hw); /* make sure the EEPROM is good */ - if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) { DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); - goto err_eeprom; + e1000_dump_eeprom(adapter); + /* + * set MAC address to all zeroes to invalidate and temporary + * disable this device for the user. This blocks regular + * traffic while still permitting ethtool ioctls from reaching + * the hardware as well as allowing the user to run the + * interface after manually setting a hw addr using + * `ip set address` + */ + memset(adapter->hw.mac_addr, 0, netdev->addr_len); + } else { + /* copy the MAC address out of the EEPROM */ + if (e1000_read_mac_addr(&adapter->hw)) + DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); } - - /* copy the MAC address out of the EEPROM */ - - if (e1000_read_mac_addr(&adapter->hw)) - DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); + /* don't block initalization here due to bad MAC address */ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); - if (!is_valid_ether_addr(netdev->perm_addr)) { + if (!is_valid_ether_addr(netdev->perm_addr)) DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); - goto err_eeprom; - } e1000_get_bus_info(&adapter->hw); @@ -2410,21 +2479,22 @@ e1000_set_mac(struct net_device *netdev, void *p) } /** - * e1000_set_multi - Multicast and Promiscuous mode set + * e1000_set_rx_mode - Secondary Unicast, 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, + * The set_rx_mode entry point is called whenever the unicast or multicast + * address lists or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper unicast, multicast, * promiscuous mode, and all-multi behavior. **/ static void -e1000_set_multi(struct net_device *netdev) +e1000_set_rx_mode(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; + struct dev_addr_list *uc_ptr; + struct dev_addr_list *mc_ptr; uint32_t rctl; uint32_t hash_value; int i, rar_entries = E1000_RAR_ENTRIES; @@ -2447,9 +2517,16 @@ e1000_set_multi(struct net_device *netdev) rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); } else if (netdev->flags & IFF_ALLMULTI) { rctl |= E1000_RCTL_MPE; - rctl &= ~E1000_RCTL_UPE; } else { - rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); + rctl &= ~E1000_RCTL_MPE; + } + + uc_ptr = NULL; + if (netdev->uc_count > rar_entries - 1) { + rctl |= E1000_RCTL_UPE; + } else if (!(netdev->flags & IFF_PROMISC)) { + rctl &= ~E1000_RCTL_UPE; + uc_ptr = netdev->uc_list; } E1000_WRITE_REG(hw, RCTL, rctl); @@ -2459,7 +2536,10 @@ e1000_set_multi(struct net_device *netdev) if (hw->mac_type == e1000_82542_rev2_0) e1000_enter_82542_rst(adapter); - /* load the first 14 multicast address into the exact filters 1-14 + /* load the first 14 addresses into the exact filters 1-14. Unicast + * addresses take precedence to avoid disabling unicast filtering + * when possible. + * * RAR 0 is used for the station MAC adddress * if there are not 14 addresses, go ahead and clear the filters * -- with 82571 controllers only 0-13 entries are filled here @@ -2467,8 +2547,11 @@ e1000_set_multi(struct net_device *netdev) mc_ptr = netdev->mc_list; for (i = 1; i < rar_entries; i++) { - if (mc_ptr) { - e1000_rar_set(hw, mc_ptr->dmi_addr, i); + if (uc_ptr) { + e1000_rar_set(hw, uc_ptr->da_addr, i); + uc_ptr = uc_ptr->next; + } else if (mc_ptr) { + e1000_rar_set(hw, mc_ptr->da_addr, i); mc_ptr = mc_ptr->next; } else { E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); @@ -2477,6 +2560,7 @@ e1000_set_multi(struct net_device *netdev) E1000_WRITE_FLUSH(hw); } } + WARN_ON(uc_ptr != NULL); /* clear the old settings from the multicast hash table */ @@ -2488,7 +2572,7 @@ e1000_set_multi(struct net_device *netdev) /* load any remaining addresses into the hash table */ for (; mc_ptr; mc_ptr = mc_ptr->next) { - hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr); + hash_value = e1000_hash_mc_addr(hw, mc_ptr->da_addr); e1000_mta_set(hw, hash_value); } @@ -3680,10 +3764,6 @@ e1000_update_stats(struct e1000_adapter *adapter) } /* Fill out the OS statistics structure */ - adapter->net_stats.rx_packets = adapter->stats.gprc; - adapter->net_stats.tx_packets = adapter->stats.gptc; - adapter->net_stats.rx_bytes = adapter->stats.gorcl; - adapter->net_stats.tx_bytes = adapter->stats.gotcl; adapter->net_stats.multicast = adapter->stats.mprc; adapter->net_stats.collisions = adapter->stats.colc; @@ -4059,6 +4139,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, } adapter->total_tx_bytes += total_tx_bytes; adapter->total_tx_packets += total_tx_packets; + adapter->net_stats.tx_bytes += total_tx_bytes; + adapter->net_stats.tx_packets += total_tx_packets; return cleaned; } @@ -4106,8 +4188,8 @@ e1000_rx_checksum(struct e1000_adapter *adapter, /* Hardware complements the payload checksum, so we undo it * and then put the value in host order for further stack use. */ - csum = ntohl(csum ^ 0xFFFF); - skb->csum = csum; + __sum16 sum = (__force __sum16)htons(csum); + skb->csum = csum_unfold(~sum); skb->ip_summed = CHECKSUM_COMPLETE; } adapter->hw_csum_good++; @@ -4281,6 +4363,8 @@ next_desc: adapter->total_rx_packets += total_rx_packets; adapter->total_rx_bytes += total_rx_bytes; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; return cleaned; } @@ -4468,6 +4552,8 @@ next_desc: adapter->total_rx_packets += total_rx_packets; adapter->total_rx_bytes += total_rx_bytes; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; return cleaned; } @@ -4631,7 +4717,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, rx_desc->read.buffer_addr[j+1] = cpu_to_le64(ps_page_dma->ps_page_dma[j]); } else - rx_desc->read.buffer_addr[j+1] = ~0; + rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0); } skb = netdev_alloc_skb(netdev, @@ -4874,22 +4960,6 @@ e1000_pci_clear_mwi(struct e1000_hw *hw) pci_clear_mwi(adapter->pdev); } -void -e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) -{ - struct e1000_adapter *adapter = hw->back; - - pci_read_config_word(adapter->pdev, reg, value); -} - -void -e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) -{ - struct e1000_adapter *adapter = hw->back; - - pci_write_config_word(adapter->pdev, reg, *value); -} - int e1000_pcix_get_mmrbc(struct e1000_hw *hw) { @@ -5095,7 +5165,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) if (wufc) { e1000_setup_rctl(adapter); - e1000_set_multi(netdev); + e1000_set_rx_mode(netdev); /* turn on all-multi mode if wake on multicast is enabled */ if (wufc & E1000_WUFC_MC) { |