From: Daniel Zahka <daniel.zahka@gmail.com>
To: Alexander Duyck <alexanderduyck@fb.com>,
Jakub Kicinski <kuba@kernel.org>,
kernel-team@meta.com, Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Paolo Abeni <pabeni@redhat.com>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Jesper Dangaard Brouer <hawk@kernel.org>,
John Fastabend <john.fastabend@gmail.com>,
Stanislav Fomichev <sdf@fomichev.me>,
Eric Dumazet <edumazet@kernel.org>,
Eric Dumazet <edumazet@kernel.org>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
bpf@vger.kernel.org
Subject: [PATCH net-next 4/4] eth: mpnic: count Rx allocation failures
Date: Fri, 09 Oct 2026 04:35:07 -0700 [thread overview]
Message-ID: <20261009-mpnic-counters3-v1-4-7dc7644cc500@gmail.com> (raw)
In-Reply-To: <20261009-mpnic-counters3-v1-0-7dc7644cc500@gmail.com>
Count both skb allocation failures and page pool allocation failures per
queue, and report them through the queue stats API. The bdq allocation
failures are added to the skb allocation failures when reporting to core
and folded into base stats during aggregation, because the qstats API
doesn't support reporting them separately.
Page pool allocation failures are also counted when the BDQs are first
filled in ndo_open, which runs in process context. mpnic_fill() disables
BH around the fill, so the u64_stats update happens with preemption
disabled.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/ethernet/meta/mpnic/mpnic_netdev.c | 24 ++++++++++++++++++++++-
drivers/net/ethernet/meta/mpnic/mpnic_netdev.h | 1 +
drivers/net/ethernet/meta/mpnic/mpnic_txrx.c | 27 +++++++++++++++++++++++---
drivers/net/ethernet/meta/mpnic/mpnic_txrx.h | 4 ++++
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c b/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c
index 9e262f939c79..7fdf57f70151 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c
@@ -147,14 +147,29 @@ static const struct net_device_ops mpnic_netdev_ops = {
.ndo_get_stats64 = mpnic_get_stats64,
};
+static u64 mpnic_bdq_alloc_failed(struct mpnic_ring *bdq)
+{
+ struct mpnic_queue_stats *stats = &bdq->stats;
+ unsigned int start;
+ u64 alloc_failed;
+
+ do {
+ start = u64_stats_fetch_begin(&stats->syncp);
+ alloc_failed = u64_stats_read(&stats->bdq.alloc_failed);
+ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ return alloc_failed;
+}
+
static void mpnic_get_queue_stats_rx(struct net_device *dev, int idx,
struct netdev_queue_stats_rx *rx)
{
struct mpnic_net *mpn = netdev_priv(dev);
struct mpnic_ring *rxr = mpn->rx[idx];
+ u64 bytes, packets, alloc_failed;
struct mpnic_queue_stats *stats;
+ struct mpnic_q_triad *qt;
unsigned int start;
- u64 bytes, packets;
if (!rxr)
return;
@@ -164,10 +179,16 @@ static void mpnic_get_queue_stats_rx(struct net_device *dev, int idx,
start = u64_stats_fetch_begin(&stats->syncp);
bytes = u64_stats_read(&stats->rcq.bytes);
packets = u64_stats_read(&stats->rcq.packets);
+ alloc_failed = u64_stats_read(&stats->rcq.alloc_failed);
} while (u64_stats_fetch_retry(&stats->syncp, start));
+ qt = container_of(rxr, struct mpnic_q_triad, cmpl);
+ alloc_failed += mpnic_bdq_alloc_failed(&qt->sub0);
+ alloc_failed += mpnic_bdq_alloc_failed(&qt->sub1);
+
rx->bytes = bytes;
rx->packets = packets;
+ rx->alloc_fail = alloc_failed;
}
static void mpnic_get_queue_stats_tx(struct net_device *dev, int idx,
@@ -221,6 +242,7 @@ static void mpnic_get_base_stats(struct net_device *dev,
rx->bytes = base->rx.bytes;
rx->packets = base->rx.packets;
+ rx->alloc_fail = base->rx.alloc_failed;
}
static const struct netdev_stat_ops mpnic_stat_ops = {
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_netdev.h b/drivers/net/ethernet/meta/mpnic/mpnic_netdev.h
index 0d1ee66dd86c..6711766ebc3c 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_netdev.h
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_netdev.h
@@ -23,6 +23,7 @@ struct mpnic_base_stats {
u64 packets;
u64 bytes;
u64 dropped;
+ u64 alloc_failed;
u64 errors;
} rx;
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
index 35129fc149e2..91b897d766a8 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
@@ -409,8 +409,12 @@ static unsigned int __mpnic_fill_bdq(struct mpnic_ring *bdq)
struct page *page;
page = page_pool_dev_alloc_pages(bdq->page_pool);
- if (!page)
+ if (!page) {
+ u64_stats_update_begin(&bdq->stats.syncp);
+ u64_stats_inc(&bdq->stats.bdq.alloc_failed);
+ u64_stats_update_end(&bdq->stats.syncp);
break;
+ }
bdq->rx_buf[i] = page;
mpnic_bd_prep(bdq, i, page);
@@ -598,6 +602,7 @@ static int mpnic_clean_rcq(struct mpnic_napi_vector *nv,
unsigned int packets = 0, bytes = 0, dropped = 0, errors = 0;
struct mpnic_ring *rcq = &qt->cmpl;
struct mpnic_rcq_state *state;
+ unsigned int alloc_failed = 0;
__le64 *raw_rcd, done;
u32 head = rcq->head;
@@ -633,6 +638,7 @@ static int mpnic_clean_rcq(struct mpnic_napi_vector *nv,
!state->pkt.add_frag_failed)) {
pkt_bytes = xdp_get_buff_len(&state->pkt.buff);
skb = xdp_build_skb_from_buff(&state->pkt.buff);
+ alloc_failed += !skb;
}
if (likely(skb)) {
@@ -667,6 +673,7 @@ static int mpnic_clean_rcq(struct mpnic_napi_vector *nv,
u64_stats_add(&rcq->stats.rcq.packets, packets - dropped - errors);
u64_stats_add(&rcq->stats.rcq.bytes, bytes);
u64_stats_add(&rcq->stats.rcq.dropped, dropped);
+ u64_stats_add(&rcq->stats.rcq.alloc_failed, alloc_failed);
u64_stats_add(&rcq->stats.rcq.errors, errors);
u64_stats_update_end(&rcq->stats.syncp);
@@ -727,12 +734,19 @@ static void mpnic_aggregate_ring_tcq_counters(struct mpnic_base_stats *base,
base->tx.wake += u64_stats_read(&tcq->stats.tcq.wake);
}
+static void mpnic_aggregate_ring_bdq_counters(struct mpnic_base_stats *base,
+ struct mpnic_ring *bdq)
+{
+ base->rx.alloc_failed += u64_stats_read(&bdq->stats.bdq.alloc_failed);
+}
+
static void mpnic_aggregate_ring_rcq_counters(struct mpnic_base_stats *base,
struct mpnic_ring *rcq)
{
base->rx.packets += u64_stats_read(&rcq->stats.rcq.packets);
base->rx.bytes += u64_stats_read(&rcq->stats.rcq.bytes);
base->rx.dropped += u64_stats_read(&rcq->stats.rcq.dropped);
+ base->rx.alloc_failed += u64_stats_read(&rcq->stats.rcq.alloc_failed);
base->rx.errors += u64_stats_read(&rcq->stats.rcq.errors);
}
@@ -769,8 +783,13 @@ void mpnic_stats_fold_rings(struct mpnic_net *mpn)
mpnic_aggregate_ring_tcq_counters(new, &qt->cmpl);
}
- for (j = 0; j < nv->rxt_count; j++, t++)
- mpnic_aggregate_ring_rcq_counters(new, &nv->qt[t].cmpl);
+ for (j = 0; j < nv->rxt_count; j++, t++) {
+ struct mpnic_q_triad *qt = &nv->qt[t];
+
+ mpnic_aggregate_ring_bdq_counters(new, &qt->sub0);
+ mpnic_aggregate_ring_bdq_counters(new, &qt->sub1);
+ mpnic_aggregate_ring_rcq_counters(new, &qt->cmpl);
+ }
}
rcu_assign_pointer(mpn->stats.base, new);
@@ -1496,7 +1515,9 @@ void mpnic_fill(struct mpnic_net *mpn)
state->hdr.idx = UINT_MAX;
state->payld.idx = UINT_MAX;
+ local_bh_disable();
mpnic_fill_qt_bdqs(qt);
+ local_bh_enable();
}
}
}
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
index 764e78918b8f..52492e3f484f 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
@@ -100,8 +100,12 @@ struct mpnic_queue_stats {
u64_stats_t packets;
u64_stats_t bytes;
u64_stats_t dropped;
+ u64_stats_t alloc_failed;
u64_stats_t errors;
} rcq;
+ struct {
+ u64_stats_t alloc_failed;
+ } bdq;
};
struct u64_stats_sync syncp;
};
--
2.52.0
prev parent reply other threads:[~2026-10-09 11:35 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 11:35 [PATCH net-next 0/4] eth: mpnic: add basic netdev statistics Daniel Zahka
2026-10-09 11:35 ` [PATCH net-next 1/4] eth: mpnic: count packets, bytes, and drops per ring Daniel Zahka
2026-10-10 11:52 ` netdev-bot+sashiko
2026-10-09 11:35 ` [PATCH net-next 2/4] eth: mpnic: report per-queue stats Daniel Zahka
2026-10-09 11:35 ` [PATCH net-next 3/4] eth: mpnic: count Tx queue stops and wakes Daniel Zahka
2026-10-09 11:35 ` Daniel Zahka [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261009-mpnic-counters3-v1-4-7dc7644cc500@gmail.com \
--to=daniel.zahka@gmail.com \
--cc=alexanderduyck@fb.com \
--cc=andrew+netdev@lunn.ch \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=hawk@kernel.org \
--cc=john.fastabend@gmail.com \
--cc=kernel-team@meta.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@fomichev.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox