mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Arthur Crepin Leblond <arthur@marmottus.net>
To: netdev-bot+sashiko@kernel.org
Cc: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, arnd@arndb.de,
	netdev@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next v8 3/3] w5100: detect carrier state using link status bit and optional interrupt
Date: Fri, 18 Sep 2026 14:18:43 +0200	[thread overview]
Message-ID: <20260918121843.GB30413@marmottus.net> (raw)
In-Reply-To: <178967573220.22033.14908658366180861063@kernel.org>

On Thu, Sep 17, 2026 at 08:08:52PM +0000, netdev-bot+sashiko@kernel.org wrote:
>[Severity: Medium]
>Should the message also mention the teardown changes that apply to all chip
>variants, not just w5500 with a link interrupt?
>

I can reword a bit the commit message to mention this.

>[Severity: Medium]
>Can a single failed PHYCFGR read leave the interface stuck with the carrier
>off while the PHY is linked?
>
>The negative case here intentionally leaves the carrier untouched, and there
>is no retry, delayed re-read or polling fallback.  The previous value at the
>two initial synchronisation points is off: w5100_probe() calls
>netif_carrier_off() before register_netdev(), and w5100_suspend() forces the
>carrier off.
>
>The errors do reach here.  w5500_spi_read() in w5100-spi.c propagates SPI
>failures:
>
>	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
>
>	return ret ? ret : data;
>
>so for example an -ENOMEM from the fallback allocation in
>spi_write_then_read() ends up as a negative return of
>w5500_get_phycfgr_lnk().
>
>The only other refresh comes from LINKLED edges, requested with
>IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING.  If the link is already up and
>stays up, the pin holds a constant level and no further edge is produced.
>
>So if the read in w5100_open() or w5100_resume() fails once, does the carrier
>stay off until the interface is manually taken down and brought back up,
>with linkwatch keeping the qdisc deactivated in the meantime?  Would
>re-arming a delayed PHYCFGR read on read failure address this?

Yes I agree, an initial SPI read failure will leave the carrier in
such state but adding some polling mechanism in this patch will
complicate it even more.

