All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Chunfeng Yun" <chunfeng.yun@mediatek.com>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH v2 4/7] thunderbolt: add platform NHI driver
Date: Tue, 10 Nov 2026 12:15:37 +0000	[thread overview]
Message-ID: <sashiko-outbox-206992@kernel.org> (raw)
In-Reply-To: <20261110114925.722014-5-chunfeng.yun@mediatek.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] thunderbolt: broken system PM when sharing tb_nhi_pm_ops on
  platform_driver
- [Medium] thunderbolt: missing cleanup in nhi_platform_init_irq() and
  tb_nhi_probe()
--

commit 185e80648753aea8ed254f3effc097c624617d73
Author: Chunfeng Yun <chunfeng.yun@mediatek.com>

thunderbolt: add platform NHI driver

This commit adds a platform driver for Thunderbolt/USB4 Native Host Interface
(NHI) controllers integrated as memory-mapped platform devices via Device Tree
or ACPI, including support for an optional dedicated wakeup interrupt.

> diff --git a/drivers/thunderbolt/platform.c b/drivers/thunderbolt/platform.c
> new file mode 100644
> index 0000000000000..3562b6c7ea7db
> --- /dev/null
> +++ b/drivers/thunderbolt/platform.c
> @@ -0,0 +1,172 @@
[ ... ]
> +static int nhi_platform_init(struct tb_nhi *nhi)
> +{
> +	/* avoid device link fail for pcie tunnel */
> +	pm_runtime_set_active(nhi->dev);
> +	pm_runtime_get_noresume(nhi->dev);
> +	pm_runtime_enable(nhi->dev);
> +
> +	device_set_wakeup_capable(nhi->dev, true);
> +	device_enable_async_suspend(nhi->dev);
> +
> +	return 0;
> +}
> +
> +static void nhi_platform_clear_wake_irq(void *dev)
> +{
> +	dev_pm_clear_wake_irq(dev);
> +}
> +
> +static int nhi_platform_init_irq(struct tb_nhi *nhi)
> +{
> +	struct device *dev = nhi->dev;
> +	int ret;
> +
> +	ret = devm_request_irq(dev, nhi->irq, tb_nhi_isr, IRQF_NO_SUSPEND,
> +			       dev_name(dev), nhi);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "request irq failed\n");
> +
> +	if (nhi->wake_irq) {
> +		ret = dev_pm_set_dedicated_wake_irq(dev, nhi->wake_irq);
> +		if (ret) {
> +			return dev_err_probe(dev, ret, "set wake irq %d failed\n", nhi->wake_irq);
> +		}
> +
> +		dev_info(dev, "wake irq %d\n", nhi->wake_irq);
> +
> +		ret = devm_add_action_or_reset(dev, nhi_platform_clear_wake_irq, dev);
> +	}
> +
> +	return ret;
> +}
> +
> +static void nhi_platform_exit(struct tb_nhi *nhi)
> +{
> +	devm_free_irq(nhi->dev, nhi->irq, nhi);
> +	flush_work(&nhi->interrupt_work);
> +
> +	pm_runtime_put_noidle(nhi->dev);
> +	pm_runtime_disable(nhi->dev);
> +	pm_runtime_set_suspended(nhi->dev);
> +}

[Severity: Medium]
Does a probe failure before tb_domain_add() bypass nhi_platform_exit(),
leaving nhi->interrupt_work unflushed and runtime PM enabled on the unbound
device?

In tb_nhi_probe(), tb_nhi_shutdown() is only called if tb_domain_add() fails:

drivers/thunderbolt/nhi.c:tb_nhi_probe() {
	...
	res = nhi->ops->init_interrupts(nhi);
	if (res)
		return dev_err_probe(dev, res, "cannot enable interrupts, aborting\n");

	spin_lock_init(&nhi->lock);

	res = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
	if (res)
		return dev_err_probe(dev, res, "failed to set DMA mask\n");

	if (nhi->ops->init) {
		res = nhi->ops->init(nhi);
		if (res)
			return dev_err_probe(dev, res, "NHI specific init failed\n");
	}

	init_completion(&nhi->domain_released);

	tb = nhi_select_cm(nhi);
	if (!tb)
		return dev_err_probe(dev, -ENODEV,
			"failed to determine connection manager, aborting\n");
	...
}

If dev_pm_set_dedicated_wake_irq() fails in nhi_platform_init_irq(), or if
dma_set_mask_and_coherent() or nhi_select_cm() fails in tb_nhi_probe(),
devres frees nhi->irq, unmaps nhi->iobase, and frees nhi without ever
flushing nhi->interrupt_work, which can cause a use-after-free if
tb_nhi_isr() scheduled the work item.  In addition, if nhi_select_cm() fails
after nhi_platform_init() has run, runtime PM stays enabled with an elevated
usage count, so pm_runtime_reinit() in device_unbind_cleanup() bails out and
a subsequent re-probe warns on unbalanced pm_runtime_enable().

[ ... ]

