]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: libwx: improve flow control setting
authorJiawen Wu <jiawenwu@trustnetic.com>
Tue, 7 Apr 2026 02:56:16 +0000 (10:56 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sun, 12 Apr 2026 15:42:29 +0000 (08:42 -0700)
Save the current mode of flow control, and enhance the statistics of
pause frames.

The received pause frames are divided into XON and XOFF to be counted.
And due to the hardware defect of SP devices, XON packets cannot be
trasmitted correctly, so Tx XON pause is disabled by default for those
devices.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Link: https://patch.msgid.link/20260407025616.33652-10-jiawenwu@trustnetic.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
drivers/net/ethernet/wangxun/libwx/wx_hw.c
drivers/net/ethernet/wangxun/libwx/wx_type.h

index 6adb8cbcad1f3fd445339c75dfbefdec1361cf2e..5df971aca9e35f2e131c222b900a2fbda4c74037 100644 (file)
@@ -211,7 +211,7 @@ void wx_get_pause_stats(struct net_device *netdev,
 
        hwstats = &wx->stats;
        stats->tx_pause_frames = hwstats->lxontxc + hwstats->lxofftxc;
-       stats->rx_pause_frames = hwstats->lxonoffrxc;
+       stats->rx_pause_frames = hwstats->lxonrxc + hwstats->lxoffrxc;
 }
 EXPORT_SYMBOL(wx_get_pause_stats);
 
index 57d6671ec61856e7a8e2a77e48d608250058350a..d3772d01e00bc8de21e18c79acd85ef41e42d234 100644 (file)
@@ -2774,6 +2774,15 @@ int wx_fc_enable(struct wx *wx, bool tx_pause, bool rx_pause)
                }
        }
 
+       if (rx_pause && tx_pause)
+               wx->fc.mode = wx_fc_full;
+       else if (rx_pause)
+               wx->fc.mode = wx_fc_rx_pause;
+       else if (tx_pause)
+               wx->fc.mode = wx_fc_tx_pause;
+       else
+               wx->fc.mode = wx_fc_none;
+
        /* Disable any previous flow control settings */
        mflcn_reg = rd32(wx, WX_MAC_RX_FLOW_CTRL);
        mflcn_reg &= ~WX_MAC_RX_FLOW_CTRL_RFE;
@@ -2792,7 +2801,9 @@ int wx_fc_enable(struct wx *wx, bool tx_pause, bool rx_pause)
 
        /* Set up and enable Rx high/low water mark thresholds, enable XON. */
        if (tx_pause && wx->fc.high_water) {
-               fcrtl = (wx->fc.low_water << 10) | WX_RDB_RFCL_XONE;
+               fcrtl = (wx->fc.low_water << 10);
+               if (wx->mac.type != wx_mac_sp)
+                       fcrtl |= WX_RDB_RFCL_XONE;
                wr32(wx, WX_RDB_RFCL, fcrtl);
                fcrth = (wx->fc.high_water << 10) | WX_RDB_RFCH_XOFFE;
        } else {
@@ -2833,6 +2844,21 @@ int wx_fc_enable(struct wx *wx, bool tx_pause, bool rx_pause)
 }
 EXPORT_SYMBOL(wx_fc_enable);
 
