X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fe1000e%2Fethtool.c;h=1bf4d2a5d34f8b7421839033c7dd4cedb748bc1c;hb=f523d2114e93c559dbcf1b49d46b339fc0eda37a;hp=3423f33769b7c52571bf57fb75a00427e3d3cd41;hpb=b9f2c0440d806e01968c3ed4def930a43be248ad;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 3423f33..1bf4d2a 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -46,8 +46,8 @@ struct e1000_stats { static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_packets", E1000_STAT(stats.gprc) }, { "tx_packets", E1000_STAT(stats.gptc) }, - { "rx_bytes", E1000_STAT(stats.gorcl) }, - { "tx_bytes", E1000_STAT(stats.gotcl) }, + { "rx_bytes", E1000_STAT(stats.gorc) }, + { "tx_bytes", E1000_STAT(stats.gotc) }, { "rx_broadcast", E1000_STAT(stats.bprc) }, { "tx_broadcast", E1000_STAT(stats.bptc) }, { "rx_multicast", E1000_STAT(stats.mprc) }, @@ -83,7 +83,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, - { "rx_long_byte_count", E1000_STAT(stats.gorcl) }, + { "rx_long_byte_count", E1000_STAT(stats.gorc) }, { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, { "rx_header_split", E1000_STAT(rx_hdr_split) }, @@ -95,23 +95,23 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "tx_dma_failed", E1000_STAT(tx_dma_failed) }, }; -#define E1000_GLOBAL_STATS_LEN \ - sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) +#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) #define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN) static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Eeprom test (offline)", "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) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + u32 status; - if (hw->media_type == e1000_media_type_copper) { + if (hw->phy.media_type == e1000_media_type_copper) { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | @@ -147,16 +147,16 @@ static int e1000_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_EXTERNAL; } - if (er32(STATUS) & E1000_STATUS_LU) { - - adapter->hw.mac.ops.get_link_up_info(hw, &adapter->link_speed, - &adapter->link_duplex); - ecmd->speed = adapter->link_speed; - - /* unfortunately FULL_DUPLEX != DUPLEX_FULL - * and HALF_DUPLEX != DUPLEX_HALF */ + status = er32(STATUS); + if (status & E1000_STATUS_LU) { + if (status & E1000_STATUS_SPEED_1000) + ecmd->speed = 1000; + else if (status & E1000_STATUS_SPEED_100) + ecmd->speed = 100; + else + ecmd->speed = 10; - if (adapter->link_duplex == FULL_DUPLEX) + if (status & E1000_STATUS_FD) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; @@ -165,11 +165,27 @@ static int e1000_get_settings(struct net_device *netdev, ecmd->duplex = -1; } - ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) || + ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; + + /* MDI-X => 2; MDI =>1; Invalid =>0 */ + if ((hw->phy.media_type == e1000_media_type_copper) && + !hw->mac.get_link_status) + ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : + ETH_TP_MDI; + else + ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; + return 0; } +static u32 e1000_get_link(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + return e1000_has_link(adapter); +} + static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) { struct e1000_mac_info *mac = &adapter->hw.mac; @@ -177,10 +193,9 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) mac->autoneg = 0; /* Fiber NICs only allow 1000 gbps Full duplex */ - if ((adapter->hw.media_type == e1000_media_type_fiber) && + if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && spddplx != (SPEED_1000 + DUPLEX_FULL)) { - ndev_err(adapter->netdev, "Unsupported Speed/Duplex " - "configuration\n"); + e_err("Unsupported Speed/Duplex configuration\n"); return -EINVAL; } @@ -203,8 +218,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: - ndev_err(adapter->netdev, "Unsupported Speed/Duplex " - "configuration\n"); + e_err("Unsupported Speed/Duplex configuration\n"); return -EINVAL; } return 0; @@ -216,11 +230,13 @@ static int e1000_set_settings(struct net_device *netdev, struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - /* When SoL/IDER sessions are active, autoneg/speed/duplex - * cannot be changed */ + /* + * When SoL/IDER sessions are active, autoneg/speed/duplex + * cannot be changed + */ if (e1000_check_reset_block(hw)) { - ndev_err(netdev, "Cannot change link " - "characteristics when SoL/IDER is active.\n"); + e_err("Cannot change link characteristics when SoL/IDER is " + "active.\n"); return -EINVAL; } @@ -229,7 +245,7 @@ static int e1000_set_settings(struct net_device *netdev, if (ecmd->autoneg == AUTONEG_ENABLE) { hw->mac.autoneg = 1; - if (hw->media_type == e1000_media_type_fiber) + if (hw->phy.media_type == e1000_media_type_fiber) hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE | ADVERTISED_Autoneg; @@ -238,6 +254,8 @@ static int e1000_set_settings(struct net_device *netdev, ADVERTISED_TP | ADVERTISED_Autoneg; ecmd->advertising = hw->phy.autoneg_advertised; + if (adapter->fc_autoneg) + hw->fc.requested_mode = e1000_fc_default; } else { if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { clear_bit(__E1000_RESETTING, &adapter->state); @@ -267,11 +285,11 @@ static void e1000_get_pauseparam(struct net_device *netdev, pause->autoneg = (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - if (hw->mac.fc == e1000_fc_rx_pause) { + if (hw->fc.current_mode == e1000_fc_rx_pause) { pause->rx_pause = 1; - } else if (hw->mac.fc == e1000_fc_tx_pause) { + } else if (hw->fc.current_mode == e1000_fc_tx_pause) { pause->tx_pause = 1; - } else if (hw->mac.fc == e1000_fc_full) { + } else if (hw->fc.current_mode == e1000_fc_full) { pause->rx_pause = 1; pause->tx_pause = 1; } @@ -289,18 +307,8 @@ static int e1000_set_pauseparam(struct net_device *netdev, while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) msleep(1); - if (pause->rx_pause && pause->tx_pause) - hw->mac.fc = e1000_fc_full; - else if (pause->rx_pause && !pause->tx_pause) - hw->mac.fc = e1000_fc_rx_pause; - else if (!pause->rx_pause && pause->tx_pause) - hw->mac.fc = e1000_fc_tx_pause; - else if (!pause->rx_pause && !pause->tx_pause) - hw->mac.fc = e1000_fc_none; - - hw->mac.original_fc = hw->mac.fc; - if (adapter->fc_autoneg == AUTONEG_ENABLE) { + hw->fc.requested_mode = e1000_fc_default; if (netif_running(adapter->netdev)) { e1000e_down(adapter); e1000e_up(adapter); @@ -308,7 +316,18 @@ static int e1000_set_pauseparam(struct net_device *netdev, e1000e_reset(adapter); } } else { - retval = ((hw->media_type == e1000_media_type_fiber) ? + if (pause->rx_pause && pause->tx_pause) + hw->fc.requested_mode = e1000_fc_full; + else if (pause->rx_pause && !pause->tx_pause) + hw->fc.requested_mode = e1000_fc_rx_pause; + else if (!pause->rx_pause && pause->tx_pause) + hw->fc.requested_mode = e1000_fc_tx_pause; + else if (!pause->rx_pause && !pause->tx_pause) + hw->fc.requested_mode = e1000_fc_none; + + hw->fc.current_mode = hw->fc.requested_mode; + + retval = ((hw->phy.media_type == e1000_media_type_fiber) ? hw->mac.ops.setup_link(hw) : e1000e_force_mac_fc(hw)); } @@ -365,8 +384,7 @@ static int e1000_set_tso(struct net_device *netdev, u32 data) netdev->features &= ~NETIF_F_TSO6; } - ndev_info(netdev, "TSO is %s\n", - data ? "Enabled" : "Disabled"); + e_info("TSO is %s\n", data ? "Enabled" : "Disabled"); adapter->flags |= FLAG_TSO_FORCE; return 0; } @@ -420,6 +438,10 @@ static void e1000_get_regs(struct net_device *netdev, regs_buff[11] = er32(TIDV); regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ + + /* ethtool doesn't use anything past this point, so all this + * code is likely legacy junk for apps that may or may not + * exist */ if (hw->phy.type == e1000_phy_m88) { e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); regs_buff[13] = (u32)phy_data; /* cable length */ @@ -435,7 +457,7 @@ static void e1000_get_regs(struct net_device *netdev, regs_buff[22] = adapter->phy_stats.receive_errors; regs_buff[23] = regs_buff[13]; /* mdix mode */ } - regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ + regs_buff[21] = 0; /* was idle_errors */ e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); regs_buff[24] = (u32)phy_data; /* phy local receiver status */ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ @@ -484,9 +506,14 @@ static int e1000_get_eeprom(struct net_device *netdev, } } - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); + if (ret_val) { + /* a read error occurred, throw away the result */ + memset(eeprom_buff, 0xff, sizeof(eeprom_buff)); + } else { + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + } memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); kfree(eeprom_buff); @@ -513,6 +540,9 @@ static int e1000_set_eeprom(struct net_device *netdev, if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16))) return -EFAULT; + if (adapter->flags & FLAG_READ_ONLY_NVM) + return -EINVAL; + max_len = hw->nvm.word_size * 2; first_word = eeprom->offset >> 1; @@ -535,6 +565,9 @@ static int e1000_set_eeprom(struct net_device *netdev, ret_val = e1000_read_nvm(hw, last_word, 1, &eeprom_buff[last_word - first_word]); + if (ret_val) + goto out; + /* Device's eeprom is always little-endian, word addressable */ for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); @@ -547,12 +580,18 @@ static int e1000_set_eeprom(struct net_device *netdev, ret_val = e1000_write_nvm(hw, first_word, last_word - first_word + 1, eeprom_buff); - /* Update the checksum over the first part of the EEPROM if needed - * and flush shadow RAM for 82573 controllers */ - if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG) || - (hw->mac.type == e1000_82573))) - e1000e_update_nvm_checksum(hw); + if (ret_val) + goto out; + /* + * Update the checksum over the first part of the EEPROM if needed + * and flush shadow RAM for applicable controllers + */ + if ((first_word <= NVM_CHECKSUM_REG) || + (hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82573)) + ret_val = e1000e_update_nvm_checksum(hw); + +out: kfree(eeprom_buff); return ret_val; } @@ -562,18 +601,18 @@ static void e1000_get_drvinfo(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); char firmware_version[32]; - u16 eeprom_data; strncpy(drvinfo->driver, e1000e_driver_name, 32); strncpy(drvinfo->version, e1000e_driver_version, 32); - /* EEPROM image version # is reported as firmware version # for - * PCI-E controllers */ - e1000_read_nvm(&adapter->hw, 5, 1, &eeprom_data); + /* + * EEPROM image version # is reported as firmware version # for + * PCI-E controllers + */ sprintf(firmware_version, "%d.%d-%d", - (eeprom_data & 0xF000) >> 12, - (eeprom_data & 0x0FF0) >> 4, - eeprom_data & 0x000F); + (adapter->eeprom_vers & 0xF000) >> 12, + (adapter->eeprom_vers & 0x0FF0) >> 4, + (adapter->eeprom_vers & 0x000F)); strncpy(drvinfo->fw_version, firmware_version, 32); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); @@ -622,10 +661,17 @@ static int e1000_set_ringparam(struct net_device *netdev, tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); if (!tx_ring) goto err_alloc_tx; + /* + * use a memcpy to save any previously configured + * items like napi structs from having to be + * reinitialized + */ + memcpy(tx_ring, tx_old, sizeof(struct e1000_ring)); rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); if (!rx_ring) goto err_alloc_rx; + memcpy(rx_ring, rx_old, sizeof(struct e1000_ring)); adapter->tx_ring = tx_ring; adapter->rx_ring = rx_ring; @@ -647,8 +693,10 @@ static int e1000_set_ringparam(struct net_device *netdev, if (err) goto err_setup_tx; - /* save the new, restore the old in order to free it, - * then restore the new back again */ + /* + * restore the old in order to free it, + * then add in the new + */ adapter->rx_ring = rx_old; adapter->tx_ring = tx_old; e1000e_free_rx_resources(adapter); @@ -679,53 +727,68 @@ err_setup: return err; } -#define REG_PATTERN_TEST(R, M, W) REG_PATTERN_TEST_ARRAY(R, 0, M, W) -#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, writeable) \ -{ \ - u32 _pat; \ - u32 _value; \ - u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ - for (_pat = 0; _pat < ARRAY_SIZE(_test); _pat++) { \ - E1000_WRITE_REG_ARRAY(hw, reg, offset, \ - (_test[_pat] & writeable)); \ - _value = E1000_READ_REG_ARRAY(hw, reg, offset); \ - if (_value != (_test[_pat] & writeable & mask)) { \ - ndev_err(netdev, "pattern test reg %04X " \ - "failed: got 0x%08X expected 0x%08X\n", \ - reg + offset, \ - value, (_test[_pat] & writeable & mask)); \ - *data = reg; \ - return 1; \ - } \ - } \ +static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, + int reg, int offset, u32 mask, u32 write) +{ + u32 pat, val; + static const u32 test[] = + {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; + for (pat = 0; pat < ARRAY_SIZE(test); pat++) { + E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, + (test[pat] & write)); + val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); + if (val != (test[pat] & write & mask)) { + e_err("pattern test reg %04X failed: got 0x%08X " + "expected 0x%08X\n", reg + offset, val, + (test[pat] & write & mask)); + *data = reg; + return 1; + } + } + return 0; } -#define REG_SET_AND_CHECK(R, M, W) \ -{ \ - u32 _value; \ - __ew32(hw, R, W & M); \ - _value = __er32(hw, R); \ - if ((W & M) != (_value & M)) { \ - ndev_err(netdev, "set/check reg %04X test failed: " \ - "got 0x%08X expected 0x%08X\n", R, (_value & M), \ - (W & M)); \ - *data = R; \ - return 1; \ - } \ +static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, + int reg, u32 mask, u32 write) +{ + u32 val; + __ew32(&adapter->hw, reg, write & mask); + val = __er32(&adapter->hw, reg); + if ((write & mask) != (val & mask)) { + e_err("set/check reg %04X test failed: got 0x%08X " + "expected 0x%08X\n", reg, (val & mask), (write & mask)); + *data = reg; + return 1; + } + return 0; } +#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \ + do { \ + if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \ + return 1; \ + } while (0) +#define REG_PATTERN_TEST(reg, mask, write) \ + REG_PATTERN_TEST_ARRAY(reg, 0, mask, write) + +#define REG_SET_AND_CHECK(reg, mask, write) \ + do { \ + if (reg_set_and_check(adapter, data, reg, mask, write)) \ + return 1; \ + } while (0) static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) { struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &adapter->hw.mac; - struct net_device *netdev = adapter->netdev; u32 value; u32 before; u32 after; u32 i; u32 toggle; + u32 mask; - /* The status register is Read Only, so a write should fail. + /* + * The status register is Read Only, so a write should fail. * Some bits that get toggled are ignored. */ switch (mac->type) { @@ -735,14 +798,9 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) case e1000_80003es2lan: toggle = 0x7FFFF3FF; break; - case e1000_82573: - case e1000_ich8lan: - case e1000_ich9lan: + default: toggle = 0x7FFFF033; break; - default: - toggle = 0xFFFFF833; - break; } before = er32(STATUS); @@ -750,16 +808,15 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) ew32(STATUS, toggle); after = er32(STATUS) & toggle; if (value != after) { - ndev_err(netdev, "failed STATUS register test got: " - "0x%08X expected: 0x%08X\n", after, value); + e_err("failed STATUS register test got: 0x%08X expected: " + "0x%08X\n", after, value); *data = 1; return 1; } /* restore previous status */ ew32(STATUS, before); - if ((mac->type != e1000_ich8lan) && - (mac->type != e1000_ich9lan)) { + if (!(adapter->flags & FLAG_IS_ICH)) { REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF); REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF); REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF); @@ -779,15 +836,28 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000); - before = (((mac->type == e1000_ich8lan) || - (mac->type == e1000_ich9lan)) ? 0x06C3B33E : 0x06DFB3FE); + before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE); REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB); REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000); - REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x01FFFFFF); - REG_PATTERN_TEST(E1000_RDBAL, 0xFFFFF000, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_TXCW, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_TDBAL, 0xFFFFF000, 0xFFFFFFFF); + REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); + if (!(adapter->flags & FLAG_IS_ICH)) + REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(E1000_TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); + REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); + mask = 0x8003FFFF; + switch (mac->type) { + case e1000_ich10lan: + case e1000_pchlan: + mask |= (1 << 18); + break; + default: + break; + } + for (i = 0; i < mac->rar_entry_count; i++) + REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), + mask, 0xFFFFFFFF); for (i = 0; i < mac->mta_reg_count; i++) REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); @@ -807,7 +877,7 @@ static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) { *data = 1; - break; + return *data; } checksum += temp; } @@ -838,10 +908,18 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) u32 shared_int = 1; u32 irq = adapter->pdev->irq; int i; + int ret_val = 0; + int int_mode = E1000E_INT_MODE_LEGACY; *data = 0; - /* NOTE: we don't test MSI interrupts here, yet */ + /* NOTE: we don't test MSI/MSI-X interrupts here, yet */ + if (adapter->int_mode == E1000E_INT_MODE_MSIX) { + int_mode = adapter->int_mode; + e1000e_reset_interrupt_capability(adapter); + adapter->int_mode = E1000E_INT_MODE_LEGACY; + e1000e_set_interrupt_capability(adapter); + } /* Hook up test interrupt handler just for this test */ if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, netdev)) { @@ -849,10 +927,10 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) } else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED, netdev->name, netdev)) { *data = 1; - return -1; + ret_val = -1; + goto out; } - ndev_info(netdev, "testing %s interrupt\n", - (shared_int ? "shared" : "unshared")); + e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared")); /* Disable all the interrupts */ ew32(IMC, 0xFFFFFFFF); @@ -860,16 +938,26 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) /* Test each interrupt */ for (i = 0; i < 10; i++) { - - if (((adapter->hw.mac.type == e1000_ich8lan) || - (adapter->hw.mac.type == e1000_ich9lan)) && i == 8) - continue; - /* Interrupt to test */ mask = 1 << i; + if (adapter->flags & FLAG_IS_ICH) { + switch (mask) { + case E1000_ICR_RXSEQ: + continue; + case 0x00000100: + if (adapter->hw.mac.type == e1000_ich8lan || + adapter->hw.mac.type == e1000_ich9lan) + continue; + break; + default: + break; + } + } + if (!shared_int) { - /* Disable the interrupt to be reported in + /* + * Disable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was posted to the bus, the @@ -886,7 +974,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) } } - /* Enable the interrupt to be reported in + /* + * Enable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was not posted to the bus, the @@ -903,7 +992,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) } if (!shared_int) { - /* Disable the other interrupts to be reported in + /* + * Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If * an interrupt was posted to the bus, the @@ -928,7 +1018,14 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) /* Unhook test interrupt handler */ free_irq(irq, netdev); - return *data; +out: + if (int_mode == E1000E_INT_MODE_MSIX) { + e1000e_reset_interrupt_capability(adapter); + adapter->int_mode = int_mode; + e1000e_set_interrupt_capability(adapter); + } + + return ret_val; } static void e1000_free_desc_rings(struct e1000_adapter *adapter) @@ -985,7 +1082,6 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; u32 rctl; - int size; int i; int ret_val; @@ -994,13 +1090,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) if (!tx_ring->count) tx_ring->count = E1000_DEFAULT_TXD; - size = tx_ring->count * sizeof(struct e1000_buffer); - tx_ring->buffer_info = kmalloc(size, GFP_KERNEL); - if (!tx_ring->buffer_info) { + tx_ring->buffer_info = kcalloc(tx_ring->count, + sizeof(struct e1000_buffer), + GFP_KERNEL); + if (!(tx_ring->buffer_info)) { ret_val = 1; goto err_nomem; } - memset(tx_ring->buffer_info, 0, size); tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); @@ -1010,21 +1106,17 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) ret_val = 2; goto err_nomem; } - memset(tx_ring->desc, 0, tx_ring->size); tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; - ew32(TDBAL, - ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); + ew32(TDBAL, ((u64) tx_ring->dma & 0x00000000FFFFFFFF)); ew32(TDBAH, ((u64) tx_ring->dma >> 32)); - ew32(TDLEN, - tx_ring->count * sizeof(struct e1000_tx_desc)); + ew32(TDLEN, tx_ring->count * sizeof(struct e1000_tx_desc)); ew32(TDH, 0); ew32(TDT, 0); - ew32(TCTL, - E1000_TCTL_PSP | E1000_TCTL_EN | - E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | - E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); + ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR | + E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | + E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); for (i = 0; i < tx_ring->count; i++) { struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); @@ -1042,16 +1134,15 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) tx_ring->buffer_info[i].dma = pci_map_single(pdev, skb->data, skb->len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(tx_ring->buffer_info[i].dma)) { + if (pci_dma_mapping_error(pdev, tx_ring->buffer_info[i].dma)) { ret_val = 4; goto err_nomem; } - tx_desc->buffer_addr = cpu_to_le64( - tx_ring->buffer_info[i].dma); + tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); tx_desc->lower.data = cpu_to_le32(skb->len); tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS | - E1000_TXD_CMD_RPS); + E1000_TXD_CMD_RS); tx_desc->upper.data = 0; } @@ -1060,13 +1151,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) if (!rx_ring->count) rx_ring->count = E1000_DEFAULT_RXD; - size = rx_ring->count * sizeof(struct e1000_buffer); - rx_ring->buffer_info = kmalloc(size, GFP_KERNEL); - if (!rx_ring->buffer_info) { + rx_ring->buffer_info = kcalloc(rx_ring->count, + sizeof(struct e1000_buffer), + GFP_KERNEL); + if (!(rx_ring->buffer_info)) { ret_val = 5; goto err_nomem; } - memset(rx_ring->buffer_info, 0, size); rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc); rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, @@ -1075,7 +1166,6 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) ret_val = 6; goto err_nomem; } - memset(rx_ring->desc, 0, rx_ring->size); rx_ring->next_to_use = 0; rx_ring->next_to_clean = 0; @@ -1087,6 +1177,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) ew32(RDH, 0); ew32(RDT, 0); rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | + E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | + E1000_RCTL_SBP | E1000_RCTL_SECRC | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); ew32(RCTL, rctl); @@ -1105,7 +1197,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) rx_ring->buffer_info[i].dma = pci_map_single(pdev, skb->data, 2048, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rx_ring->buffer_info[i].dma)) { + if (pci_dma_mapping_error(pdev, rx_ring->buffer_info[i].dma)) { ret_val = 8; goto err_nomem; } @@ -1135,22 +1227,24 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 ctrl_reg = 0; u32 stat_reg = 0; + u16 phy_reg = 0; - adapter->hw.mac.autoneg = 0; + hw->mac.autoneg = 0; - if (adapter->hw.phy.type == e1000_phy_m88) { + if (hw->phy.type == e1000_phy_m88) { /* Auto-MDI/MDIX Off */ e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); /* reset to update Auto-MDI/MDIX */ e1e_wphy(hw, PHY_CONTROL, 0x9140); /* autoneg off */ e1e_wphy(hw, PHY_CONTROL, 0x8140); - } else if (adapter->hw.phy.type == e1000_phy_gg82563) + } else if (hw->phy.type == e1000_phy_gg82563) e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); ctrl_reg = er32(CTRL); - if (adapter->hw.phy.type == e1000_phy_ife) { + switch (hw->phy.type) { + case e1000_phy_ife: /* force 100, set loopback */ e1e_wphy(hw, PHY_CONTROL, 0x6100); @@ -1160,9 +1254,33 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ E1000_CTRL_SPD_100 |/* Force Speed to 100 */ E1000_CTRL_FD); /* Force Duplex to FULL */ - } else { + break; + case e1000_phy_bm: + /* Set Default MAC Interface speed to 1GB */ + e1e_rphy(hw, PHY_REG(2, 21), &phy_reg); + phy_reg &= ~0x0007; + phy_reg |= 0x006; + e1e_wphy(hw, PHY_REG(2, 21), phy_reg); + /* Assert SW reset for above settings to take effect */ + e1000e_commit_phy(hw); + mdelay(1); + /* Force Full Duplex */ + e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); + e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C); + /* Set Link Up (in force link) */ + e1e_rphy(hw, PHY_REG(776, 16), &phy_reg); + e1e_wphy(hw, PHY_REG(776, 16), phy_reg | 0x0040); + /* Force Link */ + e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); + e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x0040); + /* Set Early Link Enable */ + e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); + e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400); + /* fall through */ + default: /* force 1000, set loopback */ e1e_wphy(hw, PHY_CONTROL, 0x4140); + mdelay(250); /* Now set up the MAC to the same speed/duplex as the PHY. */ ctrl_reg = er32(CTRL); @@ -1171,14 +1289,19 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ E1000_CTRL_FD); /* Force Duplex to FULL */ + + if (adapter->flags & FLAG_IS_ICH) + ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ } - if (adapter->hw.media_type == e1000_media_type_copper && - adapter->hw.phy.type == e1000_phy_m88) { + if (hw->phy.media_type == e1000_media_type_copper && + hw->phy.type == e1000_phy_m88) { ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ } else { - /* Set the ILOS bit on the fiber Nic if half duplex link is - * detected. */ + /* + * Set the ILOS bit on the fiber Nic if half duplex link is + * detected. + */ stat_reg = er32(STATUS); if ((stat_reg & E1000_STATUS_FD) == 0) ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); @@ -1186,10 +1309,11 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) ew32(CTRL, ctrl_reg); - /* Disable the receiver on the PHY so when a cable is plugged in, the + /* + * Disable the receiver on the PHY so when a cable is plugged in, the * PHY does not begin to autoneg when a cable is reconnected to the NIC. */ - if (adapter->hw.phy.type == e1000_phy_m88) + if (hw->phy.type == e1000_phy_m88) e1000_phy_disable_receiver(adapter); udelay(500); @@ -1205,8 +1329,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) /* special requirements for 82571/82572 fiber adapters */ - /* jump through hoops to make sure link is up because serdes - * link is hardwired up */ + /* + * jump through hoops to make sure link is up because serdes + * link is hardwired up + */ ctrl |= E1000_CTRL_SLU; ew32(CTRL, ctrl); @@ -1224,8 +1350,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) ew32(CTRL, ctrl); } - /* special write to serdes control register to enable SerDes analog - * loopback */ + /* + * special write to serdes control register to enable SerDes analog + * loopback + */ #define E1000_SERDES_LB_ON 0x410 ew32(SCTL, E1000_SERDES_LB_ON); msleep(10); @@ -1240,8 +1368,10 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) u32 ctrlext = er32(CTRL_EXT); u32 ctrl = er32(CTRL); - /* save CTRL_EXT to restore later, reuse an empty variable (unused - on mac_type 80003es2lan) */ + /* + * save CTRL_EXT to restore later, reuse an empty variable (unused + * on mac_type 80003es2lan) + */ adapter->tx_fifo_head = ctrlext; /* clear the serdes mode bits, putting the device into mac loopback */ @@ -1263,7 +1393,7 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) #define KMRNCTRLSTA_OPMODE (0x1F << 16) #define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582 ew32(KMRNCTRLSTA, - (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII)); + (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII)); return 0; } @@ -1273,8 +1403,8 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 rctl; - if (hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes) { + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { switch (hw->mac.type) { case e1000_80003es2lan: return e1000_set_es2lan_mac_loopback(adapter); @@ -1289,7 +1419,7 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter) ew32(RCTL, rctl); return 0; } - } else if (hw->media_type == e1000_media_type_copper) { + } else if (hw->phy.media_type == e1000_media_type_copper) { return e1000_integrated_phy_loopback(adapter); } @@ -1308,18 +1438,17 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter) switch (hw->mac.type) { case e1000_80003es2lan: - if (hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes) { + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { /* restore CTRL_EXT, stealing space from tx_fifo_head */ - ew32(CTRL_EXT, - adapter->tx_fifo_head); + ew32(CTRL_EXT, adapter->tx_fifo_head); adapter->tx_fifo_head = 0; } /* fall through */ case e1000_82571: case e1000_82572: - if (hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes) { + if (hw->phy.media_type == e1000_media_type_fiber || + hw->phy.media_type == e1000_media_type_internal_serdes) { #define E1000_SERDES_LB_OFF 0x400 ew32(SCTL, E1000_SERDES_LB_OFF); msleep(10); @@ -1375,7 +1504,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) ew32(RDT, rx_ring->count - 1); - /* Calculate the loop count based on the largest descriptor ring + /* + * Calculate the loop count based on the largest descriptor ring * The idea is to wrap the largest ring a number of times using 64 * send/receive pairs during each loop */ @@ -1389,8 +1519,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) l = 0; for (j = 0; j <= lc; j++) { /* loop count loop */ for (i = 0; i < 64; i++) { /* send the packets */ - e1000_create_lbtest_frame( - tx_ring->buffer_info[i].skb, 1024); + e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb, + 1024); pci_dma_sync_single_for_device(pdev, tx_ring->buffer_info[k].dma, tx_ring->buffer_info[k].length, @@ -1415,7 +1545,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) l++; if (l == rx_ring->count) l = 0; - /* time + 20 msecs (200 msecs on 2.4) is more than + /* + * time + 20 msecs (200 msecs on 2.4) is more than * enough time to complete the receives, if it's * exceeded, break and error off */ @@ -1424,7 +1555,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) ret_val = 13; /* ret_val is the same as mis-compare */ break; } - if (jiffies >= (time + 2)) { + if (jiffies >= (time + 20)) { ret_val = 14; /* error code for time out error */ break; } @@ -1434,21 +1565,22 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) { - /* PHY loopback cannot be performed if SoL/IDER - * sessions are active */ + /* + * PHY loopback cannot be performed if SoL/IDER + * sessions are active + */ if (e1000_check_reset_block(&adapter->hw)) { - ndev_err(adapter->netdev, "Cannot do PHY loopback test " - "when SoL/IDER is active.\n"); + e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); *data = 0; goto out; } *data = e1000_setup_desc_rings(adapter); - if (data) + if (*data) goto out; *data = e1000_setup_loopback_test(adapter); - if (data) + if (*data) goto err_loopback; *data = e1000_run_loopback_test(adapter); @@ -1465,12 +1597,14 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) struct e1000_hw *hw = &adapter->hw; *data = 0; - if (hw->media_type == e1000_media_type_internal_serdes) { + if (hw->phy.media_type == e1000_media_type_internal_serdes) { int i = 0; - hw->mac.serdes_has_link = 0; + hw->mac.serdes_has_link = false; - /* On some blade server designs, link establishment - * could take as long as 2-3 minutes */ + /* + * On some blade server designs, link establishment + * could take as long as 2-3 minutes + */ do { hw->mac.ops.check_for_link(hw); if (hw->mac.serdes_has_link) @@ -1521,10 +1655,12 @@ static void e1000_diag_test(struct net_device *netdev, forced_speed_duplex = adapter->hw.mac.forced_speed_duplex; autoneg = adapter->hw.mac.autoneg; - ndev_info(netdev, "offline testing starting\n"); + e_info("offline testing starting\n"); - /* Link test performed before hardware reset so autoneg doesn't - * interfere with test result */ + /* + * Link test performed before hardware reset so autoneg doesn't + * interfere with test result + */ if (e1000_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1557,15 +1693,15 @@ static void e1000_diag_test(struct net_device *netdev, adapter->hw.mac.autoneg = autoneg; /* force this routine to wait until autoneg complete/timeout */ - adapter->hw.phy.wait_for_link = 1; + adapter->hw.phy.autoneg_wait_to_complete = 1; e1000e_reset(adapter); - adapter->hw.phy.wait_for_link = 0; + adapter->hw.phy.autoneg_wait_to_complete = 0; clear_bit(__E1000_TESTING, &adapter->state); if (if_running) dev_open(netdev); } else { - ndev_info(netdev, "online testing starting\n"); + e_info("online testing starting\n"); /* Online tests */ if (e1000_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1589,19 +1725,21 @@ static void e1000_get_wol(struct net_device *netdev, wol->supported = 0; wol->wolopts = 0; - if (!(adapter->flags & FLAG_HAS_WOL)) + if (!(adapter->flags & FLAG_HAS_WOL) || + !device_can_wakeup(&adapter->pdev->dev)) return; wol->supported = WAKE_UCAST | WAKE_MCAST | - WAKE_BCAST | WAKE_MAGIC; + WAKE_BCAST | WAKE_MAGIC | + WAKE_PHY | WAKE_ARP; /* apply any specific unsupported masks here */ if (adapter->flags & FLAG_NO_WAKE_UCAST) { wol->supported &= ~WAKE_UCAST; if (adapter->wol & E1000_WUFC_EX) - ndev_err(netdev, "Interface does not support " - "directed (unicast) frame wake-up packets\n"); + e_err("Interface does not support directed (unicast) " + "frame wake-up packets\n"); } if (adapter->wol & E1000_WUFC_EX) @@ -1612,6 +1750,10 @@ static void e1000_get_wol(struct net_device *netdev, wol->wolopts |= WAKE_BCAST; if (adapter->wol & E1000_WUFC_MAG) wol->wolopts |= WAKE_MAGIC; + if (adapter->wol & E1000_WUFC_LNKC) + wol->wolopts |= WAKE_PHY; + if (adapter->wol & E1000_WUFC_ARP) + wol->wolopts |= WAKE_ARP; } static int e1000_set_wol(struct net_device *netdev, @@ -1619,10 +1761,11 @@ static int e1000_set_wol(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); - if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) + if (wol->wolopts & WAKE_MAGICSECURE) return -EOPNOTSUPP; - if (!(adapter->flags & FLAG_HAS_WOL)) + if (!(adapter->flags & FLAG_HAS_WOL) || + !device_can_wakeup(&adapter->pdev->dev)) return wol->wolopts ? -EOPNOTSUPP : 0; /* these settings will always override what we currently have */ @@ -1636,6 +1779,12 @@ static int e1000_set_wol(struct net_device *netdev, adapter->wol |= E1000_WUFC_BC; if (wol->wolopts & WAKE_MAGIC) adapter->wol |= E1000_WUFC_MAG; + if (wol->wolopts & WAKE_PHY) + adapter->wol |= E1000_WUFC_LNKC; + if (wol->wolopts & WAKE_ARP) + adapter->wol |= E1000_WUFC_ARP; + + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); return 0; } @@ -1646,26 +1795,37 @@ static int e1000_set_wol(struct net_device *netdev, /* bit defines for adapter->led_status */ #define E1000_LED_ON 0 -static void e1000_led_blink_callback(unsigned long data) +static void e1000e_led_blink_task(struct work_struct *work) { - struct e1000_adapter *adapter = (struct e1000_adapter *) data; + struct e1000_adapter *adapter = container_of(work, + struct e1000_adapter, led_blink_task); if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) adapter->hw.mac.ops.led_off(&adapter->hw); else adapter->hw.mac.ops.led_on(&adapter->hw); +} +static void e1000_led_blink_callback(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + + schedule_work(&adapter->led_blink_task); mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); } static int e1000_phys_id(struct net_device *netdev, u32 data) { struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + if (!data) + data = INT_MAX; - if (adapter->hw.phy.type == e1000_phy_ife) { + if ((hw->phy.type == e1000_phy_ife) || + (hw->mac.type == e1000_pchlan) || + (hw->mac.type == e1000_82574)) { + INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); if (!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = @@ -1675,16 +1835,57 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) mod_timer(&adapter->blink_timer, jiffies); msleep_interruptible(data * 1000); del_timer_sync(&adapter->blink_timer); - e1e_wphy(&adapter->hw, - IFE_PHY_SPECIAL_CONTROL_LED, 0); + if (hw->phy.type == e1000_phy_ife) + e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); } else { - e1000e_blink_led(&adapter->hw); + e1000e_blink_led(hw); msleep_interruptible(data * 1000); } - adapter->hw.mac.ops.led_off(&adapter->hw); + hw->mac.ops.led_off(hw); clear_bit(E1000_LED_ON, &adapter->led_status); - adapter->hw.mac.ops.cleanup_led(&adapter->hw); + hw->mac.ops.cleanup_led(hw); + + return 0; +} + +static int e1000_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (adapter->itr_setting <= 3) + ec->rx_coalesce_usecs = adapter->itr_setting; + else + ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; + + return 0; +} + +static int e1000_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || + ((ec->rx_coalesce_usecs > 3) && + (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || + (ec->rx_coalesce_usecs == 2)) + return -EINVAL; + + if (ec->rx_coalesce_usecs <= 3) { + adapter->itr = 20000; + adapter->itr_setting = ec->rx_coalesce_usecs; + } else { + adapter->itr = (1000000 / ec->rx_coalesce_usecs); + adapter->itr_setting = adapter->itr & ~3; + } + + if (adapter->itr_setting != 0) + ew32(ITR, 1000000000 / (adapter->itr * 256)); + else + ew32(ITR, 0); return 0; } @@ -1720,8 +1921,7 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset, switch (stringset) { case ETH_SS_TEST: - memcpy(data, *e1000_gstrings_test, - E1000_TEST_LEN*ETH_GSTRING_LEN); + memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test)); break; case ETH_SS_STATS: for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { @@ -1744,7 +1944,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { .get_msglevel = e1000_get_msglevel, .set_msglevel = e1000_set_msglevel, .nway_reset = e1000_nway_reset, - .get_link = ethtool_op_get_link, + .get_link = e1000_get_link, .get_eeprom_len = e1000_get_eeprom_len, .get_eeprom = e1000_get_eeprom, .set_eeprom = e1000_set_eeprom, @@ -1765,6 +1965,8 @@ static const struct ethtool_ops e1000_ethtool_ops = { .phys_id = e1000_phys_id, .get_ethtool_stats = e1000_get_ethtool_stats, .get_sset_count = e1000e_get_sset_count, + .get_coalesce = e1000_get_coalesce, + .set_coalesce = e1000_set_coalesce, }; void e1000e_set_ethtool_ops(struct net_device *netdev)