From: sashiko-bot@kernel.org
To: "Szuying Chen" <Chloe_Chen@asmedia.com.tw>, linux-gpio@vger.kernel.org
Subject: Re: [PATCH v2] gpio: amdptpci: add support for AMD PT PCI controller
Date: Tue, 13 Oct 2026 08:30:41 +0000 [thread overview]
Message-ID: <sashiko-outbox-169255@kernel.org> (raw)
In-Reply-To: <20261013081631.5841-1-Chloe_Chen@asmedia.com.tw>
Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
- [High] gpio: amdptpci: hardware access occurs after failed device resume
- [High] gpio: amdptpci: pending wakeup interrupts are destroyed during resume
- [High] pm: ISR accesses suspended MMIO due to irq_pm_held flag race
- [High] gpio: interrupt storm due to registering GPIO chip before parent IRQ
- [Medium] gpio: amdptpci: invalid bitmask writes to reserved bits during suspend
- [Medium] gpio: amdptpci: device can never runtime suspend if wake IRQ is configured
- [Medium] gpio: amdptpci: S3 wakeups broken if device autosuspends before system suspend
- [Low] gpio: amdptpci: missing pm_runtime_dont_use_autosuspend() on probe error path
--
commit 84767db1836e202d0ec481c787ac2cf3407a669a
Author: Szuying Chen <Chloe_Chen@asmedia.com.tw>
gpio: amdptpci: add support for AMD PT PCI controller
This commit implements the new gpio-amdptpci driver to support the
GPIO functionality on AMD PT PCI platforms.
> diff --git a/drivers/gpio/gpio-amdptpci.c b/drivers/gpio/gpio-amdptpci.c
> new file mode 100644
> index 0000000000000..c63e9b6dcf7ad
> --- /dev/null
> +++ b/drivers/gpio/gpio-amdptpci.c
[ ... ]
> +static void pt27_restore_regs(struct pt27_gpio *chip)
> +{
[ ... ]
> + pt27_wr16(chip, PT27_REG_WAKE_LVL, chip->saved.wake_lvl);
> + pt27_wr16(chip, PT27_REG_WAKE_MODE, chip->saved.wake_mode);
> + pt27_wr16(chip, PT27_REG_WAKE_EN, chip->saved.wake_en);
> +
> + pt27_wr32(chip, PT27_REG_INT_STAT, PT27_GPIO_MASK);
> + pt27_wr16(chip, PT27_REG_WAKE_STAT, PT27_WAKE_MASK);
[Severity: High]
Does writing the mask to the status register here clear all pending interrupts
unconditionally before the ISR can service them?
When the system wakes up due to a GPIO event, the hardware logs the event in
the status register. If pt27_restore_regs() clears them assuming W1C
semantics, won't the core IRQ handler read 0 pending interrupts and return
IRQ_NONE, permanently losing the wakeup interrupt?
> +
> + pt27_wr32(chip, PT27_REG_INT_EN, chip->saved.int_en);
> + pt27_wr32(chip, PT27_REG_INT_MASK, chip->saved.int_mask);
> +
> +}
[ ... ]
> +static bool pt27_irq_regs_accessible(struct pt27_gpio *chip)
> +{
> +
> + return READ_ONCE(chip->irq_bus_active) ||
> + READ_ONCE(chip->irq_pm_held);
> +}
[Severity: High]
Will this OR condition cause the device to be accessed even if it failed to
resume?
In pt27_irq_bus_lock() below, a failed resume sets chip->irq_bus_active to
false, but chip->irq_pm_held is already set to true by
pt27_irq_request_resources(). This means pt27_irq_regs_accessible() will
evaluate to true, and subsequent IRQ operations will attempt to write to MMIO
registers of a powered-down device.
[ ... ]
> +static int pt27_irq_request_resources(struct irq_data *d)
> +{
[ ... ]
> + raw_spin_lock_irqsave(&chip->lock, flags);
> + chip->requested_irq_mask |= BIT(hwirq);
> + if (!chip->irq_pm_held) {
> + chip->irq_pm_held = true;
> +
> + pm_runtime_get_noresume(chip->dev);
> + }
> + raw_spin_unlock_irqrestore(&chip->lock, flags);
[Severity: High]
Is there a race condition here where the ISR might access suspended MMIO
hardware?
This sets chip->irq_pm_held to true and calls pm_runtime_get_noresume(),
which only increments the usage counter but does not wake the device from D3.
The device is not actually woken until pt27_irq_bus_lock() runs.
If a shared PCI INTx interrupt fires in this window, the ISR pt27_gpio_isr()
will see chip->irq_pm_held is true and bypass its suspend safeguard, leading
to an invalid MMIO read. Should this use pm_runtime_get_if_active() instead?
[ ... ]
> +static void pt27_irq_bus_lock(struct irq_data *d)
> +{
> + struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> + struct pt27_gpio *chip = gpiochip_get_data(gc);
> + int ret;
> +
> + mutex_lock(&chip->irq_bus_lock);
> +
> + ret = pm_runtime_resume_and_get(chip->dev);
> + if (ret < 0) {
> + WRITE_ONCE(chip->irq_bus_active, false);
> + dev_err_ratelimited(chip->dev,
> + "%s: cannot resume for IRQ configuration: %d\n",
> + __func__, ret);
> + return;
> + }
[Severity: High]
If pm_runtime_resume_and_get() fails here, it correctly records that the bus
is inactive. Since the core IRQ operation is not aborted, and the static flag
forces pt27_irq_regs_accessible() to evaluate to true, will the outer IRQ
code proceed to interact with the device despite this failure?
[ ... ]
> +static irqreturn_t pt27_gpio_isr(int irq, void *data)
> +{
> + struct pt27_gpio *chip = data;
> + unsigned long pending;
> + unsigned long flags;
> +
> + raw_spin_lock_irqsave(&chip->lock, flags);
> + /*
> + * No requested IRQ means nothing to dispatch, and the device may be
> + * runtime-suspended (D3): a shared INTx line can still call us, so do
> + * not touch MMIO unless the PM hold keeps the device in D0.
> + */
> + if (!chip->irq_pm_held) {
> + raw_spin_unlock_irqrestore(&chip->lock, flags);
> + return IRQ_NONE;
> + }
> + pending = pt27_pending_irqs_locked(chip);
[Severity: High]
Could this ISR bypass its suspend safeguard based on the static flag race
discussed earlier? If the hardware is suspended but the flag evaluates to
true, could this lead to a bus error or spurious interrupt?
[ ... ]
> +static int pt27_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +{
[ ... ]
> + ret = devm_gpiochip_add_data(dev, &chip->gc, chip);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to register GPIO chip\n");
> +
> + ret = devm_request_irq(dev, chip->irq, pt27_gpio_isr, irq_flags | IRQF_NO_THREAD, dev_name(dev), chip);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to request IRQ %d\n", chip->irq);
[Severity: High]
Can this initialization sequence lead to an unhandled interrupt storm?
By calling devm_gpiochip_add_data() before devm_request_irq(), the GPIO chip
is exposed to consumers before its parent ISR is registered. If a consumer
immediately requests and unmasks a GPIO IRQ, the hardware will assert the
shared PCI IRQ line, but pt27_gpio_isr() will not yet be registered to handle
it.
Reversing the order is safe because if a spurious shared interrupt occurs
before the domain is initialized, chip->irq_pm_held will be false, and the
ISR will safely return IRQ_NONE without dereferencing anything.
[Severity: Low]
If either of these registration steps fail, the probe function returns
directly. Does this leak the PM configuration by missing a call to
pm_runtime_dont_use_autosuspend(dev) to revert the PM state?
[ ... ]
> +static int __maybe_unused pt27_gpio_suspend(struct device *dev)
> +{
> + struct pt27_gpio *chip = dev_get_drvdata(dev);
> + unsigned long flags;
> + u32 int_mask;
> +
> + if (pm_runtime_status_suspended(dev)) {
> + dev_dbg(dev, "%s: already runtime-suspended, skipping save\n",
> + __func__);
> + return 0;
> + }
[Severity: Medium]
Will returning early here break S3 wakeups if the device autosuspends before
system suspend?
pt27_gpio_runtime_suspend() masks all interrupts, configuring no wake events.
By skipping the resume preparation when already suspended, this function
never unmasks wake-capable pins, completely breaking the controller's ability
to wake the system.
> +
> + raw_spin_lock_irqsave(&chip->lock, flags);
> + pt27_save_regs(chip);
> + pt27_wr32(chip, PT27_REG_INT_EN, 0);
> + int_mask = 0xFFFFFFFF & ~chip->wake_mask;
> + //int_mask = PT27_REG_INT_MASK & ~chip->wake_mask;
> + pt27_wr32(chip, PT27_REG_INT_MASK, int_mask);
[Severity: Medium]
Does this write invalid bitmasks to reserved hardware bits?
The controller supports 24 GPIOs (PT27_GPIO_MASK is 0x00FFFFFF). By using
0xFFFFFFFF, the bitwise NOT operation will write 1s to bits 24-31 of the
PT27_REG_INT_MASK register, which could trigger unintended hardware faults.
> + pt27_wr32(chip, PT27_REG_INT_STAT, PT27_GPIO_MASK);
> + pt27_wr16(chip, PT27_REG_WAKE_STAT, PT27_WAKE_MASK);
> + raw_spin_unlock_irqrestore(&chip->lock, flags);
> +
> + synchronize_irq(chip->irq);
> + return 0;
> +}
[ ... ]
> +static int __maybe_unused pt27_gpio_runtime_suspend(struct device *dev)
> +{
> + struct pt27_gpio *chip = dev_get_drvdata(dev);
> + unsigned long flags;
> + int ret = 0;
> +
> + raw_spin_lock_irqsave(&chip->lock, flags);
> +
> + if (chip->irq_pm_held || chip->requested_irq_mask) {
> + ret = -EBUSY;
> + goto out_unlock;
> + }
> +
> + if (chip->wake_mask && !device_may_wakeup(dev)) {
> + ret = -EBUSY;
> + goto out_unlock;
> + }
[Severity: Medium]
Does the first check unintentionally prevent the device from ever entering
runtime suspend when a wake IRQ is configured?
A wake IRQ is inherently a requested IRQ, meaning chip->requested_irq_mask
will always be non-zero if chip->wake_mask is non-zero. The first block will
therefore unconditionally abort the suspend with -EBUSY, making the
subsequent wake_mask check dead code and preventing the PCI device from
reaching D3.
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261013081631.5841-1-Chloe_Chen@asmedia.com.tw?part=1
next prev parent reply other threads:[~2026-10-13 8:30 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 8:16 [PATCH v2] gpio: amdptpci: add support for AMD PT PCI controller Szuying Chen
2026-10-13 8:30 ` sashiko-bot [this message]
-- strict thread matches above, loose matches on Subject: below --
2026-10-13 7:43 Szuying Chen
2026-10-13 7:56 ` sashiko-bot
2026-10-13 8:48 ` Markus Elfring
2026-10-13 23:30 ` Linus Walleij
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-169255@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=Chloe_Chen@asmedia.com.tw \
--cc=linux-gpio@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.