|
@@ -900,8 +900,6 @@ next_desc:
|
|
|
|
|
|
adapter->total_rx_bytes += total_rx_bytes;
|
|
|
adapter->total_rx_packets += total_rx_packets;
|
|
|
- netdev->stats.rx_bytes += total_rx_bytes;
|
|
|
- netdev->stats.rx_packets += total_rx_packets;
|
|
|
return cleaned;
|
|
|
}
|
|
|
|
|
@@ -1057,8 +1055,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
|
|
|
}
|
|
|
adapter->total_tx_bytes += total_tx_bytes;
|
|
|
adapter->total_tx_packets += total_tx_packets;
|
|
|
- netdev->stats.tx_bytes += total_tx_bytes;
|
|
|
- netdev->stats.tx_packets += total_tx_packets;
|
|
|
return count < tx_ring->count;
|
|
|
}
|
|
|
|
|
@@ -1245,8 +1241,6 @@ next_desc:
|
|
|
|
|
|
adapter->total_rx_bytes += total_rx_bytes;
|
|
|
adapter->total_rx_packets += total_rx_packets;
|
|
|
- netdev->stats.rx_bytes += total_rx_bytes;
|
|
|
- netdev->stats.rx_packets += total_rx_packets;
|
|
|
return cleaned;
|
|
|
}
|
|
|
|
|
@@ -1426,8 +1420,6 @@ next_desc:
|
|
|
|
|
|
adapter->total_rx_bytes += total_rx_bytes;
|
|
|
adapter->total_rx_packets += total_rx_packets;
|
|
|
- netdev->stats.rx_bytes += total_rx_bytes;
|
|
|
- netdev->stats.rx_packets += total_rx_packets;
|
|
|
return cleaned;
|
|
|
}
|
|
|
|
|
@@ -2728,7 +2720,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
|
|
|
{
|
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
|
u32 rctl, rfctl;
|
|
|
- u32 psrctl = 0;
|
|
|
u32 pages = 0;
|
|
|
|
|
|
/* Workaround Si errata on 82579 - configure jumbo frame flow */
|
|
@@ -2827,6 +2818,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
|
|
|
adapter->rx_ps_pages = 0;
|
|
|
|
|
|
if (adapter->rx_ps_pages) {
|
|
|
+ u32 psrctl = 0;
|
|
|
+
|
|
|
/* Configure extra packet-split registers */
|
|
|
rfctl = er32(RFCTL);
|
|
|
rfctl |= E1000_RFCTL_EXTEN;
|
|
@@ -3028,7 +3021,6 @@ static void e1000_set_multi(struct net_device *netdev)
|
|
|
struct netdev_hw_addr *ha;
|
|
|
u8 *mta_list;
|
|
|
u32 rctl;
|
|
|
- int i;
|
|
|
|
|
|
/* Check for Promiscuous and All Multicast modes */
|
|
|
|
|
@@ -3051,12 +3043,13 @@ static void e1000_set_multi(struct net_device *netdev)
|
|
|
ew32(RCTL, rctl);
|
|
|
|
|
|
if (!netdev_mc_empty(netdev)) {
|
|
|
+ int i = 0;
|
|
|
+
|
|
|
mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC);
|
|
|
if (!mta_list)
|
|
|
return;
|
|
|
|
|
|
/* prepare a packed array of only addresses. */
|
|
|
- i = 0;
|
|
|
netdev_for_each_mc_addr(ha, netdev)
|
|
|
memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
|
|
|
|
|
@@ -3338,6 +3331,8 @@ int e1000e_up(struct e1000_adapter *adapter)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void e1000e_update_stats(struct e1000_adapter *adapter);
|
|
|
+
|
|
|
void e1000e_down(struct e1000_adapter *adapter)
|
|
|
{
|
|
|
struct net_device *netdev = adapter->netdev;
|
|
@@ -3372,6 +3367,11 @@ void e1000e_down(struct e1000_adapter *adapter)
|
|
|
del_timer_sync(&adapter->phy_info_timer);
|
|
|
|
|
|
netif_carrier_off(netdev);
|
|
|
+
|
|
|
+ spin_lock(&adapter->stats64_lock);
|
|
|
+ e1000e_update_stats(adapter);
|
|
|
+ spin_unlock(&adapter->stats64_lock);
|
|
|
+
|
|
|
adapter->link_speed = 0;
|
|
|
adapter->link_duplex = 0;
|
|
|
|
|
@@ -3413,6 +3413,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
|
|
|
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
|
|
|
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
|
|
|
|
|
|
+ spin_lock_init(&adapter->stats64_lock);
|
|
|
+
|
|
|
e1000e_set_interrupt_capability(adapter);
|
|
|
|
|
|
if (e1000_alloc_queues(adapter))
|
|
@@ -3886,7 +3888,7 @@ release:
|
|
|
* e1000e_update_stats - Update the board statistics counters
|
|
|
* @adapter: board private structure
|
|
|
**/
|
|
|
-void e1000e_update_stats(struct e1000_adapter *adapter)
|
|
|
+static void e1000e_update_stats(struct e1000_adapter *adapter)
|
|
|
{
|
|
|
struct net_device *netdev = adapter->netdev;
|
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
@@ -3998,10 +4000,11 @@ 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;
|
|
|
|
|
|
if ((er32(STATUS) & E1000_STATUS_LU) &&
|
|
|
(adapter->hw.phy.media_type == e1000_media_type_copper)) {
|
|
|
+ int ret_val;
|
|
|
+
|
|
|
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);
|
|
@@ -4147,7 +4150,6 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|
|
struct e1000_ring *tx_ring = adapter->tx_ring;
|
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
|
u32 link, tctl;
|
|
|
- int tx_pending = 0;
|
|
|
|
|
|
link = e1000e_has_link(adapter);
|
|
|
if ((netif_carrier_ok(netdev)) && link) {
|
|
@@ -4285,7 +4287,9 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|
|
}
|
|
|
|
|
|
link_up:
|
|
|
+ spin_lock(&adapter->stats64_lock);
|
|
|
e1000e_update_stats(adapter);
|
|
|
+ spin_unlock(&adapter->stats64_lock);
|
|
|
|
|
|
mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
|
|
|
adapter->tpt_old = adapter->stats.tpt;
|
|
@@ -4299,21 +4303,18 @@ link_up:
|
|
|
|
|
|
e1000e_update_adaptive(&adapter->hw);
|
|
|
|
|
|
- if (!netif_carrier_ok(netdev)) {
|
|
|
- tx_pending = (e1000_desc_unused(tx_ring) + 1 <
|
|
|
- tx_ring->count);
|
|
|
- if (tx_pending) {
|
|
|
- /*
|
|
|
- * We've lost link, so the controller stops DMA,
|
|
|
- * but we've got queued Tx work that's never going
|
|
|
- * to get done, so reset controller to flush Tx.
|
|
|
- * (Do the reset outside of interrupt context).
|
|
|
- */
|
|
|
- adapter->tx_timeout_count++;
|
|
|
- schedule_work(&adapter->reset_task);
|
|
|
- /* return immediately since reset is imminent */
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (!netif_carrier_ok(netdev) &&
|
|
|
+ (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) {
|
|
|
+ /*
|
|
|
+ * We've lost link, so the controller stops DMA,
|
|
|
+ * but we've got queued Tx work that's never going
|
|
|
+ * to get done, so reset controller to flush Tx.
|
|
|
+ * (Do the reset outside of interrupt context).
|
|
|
+ */
|
|
|
+ adapter->tx_timeout_count++;
|
|
|
+ schedule_work(&adapter->reset_task);
|
|
|
+ /* return immediately since reset is imminent */
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
/* Simple mode for Interrupt Throttle Rate (ITR) */
|
|
@@ -4384,13 +4385,13 @@ static int e1000_tso(struct e1000_adapter *adapter,
|
|
|
u32 cmd_length = 0;
|
|
|
u16 ipcse = 0, tucse, mss;
|
|
|
u8 ipcss, ipcso, tucss, tucso, hdr_len;
|
|
|
- int err;
|
|
|
|
|
|
if (!skb_is_gso(skb))
|
|
|
return 0;
|
|
|
|
|
|
if (skb_header_cloned(skb)) {
|
|
|
- err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
|
|
|
+ int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
|
|
|
+
|
|
|
if (err)
|
|
|
return err;
|
|
|
}
|
|
@@ -4897,16 +4898,55 @@ static void e1000_reset_task(struct work_struct *work)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000_get_stats - Get System Network Statistics
|
|
|
+ * e1000_get_stats64 - Get System Network Statistics
|
|
|
* @netdev: network interface device structure
|
|
|
+ * @stats: rtnl_link_stats64 pointer
|
|
|
*
|
|
|
* Returns the address of the device statistics structure.
|
|
|
- * The statistics are actually updated from the timer callback.
|
|
|
**/
|
|
|
-static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
|
|
|
+struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
|
|
|
+ struct rtnl_link_stats64 *stats)
|
|
|
{
|
|
|
- /* only return the current stats */
|
|
|
- return &netdev->stats;
|
|
|
+ struct e1000_adapter *adapter = netdev_priv(netdev);
|
|
|
+
|
|
|
+ memset(stats, 0, sizeof(struct rtnl_link_stats64));
|
|
|
+ spin_lock(&adapter->stats64_lock);
|
|
|
+ e1000e_update_stats(adapter);
|
|
|
+ /* Fill out the OS statistics structure */
|
|
|
+ stats->rx_bytes = adapter->stats.gorc;
|
|
|
+ stats->rx_packets = adapter->stats.gprc;
|
|
|
+ stats->tx_bytes = adapter->stats.gotc;
|
|
|
+ stats->tx_packets = adapter->stats.gptc;
|
|
|
+ stats->multicast = adapter->stats.mprc;
|
|
|
+ stats->collisions = adapter->stats.colc;
|
|
|
+
|
|
|
+ /* Rx Errors */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * RLEC on some newer hardware can be incorrect so build
|
|
|
+ * our own version based on RUC and ROC
|
|
|
+ */
|
|
|
+ stats->rx_errors = adapter->stats.rxerrc +
|
|
|
+ adapter->stats.crcerrs + adapter->stats.algnerrc +
|
|
|
+ adapter->stats.ruc + adapter->stats.roc +
|
|
|
+ adapter->stats.cexterr;
|
|
|
+ stats->rx_length_errors = adapter->stats.ruc +
|
|
|
+ adapter->stats.roc;
|
|
|
+ stats->rx_crc_errors = adapter->stats.crcerrs;
|
|
|
+ stats->rx_frame_errors = adapter->stats.algnerrc;
|
|
|
+ stats->rx_missed_errors = adapter->stats.mpc;
|
|
|
+
|
|
|
+ /* Tx Errors */
|
|
|
+ stats->tx_errors = adapter->stats.ecol +
|
|
|
+ adapter->stats.latecol;
|
|
|
+ stats->tx_aborted_errors = adapter->stats.ecol;
|
|
|
+ stats->tx_window_errors = adapter->stats.latecol;
|
|
|
+ stats->tx_carrier_errors = adapter->stats.tncrs;
|
|
|
+
|
|
|
+ /* Tx Dropped needs to be maintained elsewhere */
|
|
|
+
|
|
|
+ spin_unlock(&adapter->stats64_lock);
|
|
|
+ return stats;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -5476,9 +5516,10 @@ static irqreturn_t e1000_intr_msix(int irq, void *data)
|
|
|
{
|
|
|
struct net_device *netdev = data;
|
|
|
struct e1000_adapter *adapter = netdev_priv(netdev);
|
|
|
- int vector, msix_irq;
|
|
|
|
|
|
if (adapter->msix_entries) {
|
|
|
+ int vector, msix_irq;
|
|
|
+
|
|
|
vector = 0;
|
|
|
msix_irq = adapter->msix_entries[vector].vector;
|
|
|
disable_irq(msix_irq);
|
|
@@ -5675,7 +5716,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
|
|
|
.ndo_open = e1000_open,
|
|
|
.ndo_stop = e1000_close,
|
|
|
.ndo_start_xmit = e1000_xmit_frame,
|
|
|
- .ndo_get_stats = e1000_get_stats,
|
|
|
+ .ndo_get_stats64 = e1000e_get_stats64,
|
|
|
.ndo_set_multicast_list = e1000_set_multi,
|
|
|
.ndo_set_mac_address = e1000_set_mac,
|
|
|
.ndo_change_mtu = e1000_change_mtu,
|