>[Severity: Medium]
>Making netif_carrier_off() conditional on priv->link_irq here (and the same
>change in w5100_suspend()) looks like it also fixes an existing carrier
>regression.  Should this carry a Fixes: tag for dacf281771a9 ("w5100: remove
>unused gpio link detection")?
>
>dacf281771a9 removed the only netif_carrier_on() calls, which lived in
>w5100_open() and w5100_resume(), but left the unconditional
>netif_carrier_off() in w5100_stop() and w5100_suspend().  On the baseline,
>w5100_open() has no carrier call at all, so:
>
>	ip link set dev eth0 down
>	ip link set dev eth0 up
>
>leaves every w5100/w5200/w5500 reporting no carrier, and linkwatch keeps the
>qdisc deactivated.  A suspend/resume cycle has the same effect.
>
>Without a Fixes: tag this fix will not be picked up for stable, so released
>kernels keep the unusable-after-ifdown/ifup behaviour.

This patch is not really a fix, it brings back proper support for the
link detection using an interrupt and reading the device register.

>[Severity: High]
>Can rx_work still run after unregister_netdev() here and hand an skb to
>netif_rx() with a dangling ndev?
>
>w5100_stop(), which runs from dev_close() inside unregister_netdev(), does
>not cancel or flush rx_work:
>
>	cancel_work_sync(&priv->restart_work);
>	...
>	w5100_hw_close(priv);
>	netif_stop_queue(ndev);
>	napi_disable(&priv->napi);
>
>so an rx_work item queued just before the close can run afterwards:
>
>w5100_rx_work()
>	while ((skb = w5100_rx_skb(priv->ndev)))
>		netif_rx(skb);
>
>	w5100_enable_intr(priv);
>
>netif_rx() takes no device reference, and unregister_netdev() has already
>done flush_all_backlogs() and netdev_run_todo().  If that skb sits in a
>deferred or RPS-remote backlog, is it dereferenced after the free_netdev() a
>few lines below?
>
>The main interrupt is also still registered while the cancel_work_sync()
>calls run:
>
>w5100_interrupt()
>	if (ir & S0_IR_RECV) {
>		w5100_disable_intr(priv);
>
>		if (priv->ops->may_sleep)
>			queue_work(priv->xfer_wq, &priv->rx_work);
>
>so an in-flight handler can re-queue rx_work after the cancellation.  That
>late work then touches chip registers concurrently with the w5100_hw_reset()
>above and calls w5100_enable_intr() after the handler has been freed.
>
>Before this patch, destroy_workqueue() drained rx_work while the netdev was
>still registered and after free_irq(), so neither case could happen.  Would
>freeing and synchronizing both interrupts first, then draining all work they
>can produce, and only then resetting the hardware and
>unregistering/freeing the netdev, be the right order?
>

Right, I'll fix that too. Since unregister is calling ndo_close() I can
handle this there.

>[Severity: Medium]
>Does the new cancel_work_sync(&priv->tx_work) leak priv->tx_skb?
>
>w5100_start_tx() takes ownership of the skb and defers the free entirely to
>the work item:
>
>	if (priv->ops->may_sleep) {
>		WARN_ON(priv->tx_skb);
>		priv->tx_skb = skb;
>		queue_work(priv->xfer_wq, &priv->tx_work);
>
>and w5100_tx_work() is the only consumer that clears priv->tx_skb and frees
>it via w5100_tx_skb() -> dev_kfree_skb():
>
>	struct sk_buff *skb = priv->tx_skb;
>
>	priv->tx_skb = NULL;
>
>	if (WARN_ON(!skb))
>		return;
>	w5100_tx_skb(priv->ndev, skb);
>
>If cancel_work_sync() cancels a work item that has not started yet, nothing
>releases priv->tx_skb, and remove() continues to destroy_workqueue() and
>free_netdev() with it still set.  The previous code reached the same state
>through destroy_workqueue(), which drains queued work instead of cancelling
>it, so the skb was always freed.  Would freeing priv->tx_skb explicitly
>after the cancellation, or flushing tx_work instead, be preferable?

Yes, didn't think of this one.

>[Severity: Medium]
>Should the cancel_work_sync() come before netif_carrier_off() and
>netif_device_detach() rather than after them, as it does in w5100_stop()?
>
>restart_work can be queued at any time on w5500/SPI:
>
>w5100_tx_timeout()
>	if (priv->ops->may_sleep)
>		schedule_work(&priv->restart_work);
>
>A work item that is pending or already running when suspend starts still
>passes the new guard in w5100_restart(), because netif_running() stays true
>through the suspend callback and the guard does not test
>netif_device_present():
>
>	if (!netif_running(ndev))
>		return;
>
>It then re-runs w5100_hw_reset()/w5100_hw_start(), re-enabling chip
>interrupts and re-opening socket 0, calls netif_wake_queue() which clears the
>__QUEUE_STATE_DRV_XOFF that netif_device_detach() just set, and calls
>w5500_report_carrier_state() which can turn the carrier back on right after
>suspend cleared it.
>
>With the tx queue runnable again and __dev_queue_xmit() not testing
>netif_device_present(), can the stack then reach w5100_start_tx() and issue
>SPI transfers to a chip whose socket w5100_hw_close() has closed, or to an
>already suspended SPI controller?  Would moving the cancellation ahead of the
>state changes, and/or widening the guard in w5100_restart(), close this?

Good point, I'll harden the checks.

Arthur

      reply	other threads:[~2026-09-18 12:18 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-15  8:06 [PATCH net-next v8 0/3] w5100: restore GPIO-based link detection Arthur Crepin Leblond
2026-09-15  8:06 ` [PATCH net-next v8 1/3] dt-bindings: net: wiznet,w5100: convert to DT schema Arthur Crepin Leblond
2026-09-17 20:08   ` netdev-bot+sashiko
2026-09-18  7:03     ` Arthur Crepin Leblond
2026-09-15  8:06 ` [PATCH net-next v8 2/3] dt-bindings: net: wiznet,w5100: add link status interrupt Arthur Crepin Leblond
2026-09-17 10:04   ` Krzysztof Kozlowski
2026-09-17 12:02     ` Arthur Crepin Leblond
2026-09-17 20:08   ` netdev-bot+sashiko
2026-09-18  7:17     ` Arthur Crepin Leblond
2026-09-15  8:06 ` [PATCH net-next v8 3/3] w5100: detect carrier state using link status bit and optional interrupt Arthur Crepin Leblond
2026-09-17 20:08   ` netdev-bot+sashiko
2026-09-18 12:18     ` Arthur Crepin Leblond [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=20260918121843.GB30413@marmottus.net \
    --to=arthur@marmottus.net \
    --cc=andrew+netdev@lunn.ch \
    --cc=arnd@arndb.de \
    --cc=conor+dt@kernel.org \
    --cc=davem@davemloft.net \
    --cc=devicetree@vger.kernel.org \
    --cc=edumazet@google.com \
    --cc=krzk+dt@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev-bot+sashiko@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=robh@kernel.org \
    /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®