From 34eea78a1112afc3579e06abb510a9f57521adaf Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 11 Feb 2025 10:13:52 -0800 Subject: [PATCH 1/5] net: report csum_complete via qstats Commit 13c7c941e729 ("netdev: add qstat for csum complete") reserved the entry for csum complete in the qstats uAPI. Start reporting this value now that we have a driver which needs it. Reviewed-by: Joe Damato Reviewed-by: Alexander Lobakin Link: https://patch.msgid.link/20250211181356.580800-2-kuba@kernel.org Signed-off-by: Jakub Kicinski --- include/net/netdev_queues.h | 1 + net/core/netdev-genl.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h index 73d3401261a6..825141d675e5 100644 --- a/include/net/netdev_queues.h +++ b/include/net/netdev_queues.h @@ -23,6 +23,7 @@ struct netdev_queue_stats_rx { u64 hw_drops; u64 hw_drop_overruns; + u64 csum_complete; u64 csum_unnecessary; u64 csum_none; u64 csum_bad; diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c index 0dcd4faefd8d..c18bb53d13fd 100644 --- a/net/core/netdev-genl.c +++ b/net/core/netdev-genl.c @@ -581,6 +581,7 @@ netdev_nl_stats_write_rx(struct sk_buff *rsp, struct netdev_queue_stats_rx *rx) netdev_stat_put(rsp, NETDEV_A_QSTATS_RX_ALLOC_FAIL, rx->alloc_fail) || netdev_stat_put(rsp, NETDEV_A_QSTATS_RX_HW_DROPS, rx->hw_drops) || netdev_stat_put(rsp, NETDEV_A_QSTATS_RX_HW_DROP_OVERRUNS, rx->hw_drop_overruns) || + netdev_stat_put(rsp, NETDEV_A_QSTATS_RX_CSUM_COMPLETE, rx->csum_complete) || netdev_stat_put(rsp, NETDEV_A_QSTATS_RX_CSUM_UNNECESSARY, rx->csum_unnecessary) || netdev_stat_put(rsp, NETDEV_A_QSTATS_RX_CSUM_NONE, rx->csum_none) || netdev_stat_put(rsp, NETDEV_A_QSTATS_RX_CSUM_BAD, rx->csum_bad) || From 93d2f2f36ea993841d2efec4caef1cc95f4baa84 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 11 Feb 2025 10:13:53 -0800 Subject: [PATCH 2/5] eth: fbnic: wrap tx queue stats in a struct The queue stats struct is used for Rx and Tx queues. Wrap the Tx stats in a struct and a union, so that we can reuse the same space for Rx stats on Rx queues. This also makes it easy to add an assert to the stat handling code to catch new stats not being aggregated on shutdown. Acked-by: Joe Damato Reviewed-by: Alexander Lobakin Link: https://patch.msgid.link/20250211181356.580800-3-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c | 8 ++++---- drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 10 ++++++---- drivers/net/ethernet/meta/fbnic/fbnic_txrx.h | 8 ++++++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c index 9503c36620c6..fb7139a1da46 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -1224,14 +1224,14 @@ static void fbnic_get_ts_stats(struct net_device *netdev, unsigned int start; int i; - ts_stats->pkts = fbn->tx_stats.ts_packets; - ts_stats->lost = fbn->tx_stats.ts_lost; + ts_stats->pkts = fbn->tx_stats.twq.ts_packets; + ts_stats->lost = fbn->tx_stats.twq.ts_lost; for (i = 0; i < fbn->num_tx_queues; i++) { ring = fbn->tx[i]; do { start = u64_stats_fetch_begin(&ring->stats.syncp); - ts_packets = ring->stats.ts_packets; - ts_lost = ring->stats.ts_lost; + ts_packets = ring->stats.twq.ts_packets; + ts_lost = ring->stats.twq.ts_lost; } while (u64_stats_fetch_retry(&ring->stats.syncp, start)); ts_stats->pkts += ts_packets; ts_stats->lost += ts_lost; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c index d4d7027df9a0..b60dd1c9918e 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c @@ -444,7 +444,7 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget, if (unlikely(discard)) { u64_stats_update_begin(&ring->stats.syncp); ring->stats.dropped += total_packets; - ring->stats.ts_lost += ts_lost; + ring->stats.twq.ts_lost += ts_lost; u64_stats_update_end(&ring->stats.syncp); netdev_tx_completed_queue(txq, total_packets, total_bytes); @@ -507,7 +507,7 @@ static void fbnic_clean_tsq(struct fbnic_napi_vector *nv, skb_tstamp_tx(skb, &hwtstamp); u64_stats_update_begin(&ring->stats.syncp); - ring->stats.ts_packets++; + ring->stats.twq.ts_packets++; u64_stats_update_end(&ring->stats.syncp); } @@ -1065,8 +1065,10 @@ void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn, fbn->tx_stats.bytes += stats->bytes; fbn->tx_stats.packets += stats->packets; fbn->tx_stats.dropped += stats->dropped; - fbn->tx_stats.ts_lost += stats->ts_lost; - fbn->tx_stats.ts_packets += stats->ts_packets; + fbn->tx_stats.twq.ts_lost += stats->twq.ts_lost; + fbn->tx_stats.twq.ts_packets += stats->twq.ts_packets; + /* Remember to add new stats here */ + BUILD_BUG_ON(sizeof(fbn->tx_stats.twq) / 8 != 2); } static void fbnic_remove_tx_ring(struct fbnic_net *fbn, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h index c2a94f31f71b..6b549b0e7fa4 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h @@ -56,9 +56,13 @@ struct fbnic_pkt_buff { struct fbnic_queue_stats { u64 packets; u64 bytes; + union { + struct { + u64 ts_packets; + u64 ts_lost; + } twq; + }; u64 dropped; - u64 ts_packets; - u64 ts_lost; struct u64_stats_sync syncp; }; From 67dc4eb5fc926b96145ca6d81da35f0fa20396f0 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 11 Feb 2025 10:13:54 -0800 Subject: [PATCH 3/5] eth: fbnic: report software Rx queue stats Gather and report software Rx queue stats - checksum stats and allocation failures. Acked-by: Joe Damato Reviewed-by: Alexander Lobakin Link: https://patch.msgid.link/20250211181356.580800-4-kuba@kernel.org Signed-off-by: Jakub Kicinski --- .../net/ethernet/meta/fbnic/fbnic_netdev.c | 12 +++++- drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 43 +++++++++++++++---- drivers/net/ethernet/meta/fbnic/fbnic_txrx.h | 5 +++ 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c index 14e7a8384bce..ceb6d1de9bcf 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c @@ -487,8 +487,9 @@ 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_queue_stats *stats; + u64 bytes, packets, alloc_fail; + u64 csum_complete, csum_none; unsigned int start; - u64 bytes, packets; if (!rxr) return; @@ -498,10 +499,16 @@ static void fbnic_get_queue_stats_rx(struct net_device *dev, int idx, start = u64_stats_fetch_begin(&stats->syncp); bytes = stats->bytes; packets = stats->packets; + alloc_fail = stats->rx.alloc_failed; + csum_complete = stats->rx.csum_complete; + csum_none = stats->rx.csum_none; } while (u64_stats_fetch_retry(&stats->syncp, start)); rx->bytes = bytes; rx->packets = packets; + rx->alloc_fail = alloc_fail; + rx->csum_complete = csum_complete; + rx->csum_none = csum_none; } static void fbnic_get_queue_stats_tx(struct net_device *dev, int idx, @@ -538,6 +545,9 @@ static void fbnic_get_base_stats(struct net_device *dev, rx->bytes = fbn->rx_stats.bytes; rx->packets = fbn->rx_stats.packets; + rx->alloc_fail = fbn->rx_stats.rx.alloc_failed; + rx->csum_complete = fbn->rx_stats.rx.csum_complete; + rx->csum_none = fbn->rx_stats.rx.csum_none; } static const struct netdev_stat_ops fbnic_stat_ops = { diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c index b60dd1c9918e..66ba36fd3c08 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c @@ -198,12 +198,15 @@ fbnic_tx_offloads(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta) } static void -fbnic_rx_csum(u64 rcd, struct sk_buff *skb, struct fbnic_ring *rcq) +fbnic_rx_csum(u64 rcd, struct sk_buff *skb, struct fbnic_ring *rcq, + u64 *csum_cmpl, u64 *csum_none) { skb_checksum_none_assert(skb); - if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM))) + if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM))) { + (*csum_none)++; return; + } if (FIELD_GET(FBNIC_RCD_META_L4_CSUM_UNNECESSARY, rcd)) { skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -212,6 +215,7 @@ fbnic_rx_csum(u64 rcd, struct sk_buff *skb, struct fbnic_ring *rcq) skb->ip_summed = CHECKSUM_COMPLETE; skb->csum = (__force __wsum)csum; + (*csum_cmpl)++; } } @@ -661,8 +665,13 @@ static void fbnic_fill_bdq(struct fbnic_napi_vector *nv, struct fbnic_ring *bdq) struct page *page; page = page_pool_dev_alloc_pages(nv->page_pool); - if (!page) + if (!page) { + u64_stats_update_begin(&bdq->stats.syncp); + bdq->stats.rx.alloc_failed++; + u64_stats_update_end(&bdq->stats.syncp); + break; + } fbnic_page_pool_init(bdq, i, page); fbnic_bd_prep(bdq, i, page); @@ -875,12 +884,13 @@ static void fbnic_rx_tstamp(struct fbnic_napi_vector *nv, u64 rcd, static void fbnic_populate_skb_fields(struct fbnic_napi_vector *nv, u64 rcd, struct sk_buff *skb, - struct fbnic_q_triad *qt) + struct fbnic_q_triad *qt, + u64 *csum_cmpl, u64 *csum_none) { struct net_device *netdev = nv->napi.dev; struct fbnic_ring *rcq = &qt->cmpl; - fbnic_rx_csum(rcd, skb, rcq); + fbnic_rx_csum(rcd, skb, rcq, csum_cmpl, csum_none); if (netdev->features & NETIF_F_RXHASH) skb_set_hash(skb, @@ -898,7 +908,8 @@ static bool fbnic_rcd_metadata_err(u64 rcd) static int fbnic_clean_rcq(struct fbnic_napi_vector *nv, struct fbnic_q_triad *qt, int budget) { - unsigned int packets = 0, bytes = 0, dropped = 0; + unsigned int packets = 0, bytes = 0, dropped = 0, alloc_failed = 0; + u64 csum_complete = 0, csum_none = 0; struct fbnic_ring *rcq = &qt->cmpl; struct fbnic_pkt_buff *pkt; s32 head0 = -1, head1 = -1; @@ -947,14 +958,22 @@ static int fbnic_clean_rcq(struct fbnic_napi_vector *nv, /* Populate skb and invalidate XDP */ if (!IS_ERR_OR_NULL(skb)) { - fbnic_populate_skb_fields(nv, rcd, skb, qt); + fbnic_populate_skb_fields(nv, rcd, skb, qt, + &csum_complete, + &csum_none); packets++; bytes += skb->len; napi_gro_receive(&nv->napi, skb); } else { - dropped++; + if (!skb) { + alloc_failed++; + dropped++; + } else { + dropped++; + } + fbnic_put_pkt_buff(nv, pkt, 1); } @@ -977,6 +996,9 @@ static int fbnic_clean_rcq(struct fbnic_napi_vector *nv, /* Re-add ethernet header length (removed in fbnic_build_skb) */ rcq->stats.bytes += ETH_HLEN * packets; rcq->stats.dropped += dropped; + rcq->stats.rx.alloc_failed += alloc_failed; + rcq->stats.rx.csum_complete += csum_complete; + rcq->stats.rx.csum_none += csum_none; u64_stats_update_end(&rcq->stats.syncp); /* Unmap and free processed buffers */ @@ -1054,6 +1076,11 @@ void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn, fbn->rx_stats.bytes += stats->bytes; fbn->rx_stats.packets += stats->packets; fbn->rx_stats.dropped += stats->dropped; + fbn->rx_stats.rx.alloc_failed += stats->rx.alloc_failed; + fbn->rx_stats.rx.csum_complete += stats->rx.csum_complete; + fbn->rx_stats.rx.csum_none += stats->rx.csum_none; + /* Remember to add new stats here */ + BUILD_BUG_ON(sizeof(fbn->tx_stats.rx) / 8 != 3); } void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h index 6b549b0e7fa4..c9d9001042dc 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h @@ -61,6 +61,11 @@ struct fbnic_queue_stats { u64 ts_packets; u64 ts_lost; } twq; + struct { + u64 alloc_failed; + u64 csum_complete; + u64 csum_none; + } rx; }; u64 dropped; struct u64_stats_sync syncp; From 1e07e361fd8339eff761ef9bc4c3c1dd9a9cd887 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 11 Feb 2025 10:13:55 -0800 Subject: [PATCH 4/5] eth: fbnic: report software Tx queue stats Gather and report software Tx queue stats - checksum stats and queue stop / start. Acked-by: Joe Damato Reviewed-by: Alexander Lobakin Link: https://patch.msgid.link/20250211181356.580800-5-kuba@kernel.org Signed-off-by: Jakub Kicinski --- .../net/ethernet/meta/fbnic/fbnic_netdev.c | 10 ++++++++ drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 23 +++++++++++++++---- drivers/net/ethernet/meta/fbnic/fbnic_txrx.h | 3 +++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c index ceb6d1de9bcf..b12672d1607e 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c @@ -517,6 +517,7 @@ static void fbnic_get_queue_stats_tx(struct net_device *dev, int idx, struct fbnic_net *fbn = netdev_priv(dev); struct fbnic_ring *txr = fbn->tx[idx]; struct fbnic_queue_stats *stats; + u64 stop, wake, csum; unsigned int start; u64 bytes, packets; @@ -528,10 +529,16 @@ static void fbnic_get_queue_stats_tx(struct net_device *dev, int idx, start = u64_stats_fetch_begin(&stats->syncp); bytes = stats->bytes; packets = stats->packets; + csum = stats->twq.csum_partial; + stop = stats->twq.stop; + wake = stats->twq.wake; } while (u64_stats_fetch_retry(&stats->syncp, start)); tx->bytes = bytes; tx->packets = packets; + tx->needs_csum = csum; + tx->stop = stop; + tx->wake = wake; } static void fbnic_get_base_stats(struct net_device *dev, @@ -542,6 +549,9 @@ static void fbnic_get_base_stats(struct net_device *dev, tx->bytes = fbn->tx_stats.bytes; tx->packets = fbn->tx_stats.packets; + tx->needs_csum = fbn->tx_stats.twq.csum_partial; + tx->stop = fbn->tx_stats.twq.stop; + tx->wake = fbn->tx_stats.twq.wake; rx->bytes = fbn->rx_stats.bytes; rx->packets = fbn->rx_stats.packets; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c index 66ba36fd3c08..24d2b528b66c 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c @@ -113,6 +113,11 @@ static int fbnic_maybe_stop_tx(const struct net_device *dev, res = netif_txq_maybe_stop(txq, fbnic_desc_unused(ring), size, FBNIC_TX_DESC_WAKEUP); + if (!res) { + u64_stats_update_begin(&ring->stats.syncp); + ring->stats.twq.stop++; + u64_stats_update_end(&ring->stats.syncp); + } return !res; } @@ -191,6 +196,9 @@ fbnic_tx_offloads(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta) skb->csum_offset / 2)); *meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_CSO); + u64_stats_update_begin(&ring->stats.syncp); + ring->stats.twq.csum_partial++; + u64_stats_update_end(&ring->stats.syncp); *meta |= cpu_to_le64(FIELD_PREP(FBNIC_TWD_L2_HLEN_MASK, l2len / 2) | FIELD_PREP(FBNIC_TWD_L3_IHLEN_MASK, i3len / 2)); @@ -460,9 +468,13 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget, ring->stats.packets += total_packets; u64_stats_update_end(&ring->stats.syncp); - netif_txq_completed_wake(txq, total_packets, total_bytes, - fbnic_desc_unused(ring), - FBNIC_TX_DESC_WAKEUP); + if (!netif_txq_completed_wake(txq, total_packets, total_bytes, + fbnic_desc_unused(ring), + FBNIC_TX_DESC_WAKEUP)) { + u64_stats_update_begin(&ring->stats.syncp); + ring->stats.twq.wake++; + u64_stats_update_end(&ring->stats.syncp); + } } static void fbnic_clean_tsq(struct fbnic_napi_vector *nv, @@ -1092,10 +1104,13 @@ void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn, fbn->tx_stats.bytes += stats->bytes; fbn->tx_stats.packets += stats->packets; fbn->tx_stats.dropped += stats->dropped; + fbn->tx_stats.twq.csum_partial += stats->twq.csum_partial; fbn->tx_stats.twq.ts_lost += stats->twq.ts_lost; fbn->tx_stats.twq.ts_packets += stats->twq.ts_packets; + fbn->tx_stats.twq.stop += stats->twq.stop; + fbn->tx_stats.twq.wake += stats->twq.wake; /* Remember to add new stats here */ - BUILD_BUG_ON(sizeof(fbn->tx_stats.twq) / 8 != 2); + BUILD_BUG_ON(sizeof(fbn->tx_stats.twq) / 8 != 5); } static void fbnic_remove_tx_ring(struct fbnic_net *fbn, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h index c9d9001042dc..b53a7d28ecd3 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h @@ -58,8 +58,11 @@ struct fbnic_queue_stats { u64 bytes; union { struct { + u64 csum_partial; u64 ts_packets; u64 ts_lost; + u64 stop; + u64 wake; } twq; struct { u64 alloc_failed; From 0ec023282a9d9487d5f80fd785b0c2e80a40ba43 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 11 Feb 2025 10:13:56 -0800 Subject: [PATCH 5/5] eth: fbnic: re-sort the objects in the Makefile Looks like recent commit broke the sort order, fix it. Acked-by: Joe Damato Reviewed-by: Alexander Lobakin Link: https://patch.msgid.link/20250211181356.580800-6-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/meta/fbnic/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/meta/fbnic/Makefile b/drivers/net/ethernet/meta/fbnic/Makefile index 239b2258ec65..0dbc634adb4b 100644 --- a/drivers/net/ethernet/meta/fbnic/Makefile +++ b/drivers/net/ethernet/meta/fbnic/Makefile @@ -20,6 +20,7 @@ fbnic-y := fbnic_csr.o \ fbnic_pci.o \ fbnic_phylink.o \ fbnic_rpc.o \ + fbnic_time.o \ fbnic_tlv.o \ fbnic_txrx.o \ - fbnic_time.o +# End of objects