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 --- .../net/ethernet/wangxun/libwx/wx_ethtool.c | 2 +- drivers/net/ethernet/wangxun/libwx/wx_hw.c | 46 +++++++++++++++++-- drivers/net/ethernet/wangxun/libwx/wx_type.h | 19 +++++++- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c index 6adb8cbcad1f..5df971aca9e3 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c @@ -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); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 57d6671ec618..d3772d01e00b 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -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); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 3c5a351974dd..0da5565ee4ff 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -79,7 +79,10 @@ #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 { -- 2.48.1