+static void wx_update_xoff_rx_lfc(struct wx *wx)
+{
+       struct wx_hw_stats *hwstats = &wx->stats;
+
+       if (wx->fc.mode != wx_fc_full &&
+           wx->fc.mode != wx_fc_rx_pause)
+               return;
+
+       if (wx->mac.type >= wx_mac_aml)
+               hwstats->lxoffrxc += rd32_wrap(wx, WX_MAC_LXOFFRXC_AML,
+                                              &wx->last_stats.lxoffrxc);
+       else
+               hwstats->lxoffrxc += rd64(wx, WX_MAC_LXOFFRXC);
+}
+
 /**
  * wx_update_stats - Update the board statistics counters.
  * @wx: board private structure
@@ -2887,6 +2913,8 @@ void wx_update_stats(struct wx *wx)
        wx->restart_queue = restart_queue;
        wx->tx_busy = tx_busy;
 
+       wx_update_xoff_rx_lfc(wx);
+
        hwstats->gprc += rd32(wx, WX_RDM_PKT_CNT);
        hwstats->gptc += rd32(wx, WX_TDM_PKT_CNT);
        hwstats->gorc += rd64(wx, WX_RDM_BYTE_CNT_LSB);
@@ -2901,7 +2929,11 @@ void wx_update_stats(struct wx *wx)
        hwstats->mptc += rd64(wx, WX_TX_MC_FRAMES_GOOD_L);
        hwstats->roc += rd32(wx, WX_RX_OVERSIZE_FRAMES_GOOD);
        hwstats->ruc += rd32(wx, WX_RX_UNDERSIZE_FRAMES_GOOD);
-       hwstats->lxonoffrxc += rd32(wx, WX_MAC_LXONOFFRXC);
+       if (wx->mac.type >= wx_mac_aml)
+               hwstats->lxonrxc += rd32_wrap(wx, WX_MAC_LXONRXC_AML,
+                                             &wx->last_stats.lxonrxc);
+       else
+               hwstats->lxonrxc += rd32(wx, WX_MAC_LXONRXC);
        hwstats->lxontxc += rd32(wx, WX_RDB_LXONTXC);
        hwstats->lxofftxc += rd32(wx, WX_RDB_LXOFFTXC);
        hwstats->o2bgptc += rd32(wx, WX_TDM_OS2BMC_CNT);
@@ -2958,7 +2990,15 @@ void wx_clear_hw_cntrs(struct wx *wx)
        rd64(wx, WX_RX_LEN_ERROR_FRAMES_L);
        rd32(wx, WX_RDB_LXONTXC);
        rd32(wx, WX_RDB_LXOFFTXC);
-       rd32(wx, WX_MAC_LXONOFFRXC);
+       if (wx->mac.type >= wx_mac_aml) {
+               wr32(wx, WX_MAC_LXONRXC_AML, 0);
+               wr32(wx, WX_MAC_LXOFFRXC_AML, 0);
+               wx->last_stats.lxonrxc = 0;
+               wx->last_stats.lxoffrxc = 0;
+       } else {
+               rd32(wx, WX_MAC_LXONRXC);
+               rd64(wx, WX_MAC_LXOFFRXC);
+       }
 }
 EXPORT_SYMBOL(wx_clear_hw_cntrs);
 
index 3c5a351974dd3c74c3dc9f48cd7220ca67cb9807..0da5565ee4ffa617cd0d3a16aeda44b02a59f36e 100644 (file)
 #define WX_RX_LEN_ERROR_FRAMES_L     0x11978
 #define WX_RX_UNDERSIZE_FRAMES_GOOD  0x11938
 #define WX_RX_OVERSIZE_FRAMES_GOOD   0x1193C
-#define WX_MAC_LXONOFFRXC            0x11E0C
+#define WX_MAC_LXOFFRXC              0x11988
+#define WX_MAC_LXONRXC               0x11E0C
+#define WX_MAC_LXOFFRXC_AML          0x11F80
+#define WX_MAC_LXONRXC_AML           0x11F84
 
 /*********************** Receive DMA registers **************************/
 #define WX_RDM_VF_RE(_i)             (0x12004 + ((_i) * 4))
@@ -1148,9 +1151,18 @@ enum wx_isb_idx {
        WX_ISB_MAX
 };
 
+/* Flow Control Settings */
+enum wx_fc_mode {
+       wx_fc_none = 0,
+       wx_fc_rx_pause,
+       wx_fc_tx_pause,
+       wx_fc_full
+};
+
 struct wx_fc_info {
        u32 high_water; /* Flow Ctrl High-water */
        u32 low_water; /* Flow Ctrl Low-water */
+       enum wx_fc_mode mode; /* Flow Control Mode */
 };
 
 /* Statistics counters collected by the MAC */
@@ -1167,7 +1179,8 @@ struct wx_hw_stats {
        u64 mptc;
        u64 roc;
        u64 ruc;
-       u64 lxonoffrxc;
+       u64 lxonrxc;
+       u64 lxoffrxc;
        u64 lxontxc;
        u64 lxofftxc;
        u64 o2bgptc;
@@ -1184,6 +1197,8 @@ struct wx_hw_stats {
 
 struct wx_last_stats {
        u32 qmprc[128];
+       u32 lxoffrxc;
+       u32 lxonrxc;
 };
 
 enum wx_state {