From: Jakub Kicinski <kuba@kernel.org>
To: dong100@mucse.com
Cc: Jakub Kicinski <kuba@kernel.org>,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, vadim.fedorenko@linux.dev,
u.kleine-koenig@baylibre.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, yaojun@mucse.com
Subject: Re: [PATCH net-next v10 3/5] net: rnpgbe: Add RX packet reception support
Date: Fri, 4 Sep 2026 14:57:15 -0700 [thread overview]
Message-ID: <20260904215715.3999973-1-kuba@kernel.org> (raw)
In-Reply-To: <91082393C60E8281+20260831073608.401988-4-dong100@mucse.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: rnpgbe: Add RX packet reception support
This adds the RX path for rnpgbe: the RX descriptor union, page_pool
backed RX buffers, the NAPI poll callback, RX ring setup/teardown and RX
statistics. It also adds a per-q_vector timer that retries failed page
allocations by scheduling NAPI, and RX DMA quiesce handling on teardown.
A few questions about the new RX code below.
> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c
> index ff81d222edd3..346e9a1cca8a 100644
> --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c
> +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c
[ ... ]
> @@ -198,15 +200,419 @@ static bool rnpgbe_clean_tx_irq(struct mucse_q_vector *q_vector,
> return !!budget;
> }
>
[ ... ]
> +/**
> + * rnpgbe_rx_alloc_retry - Retry RX buffer allocation
> + * @timer: RX allocation retry timer
> + *
> + * Schedules NAPI after RX buffer allocation fails during polling or
> + * initial ring configuration.
> + **/
> +static void rnpgbe_rx_alloc_retry(struct timer_list *timer)
> +{
> + struct mucse_q_vector *q_vector =
> + timer_container_of(q_vector, timer, rx_alloc_timer);
> +
> + napi_schedule(&q_vector->napi);
> +}
[Severity: Medium]
Can this retry be silently lost when the timer is armed from
rnpgbe_configure_rx_ring()?
At that point NAPI has not been enabled yet. The open path is:
rnpgbe_open()
rnpgbe_configure()
rnpgbe_configure_rx()
rnpgbe_configure_rx_ring()
if (rnpgbe_alloc_rx_buffers(ring, mucse_desc_unused_rx(ring))) {
mod_timer(&ring->q_vector->rx_alloc_timer,
jiffies + msecs_to_jiffies(500));
}
rnpgbe_up_complete()
rnpgbe_napi_enable_all()
clear_bit(__MUCSE_DOWN, &mucse->state);
netif_napi_add_weight() leaves NAPI_STATE_SCHED and NAPI_STATE_NPSVC set
until napi_enable_locked() runs, so napi_schedule_prep() returns false and
only sets NAPIF_STATE_MISSED, which napi_enable_locked() does not act on.
rnpgbe_rx_alloc_retry() ignores the return value of napi_schedule() and does
not re-arm, so if the timer expires in the window before
rnpgbe_napi_enable_all() the retry is dropped. If the initial refill failed
for every descriptor, no descriptors are posted, no RX interrupt can arrive
and the ring stays empty until an administrative down/up.
Would arming the timer only after NAPI is enabled, or re-arming from the
callback when napi_schedule() returns false, be more robust?
[ ... ]
> +static int rnpgbe_clean_rx_irq(struct mucse_q_vector *q_vector,
> + struct mucse_ring *rx_ring,
> + int budget)
> +{
> + unsigned int max_size = SKB_WITH_OVERHEAD(PAGE_SIZE) - RNPGBE_SKB_PAD;
[ ... ]
> + dma_rmb();
> + /* Hardware enforces: minimum 33-bytes descriptor(no 1-13 byte
> + * size), multi-descriptors only for jumbo frames > 1536 bytes
> + * (controlled by M_DEFAULT_SG=96, each descriptor no more than
> + * 1536 bytes). Small packets use single descriptor.
> + */
> + size = le16_to_cpu(rx_desc->wb.len);
[ ... ]
> + if (unlikely(!size || size > max_size)) {
[Severity: Medium]
Is there anything that prevents a first descriptor with size in the 1..13
range from starting a fragmented packet here?
The only length check is the one above, which accepts any size from 1 to
max_size. If such a short descriptor is non-EOP, rnpgbe_is_non_eop() parks
the skb and the following descriptors are attached with skb_add_rx_frag(),
leaving an skb whose linear head is shorter than ETH_HLEN while data_len is
non-zero.
rnpgbe_cleanup_headers() only calls eth_skb_pad(), which does nothing once
skb->len is already at least ETH_ZLEN, so the short head survives.
rnpgbe_process_skb_fields() then does:
skb->protocol = eth_type_trans(skb, dev);
and eth_type_trans() -> eth_skb_pull_mac() -> skb_pull_inline(ETH_HLEN)
reaches the __skb_pull() check:
include/linux/skbuff.h:__skb_pull() {
...
BUG_ON(skb->len < skb->data_len);
...
}
The comment above states the hardware enforces a 33-byte minimum, but the
code does not enforce it. Would rejecting descriptors that cannot supply an
ETH_HLEN linear head, or a pskb_may_pull(skb, ETH_HLEN) before
eth_type_trans(), be worth adding?
[ ... ]
> @@ -225,11 +632,27 @@ static int rnpgbe_poll(struct napi_struct *napi, int budget)
> if (unlikely(!budget))
> return 0;
>
> + if (q_vector->rx.count > 1)
> + per_ring_budget = max(budget / q_vector->rx.count, 1);
> + else
> + per_ring_budget = budget;
> +
> + mucse_for_each_ring(ring, q_vector->rx) {
> + int cleaned = 0;
> +
> + cleaned = rnpgbe_clean_rx_irq(q_vector, ring, per_ring_budget);
> + work_done += cleaned;
> + if (cleaned >= per_ring_budget)
> + clean_complete = false;
> + }
> +
> if (!clean_complete)
> return budget;
>
> - if (likely(napi_complete_done(napi, work_done)))
> - rnpgbe_irq_enable_queues(q_vector);
> + if (likely(napi_complete_done(napi, work_done))) {
> + if (!test_bit(__MUCSE_DOWN, &q_vector->mucse->state))
> + rnpgbe_irq_enable_queues(q_vector);
> + }
[Severity: Medium]
Does this __MUCSE_DOWN test actually close the window the commit message
describes with "Do not re-enable queue interrupts while the device is
down"?
napi_complete_done() clears NAPI_STATE_SCHED before the test_bit() and the
MMIO unmask run, and napi_disable_locked() only waits for SCHED/NPSVC to
clear:
net/core/dev.c:napi_disable_locked() {
...
while (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) {
usleep_range(20, 200);
val = READ_ONCE(n->state);
}
...
}
So this interleaving looks possible:
CPU0 rnpgbe_poll()
napi_complete_done() /* SCHED released */
test_bit(__MUCSE_DOWN) == 0
CPU1 rnpgbe_down()
test_and_set_bit(__MUCSE_DOWN, &mucse->state);
rnpgbe_napi_disable_all();
rnpgbe_irq_disable(); /* includes synchronize_irq() */
rnpgbe_stop_all_rx_rings();
rnpgbe_clean_all_rx_rings();
CPU0 (continues)
rnpgbe_irq_enable_queues(q_vector); /* unmask + trig write */
After rnpgbe_down() returns the queue interrupt would be left unmasked and
explicitly re-triggered, after RX DMA was quiesced and the RX buffers were
released, and just before rnpgbe_free_irq().
Would unmasking before napi_complete_done() releases SCHED, or re-masking
after rnpgbe_napi_disable_all() in rnpgbe_down(), give the guarantee the
changelog claims?
[ ... ]
next prev parent reply other threads:[~2026-09-04 21:57 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260831073608.401988-1-dong100@mucse.com>
2026-08-31 7:36 ` [PATCH net-next v10 1/5] net: rnpgbe: Add interrupt handling Dong Yibo
2026-09-04 21:54 ` Jakub Kicinski
2026-08-31 7:36 ` [PATCH net-next v10 2/5] net: rnpgbe: Add basic TX packet transmission support Dong Yibo
2026-09-04 21:57 ` Jakub Kicinski
2026-08-31 7:36 ` [PATCH net-next v10 3/5] net: rnpgbe: Add RX packet reception support Dong Yibo
2026-09-04 21:57 ` Jakub Kicinski [this message]
2026-08-31 7:36 ` [PATCH net-next v10 4/5] net: rnpgbe: Add receive mode support Dong Yibo
2026-09-04 21:57 ` Jakub Kicinski
2026-08-31 7:36 ` [PATCH net-next v10 5/5] net: rnpgbe: Add link status handling support Dong Yibo
2026-09-04 21:57 ` Jakub Kicinski
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=20260904215715.3999973-1-kuba@kernel.org \
--to=kuba@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=dong100@mucse.com \
--cc=edumazet@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=u.kleine-koenig@baylibre.com \
--cc=vadim.fedorenko@linux.dev \
--cc=yaojun@mucse.com \
/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