diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 01c88664bad3..462351ca2c81 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1326,12 +1326,10 @@ struct e1000_info e1000_82571_info = { .mac = e1000_82571, .flags = FLAG_HAS_HW_VLAN_FILTER | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_STATS_PTC_PRC | FLAG_HAS_WOL | FLAG_APME_IN_CTRL3 | FLAG_RX_CSUM_ENABLED | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_STATS_ICR_ICT | FLAG_HAS_SMART_POWER_DOWN | FLAG_RESET_OVERWRITES_LAA /* errata */ | FLAG_TARC_SPEED_MODE_BIT /* errata */ @@ -1347,12 +1345,10 @@ struct e1000_info e1000_82572_info = { .mac = e1000_82572, .flags = FLAG_HAS_HW_VLAN_FILTER | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_STATS_PTC_PRC | FLAG_HAS_WOL | FLAG_APME_IN_CTRL3 | FLAG_RX_CSUM_ENABLED | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_STATS_ICR_ICT | FLAG_TARC_SPEED_MODE_BIT, /* errata */ .pba = 38, .get_variants = e1000_get_variants_82571, @@ -1365,11 +1361,9 @@ struct e1000_info e1000_82573_info = { .mac = e1000_82573, .flags = FLAG_HAS_HW_VLAN_FILTER | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_STATS_PTC_PRC | FLAG_HAS_WOL | FLAG_APME_IN_CTRL3 | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_STATS_ICR_ICT | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_ERT diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 572cfd44397a..4fb9d8722739 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -527,8 +527,10 @@ #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ #define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ #define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ /* NVM Control */ #define E1000_EECD_SK 0x00000001 /* NVM Clock */ diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 5a89dff52264..4d3d1c2991c9 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -147,6 +147,18 @@ struct e1000_ring { struct e1000_queue_stats stats; }; +/* PHY register snapshot values */ +struct e1000_phy_regs { + u16 bmcr; /* basic mode control register */ + u16 bmsr; /* basic mode status register */ + u16 advertise; /* auto-negotiation advertisement */ + u16 lpa; /* link partner ability register */ + u16 expansion; /* auto-negotiation expansion reg */ + u16 ctrl1000; /* 1000BASE-T control register */ + u16 stat1000; /* 1000BASE-T status register */ + u16 estatus; /* extended status register */ +}; + /* board specific private data structure */ struct e1000_adapter { struct timer_list watchdog_timer; @@ -202,8 +214,8 @@ struct e1000_adapter { /* Tx stats */ u64 tpt_old; u64 colc_old; - u64 gotcl_old; - u32 gotcl; + u32 gotc; + u64 gotc_old; u32 tx_timeout_count; u32 tx_fifo_head; u32 tx_head_addr; @@ -227,8 +239,8 @@ struct e1000_adapter { u64 hw_csum_err; u64 hw_csum_good; u64 rx_hdr_split; - u64 gorcl_old; - u32 gorcl; + u32 gorc; + u64 gorc_old; u32 alloc_rx_buff_failed; u32 rx_dma_failed; @@ -250,6 +262,9 @@ struct e1000_adapter { struct e1000_phy_info phy_info; struct e1000_phy_stats phy_stats; + /* Snapshot of PHY registers */ + struct e1000_phy_regs phy_regs; + struct e1000_ring test_tx_ring; struct e1000_ring test_rx_ring; u32 test_icr; @@ -286,8 +301,6 @@ struct e1000_info { #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) #define FLAG_HAS_SWSM_ON_LOAD (1 << 6) #define FLAG_HAS_JUMBO_FRAMES (1 << 7) -#define FLAG_HAS_STATS_ICR_ICT (1 << 9) -#define FLAG_HAS_STATS_PTC_PRC (1 << 10) #define FLAG_HAS_SMART_POWER_DOWN (1 << 11) #define FLAG_IS_QUAD_PORT_A (1 << 12) #define FLAG_IS_QUAD_PORT (1 << 13) diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index d59a99ae44be..13a6f4484de9 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -1231,12 +1231,10 @@ struct e1000_info e1000_es2_info = { .mac = e1000_80003es2lan, .flags = FLAG_HAS_HW_VLAN_FILTER | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_STATS_PTC_PRC | FLAG_HAS_WOL | FLAG_APME_IN_CTRL3 | FLAG_RX_CSUM_ENABLED | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_STATS_ICR_ICT | FLAG_RX_NEEDS_RESTART /* errata */ | FLAG_TARC_SET_BIT_ZERO /* errata */ | FLAG_APME_CHECK_PORT_B diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 6d1b257bbda6..c894a6f03bb4 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) }, diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 53f1ac6327fa..a930e6d9cf02 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -592,10 +592,8 @@ struct e1000_hw_stats { u64 bprc; u64 mprc; u64 gptc; - u64 gorcl; - u64 gorch; - u64 gotcl; - u64 gotch; + u64 gorc; + u64 gotc; u64 rnbc; u64 ruc; u64 rfc; @@ -604,10 +602,8 @@ struct e1000_hw_stats { u64 mgprc; u64 mgpdc; u64 mgptc; - u64 torl; - u64 torh; - u64 totl; - u64 toth; + u64 tor; + u64 tot; u64 tpr; u64 tpt; u64 ptc64; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index c8dc47fd132a..9d1143aa6189 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -466,10 +466,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, if (cleaned_count) adapter->alloc_rx_buf(adapter, cleaned_count); - adapter->total_rx_packets += total_rx_packets; adapter->total_rx_bytes += total_rx_bytes; - adapter->net_stats.rx_packets += total_rx_packets; + adapter->total_rx_packets += total_rx_packets; adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; return cleaned; } @@ -606,8 +606,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) } adapter->total_tx_bytes += total_tx_bytes; adapter->total_tx_packets += total_tx_packets; - adapter->net_stats.tx_packets += total_tx_packets; adapter->net_stats.tx_bytes += total_tx_bytes; + adapter->net_stats.tx_packets += total_tx_packets; return cleaned; } @@ -775,10 +775,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, if (cleaned_count) adapter->alloc_rx_buf(adapter, cleaned_count); - adapter->total_rx_packets += total_rx_packets; adapter->total_rx_bytes += total_rx_bytes; - adapter->net_stats.rx_packets += total_rx_packets; + adapter->total_rx_packets += total_rx_packets; adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; return cleaned; } @@ -2506,56 +2506,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter) adapter->stats.crcerrs += er32(CRCERRS); adapter->stats.gprc += er32(GPRC); - adapter->stats.gorcl += er32(GORCL); - adapter->stats.gorch += er32(GORCH); + adapter->stats.gorc += er32(GORCL); + er32(GORCH); /* Clear gorc */ adapter->stats.bprc += er32(BPRC); adapter->stats.mprc += er32(MPRC); adapter->stats.roc += er32(ROC); - if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) { - adapter->stats.prc64 += er32(PRC64); - adapter->stats.prc127 += er32(PRC127); - adapter->stats.prc255 += er32(PRC255); - adapter->stats.prc511 += er32(PRC511); - adapter->stats.prc1023 += er32(PRC1023); - adapter->stats.prc1522 += er32(PRC1522); - adapter->stats.symerrs += er32(SYMERRS); - adapter->stats.sec += er32(SEC); - } - adapter->stats.mpc += er32(MPC); adapter->stats.scc += er32(SCC); adapter->stats.ecol += er32(ECOL); adapter->stats.mcc += er32(MCC); adapter->stats.latecol += er32(LATECOL); adapter->stats.dc += er32(DC); - adapter->stats.rlec += er32(RLEC); adapter->stats.xonrxc += er32(XONRXC); adapter->stats.xontxc += er32(XONTXC); adapter->stats.xoffrxc += er32(XOFFRXC); adapter->stats.xofftxc += er32(XOFFTXC); - adapter->stats.fcruc += er32(FCRUC); adapter->stats.gptc += er32(GPTC); - adapter->stats.gotcl += er32(GOTCL); - adapter->stats.gotch += er32(GOTCH); + adapter->stats.gotc += er32(GOTCL); + er32(GOTCH); /* Clear gotc */ adapter->stats.rnbc += er32(RNBC); adapter->stats.ruc += er32(RUC); - adapter->stats.rfc += er32(RFC); - adapter->stats.rjc += er32(RJC); - adapter->stats.torl += er32(TORL); - adapter->stats.torh += er32(TORH); - adapter->stats.totl += er32(TOTL); - adapter->stats.toth += er32(TOTH); - adapter->stats.tpr += er32(TPR); - - if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) { - adapter->stats.ptc64 += er32(PTC64); - adapter->stats.ptc127 += er32(PTC127); - adapter->stats.ptc255 += er32(PTC255); - adapter->stats.ptc511 += er32(PTC511); - adapter->stats.ptc1023 += er32(PTC1023); - adapter->stats.ptc1522 += er32(PTC1522); - } adapter->stats.mptc += er32(MPTC); adapter->stats.bptc += er32(BPTC); @@ -2574,19 +2545,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter) adapter->stats.tsctc += er32(TSCTC); adapter->stats.tsctfc += er32(TSCTFC); - adapter->stats.iac += er32(IAC); - - if (adapter->flags & FLAG_HAS_STATS_ICR_ICT) { - adapter->stats.icrxoc += er32(ICRXOC); - adapter->stats.icrxptc += er32(ICRXPTC); - adapter->stats.icrxatc += er32(ICRXATC); - adapter->stats.ictxptc += er32(ICTXPTC); - adapter->stats.ictxatc += er32(ICTXATC); - adapter->stats.ictxqec += er32(ICTXQEC); - adapter->stats.ictxqmtc += er32(ICTXQMTC); - adapter->stats.icrxdmtc += er32(ICRXDMTC); - } - /* Fill out the OS statistics structure */ adapter->net_stats.multicast = adapter->stats.mprc; adapter->net_stats.collisions = adapter->stats.colc; @@ -2633,6 +2591,54 @@ void e1000e_update_stats(struct e1000_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); } +/** + * e1000_phy_read_status - Update the PHY register status snapshot + * @adapter: board private structure + **/ +static void e1000_phy_read_status(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct e1000_phy_regs *phy = &adapter->phy_regs; + int ret_val; + unsigned long irq_flags; + + + spin_lock_irqsave(&adapter->stats_lock, irq_flags); + + if ((er32(STATUS) & E1000_STATUS_LU) && + (adapter->hw.phy.media_type == e1000_media_type_copper)) { + ret_val = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr); + ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr); + ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise); + ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa); + ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion); + ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000); + ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000); + ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus); + if (ret_val) + ndev_warn(adapter->netdev, + "Error reading PHY register\n"); + } else { + /* + * Do not read PHY registers if link is not up + * Set values to typical power-on defaults + */ + phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); + phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | + BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | + BMSR_ERCAP); + phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | + ADVERTISE_ALL | ADVERTISE_CSMA); + phy->lpa = 0; + phy->expansion = EXPANSION_ENABLENPAGE; + phy->ctrl1000 = ADVERTISE_1000FULL; + phy->stat1000 = 0; + phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); + } + + spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); +} + static void e1000_print_link_info(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; @@ -2745,6 +2751,7 @@ static void e1000_watchdog_task(struct work_struct *work) if (!netif_carrier_ok(netdev)) { bool txb2b = 1; /* update snapshot of PHY registers on LSC */ + e1000_phy_read_status(adapter); mac->ops.get_link_up_info(&adapter->hw, &adapter->link_speed, &adapter->link_duplex); @@ -2842,10 +2849,10 @@ static void e1000_watchdog_task(struct work_struct *work) mac->collision_delta = adapter->stats.colc - adapter->colc_old; adapter->colc_old = adapter->stats.colc; - adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; - adapter->gorcl_old = adapter->stats.gorcl; - adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; - adapter->gotcl_old = adapter->stats.gotcl; + adapter->gorc = adapter->stats.gorc - adapter->gorc_old; + adapter->gorc_old = adapter->stats.gorc; + adapter->gotc = adapter->stats.gotc - adapter->gotc_old; + adapter->gotc_old = adapter->stats.gotc; e1000e_update_adaptive(&adapter->hw); @@ -3500,7 +3507,6 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, { struct e1000_adapter *adapter = netdev_priv(netdev); struct mii_ioctl_data *data = if_mii(ifr); - unsigned long irq_flags; if (adapter->hw.phy.media_type != e1000_media_type_copper) return -EOPNOTSUPP; @@ -3512,13 +3518,40 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, case SIOCGMIIREG: if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_irqsave(&adapter->stats_lock, irq_flags); - if (e1e_rphy(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) { - spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); + switch (data->reg_num & 0x1F) { + case MII_BMCR: + data->val_out = adapter->phy_regs.bmcr; + break; + case MII_BMSR: + data->val_out = adapter->phy_regs.bmsr; + break; + case MII_PHYSID1: + data->val_out = (adapter->hw.phy.id >> 16); + break; + case MII_PHYSID2: + data->val_out = (adapter->hw.phy.id & 0xFFFF); + break; + case MII_ADVERTISE: + data->val_out = adapter->phy_regs.advertise; + break; + case MII_LPA: + data->val_out = adapter->phy_regs.lpa; + break; + case MII_EXPANSION: + data->val_out = adapter->phy_regs.expansion; + break; + case MII_CTRL1000: + data->val_out = adapter->phy_regs.ctrl1000; + break; + case MII_STAT1000: + data->val_out = adapter->phy_regs.stat1000; + break; + case MII_ESTATUS: + data->val_out = adapter->phy_regs.estatus; + break; + default: return -EIO; } - spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); break; case SIOCSMIIREG: default: