* [PATCH net-next 1/4] eth: mpnic: use WRITE_ONCE() for BDQ head and tail updates
2026-10-01 16:38 [PATCH net-next 0/4] mpnic: add NAPI buffer depletion check Daniel Zahka
@ 2026-10-01 16:38 ` Daniel Zahka
2026-10-01 16:38 ` [PATCH net-next 2/4] eth: mpnic: add a service task Daniel Zahka
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-10-01 16:38 UTC (permalink / raw)
To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni
Cc: netdev, linux-kernel
Convert writes to BDQ ring head and tail in the NAPI path to
WRITE_ONCE(), so that a buffer NAPI depletion check task later in the
series can READ_ONCE() those fields from a workqueue outside of NAPI.
The remaining writers in mpnic_enable_bdq() and mpnic_clean_bdq() run
with NAPI disabled and the instance lock, so don't bother converting
them. The NAPI depletion check later in the series will run under the
instance lock.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/ethernet/meta/mpnic/mpnic_txrx.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
index edb07b7f334b..49061c7316d5 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
@@ -384,7 +384,7 @@ static unsigned int __mpnic_fill_bdq(struct mpnic_ring *bdq)
static void __mpnic_bdq_commit_tail(struct mpnic_ring *bdq, unsigned int tail)
{
if (bdq->tail != tail) {
- bdq->tail = tail;
+ WRITE_ONCE(bdq->tail, tail);
writeq(tail, bdq->doorbell);
}
@@ -483,7 +483,7 @@ mpnic_pkt_prepare(u64 rcd, struct mpnic_rcq_state *state,
pg_start = mpnic_hdr_pg_start(pg_off);
page = mpnic_page_pool_get(&state->hdr, &qt->sub0, pg_idx);
- qt->sub0.head = (pg_idx + 1) & qt->sub0.size_mask;
+ WRITE_ONCE(qt->sub0.head, (pg_idx + 1) & qt->sub0.size_mask);
/* Short-cut the end calculation if the page is fully consumed */
pg_end = fin ? page_size(page) : mpnic_hdr_pg_end(pg_off, len);
@@ -513,7 +513,7 @@ mpnic_add_rx_frag(u64 rcd, struct mpnic_rcq_state *state,
struct page *page;
page = mpnic_page_pool_get(&state->payld, &qt->sub1, pg_idx);
- qt->sub1.head = (pg_idx + 1) & qt->sub1.size_mask;
+ WRITE_ONCE(qt->sub1.head, (pg_idx + 1) & qt->sub1.size_mask);
truesz = (fin ? page_size(page) : ALIGN(pg_off + len, 128)) - pg_off;
--
2.52.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH net-next 2/4] eth: mpnic: add a service task
2026-10-01 16:38 [PATCH net-next 0/4] mpnic: add NAPI buffer depletion check Daniel Zahka
2026-10-01 16:38 ` [PATCH net-next 1/4] eth: mpnic: use WRITE_ONCE() for BDQ head and tail updates Daniel Zahka
@ 2026-10-01 16:38 ` Daniel Zahka
2026-10-01 16:39 ` [PATCH net-next 3/4] eth: mpnic: set Rx buffer minimums using page size and mtu Daniel Zahka
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-10-01 16:38 UTC (permalink / raw)
To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni
Cc: netdev, linux-kernel
Add a service task that runs while the netdevice is running. For now,
the service task does nothing besides conditionally reschedule itself.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/ethernet/meta/mpnic/mpnic.h | 3 +++
drivers/net/ethernet/meta/mpnic/mpnic_netdev.c | 3 +++
drivers/net/ethernet/meta/mpnic/mpnic_pci.c | 17 +++++++++++++++++
3 files changed, 23 insertions(+)
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic.h b/drivers/net/ethernet/meta/mpnic/mpnic.h
index 78359ab6abb1..8b08af0fadcc 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic.h
+++ b/drivers/net/ethernet/meta/mpnic/mpnic.h
@@ -7,6 +7,7 @@
#include <linux/interrupt.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
#include "mpnic_csr.h"
@@ -27,6 +28,8 @@ struct mpnic_dev {
u32 __iomem *uc_addr0;
+ struct delayed_work service_task;
+
u16 num_irqs;
u64 dsn;
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c b/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c
index 2c0309d0c221..bd10df4a9d46 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_netdev.c
@@ -35,6 +35,8 @@ static int mpnic_open(struct net_device *netdev)
netif_tx_wake_all_queues(netdev);
netif_carrier_on(netdev);
+ schedule_delayed_work(&mpn->mpd->service_task, HZ);
+
return 0;
err_free_resources:
@@ -48,6 +50,7 @@ static int mpnic_stop(struct net_device *netdev)
{
struct mpnic_net *mpn = netdev_priv(netdev);
+ cancel_delayed_work(&mpn->mpd->service_task);
netif_carrier_off(netdev);
mpnic_napi_disable(mpn);
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_pci.c b/drivers/net/ethernet/meta/mpnic/mpnic_pci.c
index 968cd611b8ea..17eae5a9ba16 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_pci.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_pci.c
@@ -53,6 +53,20 @@ u64 mpnic_rd64(struct mpnic_dev *mpd, u32 reg)
return ~0ULL;
}
+static void mpnic_service_task(struct work_struct *work)
+{
+ struct mpnic_dev *mpd = container_of(to_delayed_work(work),
+ struct mpnic_dev, service_task);
+ struct net_device *netdev = mpd->netdev;
+
+ netdev_lock(netdev);
+
+ if (netif_running(netdev))
+ schedule_delayed_work(&mpd->service_task, HZ);
+
+ netdev_unlock(netdev);
+}
+
static struct mpnic_dev *mpnic_alloc(struct pci_dev *pdev)
{
struct mpnic_dev *mpd;
@@ -69,6 +83,8 @@ static struct mpnic_dev *mpnic_alloc(struct pci_dev *pdev)
mpd->readrq = pcie_get_readrq(pdev);
mpd->relaxed_ord = pcie_relaxed_ordering_enabled(pdev);
+ INIT_DELAYED_WORK(&mpd->service_task, mpnic_service_task);
+
return mpd;
}
@@ -162,6 +178,7 @@ static void mpnic_remove(struct pci_dev *pdev)
struct mpnic_dev *mpd = pci_get_drvdata(pdev);
unregister_netdev(mpd->netdev);
+ cancel_delayed_work_sync(&mpd->service_task);
mpnic_netdev_free(mpd);
mpnic_free_irqs(mpd);
kfree(mpd);
--
2.52.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH net-next 3/4] eth: mpnic: set Rx buffer minimums using page size and mtu
2026-10-01 16:38 [PATCH net-next 0/4] mpnic: add NAPI buffer depletion check Daniel Zahka
2026-10-01 16:38 ` [PATCH net-next 1/4] eth: mpnic: use WRITE_ONCE() for BDQ head and tail updates Daniel Zahka
2026-10-01 16:38 ` [PATCH net-next 2/4] eth: mpnic: add a service task Daniel Zahka
@ 2026-10-01 16:39 ` Daniel Zahka
2026-10-01 16:39 ` [PATCH net-next 4/4] eth: mpnic: add a NAPI depletion check Daniel Zahka
2026-10-01 16:45 ` [PATCH net-next 0/4] mpnic: add NAPI buffer " netdev-bot+sinfo
4 siblings, 0 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-10-01 16:39 UTC (permalink / raw)
To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni
Cc: netdev, linux-kernel
Set buffer based drop thresholds in the Rx path based on page size and
the max MTU supported. The device will drop packets if it does not have
at least the minimum number of completely unused buffer descriptors
available.
These thresholds are currently set to 17 BDs for both HPQ and PPQ. These
are overly conservative. With our current max MTU of 9742B, the settings
we should target are:
4KiB page size: 1 HPQ, 3 PPQ
64KiB page size: 1 HPQ, 1 PPQ
The HPQ and PPQ rings are always given PAGE_SIZE sized buffers.
The RDE_CTL register encodes the thresholds as one less than the number
of BDs needed.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/ethernet/meta/mpnic/mpnic_init.c | 13 +++++++++----
drivers/net/ethernet/meta/mpnic/mpnic_txrx.h | 6 ++++++
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_init.c b/drivers/net/ethernet/meta/mpnic/mpnic_init.c
index 2daed458f5fc..ace4124158fb 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_init.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_init.c
@@ -10,6 +10,7 @@
#include <linux/sizes.h>
#include "mpnic.h"
+#include "mpnic_txrx.h"
#define MPNIC_MEM_INIT_POLL_US 500
#define MPNIC_MEM_INIT_TO_US 5000
@@ -272,10 +273,14 @@ static void mpnic_rxglb_init(struct mpnic_dev *mpd)
* the per-queue prefetch FIFO.
*/
mpnic_wr64(mpd, MPNIC_RDE_CTL,
- FIELD_PREP(MPNIC_RDE_CTL_HPQ_DROP_THRESHOLD, 16) |
- FIELD_PREP(MPNIC_RDE_CTL_PPQ_DROP_THRESHOLD, 16) |
- FIELD_PREP(MPNIC_RDE_CTL_HPQ_LOCAL_DROP_THRESHOLD, 16) |
- FIELD_PREP(MPNIC_RDE_CTL_PPQ_LOCAL_DROP_THRESHOLD, 16));
+ FIELD_PREP(MPNIC_RDE_CTL_HPQ_DROP_THRESHOLD,
+ MPNIC_RX_HPQ_DROP_THRS - 1) |
+ FIELD_PREP(MPNIC_RDE_CTL_PPQ_DROP_THRESHOLD,
+ MPNIC_RX_PPQ_DROP_THRS - 1) |
+ FIELD_PREP(MPNIC_RDE_CTL_HPQ_LOCAL_DROP_THRESHOLD,
+ MPNIC_RX_HPQ_DROP_THRS - 1) |
+ FIELD_PREP(MPNIC_RDE_CTL_PPQ_LOCAL_DROP_THRESHOLD,
+ MPNIC_RX_PPQ_DROP_THRS - 1));
/* Receive side coalescing is not supported yet */
mpnic_wr64(mpd, MPNIC_RSC_GLOBAL_CONF,
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
index 834eb9bfffd1..9397010557eb 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
@@ -58,6 +58,12 @@ struct mpnic_net;
#define MPNIC_MAX_JUMBO_FRAME_SIZE 9742
+#define MPNIC_RX_HPQ_DROP_THRS \
+ DIV_ROUND_UP(MPNIC_RX_HROOM + MPNIC_RX_MAX_HDR + MPNIC_RX_TROOM, \
+ PAGE_SIZE)
+#define MPNIC_RX_PPQ_DROP_THRS \
+ DIV_ROUND_UP(MPNIC_MAX_JUMBO_FRAME_SIZE, PAGE_SIZE)
+
/* The page a buffer descriptor queue is currently handing out. Records
* how many of the references taken on it are still unused.
*/
--
2.52.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next 4/4] eth: mpnic: add a NAPI depletion check
2026-10-01 16:38 [PATCH net-next 0/4] mpnic: add NAPI buffer depletion check Daniel Zahka
` (2 preceding siblings ...)
2026-10-01 16:39 ` [PATCH net-next 3/4] eth: mpnic: set Rx buffer minimums using page size and mtu Daniel Zahka
@ 2026-10-01 16:39 ` Daniel Zahka
2026-10-01 16:45 ` [PATCH net-next 0/4] mpnic: add NAPI buffer " netdev-bot+sinfo
4 siblings, 0 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-10-01 16:39 UTC (permalink / raw)
To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni
Cc: netdev, linux-kernel
The Rx path can wedge if page pool allocations fail in
__mpnic_fill_bdq(). The problematic sequence is: page pool allocations
fail, bdq rings are empty, device receives packet from the network, but
drops it for lack of buffer space and does not raise interrupt,
mpnic_poll() does not run, so page pool allocations are not retried.
To break out of this cycle, we can add a depletion check to our service
task. The depletion check checks if posted buffers are under a low
watermark, and raises a completion queue interrupt, so that mpnic_poll
will run on the corresponding napi vector.
A note about the lock free reads: We don't bother synchronizing the ring
head and tail reads with mpnic_poll(), because a false positive signal
would simply raise a spurious interrupt scheduling mpnic_poll(), and a
false negative signal will result in a retry, where if mpnic_poll() has
truly not been running, should then report accurately whether or not
posted Rx buffers are low.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/ethernet/meta/mpnic/mpnic_pci.c | 4 ++++
drivers/net/ethernet/meta/mpnic/mpnic_txrx.c | 31 ++++++++++++++++++++++++++++
drivers/net/ethernet/meta/mpnic/mpnic_txrx.h | 1 +
3 files changed, 36 insertions(+)
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_pci.c b/drivers/net/ethernet/meta/mpnic/mpnic_pci.c
index 17eae5a9ba16..125fb26edf93 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_pci.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_pci.c
@@ -11,6 +11,7 @@
#include "mpnic.h"
#include "mpnic_netdev.h"
+#include "mpnic_txrx.h"
#define PCI_DEVICE_ID_META_MPNIC 0x0014
@@ -61,6 +62,9 @@ static void mpnic_service_task(struct work_struct *work)
netdev_lock(netdev);
+ if (netif_carrier_ok(netdev))
+ mpnic_napi_depletion_check(netdev_priv(netdev));
+
if (netif_running(netdev))
schedule_delayed_work(&mpd->service_task, HZ);
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
index 49061c7316d5..5495e9a9aa65 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
@@ -55,6 +55,12 @@ static unsigned int mpnic_desc_unused(struct mpnic_ring *ring)
return (ring->head - ring->tail - 1) & ring->size_mask;
}
+static unsigned int mpnic_desc_used(struct mpnic_ring *ring)
+{
+ return (READ_ONCE(ring->tail) - READ_ONCE(ring->head)) &
+ ring->size_mask;
+}
+
static struct netdev_queue *mpnic_txring_txq(const struct net_device *dev,
const struct mpnic_ring *ring)
{
@@ -1393,3 +1399,28 @@ void mpnic_napi_enable(struct mpnic_net *mpn)
mpnic_wrfl(mpn->mpd);
}
+
+void mpnic_napi_depletion_check(struct mpnic_net *mpn)
+{
+ int i, j, t;
+
+ for (i = 0; i < mpn->num_napi; i++) {
+ struct mpnic_napi_vector *nv = mpn->napi[i];
+
+ for (t = nv->txt_count, j = 0; j < nv->rxt_count; j++, t++) {
+ /* Check if BDs posted covers a max sized frame
+ * + 1 BD held by RDE as a spare
+ * + 1 BD of extra safety margin
+ */
+ if (mpnic_desc_used(&nv->qt[t].sub0) <
+ MPNIC_RX_HPQ_DROP_THRS + 2 ||
+ mpnic_desc_used(&nv->qt[t].sub1) <
+ MPNIC_RX_PPQ_DROP_THRS + 2) {
+ mpnic_nv_irq_trigger(nv);
+ break;
+ }
+ }
+ }
+
+ mpnic_wrfl(mpn->mpd);
+}
diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
index 9397010557eb..767d87a36c35 100644
--- a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
+++ b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.h
@@ -148,6 +148,7 @@ int mpnic_set_netif_queues(struct mpnic_net *mpn);
void mpnic_reset_netif_queues(struct mpnic_net *mpn);
void mpnic_napi_enable(struct mpnic_net *mpn);
void mpnic_napi_disable(struct mpnic_net *mpn);
+void mpnic_napi_depletion_check(struct mpnic_net *mpn);
void mpnic_enable(struct mpnic_net *mpn);
void mpnic_disable(struct mpnic_net *mpn);
void mpnic_wait_all_queues_idle(struct mpnic_dev *mpd);
--
2.52.0
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH net-next 0/4] mpnic: add NAPI buffer depletion check
2026-10-01 16:38 [PATCH net-next 0/4] mpnic: add NAPI buffer depletion check Daniel Zahka
` (3 preceding siblings ...)
2026-10-01 16:39 ` [PATCH net-next 4/4] eth: mpnic: add a NAPI depletion check Daniel Zahka
@ 2026-10-01 16:45 ` netdev-bot+sinfo
2026-10-01 18:26 ` Daniel Zahka
4 siblings, 1 reply; 7+ messages in thread
From: netdev-bot+sinfo @ 2026-10-01 16:45 UTC (permalink / raw)
To: Daniel Zahka
Cc: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni, netdev, linux-kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
- What hardware the change was tested on. For driver fixes please
mention the device (and if relevant firmware version) used for
testing, or say that the change was not tested on real hardware.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH net-next 0/4] mpnic: add NAPI buffer depletion check
2026-10-01 16:45 ` [PATCH net-next 0/4] mpnic: add NAPI buffer " netdev-bot+sinfo
@ 2026-10-01 18:26 ` Daniel Zahka
0 siblings, 0 replies; 7+ messages in thread
From: Daniel Zahka @ 2026-10-01 18:26 UTC (permalink / raw)
To: netdev-bot+sinfo, Daniel Zahka
Cc: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni, netdev, linux-kernel
On Thu Oct 1, 2026 at 12:45 PM EDT, netdev-bot+sinfo wrote:
> Hi!
>
> This is an automated message. This series looks like a fix, but its
> commit messages seem to be missing some information:
>
> - How the issue was discovered, e.g. hit in production, hit during
> development, syzbot report, manual code inspection, LLM or static
> analysis tool scan.
>
> - Whether the issue was actually triggered, or is only theoretical
> (e.g. found by code inspection). If it was triggered please include
> the symptoms, like the stack trace or error messages.
>
> - What hardware the change was tested on. For driver fixes please
> mention the device (and if relevant firmware version) used for
> testing, or say that the change was not tested on real hardware.
>
> Please do not repost the series just to address the above. Instead,
> reply to this email with the missing information, so that reviewers
> can take it into account. If the series needs another revision for
> other reasons, please include the information in the commit messages
> then.
>
> The evaluation is done by an LLM so it may be wrong, if you think
> that is the case please reply and explain.
This is not a fix. See:
https://lore.kernel.org/netdev/20260928190326.59784ee9@kernel.org/
^ permalink raw reply [flat|nested] 7+ messages in thread