mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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

      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®