> +static struct platform_driver nhi_platform_driver = {
> +	.probe = nhi_platform_probe,
> +	.remove = nhi_platform_remove,
> +	.shutdown = nhi_platform_shutdown,
> +	.driver = {
> +		.name = "thunderbolt",
> +		.of_match_table = of_match_ptr(nhi_platform_of_match),
> +		.acpi_match_table = ACPI_PTR(nhi_platform_acpi_match),
> +		.pm = &tb_nhi_pm_ops,
> +	},
> +};

[Severity: High]
Can system suspend and resume run while the platform NHI is runtime-suspended
when using tb_nhi_pm_ops directly on a platform_driver?

On PCI, pci_pm_suspend() runtime-resumes the device before calling the
driver's .suspend and .suspend_noirq callbacks.  Neither the platform bus,
genpd, nor nhi_suspend() does that, and device_wakeup_enable() prevents
direct_complete.  If the controller has autosuspended before system suspend:

1. nhi_suspend_noirq() -> tb_domain_suspend_noirq() runs while the device is
   runtime-suspended (with clocks or power domains gated) and calls
   tb_ctl_stop() on rings already stopped by nhi_runtime_suspend(), triggering
   dev_WARN() in tb_ring_stop().
2. On resume, nhi_resume_noirq() -> tb_domain_resume_noirq() calls
   tb_ctl_start(), touching MMIO while runtime status is still RPM_SUSPENDED
   and queuing ctl->rx_packets[] onto ctl->rx->in_flight.
3. In the complete phase, nhi_complete() sees pm_runtime_suspended(dev) is
    still true and calls pm_runtime_resume(dev) -> nhi_runtime_resume() ->
   tb_ctl_start() a second time:

drivers/thunderbolt/nhi.c:nhi_complete() {
	struct tb *tb = dev_get_drvdata(dev);

	/*
	 * If we were runtime suspended when system suspend started,
	 * schedule runtime resume now. It should bring the domain back
	 * to functional state.
	 */
	if (pm_runtime_suspended(dev))
		pm_runtime_resume(dev);
	else
		tb_domain_complete(tb);
}

The second tb_ctl_start() warns that the rings are already started and calls
tb_ctl_rx_submit() -> __tb_ring_enqueue() -> list_add_tail() on
ctl->rx_packets[] frames that are already linked in ctl->rx->in_flight,
corrupting the ring list.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261110114925.722014-2-chunfeng.yun@mediatek.com?part=4

  reply	other threads:[~2026-11-10 12:15 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 11:48 [PATCH 0/7] thunderbolt: Add support platform NHI driver Chunfeng Yun
2026-11-10 11:48 ` [PATCH v2 1/7] thunderbolt: Prefix NHI core functions with tb_ and tb_ring_ Chunfeng Yun
2026-11-10 11:53   ` sashiko-bot
2026-11-10 12:42   ` Konrad Dybcio
2026-11-11  2:26     ` Chunfeng Yun (云春峰)
2026-11-10 11:48 ` [PATCH v2 2/7] thunderbolt: Move ICM mailbox functions to icm.c and internalize interrupt work Chunfeng Yun
2026-11-10 12:02   ` sashiko-bot
2026-11-10 14:24   ` Mika Westerberg
2026-11-11  2:37     ` Chunfeng Yun (云春峰)
2026-11-10 11:48 ` [PATCH v2 3/7] thunderbolt: Make PCIe NHI support opt-in Chunfeng Yun
2026-11-10 12:09   ` sashiko-bot
2026-11-11 12:17     ` Chunfeng Yun (云春峰)
2026-11-10 11:48 ` [PATCH v2 4/7] thunderbolt: add platform NHI driver Chunfeng Yun
2026-11-10 12:15   ` sashiko-bot [this message]
2026-11-10 12:43   ` Konrad Dybcio
2026-11-11 13:29     ` Chunfeng Yun (云春峰)
2026-11-10 14:37   ` Mika Westerberg
2026-11-10 11:48 ` [PATCH v2 5/7] thunderbolt: increase the lane adapter link-up timeout value Chunfeng Yun
2026-11-10 11:55   ` sashiko-bot
2026-11-12  7:27     ` Chunfeng Yun (云春峰)
2026-11-10 14:39   ` Mika Westerberg
2026-11-12  7:24     ` Chunfeng Yun (云春峰)
2026-11-10 11:48 ` [PATCH v2 6/7] thunderbolt: decouple the waiting time of TB_PORT_UNPLUGGED and TB_PORT_UP Chunfeng Yun
2026-11-10 11:55   ` sashiko-bot
2026-11-10 14:40   ` Mika Westerberg
2026-11-12  8:00     ` Chunfeng Yun (云春峰)
2026-11-10 11:48 ` [PATCH v2 7/7] thunderbolt: prevent pcie tunnel activation/teardown warnings Chunfeng Yun
2026-11-10 12:01   ` sashiko-bot
2026-11-10 14:50   ` Mika Westerberg

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=sashiko-outbox-206992@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=chunfeng.yun@mediatek.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.