}
}
+ 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;
/* 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 {
}
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
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);
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);
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);
#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))
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 */
u64 mptc;
u64 roc;
u64 ruc;
- u64 lxonoffrxc;
+ u64 lxonrxc;
+ u64 lxoffrxc;
u64 lxontxc;
u64 lxofftxc;
u64 o2bgptc;
struct wx_last_stats {
u32 qmprc[128];
+ u32 lxoffrxc;
+ u32 lxonrxc;
};
enum wx_state {