summaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000/e1000_ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/e1000/e1000_ethtool.c')
-rw-r--r--drivers/net/e1000/e1000_ethtool.c111
1 files changed, 85 insertions, 26 deletions
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 8eae8ba27e84..c88f1a3c1b1d 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -562,10 +562,29 @@ e1000_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ char firmware_version[32];
+ uint16_t eeprom_data;
strncpy(drvinfo->driver, e1000_driver_name, 32);
strncpy(drvinfo->version, e1000_driver_version, 32);
- strncpy(drvinfo->fw_version, "N/A", 32);
+
+ /* EEPROM image version # is reported as firware version # for
+ * 8257{1|2|3} controllers */
+ e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
+ switch (adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_82573:
+ sprintf(firmware_version, "%d.%d-%d",
+ (eeprom_data & 0xF000) >> 12,
+ (eeprom_data & 0x0FF0) >> 4,
+ eeprom_data & 0x000F);
+ break;
+ default:
+ sprintf(firmware_version, "n/a");
+ }
+
+ strncpy(drvinfo->fw_version, firmware_version, 32);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
drvinfo->n_stats = E1000_STATS_LEN;
drvinfo->testinfo_len = E1000_TEST_LEN;
@@ -960,13 +979,21 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
}
}
- if(txdr->desc)
+ if(txdr->desc) {
pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
- if(rxdr->desc)
+ txdr->desc = NULL;
+ }
+ if(rxdr->desc) {
pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+ rxdr->desc = NULL;
+ }
kfree(txdr->buffer_info);
+ txdr->buffer_info = NULL;
+
kfree(rxdr->buffer_info);
+ rxdr->buffer_info = NULL;
+
return;
}
@@ -1301,21 +1328,32 @@ static int
e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
uint32_t rctl;
+ struct e1000_hw *hw = &adapter->hw;
- if(adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes) {
- if(adapter->hw.mac_type == e1000_82545 ||
- adapter->hw.mac_type == e1000_82546 ||
- adapter->hw.mac_type == e1000_82545_rev_3 ||
- adapter->hw.mac_type == e1000_82546_rev_3)
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes) {
+ switch (hw->mac_type) {
+ case e1000_82545:
+ case e1000_82546:
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
return e1000_set_phy_loopback(adapter);
- else {
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ break;
+ case e1000_82571:
+ case e1000_82572:
+#define E1000_SERDES_LB_ON 0x410
+ e1000_set_phy_loopback(adapter);
+ E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+ msec_delay(10);
+ return 0;
+ break;
+ default:
+ rctl = E1000_READ_REG(hw, RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ E1000_WRITE_REG(hw, RCTL, rctl);
return 0;
}
- } else if(adapter->hw.media_type == e1000_media_type_copper)
+ } else if (hw->media_type == e1000_media_type_copper)
return e1000_set_phy_loopback(adapter);
return 7;
@@ -1326,25 +1364,36 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
uint32_t rctl;
uint16_t phy_reg;
+ struct e1000_hw *hw = &adapter->hw;
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- if(adapter->hw.media_type == e1000_media_type_copper ||
- ((adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes) &&
- (adapter->hw.mac_type == e1000_82545 ||
- adapter->hw.mac_type == e1000_82546 ||
- adapter->hw.mac_type == e1000_82545_rev_3 ||
- adapter->hw.mac_type == e1000_82546_rev_3))) {
- adapter->hw.autoneg = TRUE;
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
- if(phy_reg & MII_CR_LOOPBACK) {
+ switch (hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes){
+#define E1000_SERDES_LB_OFF 0x400
+ E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+ msec_delay(10);
+ break;
+ }
+ /* fall thru for Cu adapters */
+ case e1000_82545:
+ case e1000_82546:
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ default:
+ hw->autoneg = TRUE;
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
+ if (phy_reg & MII_CR_LOOPBACK) {
phy_reg &= ~MII_CR_LOOPBACK;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
- e1000_phy_reset(&adapter->hw);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
+ e1000_phy_reset(hw);
}
+ break;
}
}
@@ -1440,9 +1489,11 @@ static int
e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
{
if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
- if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
+ if((*data = e1000_setup_loopback_test(adapter)))
+ goto err_loopback_setup;
*data = e1000_run_loopback_test(adapter);
e1000_loopback_cleanup(adapter);
+err_loopback_setup:
e1000_free_desc_rings(adapter);
err_loopback:
return *data;
@@ -1671,6 +1722,14 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
}
+ else if(adapter->hw.mac_type < e1000_82573) {
+ E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
+ E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+ msleep_interruptible(data * 1000);
+ }
else {
E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |