mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net 0/2] net: ngbe: fix error handling in resume and open paths
@ 2026-09-17  9:00 Zhang Yunfei
  2026-09-17  9:00 ` [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core Zhang Yunfei
  2026-09-17  9:00 ` [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails Zhang Yunfei
  0 siblings, 2 replies; 7+ messages in thread
From: Zhang Yunfei @ 2026-09-17  9:00 UTC (permalink / raw)
  To: netdev
  Cc: jiawenwu, mengyuanlou, andrew+netdev, davem, edumazet, kuba,
	pabeni, aleksandr.loktionov, leitao, weirongguang,
	u.kleine-koenig, linux-kernel, stable

Two error-handling fixes for the ngbe PM/open paths.

ngbe_resume() declared err as u32 and returned 0 unconditionally, so a
failed wx_init_interrupt_scheme() or ngbe_open() left the device in
netif_device_detach() state with a broken interrupt scheme while the PM
core was told the resume succeeded; the reset task bails out on the
missing netif_device_present() check, so the device cannot self-heal.
Patch 1 fixes the type and propagates the error, making the tail of the
resume path consistent with the pci_enable_device_mem() failure path at
the top, which already reports its error.

ngbe_open() sets the WX_CFG_PORT_CTL_DRV_LOAD bit to tell the management
firmware the host has taken over the port, but no error path cleared it,
leaving the firmware owning a port whose rings and IRQs are gone. Patch 2
rolls the bit back on all open error paths, matching ngbe_close() and
ngbe_dev_shutdown().

Zhang Yunfei (2):
  net: ngbe: propagate resume errors to the PM core
  net: ngbe: clear DRV_LOAD bit when ngbe_open() fails

 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)


base-commit: 587858367581b9c55c3690f4e63382ad622719d4
-- 
2.25.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core
  2026-09-17  9:00 [PATCH net 0/2] net: ngbe: fix error handling in resume and open paths Zhang Yunfei
