X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fe1000e%2Fethtool.c;h=a89498dcb6368f600809360bf01bac6daac38b3c;hb=f4187b56e1f8a05dd110875d5094b21b51ebd79b;hp=4ae00567bba69e10cfd1808939ea7f70553a3115;hpb=318a94d68979cbe9cc98a3050b4b7be2f08513c8;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 4ae0056..a89498d 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -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) }, @@ -177,7 +177,7 @@ static u32 e1000_get_link(struct net_device *netdev) u32 status; status = er32(STATUS); - return (status & E1000_STATUS_LU); + return (status & E1000_STATUS_LU) ? 1 : 0; } static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) @@ -189,8 +189,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) /* Fiber NICs only allow 1000 gbps Full duplex */ 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; } @@ -213,8 +212,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; @@ -231,8 +229,8 @@ static int e1000_set_settings(struct net_device *netdev, * 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; } @@ -380,8 +378,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; } @@ -494,8 +491,12 @@ static int e1000_get_eeprom(struct net_device *netdev, for (i = 0; i < last_word - first_word + 1; i++) { ret_val = e1000_read_nvm(hw, first_word + i, 1, &eeprom_buff[i]); - if (ret_val) + if (ret_val) { + /* a read error occurred, throw away the + * result */ + memset(eeprom_buff, 0xff, sizeof(eeprom_buff)); break; + } } } @@ -641,10 +642,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; @@ -700,68 +708,59 @@ err_setup: return err; } -static bool reg_pattern_test_array(struct e1000_adapter *adapter, u64 *data, - int reg, int offset, u32 mask, u32 write) +static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, + int reg, int offset, u32 mask, u32 write) { - int i; - u32 read; + u32 pat, val; static const u32 test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; - for (i = 0; i < ARRAY_SIZE(test); i++) { + for (pat = 0; pat < ARRAY_SIZE(test); pat++) { E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, - (test[i] & write)); - read = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); - if (read != (test[i] & write & mask)) { - ndev_err(adapter->netdev, "pattern test reg %04X " - "failed: got 0x%08X expected 0x%08X\n", - reg + offset, - read, (test[i] & write & mask)); + (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 true; + return 1; } } - return false; + return 0; } static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg, u32 mask, u32 write) { - u32 read; + u32 val; __ew32(&adapter->hw, reg, write & mask); - read = __er32(&adapter->hw, reg); - if ((write & mask) != (read & mask)) { - ndev_err(adapter->netdev, "set/check reg %04X test failed: " - "got 0x%08X expected 0x%08X\n", reg, (read & mask), - (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 true; + return 1; } - return false; + return 0; } - -#define REG_PATTERN_TEST(R, M, W) \ - do { \ - if (reg_pattern_test_array(adapter, data, R, 0, M, W)) \ - return 1; \ - } while (0) - -#define REG_PATTERN_TEST_ARRAY(R, offset, M, W) \ - do { \ - if (reg_pattern_test_array(adapter, data, R, offset, M, W)) \ - return 1; \ +#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(R, M, W) \ - do { \ - if (reg_set_and_check(adapter, data, R, M, W)) \ - return 1; \ +#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; @@ -782,6 +781,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) case e1000_82573: case e1000_ich8lan: case e1000_ich9lan: + case e1000_ich10lan: toggle = 0x7FFFF033; break; default: @@ -794,16 +794,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); @@ -823,21 +822,21 @@ 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, before, 0xFFFFFFFF); REG_PATTERN_TEST(E1000_RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); - if ((mac->type != e1000_ich8lan) && - (mac->type != e1000_ich9lan)) + 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); for (i = 0; i < mac->rar_entry_count; i++) REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), - 0x8003FFFF, 0xFFFFFFFF); + ((mac->type == e1000_ich10lan) ? + 0x8007FFFF : 0x8003FFFF), + 0xFFFFFFFF); for (i = 0; i < mac->mta_reg_count; i++) REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); @@ -901,8 +900,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) *data = 1; return -1; } - 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); @@ -910,14 +908,23 @@ 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 @@ -1038,7 +1045,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; @@ -1047,13 +1053,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); @@ -1063,21 +1069,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); @@ -1095,16 +1097,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; } @@ -1113,13 +1114,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, @@ -1128,7 +1129,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; @@ -1140,6 +1140,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); @@ -1158,7 +1160,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; } @@ -1188,6 +1190,7 @@ 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; hw->mac.autoneg = 0; @@ -1203,7 +1206,8 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) ctrl_reg = er32(CTRL); - if (hw->phy.type == e1000_phy_ife) { + switch (hw->phy.type) { + case e1000_phy_ife: /* force 100, set loopback */ e1e_wphy(hw, PHY_CONTROL, 0x6100); @@ -1213,9 +1217,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); @@ -1224,6 +1252,9 @@ 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 (hw->phy.media_type == e1000_media_type_copper && @@ -1325,7 +1356,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; } @@ -1451,8 +1482,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, @@ -1487,7 +1518,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; } @@ -1502,8 +1533,7 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) * 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; } @@ -1588,7 +1618,7 @@ 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 @@ -1634,7 +1664,7 @@ static void e1000_diag_test(struct net_device *netdev, 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; @@ -1670,8 +1700,8 @@ static void e1000_get_wol(struct net_device *netdev, 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) @@ -1767,6 +1797,47 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) 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; +} + static int e1000_nway_reset(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); @@ -1842,6 +1913,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)