mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: dong100@mucse.com
Cc: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, 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 v12 3/5] net: rnpgbe: Add RX packet reception support
Date: Thu, 17 Sep 2026 01:32:31 +0000	[thread overview]
Message-ID: <178960875124.22033.1444221735823171245@kernel.org> (raw)
In-Reply-To: <4AFB00F5B64834A7+20260914013229.2262639-1-dong100@mucse.com>

Thank you for your contribution! Sashiko AI review found 4 potential
issue(s) to consider:

Critical: 0 · High: 0 · Medium: 0 · Low: 4

- [Low] Commit claims to add RX packet reception, but at this commit no
  MAC-level receive enable or address filtering exists (verified: `git…
- [Low] In rnpgbe_configure_rx_ring() the comment "/* Start an initial
  retry after NAPI is enabled.
- [Low] rnpgbe_stop_all_rx_rings() is documented "Return: 0 when RX DMA
  was quiesced, negative errno otherwise" and rnpgbe_configure_rx()…
- [Low] rnpgbe_free_rx_resources() is not self-contained even though its
  kernel-doc says "Free all receive software resources": it vfree()s…

--

net: rnpgbe: Add RX packet reception support

This adds the RX descriptor format, page_pool based RX buffer management,
the NAPI poll callback with RX cleanup, RX ring setup/teardown and RX
statistics for the rnpgbe driver.  A per q_vector timer retries failed
page allocations, and an RX DMA quiesce timeout is treated as a terminal
AXI fault.

A few questions below about the new RX teardown paths and some of the
new comments.

> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c
> index fed07d53e5fe1..e4b7ff992c4d0 100644
> --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c
> +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_lib.c

[ ... ]

> @@ -719,6 +1165,31 @@ static int rnpgbe_wait_tx_dma_idle(struct mucse *mucse)
>  	return err;
>  }
>  
> +static int rnpgbe_wait_rx_dma_idle(struct mucse *mucse)
> +{
> +	struct mucse_hw *hw = &mucse->hw;
> +	u32 dma_status;
> +	int err;
> +
> +	/* A timeout indicates a terminal AXI fault. Hardware stops all PCIe
> +	 * DMA requests in this state, including requests accepted before the
> +	 * fault. Teardown may therefore release mappings and descriptor memory.
> +	 * Recovery requires a chip-level reset.
> +	 */
> +	err = readl_poll_timeout(hw->hw_addr + RNPGBE_DMA_STATUS,
> +				 dma_status,
> +				 (dma_status & RNPGBE_DMA_RX_STATUS) ==
> +				 RNPGBE_DMA_RX_STATUS,
> +				 10, 100000);
> +	if (err) {
> +		set_bit(__MUCSE_AXI_FAULT, &mucse->state);
> +		dev_err(&mucse->pdev->dev,
> +			"RX DMA failed to quiesce, status %#x\n", dma_status);
> +	}
> +
> +	return err;
> +}
> +

[ ... ]

> @@ -838,6 +1309,66 @@ void rnpgbe_clean_all_tx_rings(struct mucse *mucse)
>  		rnpgbe_clean_tx_ring(mucse->tx_ring[i]);
>  }
>  
> +static void rnpgbe_stop_rx_ring(struct mucse_ring *rx_ring)
> +{
> +	/* Stop hw. hardware design guarantees:
> +	 * - No new descriptors will be fetched after RX_START=0
> +	 * - No DMA will be initiated for already-fetched descriptors
> +	 */
> +	mucse_ring_wr32(rx_ring, RNPGBE_RX_START, 0);
> +	/* Flush posted write to ensure hardware sees RX_START=0 */
> +	(void)mucse_ring_rd32(rx_ring, RNPGBE_RX_START);
> +}
> +
> +/**
> + * rnpgbe_stop_all_rx_rings - Stop RX DMA for all queues
> + * @mucse: board private structure
> + *
> + * Return: 0 when RX DMA was quiesced, negative errno otherwise
> + **/
> +static int rnpgbe_stop_all_rx_rings(struct mucse *mucse)
> +{
> +	struct mucse_hw *hw = &mucse->hw;
> +	u32 dma_axi_ctl;
> +	int err = 0;
> +
> +	for (int i = 0; i < mucse->num_rx_queues; i++)
> +		rnpgbe_stop_rx_ring(mucse->rx_ring[i]);
> +
> +	if (mucse->num_rx_queues &&
> +	    !test_bit(__MUCSE_AXI_FAULT, &mucse->state))
> +		err = rnpgbe_wait_rx_dma_idle(mucse);
> +
> +	dma_axi_ctl = mucse_hw_rd32(hw, RNPGBE_DMA_AXI_EN);
> +	dma_axi_ctl &= ~RX_AXI_RW_EN;
> +	mucse_hw_wr32(hw, RNPGBE_DMA_AXI_EN, dma_axi_ctl);
> +	/* Flush the posted write before continuing. */
> +	(void)mucse_hw_rd32(hw, RNPGBE_DMA_AXI_EN);
> +
> +	if (!test_bit(__MUCSE_AXI_FAULT, &mucse->state))
> +		return 0;
> +
> +	return err ? err : -EIO;
> +}

[Severity: Low]
Does the return value here match the kernel-doc "Return: 0 when RX DMA was
quiesced, negative errno otherwise"?

If __MUCSE_AXI_FAULT is already latched, for example set earlier by
rnpgbe_wait_tx_dma_idle(), then the RX wait is skipped:

	if (mucse->num_rx_queues &&
	    !test_bit(__MUCSE_AXI_FAULT, &mucse->state))
		err = rnpgbe_wait_rx_dma_idle(mucse);

err stays 0, yet the tail of the function still does:

	return err ? err : -EIO;

So -EIO is reported as "RX DMA did not quiesce" without RNPGBE_DMA_RX_STATUS
ever having been read.  rnpgbe_configure_rx() then forwards that -EIO to
rnpgbe_open() under the same wording in its own kernel-doc.

Refusing to bring the interface up after a terminal AXI fault looks
intentional, so would it be clearer to describe the sticky-fault case in
the kernel-doc of both functions rather than have it read as an RX quiesce
timeout?

[ ... ]

> @@ -1270,5 +1807,255 @@ void rnpgbe_get_stats64(struct net_device *netdev,

[ ... ]

> +/**
> + * rnpgbe_clean_rx_ring - Free Rx Buffers per Queue
> + * @rx_ring: ring to free buffers from
> + **/
> +static void rnpgbe_clean_rx_ring(struct mucse_ring *rx_ring)
> +{
> +	struct mucse_rx_buffer *rx_buffer;
> +	u16 i;
> +
> +	/* ring already cleared, nothing to do */
> +	if (!rx_ring->rx_buffer_info)
> +		return;
> +	/* Free all the Rx ring sk_buffs */
> +	for (i = 0; i < rx_ring->count; i++) {
> +		rx_buffer = &rx_ring->rx_buffer_info[i];
> +
> +		if (rx_buffer->skb) {
> +			struct sk_buff *skb = rx_buffer->skb;
> +
> +			dev_kfree_skb(skb);
> +			rx_buffer->skb = NULL;
> +		}
> +
> +		if (rx_buffer->page) {
> +			page_pool_put_full_page(rx_ring->page_pool,
> +						rx_buffer->page, false);
> +			rx_buffer->page = NULL;
> +		}
> +	}
> +
> +	rx_ring->next_to_clean = 0;
> +	rx_ring->next_to_use = 0;
> +}
> +
> +/**
> + * rnpgbe_free_rx_resources - Free Rx Resources
> + * @rx_ring: ring to clean the resources from
> + *
> + * Free all receive software resources
> + **/
> +static void rnpgbe_free_rx_resources(struct mucse_ring *rx_ring)
> +{
> +	vfree(rx_ring->rx_buffer_info);
> +	rx_ring->rx_buffer_info = NULL;
> +	/* if not set, then don't free */
> +	if (!rx_ring->desc)
> +		return;
> +
> +	dma_free_coherent(rx_ring->dev, rx_ring->size, rx_ring->desc,
> +			  rx_ring->dma);
> +	rx_ring->desc = NULL;
> +	if (rx_ring->page_pool) {
> +		page_pool_destroy(rx_ring->page_pool);
> +		rx_ring->page_pool = NULL;
> +	}
> +}

[Severity: Low]
Can this leak the page_pool pages held in rx_buffer_info?

rnpgbe_free_rx_resources() is documented as "Free all receive software
resources", but it vfree()s rx_buffer_info first, which discards every
page pointer and every chained skb pointer that rnpgbe_clean_rx_ring()
would have released:

	vfree(rx_ring->rx_buffer_info);
	rx_ring->rx_buffer_info = NULL;

page_pool_destroy() is also placed after the early bail-out:

	if (!rx_ring->desc)
		return;

so a ring that has a pool but no descriptor memory keeps the pool.

That makes rnpgbe_free_all_rx_resources() correct only when the caller has
already run rnpgbe_clean_all_rx_rings(), which is not stated anywhere.
rnpgbe_close() gets that ordering through rnpgbe_down(), but the new
err_free_rx label in rnpgbe_open() calls it with no preceding RX clean,
while the adjacent err_free_tx label does clean-then-free.

Since rnpgbe_configure_rx_ring() already posts up to ring->count -
M_RX_BUFFER_WRITE (496) pages per queue, any future failure return added at
or after that fill would reach err_free_rx with the page pointers gone, and
page_pool_destroy() would then run with inflight pages and keep warning
about a stalled pool shutdown.

Would it be safer to call rnpgbe_clean_rx_ring() from
rnpgbe_free_rx_resources() and destroy the pool before the desc check, so
the free path is self-contained?

[ ... ]

> +/**
> + * rnpgbe_configure_rx_ring - Configure Rx ring info to hw
> + * @mucse: pointer to private structure
> + * @ring: structure containing ring specific data
> + *
> + * Configure the Rx descriptor ring after a reset.
> + **/
> +static void rnpgbe_configure_rx_ring(struct mucse *mucse,
> +				     struct mucse_ring *ring)
> +{

[ ... ]

> +	mucse_ring_wr32(ring, RNPGBE_RX_INT_PKTCNT, M_DEFAULT_RX_INT_PKTCNT);
> +	/* Start an initial retry after NAPI is enabled. */
> +	rnpgbe_alloc_rx_buffers(ring, mucse_desc_unused_rx(ring));
> +}

[Severity: Low]
Is this comment describing the right call?  The call below it is the
initial synchronous fill, not a retry, and it runs before NAPI is enabled:

  rnpgbe_open() -> rnpgbe_configure() -> rnpgbe_configure_rx()
    -> rnpgbe_configure_rx_ring()

while napi_enable happens later in rnpgbe_up_complete() ->
rnpgbe_napi_enable_all().  The behaviour the comment describes looks like
rnpgbe_schedule_rx_retry(), which up_complete() calls after NAPI is
enabled.

This is also the only call site that discards the documented return value
of rnpgbe_alloc_rx_buffers() ("Return: true if alloc failed"), so a fully
failed initial fill leaves the ring empty with no rx_alloc_timer armed
until rnpgbe_schedule_rx_retry() re-checks.  Was that intended?

> +
> +/**
> + * rnpgbe_configure_rx - Configure Receive Unit after Reset
> + * @mucse: pointer to private structure
> + *
> + * Configure the Rx unit after a reset.
> + *
> + * Return: 0 on success, negative errno if RX DMA did not quiesce
> + **/
> +int rnpgbe_configure_rx(struct mucse *mucse)
> +{

[ ... ]

> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> index 21136abe12317..6e006fbd17ad5 100644
> --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> @@ -31,13 +31,19 @@ static struct pci_device_id rnpgbe_pci_tbl[] = {
>   * rnpgbe_configure - Configure the hardware
>   * @mucse: pointer to private structure
>   *
> - * Configure Tx registers in hardware.
> + * Configure Tx and Rx registers in hardware.
>   *
>   * Return: 0 on success, negative errno if hardware configuration fails
>   **/
>  static int rnpgbe_configure(struct mucse *mucse)
>  {
> -	return rnpgbe_configure_tx(mucse);
> +	int err;
> +
> +	err = rnpgbe_configure_tx(mucse);
> +	if (err)
> +		return err;
> +
> +	return rnpgbe_configure_rx(mucse);
>  }

[Severity: Low]
The changelog says "Add basic RX packet reception for the RNPGBE driver",
but at this commit only the DMA side is programmed.  There is no MAC-level
receive enable and no address filtering yet:

  git grep -E 'GMAC|set_rx_mode|set_link' drivers/net/ethernet/mucse/

returns nothing at this commit.  The pieces arrive later in the same
series, where rnpgbe_set_rx_mode() programs the RAR and multicast hash and
is registered as .ndo_set_rx_mode, and rnpgbe_set_link() sets
GMAC_CONTROL_RE plus GMAC_FRAME_FILTER = GMAC_RX_ALL on link up.

Could the changelog mention that MAC receive enable and filtering come in
follow-up patches, so it is clear packets are not yet received at this
step?

> @@ -69,13 +75,18 @@ static int rnpgbe_open(struct net_device *netdev)
>  	err = rnpgbe_setup_all_tx_resources(mucse);
>  	if (err)
>  		goto err_free_irqs;
> +	err = rnpgbe_setup_all_rx_resources(mucse);
> +	if (err)
> +		goto err_free_tx;
>  
>  	err = rnpgbe_configure(mucse);
>  	if (err)
> -		goto err_free_tx;
> +		goto err_free_rx;
>  	rnpgbe_up_complete(mucse);
>  
>  	return 0;
> +err_free_rx:
> +	rnpgbe_free_all_rx_resources(mucse);
>  err_free_tx:
>  	rnpgbe_clean_all_tx_rings(mucse);
>  	rnpgbe_free_all_tx_resources(mucse);

[Severity: Low]
Same point as above, from the caller side: should err_free_rx mirror
err_free_tx and clean the RX rings before freeing their resources?

err_free_tx does:

	rnpgbe_clean_all_tx_rings(mucse);
	rnpgbe_free_all_tx_resources(mucse);

while err_free_rx only frees.  Today every failure return reaches this
label before rnpgbe_configure_rx_ring() has posted any page, so nothing
leaks yet, but the asymmetry makes the path fragile if a later failure
return is added after the RX buffer fill.

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/64BE41C2D2C0836A%2B20260914013019.2262317-1-dong100%40mucse.com

  reply	other threads:[~2026-09-17  1:32 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14  1:30 [PATCH net-next v12 0/5] net: rnpgbe: Add TX/RX and link status support Dong Yibo
2026-09-14  1:32 ` [PATCH net-next v12 1/5] net: rnpgbe: Add interrupt handling Dong Yibo
2026-09-17  1:32   ` netdev-bot+sashiko
2026-09-14  1:32 ` [PATCH net-next v12 2/5] net: rnpgbe: Add basic TX packet transmission support Dong Yibo
2026-09-17  1:32   ` netdev-bot+sashiko
2026-09-14  1:32 ` [PATCH net-next v12 3/5] net: rnpgbe: Add RX packet reception support Dong Yibo
2026-09-17  1:32   ` netdev-bot+sashiko [this message]
2026-09-14  1:32 ` [PATCH net-next v12 4/5] net: rnpgbe: Add receive mode support Dong Yibo
2026-09-14  1:32 ` [PATCH net-next v12 5/5] net: rnpgbe: Add link status handling support Dong Yibo
2026-09-17  1:32   ` netdev-bot+sashiko

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=178960875124.22033.1444221735823171245@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dong100@mucse.com \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --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

all inboxes | Powered by JetHome®