/*******************************************************************************
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,
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) },
{ "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) },
{ "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_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 |
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;
return 0;
}
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");
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");
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;
ADVERTISED_TP |
ADVERTISED_Autoneg;
ecmd->advertising = hw->phy.autoneg_advertised;
+ if (adapter->fc_autoneg)
+ hw->fc.original_type = e1000_fc_default;
} else {
if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
clear_bit(__E1000_RESETTING, &adapter->state);
pause->autoneg =
(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
- if (hw->mac.fc == e1000_fc_rx_pause) {
+ if (hw->fc.type == e1000_fc_rx_pause) {
pause->rx_pause = 1;
- } else if (hw->mac.fc == e1000_fc_tx_pause) {
+ } else if (hw->fc.type == e1000_fc_tx_pause) {
pause->tx_pause = 1;
- } else if (hw->mac.fc == e1000_fc_full) {
+ } else if (hw->fc.type == e1000_fc_full) {
pause->rx_pause = 1;
pause->tx_pause = 1;
}
msleep(1);
if (pause->rx_pause && pause->tx_pause)
- hw->mac.fc = e1000_fc_full;
+ hw->fc.type = e1000_fc_full;
else if (pause->rx_pause && !pause->tx_pause)
- hw->mac.fc = e1000_fc_rx_pause;
+ hw->fc.type = e1000_fc_rx_pause;
else if (!pause->rx_pause && pause->tx_pause)
- hw->mac.fc = e1000_fc_tx_pause;
+ hw->fc.type = e1000_fc_tx_pause;
else if (!pause->rx_pause && !pause->tx_pause)
- hw->mac.fc = e1000_fc_none;
+ hw->fc.type = e1000_fc_none;
- hw->mac.original_fc = hw->mac.fc;
+ hw->fc.original_type = hw->fc.type;
if (adapter->fc_autoneg == AUTONEG_ENABLE) {
- hw->mac.fc = e1000_fc_default;
+ hw->fc.type = e1000_fc_default;
if (netif_running(adapter->netdev)) {
e1000e_down(adapter);
e1000e_up(adapter);
e1000e_reset(adapter);
}
} else {
- retval = ((hw->media_type == e1000_media_type_fiber) ?
+ retval = ((hw->phy.media_type == e1000_media_type_fiber) ?
hw->mac.ops.setup_link(hw) : e1000e_force_mac_fc(hw));
}
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;
+ }
}
}
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 */
+ /*
+ * 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);
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 */
+ /*
+ * EEPROM image version # is reported as firmware version # for
+ * PCI-E controllers
+ */
e1000_read_nvm(&adapter->hw, 5, 1, &eeprom_data);
sprintf(firmware_version, "%d.%d-%d",
(eeprom_data & 0xF000) >> 12,
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;
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);
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)) {
+ ndev_err(adapter->netdev, "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)) {
+ ndev_err(adapter->netdev, "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)
{
u32 i;
u32 toggle;
- /* 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) {
/* 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);
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);
/* Test each interrupt */
for (i = 0; i < 10; i++) {
-
- if (((adapter->hw.mac.type == e1000_ich8lan) ||
- (adapter->hw.mac.type == e1000_ich9lan)) && i == 8)
+ if ((adapter->flags & FLAG_IS_ICH) && (i == 8))
continue;
/* Interrupt to test */
mask = 1 << i;
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
}
}
- /* 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
}
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
struct pci_dev *pdev = adapter->pdev;
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
- int size;
int i;
int ret_val;
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);
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);
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;
}
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,
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;
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);
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);
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);
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);
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);
/* 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);
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);
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 */
#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;
}
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);
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);
}
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);
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
*/
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,
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
*/
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;
}
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");
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;
- /* 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)
ndev_info(netdev, "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;
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)
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->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,
{
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))
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;
return 0;
}
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);
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++) {
.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)