From: netdev-bot+sashiko@kernel.org
To: f@lex.la
Cc: netdev@vger.kernel.org, chester.a.unal@arinc9.com,
daniel@makrotopia.org, andrew@lunn.ch, olteanv@gmail.com,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, matthias.bgg@gmail.com,
angelogioacchino.delregno@collabora.com,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org
Subject: Re: [PATCH net 2/2] net: dsa: mt7530: unregister the switch before freeing its MDIO IRQs
Date: Thu, 17 Sep 2026 08:25:57 +0000 [thread overview]
Message-ID: <178963355760.22033.11986863924471016494@kernel.org> (raw)
In-Reply-To: <20260914202421.2737079-3-f@lex.la>
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 1 · Medium: 0 (1) · Low: 0
- [High] Incomplete fix: mt7530_remove_common()
(drivers/net/dsa/mt7530.c:3593-3602) still calls…
Pre-existing issues:
- [Medium] Power-sequencing ordering on the MDIO front end:
mt7530_remove() in drivers/net/dsa/mt7530-mdio.c disables…
--
net: dsa: mt7530: unregister the switch before freeing its MDIO IRQs
This moves dsa_unregister_switch() ahead of the per-PHY interrupt
disposal in mt7530_remove_common(), so that phylib frees the nested PHY
interrupts before their mappings are destroyed. The reported symptom is a
remove_proc_entry() warning from irq_free_descs() followed by a NULL
dereference in handle_nested_irq().
> diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
> index 3e61eb3c2b1e2..90fd04665ebf1 100644
> --- a/drivers/net/dsa/mt7530.c
> +++ b/drivers/net/dsa/mt7530.c
> @@ -3593,11 +3593,11 @@ EXPORT_SYMBOL_GPL(mt7530_probe_common);
> void
> mt7530_remove_common(struct mt7530_priv *priv)
> {
> + dsa_unregister_switch(priv->ds);
> +
> if (priv->irq_domain)
> mt7530_free_mdio_irq(priv);
[Severity: High]
Does this reorder actually close the handle_nested_irq() fault described
in the changelog, or does it only close the phylib half of it?
The parent threaded interrupt is owned by devres. mt7530_setup_irq()
registers the chip with devm_regmap_add_irq_chip_fwnode() and keeps only
the domain pointer:
drivers/net/dsa/mt7530.c:mt7530_setup_irq() {
ret = devm_regmap_add_irq_chip_fwnode(dev, dev_fwnode(dev),
priv->regmap, irq,
IRQF_ONESHOT,
0, chip,
&irq_data);
...
priv->irq_domain = regmap_irq_get_domain(irq_data);
}
so free_irq() on the parent and irq_domain_remove() happen only from the
devres release, devm_regmap_irq_chip_release() -> regmap_del_irq_chip(),
which runs after mt7530_remove() has returned. Nothing in
mt7530_remove_common() disables, frees or synchronizes against that
parent IRQ, so the regmap-irq thread is still live while
mt7530_free_mdio_irq() destroys the mappings.
On the thread side there is no zero check on the lookup:
drivers/base/regmap/regmap-irq.c:regmap_irq_thread() {
...
data->status_buf[i] &= ~data->mask_buf[i];
...
handle_nested_irq(irq_find_mapping(data->domain, i));
}
mask_buf is read there without data->lock, so the thread can carry a
pre-mask snapshot past the filter. Can the following still happen with
this patch applied, on a part with a PHY_LC bit latched?
regmap_irq_thread() mt7530_remove_common()
read_irq_data(), PHY0_LC set
passes the mask_buf filter
dsa_unregister_switch()
phy_disconnect()
phy_free_interrupt()
free_irq(nested virq)
mt7530_free_mdio_irq()
irq_dispose_mapping()
irq_find_mapping() -> 0
handle_nested_irq(0)
kernel/irq/chip.c:handle_nested_irq() has no NULL check:
struct irq_desc *desc = irq_to_desc(irq);
...
scoped_guard(raw_spinlock_irq, &desc->lock) {
which is the read at handle_nested_irq+0xac quoted in the changelog.
Is the driver-side disposal loop needed at all? regmap_del_irq_chip()
already walks the domain and disposes every mapping, and it does so in
the safe order:
drivers/base/regmap/regmap-irq.c:regmap_del_irq_chip() {
free_irq(irq, d);
/* Dispose all virtual irq from irq domain before removing it */
...
}
Would dropping mt7530_free_mdio_irq() from the remove path (leaving the
disposal to regmap_del_irq_chip(), which runs after the parent IRQ is
freed) be a better fix than moving it after dsa_unregister_switch()?
> - dsa_unregister_switch(priv->ds);
> -
> mutex_destroy(&priv->reg_mutex);
> }
> EXPORT_SYMBOL_GPL(mt7530_remove_common);
[Severity: Medium]
This is a pre-existing ordering problem and not something this patch
introduces, but it interacts with the new placement of
dsa_unregister_switch(), so it may be worth mentioning.
On the MDIO front end the supplies are dropped before any of this runs:
drivers/net/dsa/mt7530-mdio.c:mt7530_remove() {
if (priv->id == ID_MT7530) {
ret = regulator_disable(priv->core_pwr);
...
ret = regulator_disable(priv->io_pwr);
...
}
mt7530_remove_common(priv);
}
After this patch the whole register-level teardown reached from
dsa_unregister_switch() - internal PHY power-down, port disable writes,
and the regmap-irq mask sync that clears the PHY_LC bits through
mt7530_irq_mask_sync() - is the first thing mt7530_remove_common() does,
i.e. entirely after core_pwr and io_pwr were released on ID_MT7530.
Can those writes still reach the chip? MDIO writes are unacknowledged,
and regmap-irq updates its mask_buf shadow regardless of what
handle_mask_sync() returns:
drivers/net/dsa/mt7530.c:mt7530_irq_mask_sync() {
ret = regmap_update_bits(priv->regmap, MT7530_SYS_INT_EN,
mask_buf_def, ~mask_buf);
...
}
so MT7530_SYS_INT_EN can be left armed and MT7530_SYS_INT_STS latched
while software believes they are masked. MT7530_TOP_SIG_CTRL's
TOP_SIG_CTRL_NORMAL bit, set in mt7530_setup_irq(), likewise has no
teardown counterpart. Should the regulator_disable() calls move after
mt7530_remove_common() instead?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260914202421.2737079-1-f%40lex.la
prev parent reply other threads:[~2026-09-17 8:26 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-14 20:24 [PATCH net 0/2] net: dsa: mt7530: fix two crashes on driver unbind Aleksei Sviridkin
2026-09-14 20:24 ` [PATCH net 1/2] net: dsa: mt7530: fix NULL dereference on unbind of MT7531 and MT7621 Aleksei Sviridkin
2026-09-14 20:24 ` [PATCH net 2/2] net: dsa: mt7530: unregister the switch before freeing its MDIO IRQs Aleksei Sviridkin
2026-09-17 8:25 ` netdev-bot+sashiko [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=178963355760.22033.11986863924471016494@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=andrew@lunn.ch \
--cc=angelogioacchino.delregno@collabora.com \
--cc=chester.a.unal@arinc9.com \
--cc=daniel@makrotopia.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=f@lex.la \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.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®