eth: fbnic: add coverage for hw queue stats
This patch provides support for hardware queue stats and covers
packet errors for RX-DMA engine, RCQ drops and BDQ drops.
The packet errors are also aggregated with the `rx_errors` stats in the
`rtnl_link_stats` as well as with the `hw_drops` in the queue API.
The RCQ and BDQ drops are aggregated with `rx_over_errors` in the
`rtnl_link_stats` as well as with the `hw_drop_overruns` in the queue API.
ethtool -S eth0 | grep -E 'rde'
rde_0_pkt_err: 0
rde_0_pkt_cq_drop: 0
rde_0_pkt_bdq_drop: 0
---
---
rde_127_pkt_err: 0
rde_127_pkt_cq_drop: 0
rde_127_pkt_bdq_drop: 0
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Mohsin Bashir <mohsin.bashr@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250410070859.4160768-3-mohsin.bashr@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
9f61eb2d18
commit
8f20a2bfa4
|
|
@ -44,6 +44,15 @@ RPC (Rx parser)
|
|||
- ``rpc_out_of_hdr_err``: frames where header was larger than parsable region
|
||||
- ``ovr_size_err``: oversized frames
|
||||
|
||||
Hardware Queues
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
1. RX DMA Engine:
|
||||
|
||||
- ``rde_[i]_pkt_err``: packets with MAC EOP, RPC parser, RXB truncation, or RDE frame truncation errors. These error are flagged in the packet metadata because of cut-through support but the actual drop happens once PCIE/RDE is reached.
|
||||
- ``rde_[i]_pkt_cq_drop``: packets dropped because RCQ is full
|
||||
- ``rde_[i]_pkt_bdq_drop``: packets dropped because HPQ or PPQ ran out of host buffer
|
||||
|
||||
PCIe
|
||||
~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -864,6 +864,12 @@ enum {
|
|||
#define FBNIC_QUEUE_TWQ1_BAL 0x022 /* 0x088 */
|
||||
#define FBNIC_QUEUE_TWQ1_BAH 0x023 /* 0x08c */
|
||||
|
||||
/* Tx Work Queue Statistics Registers */
|
||||
#define FBNIC_QUEUE_TWQ0_PKT_CNT 0x062 /* 0x188 */
|
||||
#define FBNIC_QUEUE_TWQ0_ERR_CNT 0x063 /* 0x18c */
|
||||
#define FBNIC_QUEUE_TWQ1_PKT_CNT 0x072 /* 0x1c8 */
|
||||
#define FBNIC_QUEUE_TWQ1_ERR_CNT 0x073 /* 0x1cc */
|
||||
|
||||
/* Tx Completion Queue Registers */
|
||||
#define FBNIC_QUEUE_TCQ_CTL 0x080 /* 0x200 */
|
||||
#define FBNIC_QUEUE_TCQ_CTL_RESET CSR_BIT(0)
|
||||
|
|
@ -953,6 +959,12 @@ enum {
|
|||
FBNIC_QUEUE_RDE_CTL1_PAYLD_PACK_RSS = 2,
|
||||
};
|
||||
|
||||
/* Rx Per CQ Statistics Counters */
|
||||
#define FBNIC_QUEUE_RDE_PKT_CNT 0x2a2 /* 0xa88 */
|
||||
#define FBNIC_QUEUE_RDE_PKT_ERR_CNT 0x2a3 /* 0xa8c */
|
||||
#define FBNIC_QUEUE_RDE_CQ_DROP_CNT 0x2a4 /* 0xa90 */
|
||||
#define FBNIC_QUEUE_RDE_BDQ_DROP_CNT 0x2a5 /* 0xa94 */
|
||||
|
||||
/* Rx Interrupt Manager Registers */
|
||||
#define FBNIC_QUEUE_RIM_CTL 0x2c0 /* 0xb00 */
|
||||
#define FBNIC_QUEUE_RIM_CTL_MSIX_MASK CSR_GENMASK(7, 0)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,20 @@ static const struct fbnic_stat fbnic_gstrings_hw_stats[] = {
|
|||
};
|
||||
|
||||
#define FBNIC_HW_FIXED_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_stats)
|
||||
#define FBNIC_HW_STATS_LEN FBNIC_HW_FIXED_STATS_LEN
|
||||
|
||||
#define FBNIC_HW_Q_STAT(name, stat) \
|
||||
FBNIC_STAT_FIELDS(fbnic_hw_q_stats, name, stat.value)
|
||||
|
||||
static const struct fbnic_stat fbnic_gstrings_hw_q_stats[] = {
|
||||
FBNIC_HW_Q_STAT("rde_%u_pkt_err", rde_pkt_err),
|
||||
FBNIC_HW_Q_STAT("rde_%u_pkt_cq_drop", rde_pkt_cq_drop),
|
||||
FBNIC_HW_Q_STAT("rde_%u_pkt_bdq_drop", rde_pkt_bdq_drop),
|
||||
};
|
||||
|
||||
#define FBNIC_HW_Q_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_q_stats)
|
||||
#define FBNIC_HW_STATS_LEN \
|
||||
(FBNIC_HW_FIXED_STATS_LEN + \
|
||||
FBNIC_HW_Q_STATS_LEN * FBNIC_MAX_QUEUES)
|
||||
|
||||
static void
|
||||
fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
|
||||
|
|
@ -300,29 +313,57 @@ err_free_clone:
|
|||
|
||||
static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
|
||||
{
|
||||
int i;
|
||||
const struct fbnic_stat *stat;
|
||||
int i, idx;
|
||||
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
for (i = 0; i < FBNIC_HW_STATS_LEN; i++)
|
||||
for (i = 0; i < FBNIC_HW_FIXED_STATS_LEN; i++)
|
||||
ethtool_puts(&data, fbnic_gstrings_hw_stats[i].string);
|
||||
|
||||
for (idx = 0; idx < FBNIC_MAX_QUEUES; idx++) {
|
||||
stat = fbnic_gstrings_hw_q_stats;
|
||||
|
||||
for (i = 0; i < FBNIC_HW_Q_STATS_LEN; i++, stat++)
|
||||
ethtool_sprintf(&data, stat->string, idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void fbnic_report_hw_stats(const struct fbnic_stat *stat,
|
||||
const void *base, int len, u64 **data)
|
||||
{
|
||||
while (len--) {
|
||||
u8 *curr = (u8 *)base + stat->offset;
|
||||
|
||||
**data = *(u64 *)curr;
|
||||
|
||||
stat++;
|
||||
(*data)++;
|
||||
}
|
||||
}
|
||||
|
||||
static void fbnic_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct fbnic_net *fbn = netdev_priv(dev);
|
||||
const struct fbnic_stat *stat;
|
||||
struct fbnic_dev *fbd = fbn->fbd;
|
||||
int i;
|
||||
|
||||
fbnic_get_hw_stats(fbn->fbd);
|
||||
|
||||
for (i = 0; i < FBNIC_HW_STATS_LEN; i++) {
|
||||
stat = &fbnic_gstrings_hw_stats[i];
|
||||
data[i] = *(u64 *)((u8 *)&fbn->fbd->hw_stats + stat->offset);
|
||||
spin_lock(&fbd->hw_stats_lock);
|
||||
fbnic_report_hw_stats(fbnic_gstrings_hw_stats, &fbd->hw_stats,
|
||||
FBNIC_HW_FIXED_STATS_LEN, &data);
|
||||
|
||||
for (i = 0; i < FBNIC_MAX_QUEUES; i++) {
|
||||
const struct fbnic_hw_q_stats *hw_q = &fbd->hw_stats.hw_q[i];
|
||||
|
||||
fbnic_report_hw_stats(fbnic_gstrings_hw_q_stats, hw_q,
|
||||
FBNIC_HW_Q_STATS_LEN, &data);
|
||||
}
|
||||
spin_unlock(&fbd->hw_stats_lock);
|
||||
}
|
||||
|
||||
static int fbnic_get_sset_count(struct net_device *dev, int sset)
|
||||
|
|
|
|||
|
|
@ -117,6 +117,54 @@ static void fbnic_get_rpc_stats32(struct fbnic_dev *fbd,
|
|||
&rpc->ovr_size_err);
|
||||
}
|
||||
|
||||
static void fbnic_reset_hw_rxq_stats(struct fbnic_dev *fbd,
|
||||
struct fbnic_hw_q_stats *hw_q)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fbd->max_num_queues; i++, hw_q++) {
|
||||
u32 base = FBNIC_QUEUE(i);
|
||||
|
||||
fbnic_hw_stat_rst32(fbd,
|
||||
base + FBNIC_QUEUE_RDE_PKT_ERR_CNT,
|
||||
&hw_q->rde_pkt_err);
|
||||
fbnic_hw_stat_rst32(fbd,
|
||||
base + FBNIC_QUEUE_RDE_CQ_DROP_CNT,
|
||||
&hw_q->rde_pkt_cq_drop);
|
||||
fbnic_hw_stat_rst32(fbd,
|
||||
base + FBNIC_QUEUE_RDE_BDQ_DROP_CNT,
|
||||
&hw_q->rde_pkt_bdq_drop);
|
||||
}
|
||||
}
|
||||
|
||||
static void fbnic_get_hw_rxq_stats32(struct fbnic_dev *fbd,
|
||||
struct fbnic_hw_q_stats *hw_q)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fbd->max_num_queues; i++, hw_q++) {
|
||||
u32 base = FBNIC_QUEUE(i);
|
||||
|
||||
fbnic_hw_stat_rd32(fbd,
|
||||
base + FBNIC_QUEUE_RDE_PKT_ERR_CNT,
|
||||
&hw_q->rde_pkt_err);
|
||||
fbnic_hw_stat_rd32(fbd,
|
||||
base + FBNIC_QUEUE_RDE_CQ_DROP_CNT,
|
||||
&hw_q->rde_pkt_cq_drop);
|
||||
fbnic_hw_stat_rd32(fbd,
|
||||
base + FBNIC_QUEUE_RDE_BDQ_DROP_CNT,
|
||||
&hw_q->rde_pkt_bdq_drop);
|
||||
}
|
||||
}
|
||||
|
||||
void fbnic_get_hw_q_stats(struct fbnic_dev *fbd,
|
||||
struct fbnic_hw_q_stats *hw_q)
|
||||
{
|
||||
spin_lock(&fbd->hw_stats_lock);
|
||||
fbnic_get_hw_rxq_stats32(fbd, hw_q);
|
||||
spin_unlock(&fbd->hw_stats_lock);
|
||||
}
|
||||
|
||||
static void fbnic_reset_pcie_stats_asic(struct fbnic_dev *fbd,
|
||||
struct fbnic_pcie_stats *pcie)
|
||||
{
|
||||
|
|
@ -205,6 +253,7 @@ void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
|
|||
{
|
||||
spin_lock(&fbd->hw_stats_lock);
|
||||
fbnic_reset_rpc_stats(fbd, &fbd->hw_stats.rpc);
|
||||
fbnic_reset_hw_rxq_stats(fbd, fbd->hw_stats.hw_q);
|
||||
fbnic_reset_pcie_stats_asic(fbd, &fbd->hw_stats.pcie);
|
||||
spin_unlock(&fbd->hw_stats_lock);
|
||||
}
|
||||
|
|
@ -212,6 +261,7 @@ void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
|
|||
static void __fbnic_get_hw_stats32(struct fbnic_dev *fbd)
|
||||
{
|
||||
fbnic_get_rpc_stats32(fbd, &fbd->hw_stats.rpc);
|
||||
fbnic_get_hw_rxq_stats32(fbd, fbd->hw_stats.hw_q);
|
||||
}
|
||||
|
||||
void fbnic_get_hw_stats32(struct fbnic_dev *fbd)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ struct fbnic_rpc_stats {
|
|||
struct fbnic_stat_counter tcp_opt_err, out_of_hdr_err, ovr_size_err;
|
||||
};
|
||||
|
||||
struct fbnic_hw_q_stats {
|
||||
struct fbnic_stat_counter rde_pkt_err;
|
||||
struct fbnic_stat_counter rde_pkt_cq_drop;
|
||||
struct fbnic_stat_counter rde_pkt_bdq_drop;
|
||||
};
|
||||
|
||||
struct fbnic_pcie_stats {
|
||||
struct fbnic_stat_counter ob_rd_tlp, ob_rd_dword;
|
||||
struct fbnic_stat_counter ob_wr_tlp, ob_wr_dword;
|
||||
|
|
@ -56,12 +62,15 @@ struct fbnic_pcie_stats {
|
|||
struct fbnic_hw_stats {
|
||||
struct fbnic_mac_stats mac;
|
||||
struct fbnic_rpc_stats rpc;
|
||||
struct fbnic_hw_q_stats hw_q[FBNIC_MAX_QUEUES];
|
||||
struct fbnic_pcie_stats pcie;
|
||||
};
|
||||
|
||||
u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset);
|
||||
|
||||
void fbnic_reset_hw_stats(struct fbnic_dev *fbd);
|
||||
void fbnic_get_hw_q_stats(struct fbnic_dev *fbd,
|
||||
struct fbnic_hw_q_stats *hw_q);
|
||||
void fbnic_get_hw_stats32(struct fbnic_dev *fbd);
|
||||
void fbnic_get_hw_stats(struct fbnic_dev *fbd);
|
||||
|
||||
|
|
|
|||
|
|
@ -403,11 +403,15 @@ static int fbnic_hwtstamp_set(struct net_device *netdev,
|
|||
static void fbnic_get_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *stats64)
|
||||
{
|
||||
u64 rx_bytes, rx_packets, rx_dropped = 0, rx_errors = 0;
|
||||
u64 tx_bytes, tx_packets, tx_dropped = 0;
|
||||
u64 rx_bytes, rx_packets, rx_dropped = 0;
|
||||
struct fbnic_net *fbn = netdev_priv(dev);
|
||||
struct fbnic_dev *fbd = fbn->fbd;
|
||||
struct fbnic_queue_stats *stats;
|
||||
unsigned int start, i;
|
||||
u64 rx_over = 0;
|
||||
|
||||
fbnic_get_hw_stats(fbd);
|
||||
|
||||
stats = &fbn->tx_stats;
|
||||
|
||||
|
|
@ -444,9 +448,22 @@ static void fbnic_get_stats64(struct net_device *dev,
|
|||
rx_packets = stats->packets;
|
||||
rx_dropped = stats->dropped;
|
||||
|
||||
spin_lock(&fbd->hw_stats_lock);
|
||||
for (i = 0; i < fbd->max_num_queues; i++) {
|
||||
/* Report packets dropped due to CQ/BDQ being full/empty */
|
||||
rx_over += fbd->hw_stats.hw_q[i].rde_pkt_cq_drop.value;
|
||||
rx_over += fbd->hw_stats.hw_q[i].rde_pkt_bdq_drop.value;
|
||||
|
||||
/* Report packets with errors */
|
||||
rx_errors += fbd->hw_stats.hw_q[i].rde_pkt_err.value;
|
||||
}
|
||||
spin_unlock(&fbd->hw_stats_lock);
|
||||
|
||||
stats64->rx_bytes = rx_bytes;
|
||||
stats64->rx_packets = rx_packets;
|
||||
stats64->rx_dropped = rx_dropped;
|
||||
stats64->rx_over_errors = rx_over;
|
||||
stats64->rx_errors = rx_errors;
|
||||
|
||||
for (i = 0; i < fbn->num_rx_queues; i++) {
|
||||
struct fbnic_ring *rxr = fbn->rx[i];
|
||||
|
|
@ -486,6 +503,7 @@ static void fbnic_get_queue_stats_rx(struct net_device *dev, int idx,
|
|||
{
|
||||
struct fbnic_net *fbn = netdev_priv(dev);
|
||||
struct fbnic_ring *rxr = fbn->rx[idx];
|
||||
struct fbnic_dev *fbd = fbn->fbd;
|
||||
struct fbnic_queue_stats *stats;
|
||||
u64 bytes, packets, alloc_fail;
|
||||
u64 csum_complete, csum_none;
|
||||
|
|
@ -509,6 +527,15 @@ static void fbnic_get_queue_stats_rx(struct net_device *dev, int idx,
|
|||
rx->alloc_fail = alloc_fail;
|
||||
rx->csum_complete = csum_complete;
|
||||
rx->csum_none = csum_none;
|
||||
|
||||
fbnic_get_hw_q_stats(fbd, fbd->hw_stats.hw_q);
|
||||
|
||||
spin_lock(&fbd->hw_stats_lock);
|
||||
rx->hw_drop_overruns = fbd->hw_stats.hw_q[idx].rde_pkt_cq_drop.value +
|
||||
fbd->hw_stats.hw_q[idx].rde_pkt_bdq_drop.value;
|
||||
rx->hw_drops = fbd->hw_stats.hw_q[idx].rde_pkt_err.value +
|
||||
rx->hw_drop_overruns;
|
||||
spin_unlock(&fbd->hw_stats_lock);
|
||||
}
|
||||
|
||||
static void fbnic_get_queue_stats_tx(struct net_device *dev, int idx,
|
||||
|
|
|
|||
Loading…
Reference in New Issue