diff options
Diffstat (limited to 'drivers/net/benet/be_main.c')
-rw-r--r-- | drivers/net/benet/be_main.c | 77 |
1 files changed, 48 insertions, 29 deletions
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 9cfbfdfb3674..9f2f66c66be6 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -396,36 +396,44 @@ void be_parse_stats(struct be_adapter *adapter) erx->rx_drops_no_fragments[rxo->q.id]; } -void netdev_stats_update(struct be_adapter *adapter) +static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) { + struct be_adapter *adapter = netdev_priv(netdev); struct be_drv_stats *drvs = &adapter->drv_stats; - struct net_device_stats *dev_stats = &adapter->netdev->stats; struct be_rx_obj *rxo; struct be_tx_obj *txo; - unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0; + u64 pkts, bytes; + unsigned int start; int i; for_all_rx_queues(adapter, rxo, i) { - pkts += rx_stats(rxo)->rx_pkts; - bytes += rx_stats(rxo)->rx_bytes; - mcast += rx_stats(rxo)->rx_mcast_pkts; - drops += rx_stats(rxo)->rx_drops_no_skbs; + const struct be_rx_stats *rx_stats = rx_stats(rxo); + do { + start = u64_stats_fetch_begin_bh(&rx_stats->sync); + pkts = rx_stats(rxo)->rx_pkts; + bytes = rx_stats(rxo)->rx_bytes; + } while (u64_stats_fetch_retry_bh(&rx_stats->sync, start)); + stats->rx_packets += pkts; + stats->rx_bytes += bytes; + stats->multicast += rx_stats(rxo)->rx_mcast_pkts; + stats->rx_dropped += rx_stats(rxo)->rx_drops_no_skbs + + rx_stats(rxo)->rx_drops_no_frags; } - dev_stats->rx_packets = pkts; - dev_stats->rx_bytes = bytes; - dev_stats->multicast = mcast; - dev_stats->rx_dropped = drops; - pkts = bytes = 0; for_all_tx_queues(adapter, txo, i) { - pkts += tx_stats(txo)->tx_pkts; - bytes += tx_stats(txo)->tx_bytes; + const struct be_tx_stats *tx_stats = tx_stats(txo); + do { + start = u64_stats_fetch_begin_bh(&tx_stats->sync); + pkts = tx_stats(txo)->tx_pkts; + bytes = tx_stats(txo)->tx_bytes; + } while (u64_stats_fetch_retry_bh(&tx_stats->sync, start)); + stats->tx_packets += pkts; + stats->tx_bytes += bytes; } - dev_stats->tx_packets = pkts; - dev_stats->tx_bytes = bytes; /* bad pkts received */ - dev_stats->rx_errors = drvs->rx_crc_errors + + stats->rx_errors = drvs->rx_crc_errors + drvs->rx_alignment_symbol_errors + drvs->rx_in_range_errors + drvs->rx_out_range_errors + @@ -434,26 +442,24 @@ void netdev_stats_update(struct be_adapter *adapter) drvs->rx_dropped_too_short + drvs->rx_dropped_header_too_small + drvs->rx_dropped_tcp_length + - drvs->rx_dropped_runt + - drvs->rx_tcp_checksum_errs + - drvs->rx_ip_checksum_errs + - drvs->rx_udp_checksum_errs; + drvs->rx_dropped_runt; /* detailed rx errors */ - dev_stats->rx_length_errors = drvs->rx_in_range_errors + + stats->rx_length_errors = drvs->rx_in_range_errors + drvs->rx_out_range_errors + drvs->rx_frame_too_long; - dev_stats->rx_crc_errors = drvs->rx_crc_errors; + stats->rx_crc_errors = drvs->rx_crc_errors; /* frame alignment errors */ - dev_stats->rx_frame_errors = drvs->rx_alignment_symbol_errors; + stats->rx_frame_errors = drvs->rx_alignment_symbol_errors; /* receiver fifo overrun */ /* drops_no_pbuf is no per i/f, it's per BE card */ - dev_stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop + + stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop + drvs->rx_input_fifo_overflow_drop + drvs->rx_drops_no_pbuf; + return stats; } void be_link_status_update(struct be_adapter *adapter, bool link_up) @@ -479,12 +485,14 @@ static void be_tx_stats_update(struct be_tx_obj *txo, { struct be_tx_stats *stats = tx_stats(txo); + u64_stats_update_begin(&stats->sync); stats->tx_reqs++; stats->tx_wrbs += wrb_cnt; stats->tx_bytes += copied; stats->tx_pkts += (gso_segs ? gso_segs : 1); if (stopped) stats->tx_stops++; + u64_stats_update_end(&stats->sync); } /* Determine number of WRB entries needed to xmit data in an skb */ @@ -905,7 +913,8 @@ static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo) struct be_rx_stats *stats = rx_stats(rxo); ulong now = jiffies; ulong delta = now - stats->rx_jiffies; - u32 eqd; + u64 pkts; + unsigned int start, eqd; if (!rx_eq->enable_aic) return; @@ -920,8 +929,13 @@ static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo) if (delta < HZ) return; - stats->rx_pps = (stats->rx_pkts - stats->rx_pkts_prev) / (delta / HZ); - stats->rx_pkts_prev = stats->rx_pkts; + do { + start = u64_stats_fetch_begin_bh(&stats->sync); + pkts = stats->rx_pkts; + } while (u64_stats_fetch_retry_bh(&stats->sync, start)); + + stats->rx_pps = (pkts - stats->rx_pkts_prev) / (delta / HZ); + stats->rx_pkts_prev = pkts; stats->rx_jiffies = now; eqd = stats->rx_pps / 110000; eqd = eqd << 3; @@ -942,6 +956,7 @@ static void be_rx_stats_update(struct be_rx_obj *rxo, { struct be_rx_stats *stats = rx_stats(rxo); + u64_stats_update_begin(&stats->sync); stats->rx_compl++; stats->rx_bytes += rxcp->pkt_size; stats->rx_pkts++; @@ -949,6 +964,7 @@ static void be_rx_stats_update(struct be_rx_obj *rxo, stats->rx_mcast_pkts++; if (rxcp->err) stats->rx_compl_err++; + u64_stats_update_end(&stats->sync); } static inline bool csum_passed(struct be_rx_compl_info *rxcp) @@ -1878,8 +1894,9 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) netif_wake_subqueue(adapter->netdev, i); } - adapter->drv_stats.tx_events++; + u64_stats_update_begin(&tx_stats(txo)->sync_compl); tx_stats(txo)->tx_compl += tx_compl; + u64_stats_update_end(&tx_stats(txo)->sync_compl); } } @@ -1893,6 +1910,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) napi_complete(napi); be_eq_notify(adapter, tx_eq->q.id, true, false, 0); + adapter->drv_stats.tx_events++; return 1; } @@ -2843,6 +2861,7 @@ static struct net_device_ops be_netdev_ops = { .ndo_set_rx_mode = be_set_multicast_list, .ndo_set_mac_address = be_mac_addr_set, .ndo_change_mtu = be_change_mtu, + .ndo_get_stats64 = be_get_stats64, .ndo_validate_addr = eth_validate_addr, .ndo_vlan_rx_add_vid = be_vlan_add_vid, .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, |