/* When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed
*/ if (hw->phy.ops.check_reset_block &&
hw->phy.ops.check_reset_block(hw)) {
e_err("Cannot change link characteristics when SoL/IDER is active.\n"); return -EINVAL;
}
/* MDI setting is only allowed when autoneg enabled because * some hardware doesn't allow MDI setting when speed or * duplex is forced.
*/ if (cmd->base.eth_tp_mdix_ctrl) { if (hw->phy.media_type != e1000_media_type_copper) return -EOPNOTSUPP;
if ((cmd->base.eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) &&
(cmd->base.autoneg != AUTONEG_ENABLE)) {
e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); return -EINVAL;
}
}
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
usleep_range(1000, 2000);
/* MDI-X => 2; MDI => 1; Auto => 3 */ if (cmd->base.eth_tp_mdix_ctrl) { /* fix up the value for auto (3 => 0) as zero is mapped * internally to auto
*/ if (cmd->base.eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
hw->phy.mdix = AUTO_ALL_MODES; else
hw->phy.mdix = cmd->base.eth_tp_mdix_ctrl;
}
/* reset the link */ if (netif_running(adapter->netdev)) {
e1000e_down(adapter, true);
e1000e_up(adapter);
} else {
e1000e_reset(adapter);
}
if (eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ /* only the second byte of the word is being modified */
ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]);
ptr++;
} if (((eeprom->offset + eeprom->len) & 1) && (!ret_val)) /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */
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]);
memcpy(ptr, bytes, eeprom->len);
for (i = 0; i < last_word - first_word + 1; i++)
cpu_to_le16s(&eeprom_buff[i]);
/* 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_82583) ||
(hw->mac.type == e1000_82574) ||
(hw->mac.type == e1000_82573))
ret_val = e1000e_update_nvm_checksum(hw);
/* Allocate temporary storage for ring updates */ if (set_tx) {
temp_tx = vmalloc(size); if (!temp_tx) {
err = -ENOMEM; goto free_temp;
}
} if (set_rx) {
temp_rx = vmalloc(size); if (!temp_rx) {
err = -ENOMEM; goto free_temp;
}
}
e1000e_down(adapter, true);
/* We can't just free everything and then setup again, because the * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring * structs. First, attempt to allocate new resources...
*/ if (set_tx) {
memcpy(temp_tx, adapter->tx_ring, size);
temp_tx->count = new_tx_count;
err = e1000e_setup_tx_resources(temp_tx); if (err) goto err_setup;
} if (set_rx) {
memcpy(temp_rx, adapter->rx_ring, size);
temp_rx->count = new_rx_count;
err = e1000e_setup_rx_resources(temp_rx); if (err) goto err_setup_rx;
}
/* ...then free the old resources and copy back any new ring data */ if (set_tx) {
e1000e_free_tx_resources(adapter->tx_ring);
memcpy(adapter->tx_ring, temp_tx, size);
adapter->tx_ring_count = new_tx_count;
} if (set_rx) {
e1000e_free_rx_resources(adapter->rx_ring);
memcpy(adapter->rx_ring, temp_rx, size);
adapter->rx_ring_count = new_rx_count;
}
/* The status register is Read Only, so a write should fail. * Some bits that get toggled are ignored. There are several bits * on newer hardware that are r/w.
*/ switch (mac->type) { case e1000_82571: case e1000_82572: case e1000_80003es2lan:
toggle = 0x7FFFF3FF; break; default:
toggle = 0x7FFFF033; break;
}
before = er32(STATUS);
value = (er32(STATUS) & toggle);
ew32(STATUS, toggle);
after = er32(STATUS) & toggle; if (value != after) {
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);
REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF);
REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); if (!(adapter->flags & FLAG_IS_ICH))
REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);
mask = 0x8003FFFF; switch (mac->type) { case e1000_ich10lan: case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: case e1000_pch_cnp: case e1000_pch_tgp: case e1000_pch_adp: case e1000_pch_mtp: case e1000_pch_lnp: case e1000_pch_ptp: case e1000_pch_nvp:
mask |= BIT(18); break; default: break;
}
if (mac->type >= e1000_pch_lpt)
wlock_mac = FIELD_GET(E1000_FWSM_WLOCK_MAC_MASK, er32(FWSM));
for (i = 0; i < mac->rar_entry_count; i++) { if (mac->type >= e1000_pch_lpt) { /* Cannot test write-protected SHRAL[n] registers */ if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac))) continue;
/* SHRAH[9] different than the others */ if (i == 10)
mask |= BIT(30); else
mask &= ~BIT(30);
} if (mac->type == e1000_pch2lan) { /* SHRAH[0,1,2] different than previous */ if (i == 1)
mask &= 0xFFF4FFFF; /* SHRAH[3] different than SHRAH[0,1,2] */ if (i == 4)
mask |= BIT(30); /* RAR[1-6] owned by management engine - skipping */ if (i > 0)
i += 6;
}
REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), mask,
0xFFFFFFFF); /* reset index to actual value */ if ((mac->type == e1000_pch2lan) && (i > 6))
i -= 6;
}
for (i = 0; i < mac->mta_reg_count; i++)
REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
*data = 0; /* Read and add up the contents of the EEPROM */ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) {
*data = 1; return *data;
}
checksum += temp;
}
/* If Checksum is not Correct return error else test passed */ if ((checksum != (u16)NVM_SUM) && !(*data))
*data = 2;
/* 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)) {
shared_int = 0;
} elseif (request_irq(irq, e1000_test_intr, IRQF_SHARED, netdev->name,
netdev)) {
*data = 1;
ret_val = -1; goto out;
}
e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared"));
/* Disable all the interrupts */
ew32(IMC, 0xFFFFFFFF);
e1e_flush();
usleep_range(10000, 11000);
/* Test each interrupt */ for (i = 0; i < 10; i++) { /* Interrupt to test */
mask = BIT(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 * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was posted to the bus, the * test failed.
*/
adapter->test_icr = 0;
ew32(IMC, mask);
ew32(ICS, mask);
e1e_flush();
usleep_range(10000, 11000);
/* 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 * test failed.
*/
adapter->test_icr = 0;
ew32(IMS, mask);
ew32(ICS, mask);
e1e_flush();
usleep_range(10000, 11000);
if (!(adapter->test_icr & mask)) {
*data = 4; break;
}
if (!shared_int) { /* 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 * test failed.
*/
adapter->test_icr = 0;
ew32(IMC, ~mask & 0x00007FFF);
ew32(ICS, ~mask & 0x00007FFF);
e1e_flush();
usleep_range(10000, 11000);
if (adapter->test_icr) {
*data = 5; break;
}
}
}
/* Disable all the interrupts */
ew32(IMC, 0xFFFFFFFF);
e1e_flush();
usleep_range(10000, 11000);
/* Unhook test interrupt handler */
free_irq(irq, netdev);
if (hw->phy.type == e1000_phy_ife) { /* force 100, set loopback */
e1e_wphy(hw, MII_BMCR, 0x6100);
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg = er32(CTRL);
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_100 |/* Force Speed to 100 */
E1000_CTRL_FD); /* Force Duplex to FULL */
/* Specific PHY configuration for loopback */ switch (hw->phy.type) { case e1000_phy_m88: /* Auto-MDI/MDIX Off */
e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); /* reset to update Auto-MDI/MDIX */
e1e_wphy(hw, MII_BMCR, 0x9140); /* autoneg off */
e1e_wphy(hw, MII_BMCR, 0x8140); break; case e1000_phy_gg82563:
e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); 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 */
hw->phy.ops.commit(hw);
usleep_range(1000, 2000); /* 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); break; case e1000_phy_82577: case e1000_phy_82578: /* Workaround: K1 must be disabled for stable 1Gbps operation */
ret_val = hw->phy.ops.acquire(hw); if (ret_val) {
e_err("Cannot setup 1Gbps loopback.\n"); return ret_val;
}
e1000_configure_k1_ich8lan(hw, false);
hw->phy.ops.release(hw); break; case e1000_phy_82579: /* Disable PHY energy detect power down */
e1e_rphy(hw, PHY_REG(0, 21), &phy_reg);
e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~BIT(3)); /* Disable full chip energy detect */
e1e_rphy(hw, PHY_REG(776, 18), &phy_reg);
e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1); /* Enable loopback on the PHY */
e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001); break; default: break;
}
/* force 1000, set loopback */
e1e_wphy(hw, MII_BMCR, 0x4140);
msleep(250);
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg = er32(CTRL);
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
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 &&
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.
*/ if ((er32(STATUS) & 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 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/ if (hw->phy.type == e1000_phy_m88)
e1000_phy_disable_receiver(adapter);
if (!link) { /* set invert loss of signal */
ctrl = er32(CTRL);
ctrl |= E1000_CTRL_ILOS;
ew32(CTRL, ctrl);
}
/* special write to serdes control register to enable SerDes analog * loopback
*/
ew32(SCTL, E1000_SCTL_ENABLE_SERDES_LOOPBACK);
e1e_flush();
usleep_range(10000, 11000);
return 0;
}
/* only call this for fiber/serdes connections to es2lan */ staticint e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
{ struct e1000_hw *hw = &adapter->hw;
u32 ctrlext = er32(CTRL_EXT);
u32 ctrl = er32(CTRL);
/* 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 */
ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
ew32(CTRL_EXT, ctrlext);
/* force speed to 1000/FD, link up */
ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX |
E1000_CTRL_SPD_1000 | E1000_CTRL_FD);
ew32(CTRL, ctrl);
/* set mac loopback */
ctrl = er32(RCTL);
ctrl |= E1000_RCTL_LBM_MAC;
ew32(RCTL, ctrl);
/* set testing mode parameters (no need to reset later) */ #define KMRNCTRLSTA_OPMODE (0x1F << 16) #define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582
ew32(KMRNCTRLSTA,
(KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));
staticint e1000_run_loopback_test(struct e1000_adapter *adapter)
{ struct e1000_ring *tx_ring = &adapter->test_tx_ring; struct e1000_ring *rx_ring = &adapter->test_rx_ring; struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; struct e1000_buffer *buffer_info; int i, j, k, l; int lc; int good_cnt; int ret_val = 0; unsignedlong time;
ew32(RDT(0), rx_ring->count - 1);
/* 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
*/
k = 0;
l = 0; /* loop count loop */ for (j = 0; j <= lc; j++) { /* send the packets */ for (i = 0; i < 64; i++) {
buffer_info = &tx_ring->buffer_info[k];
e1000_create_lbtest_frame(buffer_info->skb, 1024);
dma_sync_single_for_device(&pdev->dev,
buffer_info->dma,
buffer_info->length,
DMA_TO_DEVICE);
k++; if (k == tx_ring->count)
k = 0;
}
ew32(TDT(0), k);
e1e_flush();
msleep(200);
time = jiffies; /* set the start time for the receive */
good_cnt = 0; /* receive the sent packets */ do {
buffer_info = &rx_ring->buffer_info[l];
ret_val = e1000_check_lbtest_frame(buffer_info->skb,
1024); if (!ret_val)
good_cnt++;
l++; if (l == rx_ring->count)
l = 0; /* 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
*/
} while ((good_cnt < 64) && !time_after(jiffies, time + 20)); if (good_cnt != 64) {
ret_val = 13; /* ret_val is the same as mis-compare */ break;
} if (time_after(jiffies, time + 20)) {
ret_val = 14; /* error code for time out error */ break;
}
} return ret_val;
}
/* PHY loopback cannot be performed if SoL/IDER sessions are active */ if (hw->phy.ops.check_reset_block &&
hw->phy.ops.check_reset_block(hw)) {
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) goto out;
*data = e1000_setup_loopback_test(adapter); if (*data) goto err_loopback;
*data = 0; if (hw->phy.media_type == e1000_media_type_internal_serdes) { int i = 0;
hw->mac.serdes_has_link = false;
/* 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) return *data;
msleep(20);
} while (i++ < 3750);
*data = 1;
} else {
hw->mac.ops.check_for_link(hw); if (hw->mac.autoneg) /* On some Phy/switch combinations, link establishment * can take a few seconds more than expected.
*/
msleep_interruptible(5000);
if (if_running) /* indicate we're in test mode */
e1000e_close(netdev);
if (e1000_reg_test(adapter, &data[0]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000e_reset(adapter); if (e1000_eeprom_test(adapter, &data[1]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000e_reset(adapter); if (e1000_intr_test(adapter, &data[2]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000e_reset(adapter); if (e1000_loopback_test(adapter, &data[3]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* force this routine to wait until autoneg complete/timeout */
adapter->hw.phy.autoneg_wait_to_complete = 1;
e1000e_reset(adapter);
adapter->hw.phy.autoneg_wait_to_complete = 0;
if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK)) return 0;
switch (info->flow_type) { case TCP_V4_FLOW: if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP)
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
fallthrough; case UDP_V4_FLOW: case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case IPV4_FLOW: if (mrqc & E1000_MRQC_RSS_FIELD_IPV4)
info->data |= RXH_IP_SRC | RXH_IP_DST; break; case TCP_V6_FLOW: if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP)
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
fallthrough; case UDP_V6_FLOW: case SCTP_V6_FLOW: case AH_ESP_V6_FLOW: case IPV6_FLOW: if (mrqc & E1000_MRQC_RSS_FIELD_IPV6)
info->data |= RXH_IP_SRC | RXH_IP_DST; break; default: break;
} return 0;
}
/* EEE Link Partner Advertised */
ret_val = e1000_read_emi_reg_locked(hw, lpa_addr, &phy_data); if (ret_val) goto release;
mii_eee_cap1_mod_linkmode_t(edata->lp_advertised, phy_data);
/* EEE PCS Status */
ret_val = e1000_read_emi_reg_locked(hw, pcs_stat_addr, &phy_data); if (ret_val) goto release; if (hw->phy.type == e1000_phy_82579)
phy_data <<= 8;
/* Result of the EEE auto negotiation - there is no register that * has the status of the EEE negotiation so do a best-guess based * on whether Tx or Rx LPI indications have been received.
*/ if (phy_data & (E1000_EEE_TX_LPI_RCVD | E1000_EEE_RX_LPI_RCVD))
edata->eee_active = true;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.