Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ixgbevf: Fix VF Stats accounting after reset

The counters in the 82599 Virtual Function are not clear on read. They
accumulate to the maximum value and then roll over. They are also not
cleared when the VF executes a soft reset, so it is possible they are
non-zero when the driver loads and starts. This has all been accounted
for in the code that keeps the stats up to date but there is one case
that is not. When the PF driver is reset the counters in the VF are
all reset to zero. This adds an additional accounting overhead into
the VF driver when the PF is reset under its feet. This patch adds
additional counters that are used by the VF driver to accumulate and
save stats after a PF reset has been detected. Prior to this patch
displaying the stats in the VF after the PF has reset would show
bogus data.

Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Greg Rose and committed by
David S. Miller
33bd9f60 fd3686a8

+78 -38
+28 -14
drivers/net/ixgbevf/ethtool.c
··· 46 46 int sizeof_stat; 47 47 int stat_offset; 48 48 int base_stat_offset; 49 + int saved_reset_offset; 49 50 }; 50 51 51 - #define IXGBEVF_STAT(m, b) sizeof(((struct ixgbevf_adapter *)0)->m), \ 52 - offsetof(struct ixgbevf_adapter, m), \ 53 - offsetof(struct ixgbevf_adapter, b) 52 + #define IXGBEVF_STAT(m, b, r) sizeof(((struct ixgbevf_adapter *)0)->m), \ 53 + offsetof(struct ixgbevf_adapter, m), \ 54 + offsetof(struct ixgbevf_adapter, b), \ 55 + offsetof(struct ixgbevf_adapter, r) 54 56 static struct ixgbe_stats ixgbe_gstrings_stats[] = { 55 - {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc)}, 56 - {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc)}, 57 - {"rx_bytes", IXGBEVF_STAT(stats.vfgorc, stats.base_vfgorc)}, 58 - {"tx_bytes", IXGBEVF_STAT(stats.vfgotc, stats.base_vfgotc)}, 59 - {"tx_busy", IXGBEVF_STAT(tx_busy, zero_base)}, 60 - {"multicast", IXGBEVF_STAT(stats.vfmprc, stats.base_vfmprc)}, 61 - {"rx_csum_offload_good", IXGBEVF_STAT(hw_csum_rx_good, zero_base)}, 62 - {"rx_csum_offload_errors", IXGBEVF_STAT(hw_csum_rx_error, zero_base)}, 63 - {"tx_csum_offload_ctxt", IXGBEVF_STAT(hw_csum_tx_good, zero_base)}, 64 - {"rx_header_split", IXGBEVF_STAT(rx_hdr_split, zero_base)}, 57 + {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc, 58 + stats.saved_reset_vfgprc)}, 59 + {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc, 60 + stats.saved_reset_vfgptc)}, 61 + {"rx_bytes", IXGBEVF_STAT(stats.vfgorc, stats.base_vfgorc, 62 + stats.saved_reset_vfgorc)}, 63 + {"tx_bytes", IXGBEVF_STAT(stats.vfgotc, stats.base_vfgotc, 64 + stats.saved_reset_vfgotc)}, 65 + {"tx_busy", IXGBEVF_STAT(tx_busy, zero_base, zero_base)}, 66 + {"multicast", IXGBEVF_STAT(stats.vfmprc, stats.base_vfmprc, 67 + stats.saved_reset_vfmprc)}, 68 + {"rx_csum_offload_good", IXGBEVF_STAT(hw_csum_rx_good, zero_base, 69 + zero_base)}, 70 + {"rx_csum_offload_errors", IXGBEVF_STAT(hw_csum_rx_error, zero_base, 71 + zero_base)}, 72 + {"tx_csum_offload_ctxt", IXGBEVF_STAT(hw_csum_tx_good, zero_base, 73 + zero_base)}, 74 + {"rx_header_split", IXGBEVF_STAT(rx_hdr_split, zero_base, zero_base)}, 65 75 }; 66 76 67 77 #define IXGBE_QUEUE_STATS_LEN 0 ··· 465 455 ixgbe_gstrings_stats[i].stat_offset; 466 456 char *b = (char *)adapter + 467 457 ixgbe_gstrings_stats[i].base_stat_offset; 458 + char *r = (char *)adapter + 459 + ixgbe_gstrings_stats[i].saved_reset_offset; 468 460 data[i] = ((ixgbe_gstrings_stats[i].sizeof_stat == 469 461 sizeof(u64)) ? *(u64 *)p : *(u32 *)p) - 470 462 ((ixgbe_gstrings_stats[i].sizeof_stat == 471 - sizeof(u64)) ? *(u64 *)b : *(u32 *)b); 463 + sizeof(u64)) ? *(u64 *)b : *(u32 *)b) + 464 + ((ixgbe_gstrings_stats[i].sizeof_stat == 465 + sizeof(u64)) ? *(u64 *)r : *(u32 *)r); 472 466 } 473 467 } 474 468
+44 -24
drivers/net/ixgbevf/ixgbevf_main.c
··· 1610 1610 (adapter->rx_ring[rxr].count - 1)); 1611 1611 } 1612 1612 1613 + static void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter) 1614 + { 1615 + /* Only save pre-reset stats if there are some */ 1616 + if (adapter->stats.vfgprc || adapter->stats.vfgptc) { 1617 + adapter->stats.saved_reset_vfgprc += adapter->stats.vfgprc - 1618 + adapter->stats.base_vfgprc; 1619 + adapter->stats.saved_reset_vfgptc += adapter->stats.vfgptc - 1620 + adapter->stats.base_vfgptc; 1621 + adapter->stats.saved_reset_vfgorc += adapter->stats.vfgorc - 1622 + adapter->stats.base_vfgorc; 1623 + adapter->stats.saved_reset_vfgotc += adapter->stats.vfgotc - 1624 + adapter->stats.base_vfgotc; 1625 + adapter->stats.saved_reset_vfmprc += adapter->stats.vfmprc - 1626 + adapter->stats.base_vfmprc; 1627 + } 1628 + } 1629 + 1630 + static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter) 1631 + { 1632 + struct ixgbe_hw *hw = &adapter->hw; 1633 + 1634 + adapter->stats.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC); 1635 + adapter->stats.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB); 1636 + adapter->stats.last_vfgorc |= 1637 + (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32); 1638 + adapter->stats.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC); 1639 + adapter->stats.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB); 1640 + adapter->stats.last_vfgotc |= 1641 + (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32); 1642 + adapter->stats.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC); 1643 + 1644 + adapter->stats.base_vfgprc = adapter->stats.last_vfgprc; 1645 + adapter->stats.base_vfgorc = adapter->stats.last_vfgorc; 1646 + adapter->stats.base_vfgptc = adapter->stats.last_vfgptc; 1647 + adapter->stats.base_vfgotc = adapter->stats.last_vfgotc; 1648 + adapter->stats.base_vfmprc = adapter->stats.last_vfmprc; 1649 + } 1650 + 1613 1651 static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter) 1614 1652 { 1615 1653 struct net_device *netdev = adapter->netdev; ··· 1693 1655 1694 1656 /* enable transmits */ 1695 1657 netif_tx_start_all_queues(netdev); 1658 + 1659 + ixgbevf_save_reset_stats(adapter); 1660 + ixgbevf_init_last_counter_stats(adapter); 1696 1661 1697 1662 /* bring the link up in the watchdog, this could race with our first 1698 1663 * link up interrupt but shouldn't be a problem */ ··· 2269 2228 return err; 2270 2229 } 2271 2230 2272 - static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter) 2273 - { 2274 - struct ixgbe_hw *hw = &adapter->hw; 2275 - 2276 - adapter->stats.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC); 2277 - adapter->stats.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB); 2278 - adapter->stats.last_vfgorc |= 2279 - (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32); 2280 - adapter->stats.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC); 2281 - adapter->stats.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB); 2282 - adapter->stats.last_vfgotc |= 2283 - (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32); 2284 - adapter->stats.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC); 2285 - 2286 - adapter->stats.base_vfgprc = adapter->stats.last_vfgprc; 2287 - adapter->stats.base_vfgorc = adapter->stats.last_vfgorc; 2288 - adapter->stats.base_vfgptc = adapter->stats.last_vfgptc; 2289 - adapter->stats.base_vfgotc = adapter->stats.last_vfgotc; 2290 - adapter->stats.base_vfmprc = adapter->stats.last_vfmprc; 2291 - } 2292 - 2293 2231 #define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter) \ 2294 2232 { \ 2295 2233 u32 current_counter = IXGBE_READ_REG(hw, reg); \ ··· 2436 2416 } 2437 2417 } 2438 2418 2439 - pf_has_reset: 2440 2419 ixgbevf_update_stats(adapter); 2441 2420 2421 + pf_has_reset: 2442 2422 /* Force detection of hung controller every watchdog period */ 2443 2423 adapter->detect_tx_hung = true; 2444 2424 ··· 3410 3390 /* setup the private structure */ 3411 3391 err = ixgbevf_sw_init(adapter); 3412 3392 3413 - ixgbevf_init_last_counter_stats(adapter); 3414 - 3415 3393 #ifdef MAX_SKB_FRAGS 3416 3394 netdev->features = NETIF_F_SG | 3417 3395 NETIF_F_IP_CSUM | ··· 3466 3448 goto err_register; 3467 3449 3468 3450 adapter->netdev_registered = true; 3451 + 3452 + ixgbevf_init_last_counter_stats(adapter); 3469 3453 3470 3454 /* print the MAC address */ 3471 3455 hw_dbg(hw, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
+6
drivers/net/ixgbevf/vf.h
··· 157 157 u64 vfgorc; 158 158 u64 vfgotc; 159 159 u64 vfmprc; 160 + 161 + u64 saved_reset_vfgprc; 162 + u64 saved_reset_vfgptc; 163 + u64 saved_reset_vfgorc; 164 + u64 saved_reset_vfgotc; 165 + u64 saved_reset_vfmprc; 160 166 }; 161 167 162 168 struct ixgbevf_info {