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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-ethtool-track-tx-pause-storm'

Mohsin Bashir says:

====================
net: ethtool: Track TX pause storm

With TX pause enabled, if a device cannot deliver received frames to
the stack (e.g., during a system hang), it may generate excessive pause
frames causing a pause storm. This series updates the uAPI to track TX
pause storm events as part of the pause stats (p1), proposes using the
existing pfc-prevention-tout knob to configure the storm watchdog (p2),
adds pause storm protection support for fbnic (p3), and leverages p1
to provide observability into these events for the fbnic (p4) and mlx5
(p5) drivers.

v3: https://lore.kernel.org/netdev/20260223174914.74461-1-mohsin.bashr@gmail.com/
V2: https://lore.kernel.org/20260207010525.3808842-1-mohsin.bashr@gmail.com/
V1: https://lore.kernel.org/20260122192158.428882-1-mohsin.bashr@gmail.com/
====================

Link: https://patch.msgid.link/20260302230149.1580195-1-mohsin.bashr@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+256 -2
+13
Documentation/netlink/specs/ethtool.yaml
··· 879 879 - 880 880 name: rx-frames 881 881 type: u64 882 + - 883 + name: tx-pause-storm-events 884 + type: u64 885 + doc: >- 886 + TX pause storm event count. Increments each time device 887 + detects that its pause assertion condition has been true 888 + for too long for normal operation. As a result, the device 889 + has temporarily disabled its own Pause TX function to 890 + protect the network from itself. 891 + This counter should never increment under normal overload 892 + conditions; it indicates catastrophic failure like an OS 893 + crash. The rate of incrementing is implementation specific. 894 + 882 895 - 883 896 name: pause 884 897 attr-cnt-name: __ethtool-a-pause-cnt
+30
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
··· 916 916 sz, MLX5_REG_PPCNT, 0, 0); 917 917 } 918 918 919 + static int mlx5e_stats_get_per_prio(struct mlx5_core_dev *mdev, 920 + u32 *ppcnt_per_prio, int prio) 921 + { 922 + u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {}; 923 + int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); 924 + 925 + if (!(MLX5_CAP_PCAM_FEATURE(mdev, pfcc_mask) && 926 + MLX5_CAP_DEBUG(mdev, stall_detect))) 927 + return -EOPNOTSUPP; 928 + 929 + MLX5_SET(ppcnt_reg, in, local_port, 1); 930 + MLX5_SET(ppcnt_reg, in, grp, MLX5_PER_PRIORITY_COUNTERS_GROUP); 931 + MLX5_SET(ppcnt_reg, in, prio_tc, prio); 932 + return mlx5_core_access_reg(mdev, in, sz, ppcnt_per_prio, sz, 933 + MLX5_REG_PPCNT, 0, 0); 934 + } 935 + 919 936 void mlx5e_stats_pause_get(struct mlx5e_priv *priv, 920 937 struct ethtool_pause_stats *pause_stats) 921 938 { 922 939 u32 ppcnt_ieee_802_3[MLX5_ST_SZ_DW(ppcnt_reg)]; 923 940 struct mlx5_core_dev *mdev = priv->mdev; 941 + u64 ps_stats = 0; 942 + int prio; 924 943 925 944 if (mlx5e_stats_get_ieee(mdev, ppcnt_ieee_802_3)) 926 945 return; ··· 952 933 MLX5E_READ_CTR64_BE_F(ppcnt_ieee_802_3, 953 934 eth_802_3_cntrs_grp_data_layout, 954 935 a_pause_mac_ctrl_frames_received); 936 + 937 + for (prio = 0; prio < NUM_PPORT_PRIO; prio++) { 938 + if (mlx5e_stats_get_per_prio(mdev, ppcnt_ieee_802_3, prio)) 939 + return; 940 + 941 + ps_stats += MLX5E_READ_CTR64_BE_F(ppcnt_ieee_802_3, 942 + eth_per_prio_grp_data_layout, 943 + device_stall_critical_watermark_cnt); 944 + } 945 + 946 + pause_stats->tx_pause_storm_events = ps_stats; 955 947 } 956 948 957 949 void mlx5e_stats_eth_phy_get(struct mlx5e_priv *priv,
+3
drivers/net/ethernet/meta/fbnic/fbnic.h
··· 98 98 99 99 /* MDIO bus for PHYs */ 100 100 struct mii_bus *mdio_bus; 101 + 102 + /* In units of ms since API supports values in ms */ 103 + u16 ps_timeout; 101 104 }; 102 105 103 106 /* Reserve entry 0 in the MSI-X "others" array until we have filled all
+11
drivers/net/ethernet/meta/fbnic/fbnic_csr.h
··· 230 230 #define FBNIC_INTR_MSIX_CTRL_VECTOR_MASK CSR_GENMASK(7, 0) 231 231 #define FBNIC_INTR_MSIX_CTRL_ENABLE CSR_BIT(31) 232 232 enum { 233 + FBNIC_INTR_MSIX_CTRL_RXB_IDX = 7, 233 234 FBNIC_INTR_MSIX_CTRL_PCS_IDX = 34, 234 235 }; 235 236 ··· 561 560 #define FBNIC_RXB_DROP_THLD_CNT 8 562 561 #define FBNIC_RXB_DROP_THLD_ON CSR_GENMASK(12, 0) 563 562 #define FBNIC_RXB_DROP_THLD_OFF CSR_GENMASK(25, 13) 563 + #define FBNIC_RXB_PAUSE_STORM(n) (0x08019 + (n)) /* 0x20064 + 4*n */ 564 + #define FBNIC_RXB_PAUSE_STORM_CNT 4 565 + #define FBNIC_RXB_PAUSE_STORM_FORCE_NORMAL CSR_BIT(20) 566 + #define FBNIC_RXB_PAUSE_STORM_THLD_TIME CSR_GENMASK(19, 0) 567 + #define FBNIC_RXB_PAUSE_STORM_UNIT_WR 0x0801d /* 0x20074 */ 564 568 #define FBNIC_RXB_ECN_THLD(n) (0x0801e + (n)) /* 0x20078 + 4*n */ 565 569 #define FBNIC_RXB_ECN_THLD_CNT 8 566 570 #define FBNIC_RXB_ECN_THLD_ON CSR_GENMASK(12, 0) ··· 602 596 #define FBNIC_RXB_INTF_CREDIT_MASK2 CSR_GENMASK(11, 8) 603 597 #define FBNIC_RXB_INTF_CREDIT_MASK3 CSR_GENMASK(15, 12) 604 598 599 + #define FBNIC_RXB_ERR_INTR_STS 0x08050 /* 0x20140 */ 600 + #define FBNIC_RXB_ERR_INTR_STS_PS CSR_GENMASK(15, 12) 601 + #define FBNIC_RXB_ERR_INTR_MASK 0x08052 /* 0x20148 */ 605 602 #define FBNIC_RXB_PAUSE_EVENT_CNT(n) (0x08053 + (n)) /* 0x2014c + 4*n */ 606 603 #define FBNIC_RXB_DROP_FRMS_STS(n) (0x08057 + (n)) /* 0x2015c + 4*n */ 607 604 #define FBNIC_RXB_DROP_BYTES_STS_L(n) \ ··· 627 618 FBNIC_RXB_ENQUEUE_INDICES = 4 628 619 }; 629 620 621 + #define FBNIC_RXB_INTR_PS_COUNT(n) (0x080e9 + (n)) /* 0x203a4 + 4*n */ 630 622 #define FBNIC_RXB_DRBO_FRM_CNT_SRC(n) (0x080f9 + (n)) /* 0x203e4 + 4*n */ 631 623 #define FBNIC_RXB_DRBO_BYTE_CNT_SRC_L(n) \ 632 624 (0x080fd + (n)) /* 0x203f4 + 4*n */ ··· 646 636 647 637 #define FBNIC_RXB_PBUF_FIFO_LEVEL(n) (0x0811d + (n)) /* 0x20474 + 4*n */ 648 638 639 + #define FBNIC_RXB_PAUSE_STORM_UNIT_RD 0x08125 /* 0x20494 */ 649 640 #define FBNIC_RXB_INTEGRITY_ERR(n) (0x0812f + (n)) /* 0x204bc + 4*n */ 650 641 #define FBNIC_RXB_MAC_ERR(n) (0x08133 + (n)) /* 0x204cc + 4*n */ 651 642 #define FBNIC_RXB_PARSER_ERR(n) (0x08137 + (n)) /* 0x204dc + 4*n */
+46
drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
··· 1641 1641 } 1642 1642 } 1643 1643 1644 + static int fbnic_get_tunable(struct net_device *netdev, 1645 + const struct ethtool_tunable *tun, 1646 + void *data) 1647 + { 1648 + struct fbnic_net *fbn = netdev_priv(netdev); 1649 + int err = 0; 1650 + 1651 + switch (tun->id) { 1652 + case ETHTOOL_PFC_PREVENTION_TOUT: 1653 + *(u16 *)data = fbn->fbd->ps_timeout; 1654 + break; 1655 + default: 1656 + err = -EOPNOTSUPP; 1657 + break; 1658 + } 1659 + 1660 + return err; 1661 + } 1662 + 1663 + static int fbnic_set_tunable(struct net_device *netdev, 1664 + const struct ethtool_tunable *tun, 1665 + const void *data) 1666 + { 1667 + struct fbnic_net *fbn = netdev_priv(netdev); 1668 + int err; 1669 + 1670 + switch (tun->id) { 1671 + case ETHTOOL_PFC_PREVENTION_TOUT: { 1672 + u16 ps_timeout = *(u16 *)data; 1673 + 1674 + err = fbnic_mac_ps_protect_to_config(fbn->fbd, ps_timeout); 1675 + break; 1676 + } 1677 + default: 1678 + err = -EOPNOTSUPP; 1679 + break; 1680 + } 1681 + 1682 + return err; 1683 + } 1684 + 1644 1685 static int 1645 1686 fbnic_get_module_eeprom_by_page(struct net_device *netdev, 1646 1687 const struct ethtool_module_eeprom *page_data, ··· 1754 1713 struct fbnic_net *fbn = netdev_priv(netdev); 1755 1714 struct fbnic_mac_stats *mac_stats; 1756 1715 struct fbnic_dev *fbd = fbn->fbd; 1716 + u64 tx_ps_events; 1757 1717 1758 1718 mac_stats = &fbd->hw_stats.mac; 1759 1719 ··· 1762 1720 1763 1721 pause_stats->tx_pause_frames = mac_stats->pause.tx_pause_frames.value; 1764 1722 pause_stats->rx_pause_frames = mac_stats->pause.rx_pause_frames.value; 1723 + tx_ps_events = mac_stats->pause.tx_pause_storm_events.value; 1724 + pause_stats->tx_pause_storm_events = tx_ps_events; 1765 1725 } 1766 1726 1767 1727 static void ··· 1959 1915 .set_channels = fbnic_set_channels, 1960 1916 .get_ts_info = fbnic_get_ts_info, 1961 1917 .get_ts_stats = fbnic_get_ts_stats, 1918 + .get_tunable = fbnic_get_tunable, 1919 + .set_tunable = fbnic_set_tunable, 1962 1920 .get_link_ksettings = fbnic_phylink_ethtool_ksettings_get, 1963 1921 .get_fec_stats = fbnic_get_fec_stats, 1964 1922 .get_fecparam = fbnic_phylink_get_fecparam,
+1
drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h
··· 54 54 struct fbnic_pause_stats { 55 55 struct fbnic_stat_counter tx_pause_frames; 56 56 struct fbnic_stat_counter rx_pause_frames; 57 + struct fbnic_stat_counter tx_pause_storm_events; 57 58 }; 58 59 59 60 struct fbnic_eth_mac_stats {
+2
drivers/net/ethernet/meta/fbnic/fbnic_irq.c
··· 170 170 fbnic_wr32(fbd, FBNIC_INTR_MSIX_CTRL(FBNIC_INTR_MSIX_CTRL_PCS_IDX), 171 171 FBNIC_PCS_MSIX_ENTRY | FBNIC_INTR_MSIX_CTRL_ENABLE); 172 172 173 + fbnic_wr32(fbd, FBNIC_INTR_MSIX_CTRL(FBNIC_INTR_MSIX_CTRL_RXB_IDX), 0); 174 + 173 175 fbd->mac_msix_vector = vector; 174 176 175 177 return 0;
+111
drivers/net/ethernet/meta/fbnic/fbnic_mac.c
··· 143 143 #define FBNIC_DROP_EN_MASK 0x7d 144 144 #define FBNIC_PAUSE_EN_MASK 0x14 145 145 #define FBNIC_ECN_EN_MASK 0x10 146 + #define FBNIC_PS_EN_MASK 0x01 146 147 147 148 struct fbnic_fifo_config { 148 149 unsigned int addr; ··· 418 417 stat->reported = true; 419 418 } 420 419 420 + static void fbnic_mac_stat_rd32(struct fbnic_dev *fbd, bool reset, u32 reg, 421 + struct fbnic_stat_counter *stat) 422 + { 423 + u32 new_reg_value; 424 + 425 + new_reg_value = rd32(fbd, reg); 426 + if (!reset) 427 + stat->value += new_reg_value - stat->u.old_reg_value_32; 428 + stat->u.old_reg_value_32 = new_reg_value; 429 + stat->reported = true; 430 + } 431 + 421 432 #define fbnic_mac_stat_rd64(fbd, reset, __stat, __CSR) \ 422 433 __fbnic_mac_stat_rd64(fbd, reset, FBNIC_##__CSR##_L, &(__stat)) 434 + 435 + bool fbnic_mac_check_tx_pause(struct fbnic_dev *fbd) 436 + { 437 + u32 command_config; 438 + 439 + command_config = rd32(fbd, FBNIC_MAC_COMMAND_CONFIG); 440 + return !(command_config & FBNIC_MAC_COMMAND_CONFIG_TX_PAUSE_DIS); 441 + } 423 442 424 443 static void fbnic_mac_tx_pause_config(struct fbnic_dev *fbd, bool tx_pause) 425 444 { ··· 453 432 FIELD_PREP(FBNIC_RXB_PAUSE_DROP_CTRL_PAUSE_ENABLE, 454 433 FBNIC_PAUSE_EN_MASK); 455 434 wr32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL, rxb_pause_ctrl); 435 + } 436 + 437 + static void 438 + fbnic_mac_ps_protect_to_reset(struct fbnic_dev *fbd, u16 timeout_ms) 439 + { 440 + wr32(fbd, FBNIC_RXB_PAUSE_STORM_UNIT_WR, FBNIC_RXB_PS_CLK_DIV); 441 + 442 + wr32(fbd, FBNIC_RXB_PAUSE_STORM(FBNIC_RXB_INTF_NET), 443 + FIELD_PREP(FBNIC_RXB_PAUSE_STORM_THLD_TIME, 444 + FBNIC_MAC_RXB_PS_TO(timeout_ms)) | 445 + FBNIC_RXB_PAUSE_STORM_FORCE_NORMAL); 446 + wrfl(fbd); 447 + wr32(fbd, FBNIC_RXB_PAUSE_STORM(FBNIC_RXB_INTF_NET), 448 + FIELD_PREP(FBNIC_RXB_PAUSE_STORM_THLD_TIME, 449 + FBNIC_MAC_RXB_PS_TO(timeout_ms))); 450 + } 451 + 452 + static void 453 + fbnic_mac_ps_protect_config(struct fbnic_dev *fbd, bool ps_protect) 454 + { 455 + u16 timeout; 456 + u32 reg; 457 + 458 + ps_protect = ps_protect && fbd->ps_timeout; 459 + timeout = ps_protect ? fbd->ps_timeout : FBNIC_MAC_PS_TO_DEFAULT_MS; 460 + 461 + fbnic_mac_ps_protect_to_reset(fbd, timeout); 462 + 463 + reg = rd32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL); 464 + reg &= ~FBNIC_RXB_PAUSE_DROP_CTRL_PS_ENABLE; 465 + reg |= FIELD_PREP(FBNIC_RXB_PAUSE_DROP_CTRL_PS_ENABLE, ps_protect); 466 + wr32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL, reg); 467 + 468 + /* Clear any pending interrupt status first */ 469 + wr32(fbd, FBNIC_RXB_ERR_INTR_STS, 470 + FIELD_PREP(FBNIC_RXB_ERR_INTR_STS_PS, FBNIC_PS_EN_MASK)); 471 + 472 + /* Unmask the Network to Host PS interrupt if tx_pause is on */ 473 + reg = rd32(fbd, FBNIC_RXB_ERR_INTR_MASK); 474 + reg |= FBNIC_RXB_ERR_INTR_STS_PS; 475 + if (ps_protect) 476 + reg &= ~FBNIC_RXB_ERR_INTR_STS_PS; 477 + wr32(fbd, FBNIC_RXB_ERR_INTR_MASK, reg); 456 478 } 457 479 458 480 static int fbnic_mac_get_link_event(struct fbnic_dev *fbd) ··· 722 658 u32 cmd_cfg, mac_ctrl; 723 659 724 660 fbnic_mac_tx_pause_config(fbd, tx_pause); 661 + fbnic_mac_ps_protect_config(fbd, tx_pause); 725 662 726 663 cmd_cfg = __fbnic_mac_cmd_config_asic(fbd, tx_pause, rx_pause); 727 664 mac_ctrl = rd32(fbd, FBNIC_SIG_MAC_IN0); ··· 824 759 MAC_STAT_TX_XOFF_STB); 825 760 fbnic_mac_stat_rd64(fbd, reset, pause_stats->rx_pause_frames, 826 761 MAC_STAT_RX_XOFF_STB); 762 + fbnic_mac_stat_rd32(fbd, reset, 763 + FBNIC_RXB_INTR_PS_COUNT(FBNIC_RXB_INTF_NET), 764 + &pause_stats->tx_pause_storm_events); 827 765 } 828 766 829 767 static void ··· 985 917 fbd->mac->init_regs(fbd); 986 918 987 919 return 0; 920 + } 921 + 922 + int fbnic_mac_ps_protect_to_config(struct fbnic_dev *fbd, u16 timeout_ms) 923 + { 924 + u16 old_timeout_ms = fbd->ps_timeout; 925 + 926 + if (timeout_ms == old_timeout_ms) 927 + return 0; 928 + 929 + if (timeout_ms == PFC_STORM_PREVENTION_AUTO) 930 + timeout_ms = FBNIC_MAC_PS_TO_DEFAULT_MS; 931 + 932 + if (timeout_ms > FBNIC_MAC_PS_TO_MAX_MS) 933 + return -EINVAL; 934 + 935 + fbd->ps_timeout = timeout_ms; 936 + 937 + if (!fbnic_mac_check_tx_pause(fbd)) 938 + return 0; 939 + 940 + if (timeout_ms == 0) 941 + fbnic_mac_ps_protect_config(fbd, false); 942 + else if (old_timeout_ms == 0) 943 + fbnic_mac_ps_protect_config(fbd, true); 944 + else 945 + fbnic_mac_ps_protect_to_reset(fbd, fbd->ps_timeout); 946 + 947 + return 0; 948 + } 949 + 950 + void fbnic_mac_ps_protect_handler(struct fbnic_dev *fbd) 951 + { 952 + u32 rxb_err_sts = rd32(fbd, FBNIC_RXB_ERR_INTR_STS); 953 + 954 + /* Check if pause storm interrupt for network was triggered */ 955 + if (rxb_err_sts & FIELD_PREP(FBNIC_RXB_ERR_INTR_STS_PS, 956 + FBNIC_PS_EN_MASK)) { 957 + /* Write 1 to clear the interrupt status first */ 958 + wr32(fbd, FBNIC_RXB_ERR_INTR_STS, 959 + FIELD_PREP(FBNIC_RXB_ERR_INTR_STS_PS, FBNIC_PS_EN_MASK)); 960 + 961 + fbnic_mac_ps_protect_to_reset(fbd, fbd->ps_timeout); 962 + } 988 963 }
+27
drivers/net/ethernet/meta/fbnic/fbnic_mac.h
··· 8 8 9 9 struct fbnic_dev; 10 10 11 + /* The RXB clock runs at 600 MHZ in the ASIC and the PAUSE_STORM_UNIT_WR 12 + * is 10us granularity, so set the clock to 6000 (0x1770) 13 + */ 14 + #define FBNIC_RXB_PS_CLK_DIV 0x1770 15 + 16 + /* Convert milliseconds to pause storm timeout units (10us granularity) */ 17 + #define FBNIC_MAC_RXB_PS_TO(ms) ((ms) * 100) 18 + 19 + /* Convert pause storm timeout units (10us granularity) to milliseconds */ 20 + #define FBNIC_MAC_RXB_PS_TO_MS(ps) ((ps) / 100) 21 + 22 + /* Set the default timer to 500ms, which should be longer than any 23 + * reasonable period of continuous pausing. The service task, which runs 24 + * once per second, periodically resets the pause storm trigger. 25 + * 26 + * As a result, on a functioning system, if pause continues, we enforce 27 + * a duty cycle determined by the configured pause storm timeout (50% 28 + * default). A crashed system will not have the service task and therefore 29 + * pause will remain disabled until reboot recovery. 30 + */ 31 + #define FBNIC_MAC_PS_TO_DEFAULT_MS 500 32 + #define FBNIC_MAC_PS_TO_MAX_MS \ 33 + FBNIC_MAC_RXB_PS_TO_MS(FIELD_MAX(FBNIC_RXB_PAUSE_STORM_THLD_TIME)) 34 + 11 35 #define FBNIC_MAX_JUMBO_FRAME_SIZE 9742 12 36 13 37 /* States loosely based on section 136.8.11.7.5 of IEEE 802.3-2022 Ethernet ··· 143 119 144 120 int fbnic_mac_init(struct fbnic_dev *fbd); 145 121 void fbnic_mac_get_fw_settings(struct fbnic_dev *fbd, u8 *aui, u8 *fec); 122 + int fbnic_mac_ps_protect_to_config(struct fbnic_dev *fbd, u16 timeout); 123 + void fbnic_mac_ps_protect_handler(struct fbnic_dev *fbd); 124 + bool fbnic_mac_check_tx_pause(struct fbnic_dev *fbd); 146 125 #endif /* _FBNIC_MAC_H_ */
+5
drivers/net/ethernet/meta/fbnic/fbnic_pci.c
··· 220 220 221 221 fbnic_get_hw_stats32(fbd); 222 222 223 + if (fbd->ps_timeout && fbnic_mac_check_tx_pause(fbd)) 224 + fbnic_mac_ps_protect_handler(fbd); 225 + 223 226 fbnic_fw_check_heartbeat(fbd); 224 227 225 228 fbnic_health_check(fbd); ··· 298 295 299 296 /* Populate driver with hardware-specific info and handlers */ 300 297 fbd->max_num_queues = info->max_num_queues; 298 + 299 + fbd->ps_timeout = FBNIC_MAC_PS_TO_DEFAULT_MS; 301 300 302 301 pci_set_master(pdev); 303 302 pci_save_state(pdev);
+2
include/linux/ethtool.h
··· 512 512 * 513 513 * Equivalent to `30.3.4.3 aPAUSEMACCtrlFramesReceived` 514 514 * from the standard. 515 + * @tx_pause_storm_events: TX pause storm event count (see ethtool.yaml). 515 516 */ 516 517 struct ethtool_pause_stats { 517 518 enum ethtool_mac_stats_src src; 518 519 struct_group(stats, 519 520 u64 tx_pause_frames; 520 521 u64 rx_pause_frames; 522 + u64 tx_pause_storm_events; 521 523 ); 522 524 }; 523 525
+1 -1
include/uapi/linux/ethtool.h
··· 225 225 ETHTOOL_ID_UNSPEC, 226 226 ETHTOOL_RX_COPYBREAK, 227 227 ETHTOOL_TX_COPYBREAK, 228 - ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ 228 + ETHTOOL_PFC_PREVENTION_TOUT, /* both pause and pfc, see man ethtool */ 229 229 ETHTOOL_TX_COPYBREAK_BUF_SIZE, 230 230 /* 231 231 * Add your fresh new tunable attribute above and remember to update
+3 -1
net/ethtool/pause.c
··· 130 130 if (ethtool_put_stat(skb, pause_stats->tx_pause_frames, 131 131 ETHTOOL_A_PAUSE_STAT_TX_FRAMES, pad) || 132 132 ethtool_put_stat(skb, pause_stats->rx_pause_frames, 133 - ETHTOOL_A_PAUSE_STAT_RX_FRAMES, pad)) 133 + ETHTOOL_A_PAUSE_STAT_RX_FRAMES, pad) || 134 + ethtool_put_stat(skb, pause_stats->tx_pause_storm_events, 135 + ETHTOOL_A_PAUSE_STAT_TX_PAUSE_STORM_EVENTS, pad)) 134 136 goto err_cancel; 135 137 136 138 nla_nest_end(skb, nest);