@ 2026-09-17  9:00 ` Zhang Yunfei
  2026-09-18  3:57   ` mengyuanlou
  2026-09-21  9:18   ` netdev-bot+sashiko
  2026-09-17  9:00 ` [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails Zhang Yunfei
  1 sibling, 2 replies; 7+ messages in thread
From: Zhang Yunfei @ 2026-09-17  9:00 UTC (permalink / raw)
  To: netdev
  Cc: jiawenwu, mengyuanlou, andrew+netdev, davem, edumazet, kuba,
	pabeni, aleksandr.loktionov, leitao, weirongguang,
	u.kleine-koenig, linux-kernel, stable

ngbe_resume() declares err as u32 and unconditionally returns 0, so
failures of wx_init_interrupt_scheme() or ngbe_open() are silently
swallowed. The device stays in netif_device_detach() state with a
broken interrupt scheme, the PM core is told the resume succeeded,
and the netdev never appears in the networking stack again: the
reset task also bails out early on the missing
netif_device_present() check, so the device cannot self-heal.

Fix the type to int and return err, making the tail of the resume
path consistent with the pci_enable_device_mem() failure path at
the top, which already propagates its error. A failed resume then
becomes visible to the PM core and the device can be re-probed.

Fixes: 6963e463256e ("net: ngbe: add Wake on Lan support")
Cc: stable@vger.kernel.org
Signed-off-by: Zhang Yunfei <zhangyunfei1@kylinos.cn>
---
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 855dc963c610..6d8289e2532d 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -954,7 +954,7 @@ static int ngbe_resume(struct pci_dev *pdev)
 {
 	struct net_device *netdev;
 	struct wx *wx;
-	u32 err;
+	int err;
 
 	wx = pci_get_drvdata(pdev);
 	netdev = wx->netdev;
@@ -977,7 +977,7 @@ static int ngbe_resume(struct pci_dev *pdev)
 		netif_device_attach(netdev);
 	rtnl_unlock();
 
-	return 0;
+	return err;
 }
 
 static struct pci_driver ngbe_driver = {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails
  2026-09-17  9:00 [PATCH net 0/2] net: ngbe: fix error handling in resume and open paths Zhang Yunfei
  2026-09-17  9:00 ` [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core Zhang Yunfei
@ 2026-09-17  9:00 ` Zhang Yunfei
  2026-09-18  3:55   ` mengyuanlou
  2026-09-21  9:18   ` netdev-bot+sashiko
  1 sibling, 2 replies; 7+ messages in thread
From: Zhang Yunfei @ 2026-09-17  9:00 UTC (permalink / raw)
  To: netdev
  Cc: jiawenwu, mengyuanlou, andrew+netdev, davem, edumazet, kuba,
	pabeni, aleksandr.loktionov, leitao, weirongguang,
	u.kleine-koenig, linux-kernel, stable

ngbe_open() sets the WX_CFG_PORT_CTL_DRV_LOAD bit via
wx_control_hw(wx, true) to tell the management firmware that the
host driver has taken over the port (NCSI/OOB firmware stops using
its management channel). Every error path of ngbe_open() returns
without clearing it, leaving rings, IRQs and the PHY torn down
while the firmware still believes the host owns the port, an
inconsistent driver-firmware handshake state that persists until
the next successful ifup.

Roll the bit back on all open error paths, matching ngbe_close()
and ngbe_dev_shutdown(), which already clear it.

Fixes: e7956139a6cf ("net: ngbe: Add irqs request flow")
Cc: stable@vger.kernel.org
Signed-off-by: Zhang Yunfei <zhangyunfei1@kylinos.cn>
---
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 6d8289e2532d..88f00b72a512 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -494,7 +494,7 @@ static int ngbe_open(struct net_device *netdev)
 
 	err = wx_setup_resources(wx);
 	if (err)
-		return err;
+		goto err_control_hw;
 
 	wx_configure(wx);
 
@@ -526,6 +526,8 @@ static int ngbe_open(struct net_device *netdev)
 err_free_resources:
 	wx_free_isb_resources(wx);
 	wx_free_resources(wx);
+err_control_hw:
+	wx_control_hw(wx, false);
 	return err;
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails
  2026-09-17  9:00 ` [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails Zhang Yunfei
@ 2026-09-18  3:55   ` mengyuanlou
  2026-09-21  9:18   ` netdev-bot+sashiko
  1 sibling, 0 replies; 7+ messages in thread
From: mengyuanlou @ 2026-09-18  3:55 UTC (permalink / raw)
  To: Zhang Yunfei
  Cc: netdev, jiawenwu, andrew+netdev, davem, edumazet, kuba, pabeni,
	aleksandr.loktionov, leitao, weirongguang, u.kleine-koenig,
	linux-kernel, stable



> 2026年9月17日 17:00,Zhang Yunfei <zhangyunfei1@kylinos.cn> 写道:
> 
> ngbe_open() sets the WX_CFG_PORT_CTL_DRV_LOAD bit via
> wx_control_hw(wx, true) to tell the management firmware that the
> host driver has taken over the port (NCSI/OOB firmware stops using
> its management channel). Every error path of ngbe_open() returns
> without clearing it, leaving rings, IRQs and the PHY torn down
> while the firmware still believes the host owns the port, an
> inconsistent driver-firmware handshake state that persists until
> the next successful ifup.
> 
> Roll the bit back on all open error paths, matching ngbe_close()
> and ngbe_dev_shutdown(), which already clear it.
> 
> Fixes: e7956139a6cf ("net: ngbe: Add irqs request flow")
> Cc: stable@vger.kernel.org
> Signed-off-by: Zhang Yunfei <zhangyunfei1@kylinos.cn>

Reviewed-by: Mengyuan Lou <mengyuanlou@net-swift.com>

> ---
> drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> index 6d8289e2532d..88f00b72a512 100644
> --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> @@ -494,7 +494,7 @@ static int ngbe_open(struct net_device *netdev)
> 
> err = wx_setup_resources(wx);
> if (err)
> - return err;
> + goto err_control_hw;
> 
> wx_configure(wx);
> 
> @@ -526,6 +526,8 @@ static int ngbe_open(struct net_device *netdev)
> err_free_resources:
> wx_free_isb_resources(wx);
> wx_free_resources(wx);
> +err_control_hw:
> + wx_control_hw(wx, false);
> return err;
> }
> 
> -- 
> 2.25.1
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core
  2026-09-17  9:00 ` [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core Zhang Yunfei
@ 2026-09-18  3:57   ` mengyuanlou
  2026-09-21  9:18   ` netdev-bot+sashiko
  1 sibling, 0 replies; 7+ messages in thread
From: mengyuanlou @ 2026-09-18  3:57 UTC (permalink / raw)
  To: Zhang Yunfei
  Cc: netdev, jiawenwu, andrew+netdev, davem, edumazet, kuba, pabeni,
	aleksandr.loktionov, leitao, weirongguang, u.kleine-koenig,
	linux-kernel, stable



> 2026年9月17日 17:00,Zhang Yunfei <zhangyunfei1@kylinos.cn> 写道:
> 
> ngbe_resume() declares err as u32 and unconditionally returns 0, so
> failures of wx_init_interrupt_scheme() or ngbe_open() are silently
> swallowed. The device stays in netif_device_detach() state with a
> broken interrupt scheme, the PM core is told the resume succeeded,
> and the netdev never appears in the networking stack again: the
> reset task also bails out early on the missing
> netif_device_present() check, so the device cannot self-heal.
> 
> Fix the type to int and return err, making the tail of the resume
> path consistent with the pci_enable_device_mem() failure path at
> the top, which already propagates its error. A failed resume then
> becomes visible to the PM core and the device can be re-probed.
> 
> Fixes: 6963e463256e ("net: ngbe: add Wake on Lan support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Zhang Yunfei <zhangyunfei1@kylinos.cn>

Reviewed-by: Mengyuan Lou <mengyuanlou@net-swift.com>

> ---
> drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> index 855dc963c610..6d8289e2532d 100644
> --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> @@ -954,7 +954,7 @@ static int ngbe_resume(struct pci_dev *pdev)
> {
> struct net_device *netdev;
> struct wx *wx;
> - u32 err;
> + int err;
> 
> wx = pci_get_drvdata(pdev);
> netdev = wx->netdev;
> @@ -977,7 +977,7 @@ static int ngbe_resume(struct pci_dev *pdev)
> netif_device_attach(netdev);
> rtnl_unlock();
> 
> - return 0;
> + return err;
> }
> 
> static struct pci_driver ngbe_driver = {
> -- 
> 2.25.1
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core
  2026-09-17  9:00 ` [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core Zhang Yunfei
  2026-09-18  3:57   ` mengyuanlou
@ 2026-09-21  9:18   ` netdev-bot+sashiko
  1 sibling, 0 replies; 7+ messages in thread
From: netdev-bot+sashiko @ 2026-09-21  9:18 UTC (permalink / raw)
  To: zhangyunfei1
  Cc: netdev, jiawenwu, mengyuanlou, andrew+netdev, davem, edumazet,
	kuba, pabeni, aleksandr.loktionov, leitao, weirongguang,
	u.kleine-koenig, linux-kernel, stable

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

Critical: 0 · High: 1 (1) · Medium: 1 (2) · Low: 0

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [High] ngbe_resume() still discards the return value of ngbe_reset_hw()
  (drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:971:…
- [Medium] Commit message overstates what the patch achieves: "A failed
  resume then becomes visible to the PM core and the device can be re-…

Pre-existing issues:
- [High] After a failed resume (either wx_init_interrupt_scheme() or
  ngbe_open() failing in ngbe_resume(), ngbe_main.c:973-976) the netdev…
- [Medium] The same 'swallowed resume error' defect exists in the shared
  libwx VF resume helper wxvf_resume()…
- [Medium] ngbe_open()'s error path — the path whose failure this patch
  now surfaces from ngbe_resume() — frees the Rx/Tx descriptor rings,…

--

net: ngbe: propagate resume errors to the PM core

This changes err in ngbe_resume() from u32 to int and returns err instead
of a hardcoded 0, so that failures from wx_init_interrupt_scheme() or
ngbe_open() reach the PM core. The pci_enable_device_mem() failure path at
the top of the function already propagated its error.

A few questions about the changelog and about what happens on the newly
reachable failure return.

The commit message says:

> Fix the type to int and return err, making the tail of the resume
> path consistent with the pci_enable_device_mem() failure path at
> the top, which already propagates its error. A failed resume then
> becomes visible to the PM core and the device can be re-probed.

[Severity: Medium]
Is the "the device can be re-probed" part accurate?  For the legacy PCI
.resume hook, the return value ends up in device_resume():

drivers/base/power/main.c:device_resume() {
	...
	if (error) {
		WRITE_ONCE(async_error, error);
		dpm_save_failed_dev(dev_name(dev));
		pm_dev_err(dev, state, async ? " async" : "", error);
	}
	...
}

That records and logs the failure, but there is no unbind, no re-probe and
no retry.  ngbe_resume() also does no rollback on the error return: no
pci_disable_device(), no wx_clear_interrupt_scheme(), and the netdev stays
detached while still IFF_UP.

So the user-visible state described earlier in the changelog ("the netdev
never appears in the networking stack again ... the device cannot
self-heal") looks unchanged by this patch, with one extra dmesg line as the
only difference.  Could the last sentence be reworded to claim only what
the code does?

> diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> index 855dc963c610c..6d8289e2532d0 100644
> --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> @@ -954,7 +954,7 @@ static int ngbe_resume(struct pci_dev *pdev)
>  {
>  	struct net_device *netdev;
>  	struct wx *wx;
> -	u32 err;
> +	int err;
>  
>  	wx = pci_get_drvdata(pdev);
>  	netdev = wx->netdev;

[Severity: High]
Does the same "silently swallowed" case still exist a few lines further
down in this function?  ngbe_resume() calls ngbe_reset_hw() without
capturing the result, and the next statement overwrites err:

	ngbe_reset_hw(wx);
	rtnl_lock();
	err = wx_init_interrupt_scheme(wx);

ngbe_reset_hw() in ngbe_hw.c has two real error exits:

	ret = wx_stop_adapter(wx);
	if (ret != 0)
		return ret;
	...
		if (ret) {
			wx_err(wx, "Lan reset exceed s maximum times.\n");
			return ret;
		}

On those exits ngbe_reset_misc(), wx_clear_hw_cntrs(), wx_get_mac_addr(),
wx_init_rx_addrs() and pci_set_master() are all skipped.  Execution in
ngbe_resume() continues anyway, wx_init_interrupt_scheme() and ngbe_open()
usually succeed (or ngbe_open() is skipped when the interface is
administratively down), so err is 0, netif_device_attach() runs, and the
new return err reports success even though the MAC never acknowledged the
LAN reset and the MAC/Rx address state was not restored.

ngbe_probe() treats the same call as fatal:

	err = ngbe_reset_hw(wx);
	if (err) {
		dev_err(&pdev->dev, "HW Init failed: %d\n", err);
		goto err_free_mac_table;
	}

Should the resume path check it too, so the bug class this patch targets is
actually closed for the whole function?

> @@ -977,7 +977,7 @@ static int ngbe_resume(struct pci_dev *pdev)
>  		netif_device_attach(netdev);
>  	rtnl_unlock();
>  
> -	return 0;
> +	return err;
>  }

[Severity: High]
This isn't a bug introduced by this patch (the pre-patch code reached the
same state, just with err discarded), but what state is the device left in
after this new failure return, and can a later ndo_stop oops?

After wx_init_interrupt_scheme() or ngbe_open() fails here, ngbe_open() was
called directly rather than through dev_open(), so __LINK_STATE_START stays
set and netif_running() remains true, while the datapath resources are
already released.  WX_STATE_RES_FREED, the only guard ngbe_close() has for
"resources already released", is clear: it is set only by
ngbe_down_suspend() and cleared by ngbe_up_complete().

ngbe_close() {
	if (test_bit(WX_STATE_RES_FREED, wx->state))
		goto out;

	wx_ptp_stop(wx);
	ngbe_down(wx);
	wx_free_irq(wx);
	...
}

So the next ip link set dev X down, further suspend via
ngbe_dev_shutdown(), or ngbe_remove() -> unregister_netdev() runs the full
teardown a second time over released objects:

ngbe_close() -> ngbe_down() -> wx_clean_all_rx_rings() -> wx_clean_rx_ring()
	/* Zero out the descriptor ring */
	memset(rx_ring->desc, 0, rx_ring->size);

rx_ring->desc was set to NULL by wx_free_rx_resources() while
rx_ring->size stays non-zero, so this is a write through NULL.

When wx_init_interrupt_scheme() was the failing call, the ring loops also
dereference NULL, since wx_set_num_queues() restored num_tx_queues while
the suspend-time wx_clear_interrupt_scheme() left every ring pointer NULL:

wx_clean_all_tx_rings() {
	for (i = 0; i < wx->num_tx_queues; i++)
		wx_clean_tx_ring(wx->tx_ring[i]);
}

And wx_free_irq() would call free_irq() for an IRQ that is not registered
("Trying to free already-free IRQ" warning).  Would it make sense to unwind
the resume failure here, or to set WX_STATE_RES_FREED on this path?

[Severity: Medium]
This is a pre-existing issue, but the failure that this patch now surfaces
comes from ngbe_open(), whose error path frees the Rx/Tx descriptor rings,
the page-pool pages and the ISB coherent buffer without stopping the
hardware that wx_configure() just armed:

ngbe_open() {
	...
	wx_configure(wx);

	err = ngbe_request_irq(wx);
	if (err)
		goto err_free_resources;
	...
err_free_resources:
	wx_free_isb_resources(wx);
	wx_free_resources(wx);
	...
}

wx_configure() -> wx_configure_rx_ring() programs the ring base addresses,
enables the queue and posts buffers:

	wr32(wx, WX_PX_RR_BAL(reg_idx), rdba & DMA_BIT_MASK(32));
	wr32(wx, WX_PX_RR_BAH(reg_idx), upper_32_bits(rdba));
	...
	wr32m(wx, WX_PX_RR_CFG(reg_idx), WX_PX_RR_CFG_RR_EN, WX_PX_RR_CFG_RR_EN);
	wx_enable_rx_queue(wx, ring);
	wx_alloc_rx_buffers(ring, wx_desc_unused(ring));

and wx_configure_isb() writes WX_PX_ISB_ADDR_L/H with wx->isb_dma.  The
error labels only free memory: there is no ngbe_down(), wx_stop_adapter(),
wx_disable_rx() or wx_disable_rx_queue(), and no re-reset, so RXEN, the
per-queue enables and the stale descriptor/ISB base addresses stay
programmed with bus mastering on while the memory is released.

Can the Rx engine write into those released page-pool pages afterwards?  I
could not confirm that frames arrive in this window, since phylink_start()
is only reached from ngbe_up_complete(), so the link may still be down.
Would a stop/reset in the ngbe_open() error path be worth adding while this
path is being made reachable through a reported resume failure?

>  
>  static struct pci_driver ngbe_driver = {

[Severity: Medium]
This isn't a bug introduced by this patch, but was the sibling VF resume
helper considered?  wxvf_resume() in libwx/wx_vf_common.c has the same
pattern this patch removes from ngbe_resume():

int wxvf_resume(struct device *dev_d)
{
	...
	pci_set_master(pdev);
	wx_init_interrupt_scheme(wx);
	netif_device_attach(wx->netdev);

	return 0;
}

The wx_init_interrupt_scheme() return value is dropped, the netdev is
attached regardless, and 0 is returned.  That helper is the system-sleep
resume callback for both ngbevf and txgbevf:

	static DEFINE_SIMPLE_DEV_PM_OPS(ngbevf_pm_ops, wxvf_suspend, wxvf_resume);
	static DEFINE_SIMPLE_DEV_PM_OPS(txgbevf_pm_ops, wxvf_suspend, wxvf_resume);

The VF case looks worse than the PF one, because wxvf_suspend() calls
wx_clear_interrupt_scheme() (rings NULLed, queue counts zeroed) and
wxvf_resume() attaches the netdev even when the interrupt scheme was not
re-established.  Should the two implementations of the same resume contract
be fixed together, or is there a reason the VF path is left as is?

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260917090050.1927999-1-zhangyunfei1%40kylinos.cn

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails
  2026-09-17  9:00 ` [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails Zhang Yunfei
  2026-09-18  3:55   ` mengyuanlou
@ 2026-09-21  9:18   ` netdev-bot+sashiko
  1 sibling, 0 replies; 7+ messages in thread
From: netdev-bot+sashiko @ 2026-09-21  9:18 UTC (permalink / raw)
  To: zhangyunfei1
  Cc: netdev, jiawenwu, mengyuanlou, andrew+netdev, davem, edumazet,
	kuba, pabeni, aleksandr.loktionov, leitao, weirongguang,
	u.kleine-koenig, linux-kernel, stable

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

Critical: 0 · High: 0 (2) · Medium: 1 · Low: 0 (1)

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [Medium] For all ngbe_open() failures that occur after wx_configure()
  (i.e. ngbe_request_irq(), phylink_connect_phy(),…

Pre-existing issues:
- [High] ngbe_open()'s error unwind
  (drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:522-531) frees the…
- [High] ngbe_setup_tc()
  (drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:630-647) discards the…
- [Low] The new wx_control_hw(wx, false) at
  drivers/net/ethernet/wangxun/ngbe/ngbe_main.c:530 performs an unlocked…

--

net: ngbe: clear DRV_LOAD bit when ngbe_open() fails

The patch makes every error path of ngbe_open() fall through a new
err_control_hw label that calls wx_control_hw(wx, false), so the
WX_CFG_PORT_CTL_DRV_LOAD handshake bit is rolled back when the open
fails instead of being left asserted until the next successful ifup.

A few questions about the resulting error unwind below.

> diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> index 6d8289e2532d0..88f00b72a5123 100644
> --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
> @@ -494,7 +494,7 @@ static int ngbe_open(struct net_device *netdev)
>  
>  	err = wx_setup_resources(wx);
>  	if (err)
> -		return err;
> +		goto err_control_hw;
>  
>  	wx_configure(wx);
>  
> @@ -526,6 +526,8 @@ static int ngbe_open(struct net_device *netdev)
>  err_free_resources:
>  	wx_free_isb_resources(wx);
>  	wx_free_resources(wx);
> +err_control_hw:
> +	wx_control_hw(wx, false);
>  	return err;
>  }

[Severity: Medium]

For the failures that happen after wx_configure() has run
(ngbe_request_irq(), phylink_connect_phy(),
netif_set_real_num_tx_queues(), netif_set_real_num_rx_queues()), does
this unwind free DMA memory that the hardware is still programmed to
use?

wx_configure() arms the datapath before any of those calls can fail:

  wx_configure()
    wx_configure_tx()   /* enables Tx queues, TDM, MAC transmitter */
    wx_configure_rx()
      wx_configure_rx_ring()
        wr32(wx, WX_PX_RR_BAL(reg_idx), rdba & DMA_BIT_MASK(32));
        wr32(wx, WX_PX_RR_BAH(reg_idx), upper_32_bits(rdba));
        wr32m(wx, WX_PX_RR_CFG(reg_idx), WX_PX_RR_CFG_RR_EN, WX_PX_RR_CFG_RR_EN);
        wx_enable_rx_queue(wx, ring);
        wx_alloc_rx_buffers(ring, wx_desc_unused(ring));
      wx_enable_rx(wx);
    wx_configure_isb()
      wr32(wx, WX_PX_ISB_ADDR_L, wx->isb_dma & DMA_BIT_MASK(32));

The error labels then release exactly that memory:

  wx_free_isb_resources()  /* dma_free_coherent() of the ISB buffer */
  wx_free_resources()
    wx_free_all_rx_resources()
      wx_free_rx_resources()
        wx_clean_rx_ring(rx_ring);
        dma_free_coherent(rx_ring->dev, rx_ring->size, rx_ring->desc,
                          rx_ring->dma);
        page_pool_destroy(rx_ring->page_pool);

None of the quiesce steps that ngbe_disable_device() performs run here:

  for (i = 0; i < wx->num_rx_queues; i++)
          wx_disable_rx_queue(wx, wx->rx_ring[i]);
  wx_disable_rx(wx);
  ...
  wx_irq_disable(wx);
  for (i = 0; i < wx->num_tx_queues; i++)
          wr32(wx, WX_PX_TR_CFG(reg_idx), WX_PX_TR_CFG_SWFLSH);

Can a descriptor or buffer writeback in that window land in freed
coherent memory or an unmapped IOVA?

Related to that, the commit message says the rollback is "matching
ngbe_close() and ngbe_dev_shutdown(), which already clear it".  Is the
ordering the same though?  ngbe_close() quiesces first and only then
releases the handshake:

  wx_ptp_stop(wx);
  ngbe_down(wx);
  wx_free_irq(wx);
  wx_free_isb_resources(wx);
  wx_free_resources(wx);
  phylink_disconnect_phy(wx->phylink);
out:
  wx_control_hw(wx, false);

Here the new wx_control_hw(wx, false) hands the port back to the
NCSI/OOB firmware while the Rx unit and RXEN are still enabled and the
rings have already been freed.  Would routing the error paths through
ngbe_down() (or at least the wx_disable_rx_queue()/wx_disable_rx()/
wx_irq_disable() sequence) before freeing resources and clearing
DRV_LOAD be closer to what ngbe_close() does?

[Severity: High]

This isn't a bug introduced by this patch, but while the unwind is
being reworked: should this path also set WX_STATE_RES_FREED?

ngbe_close() uses that bit as its only record of "resources already
released":

  if (test_bit(WX_STATE_RES_FREED, wx->state))
          goto out;

  wx_ptp_stop(wx);
  ngbe_down(wx);
  wx_free_irq(wx);
  wx_free_isb_resources(wx);
  wx_free_resources(wx);

ngbe_open() is also called on netdevs whose __LINK_STATE_START is
already set (ngbe_setup_tc(), ngbe_resume(), and wx_io_resume() in
libwx/wx_err.c), so a failed open leaves netif_running() true with the
IRQs, the ISB buffer and the rings freed while the bit is clear.

The next ndo_stop then repeats the teardown.  wx_free_irq() calls
free_irq() on vectors that were never requested, and
ngbe_down() -> wx_clean_all_rx_rings() -> wx_clean_rx_ring() reaches:

  /* Zero out the descriptor ring */
  memset(rx_ring->desc, 0, rx_ring->size);

with rx_ring->desc already NULL and rx_ring->size still non-zero, since
wx_free_rx_resources() clears desc but not size.  Can that oops?

[Severity: High]

This is a pre-existing issue too, but this patch makes the error return
of ngbe_open() more meaningful, so it seems worth asking: ngbe_setup_tc()
throws it away.

  wx_init_interrupt_scheme(wx);

  if (netif_running(dev))
          ngbe_open(dev);

  return 0;

wx_init_interrupt_scheme() can fail with -ENOMEM from
wx_set_interrupt_capability()/wx_alloc_q_vectors(), and every failure
exit of ngbe_open() now funnels through err_control_hw and returns a
negative errno.  Both are dropped and 0 is returned unconditionally, so
wx_set_channels() in libwx/wx_ethtool.c:

  return wx->setup_tc(dev, netdev_get_num_tc(dev));

reports success to user space while the interface stays administratively
running with rings and the ISB buffer freed, no IRQs requested, the PHY
disconnected, and now DRV_LOAD cleared with nothing re-asserting it
until a later successful ndo_open.  Should ngbe_setup_tc() propagate
these errors?

[Severity: Low]

This is a pre-existing pattern rather than something the patch
introduces, noted only for completeness: wx_control_hw() does an
unlocked read-modify-write of WX_CFG_PORT_CTL through wr32m():

  val = rd32(wx, reg);
  val = ((val & ~mask) | (field & mask));
  wr32(wx, reg, val);

__wx_enable_sriov() in libwx/wx_sriov.c updates the same register:

  wr32m(wx, WX_CFG_PORT_CTL,
        WX_CFG_PORT_CTL_NUM_VT_MASK,
        value);

and it runs from wx_pci_sriov_enable() under the PCI device_lock but
before wx_sriov_reinit() takes RTNL, so RTNL does not serialize the two.
The identical unlocked update already exists on every ifup via
wx_control_hw(wx, true), in ngbe_close() and in ngbe_dev_shutdown(), so
this line adds no new race class; serializing the WX_CFG_PORT_CTL
updates would be a separate libwx cleanup.

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260917090050.1927999-1-zhangyunfei1%40kylinos.cn

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-09-21  9:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-17  9:00 [PATCH net 0/2] net: ngbe: fix error handling in resume and open paths Zhang Yunfei
2026-09-17  9:00 ` [PATCH net 1/2] net: ngbe: propagate resume errors to the PM core Zhang Yunfei
2026-09-18  3:57   ` mengyuanlou
2026-09-21  9:18   ` netdev-bot+sashiko
2026-09-17  9:00 ` [PATCH net 2/2] net: ngbe: clear DRV_LOAD bit when ngbe_open() fails Zhang Yunfei
2026-09-18  3:55   ` mengyuanlou
2026-09-21  9:18   ` netdev-bot+sashiko

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®