From: sashiko-bot@kernel.org
To: "Herman van Hazendonk" <github.com@herrie.org>
Cc: conor+dt@kernel.org, robh@kernel.org, devicetree@vger.kernel.org
Subject: Re: [PATCH v2 2/2] irqchip: add MSM8x60 MPM wakeup interrupt controller driver
Date: Sun, 31 May 2026 04:32:13 +0000 [thread overview]
Message-ID: <20260531043213.D18801F00893@smtp.kernel.org> (raw)
In-Reply-To: <0133fce127c7507bbb907d0258ad69ac8d753218.1780195817.git.github.com@herrie.org>
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [High] Unprotected read-modify-write operations on shared vMPM registers lead to lost configuration updates.
- [High] Calling mbox_send_message() from irqchip callbacks causes a sleeping-while-atomic deadlock on PREEMPT_RT.
- [High] Identity confusion between MPM pin numbers and parent GIC SPI numbers leads to allocation failures or dropped interrupts.
- [High] Toggling the hardware ENABLE bit inside irq_set_wake inadvertently disables unmasked interrupts upon resume.
- [High] Missing suppress_bind_attrs allows sysfs unbind, causing Use-After-Free via irq_domain_remove and concurrent probes.
- [Medium] Missing read-back flush after clearing MPM interrupt status using writel_relaxed.
- [Low] Phandle resolution ignores the actual target node, leading to incorrect device linking.
--
commit c09bf824269ef596633ac65838f83c2f22429764
Author: Herman van Hazendonk <github.com@herrie.org>
irqchip: add MSM8x60 MPM wakeup interrupt controller driver
Add a driver for the MSM Power Manager (MPM) on the MSM8x60 family
(MSM8260/MSM8660/APQ8060). The MPM latches edge-triggered interrupts
during APPS power collapse and signals the RPM to wake the APPS back up.
> diff --git a/drivers/irqchip/irq-msm8660-mpm.c b/drivers/irqchip/irq-msm8660-mpm.c
> new file mode 100644
> index 0000000000000..b8394d9c076d2
> --- /dev/null
> +++ b/drivers/irqchip/irq-msm8660-mpm.c
> @@ -0,0 +1,740 @@
[ ... ]
> +static void msm8660_mpm_doorbell(struct msm8660_mpm *mpm)
> +{
> + int ret;
> +
> + if (!mpm->mbox_chan)
> + return;
> +
> + ret = mbox_send_message(mpm->mbox_chan, NULL);
[Severity: High]
Does calling mbox_send_message() from within an irqchip callback cause a
sleeping-while-atomic deadlock on PREEMPT_RT?
The irq_mask, irq_unmask, and irq_set_type callbacks run with the
raw_spinlock_t irq_desc->lock held.
The mailbox core conditionally waits and takes chan->lock, which is a spinlock_t
that gets converted to a sleepable RT-mutex on PREEMPT_RT.
Deferring the mailbox communication using irq_bus_lock and irq_bus_sync_unlock
could avoid this deadlock.
[ ... ]
> +static irqreturn_t msm8660_mpm_irq(int irq, void *data)
> +{
[ ... ]
> + /*
> + * Clear before dispatching: a new edge latched on this pin
> + * after this point will set the pending bit again and we
> + * will service it on the next IPC IRQ. Clearing AFTER the
> + * handler would race with that new latch and silently lose
> + * the new edge.
> + */
> + if (pending[i])
> + msm8660_mpm_write(mpm,
> + MSM8660_MPM_REG_CLEAR + i * 4, pending[i]);
[Severity: Medium]
Can a delayed write in the CPU store buffer overwrite newly latched edges and
drop interrupts?
Using writel_relaxed does not flush the write over the interconnect. If a
child driver triggers a new edge on a peripheral during the handler, the MPM
hardware will latch it.
If the delayed REG_CLEAR write arrives afterward, it will incorrectly wipe out
the newly latched edge. Adding a dummy read from the MPM register space ensures
the write completes before executing the handler.
[ ... ]
> +static int msm8660_mpm_hwirq_to_pin(struct msm8660_mpm *mpm, unsigned int hwirq)
> +{
> + int i;
> +
> + for (i = 0; i < mpm->pin_map_count; i++) {
> + if (mpm->pin_map[i].hwirq == hwirq)
[Severity: High]
Is the GIC SPI number being confused with the MPM pin number here?
When msm8660_mpm_set_type calls msm8660_mpm_hwirq_to_pin(mpm, d->hwirq),
it searches for mpm->pin_map[i].hwirq == hwirq.
Because d->hwirq is the MPM pin and pin_map[i].hwirq is the GIC SPI, this lookup
will fail and return -1, causing set_type to return -ENOENT.
> + return mpm->pin_map[i].pin;
> + }
> + return -1;
> +}
> +
> +static void msm8660_mpm_enable_hwirq(struct irq_data *d, bool enable)
> +{
> + struct msm8660_mpm *mpm = irq_data_get_irq_chip_data(d);
> + int pin;
> + u32 val, mask;
> +
> + pin = msm8660_mpm_hwirq_to_pin(mpm, d->hwirq);
> + if (pin < 0)
> + return;
> +
> + mask = BIT(pin % 32);
> + val = msm8660_mpm_read(mpm,
> + MSM8660_MPM_REG_ENABLE + (pin / 32) * 4);
[Severity: High]
Could this concurrent read-modify-write corrupt the shared register state?
The driver manipulates shared 32-bit registers (ENABLE, DETECT_CTL,
POLARITY) to configure individual pins.
Because the IRQ subsystem calls irq_mask and irq_unmask with the per-interrupt
irq_desc->lock held, concurrent mask/unmask operations on different interrupts
within the same bank will execute without mutual exclusion.
A driver-local raw_spinlock_t is needed to serialize these accesses.
> + if (enable)
> + val |= mask;
> + else
> + val &= ~mask;
> + msm8660_mpm_write(mpm,
> + MSM8660_MPM_REG_ENABLE + (pin / 32) * 4, val);
> +
> + msm8660_mpm_doorbell(mpm);
[Severity: High]
Is it safe to invoke the doorbell from a context where a raw_spinlock_t
is held?
The irq_mask and irq_unmask callbacks execute with irq_desc->lock held.
Calling msm8660_mpm_doorbell() here will invoke mbox_send_message(), which
sleeps on PREEMPT_RT, causing a scheduling-while-atomic deadlock.
[ ... ]
> +static int msm8660_mpm_set_type(struct irq_data *d, unsigned int type)
> +{
> + struct msm8660_mpm *mpm = irq_data_get_irq_chip_data(d);
> + u32 detect, polarity, mask;
> + int pin;
> +
> + pin = msm8660_mpm_hwirq_to_pin(mpm, d->hwirq);
> + if (pin < 0)
> + return -ENOENT;
> +
> + mask = BIT(pin % 32);
> + detect = msm8660_mpm_read(mpm,
> + MSM8660_MPM_REG_DETECT_CTL + (pin / 32) * 4);
[Severity: High]
Does this unlocked read-modify-write of the DETECT_CTL and POLARITY registers
race with other set_type calls?
Similar to the ENABLE register, these are shared across multiple pins and
need mutual exclusion to prevent lost configuration updates.
[ ... ]
> +static int msm8660_mpm_set_wake(struct irq_data *d, unsigned int on)
> +{
> + struct msm8660_mpm *mpm = irq_data_get_irq_chip_data(d);
> + int pin;
> +
> + pin = msm8660_mpm_hwirq_to_pin(mpm, d->hwirq);
> + if (pin < 0)
> + return -ENOENT;
> +
> + msm8660_mpm_enable_hwirq(d, !!on);
[Severity: High]
Will toggling the hardware ENABLE bit here cause the interrupt to remain
permanently disabled after the first system resume?
When the system suspends, IRQCHIP_MASK_ON_SUSPEND ensures non-wake
interrupts are logically masked. During resume, device drivers call
irq_set_wake(..., 0) to disable wakeup.
Since this writes 0 to the hardware ENABLE bit, but the IRQ core assumes
the interrupt is still logically unmasked, it will not call irq_unmask()
and the hardware state will remain disabled.
[ ... ]
> +static int msm8660_mpm_domain_alloc(struct irq_domain *domain,
> + unsigned int virq, unsigned int nr_irqs,
> + void *data)
> +{
[ ... ]
> + parent_fwspec.fwnode = domain->parent->fwnode;
> + parent_fwspec.param_count = 3;
> + parent_fwspec.param[0] = 0;
> + parent_fwspec.param[1] = hwirq;
[Severity: High]
Does passing the MPM pin number directly to the parent GIC domain map the
wrong interrupt?
The parent GIC domain expects a GIC SPI number in param[1], not the MPM pin
number extracted from fwspec->param[0]. The correct mapped SPI should be
looked up and passed here instead.
[ ... ]
> +struct msm8660_mpm *msm8660_mpm_get(struct device *consumer,
> + struct device_node *np,
> + const char *propname)
> +{
> + struct device_node *mpm_np;
> + struct device_link *link;
> +
> + if (!msm8660_mpm_global)
> + return ERR_PTR(-EPROBE_DEFER);
> +
> + if (np && propname) {
> + mpm_np = of_parse_phandle(np, propname, 0);
> + if (!mpm_np)
> + return ERR_PTR(-ENOENT);
> + of_node_put(mpm_np);
[Severity: Low]
Should this function verify that the resolved mpm_np actually matches
msm8660_mpm_global->dev->of_node?
If a consumer's DT property points to a completely different node by mistake,
it appears this code will still drop the reference and successfully return
the global MPM handle anyway.
> + }
> +
> + if (!consumer)
> + return msm8660_mpm_global;
> +
> + link = device_link_add(consumer, msm8660_mpm_global->dev,
> + DL_FLAG_AUTOREMOVE_CONSUMER);
[Severity: High]
Can msm8660_mpm_global->dev be dereferenced safely here without a lock?
If this races with a sysfs unbind of the MPM driver, msm8660_mpm_global
could be set to NULL or freed, leading to a use-after-free.
[ ... ]
> +int msm8660_mpm_enable_pin(struct msm8660_mpm *mpm, unsigned int pin,
> + bool enable)
> +{
> + u32 val;
> +
> + if (!mpm || pin >= MSM8660_MPM_PIN_COUNT)
> + return -EINVAL;
> +
> + val = msm8660_mpm_read(mpm,
> + MSM8660_MPM_REG_ENABLE + (pin / 32) * 4);
[Severity: High]
Does this raw-pin consumer API modify the ENABLE register without locking?
Concurrent calls from different consumer drivers could overwrite each other's
enable states without mutual exclusion.
[ ... ]
> +static void msm8660_mpm_remove(struct platform_device *pdev)
> +{
> + struct msm8660_mpm *mpm = platform_get_drvdata(pdev);
> +
> + /*
> + * Tear down in strict reverse order: drop the singleton so new
> + * consumers cannot grab a handle, free the IRQ so the handler
> + * cannot fire again, free the mailbox channel, then remove the
> + * domain. Consumer device_links established in msm8660_mpm_get()
> + * prevent the parent device from being unbound while a consumer
> + * still holds a handle.
> + */
> + msm8660_mpm_global = NULL;
> + free_irq(mpm->parent_irq, mpm);
> + if (mpm->mbox_chan)
> + mbox_free_channel(mpm->mbox_chan);
> + irq_domain_remove(mpm->domain);
[Severity: High]
Does allowing sysfs unbind lead to a use-after-free in the core IRQ subsystem?
While consumer drivers are unbound due to the device_link, their virtual IRQ
mappings persist in the core IRQ subsystem because they do not automatically
call irq_dispose_mapping().
Removing the domain here frees the domain memory, but the core IRQ subsystem
retains dangling pointers to it in irq_data structures.
> +}
[ ... ]
> +static struct platform_driver msm8660_mpm_driver = {
> + .probe = msm8660_mpm_probe,
> + .remove = msm8660_mpm_remove,
> + .driver = {
> + .name = "msm8660-mpm",
[Severity: High]
Should this driver set .suppress_bind_attrs = true?
Without it, the driver can be unbound via sysfs, which triggers the
irq_domain_remove() use-after-free issue described above.
> + .of_match_table = msm8660_mpm_of_match,
> + },
> +};
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1780195817.git.github.com@herrie.org?part=2
next prev parent reply other threads:[~2026-05-31 4:32 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-30 13:59 [PATCH 0/3] clk: qcom: add MSM8x60 Multimedia Clock Controller Herman van Hazendonk
2026-05-30 13:59 ` Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 0/2] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 0/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-30 13:59 ` [PATCH 0/2] clk: qcom: add MSM8x60 LPASS Clock Controller Herman van Hazendonk
2026-05-30 13:58 ` [PATCH 1/3] dt-bindings: clock: qcom: add mmcc-msm8660 clock IDs Herman van Hazendonk
2026-05-31 15:39 ` Dmitry Baryshkov
2026-05-30 13:58 ` [PATCH 2/3] dt-bindings: reset: qcom: add mmcc-msm8660 reset IDs Herman van Hazendonk
2026-05-30 13:58 ` [PATCH 3/3] clk: qcom: add MSM8x60 MMCC driver Herman van Hazendonk
2026-05-30 13:59 ` [PATCH 1/2] dt-bindings: clock: qcom: add lcc-msm8660 LPASS clock IDs Herman van Hazendonk
2026-05-30 14:15 ` sashiko-bot
2026-05-30 13:59 ` [PATCH 2/2] clk: qcom: add MSM8x60 LCC (LPASS) driver Herman van Hazendonk
2026-05-30 14:25 ` sashiko-bot
2026-05-31 15:46 ` Dmitry Baryshkov
2026-05-30 14:00 ` [PATCH 1/2] dt-bindings: interconnect: qcom: add msm8660 fabric IDs Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 2/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-30 14:14 ` sashiko-bot
2026-05-30 14:00 ` [PATCH 1/2] dt-bindings: interrupt-controller: qcom: add msm8660-mpm Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 2/2] irqchip: add MSM8x60 MPM wakeup interrupt controller driver Herman van Hazendonk
2026-05-30 14:22 ` sashiko-bot
2026-05-30 14:00 ` [PATCH 1/2] dt-bindings: thermal: qcom: add pm8901-temp-alarm Herman van Hazendonk
2026-05-30 14:08 ` sashiko-bot
2026-05-30 20:48 ` Rob Herring (Arm)
2026-05-30 14:00 ` [PATCH 2/2] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-05-30 14:16 ` sashiko-bot
2026-05-31 4:08 ` [PATCH v2 0/3] clk: qcom: add MSM8x60 LPASS Clock Controller Herman van Hazendonk
2026-05-31 4:09 ` [PATCH v2 1/3] dt-bindings: clock: qcom,lcc: add MSM8x60 family compatibles Herman van Hazendonk
2026-05-31 4:14 ` sashiko-bot
2026-05-31 7:58 ` Krzysztof Kozlowski
2026-05-31 4:09 ` [PATCH v2 2/3] dt-bindings: clock: qcom: add lcc-msm8660 LPASS clock IDs Herman van Hazendonk
2026-05-31 4:23 ` sashiko-bot
2026-05-31 4:09 ` [PATCH v2 3/3] clk: qcom: add MSM8x60 LCC (LPASS) driver Herman van Hazendonk
2026-05-31 4:33 ` sashiko-bot
2026-05-31 4:09 ` [PATCH v2 0/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-31 4:09 ` Herman van Hazendonk
2026-05-31 4:09 ` [PATCH v2 0/3] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-05-31 4:09 ` [PATCH v2 1/2] dt-bindings: interconnect: qcom: add msm8660 fabric IDs Herman van Hazendonk
2026-05-31 8:00 ` Krzysztof Kozlowski
2026-05-31 4:09 ` [PATCH v2 2/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-31 4:34 ` sashiko-bot
2026-05-31 4:09 ` [PATCH v2 1/3] dt-bindings: mfd: qcom-pm8xxx: allow temp-alarm subnode Herman van Hazendonk
2026-05-31 7:59 ` Krzysztof Kozlowski
2026-05-31 4:09 ` [PATCH v2 2/3] dt-bindings: thermal: qcom: add pm8901-temp-alarm Herman van Hazendonk
2026-05-31 4:09 ` [PATCH v2 3/3] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-05-31 4:41 ` sashiko-bot
2026-05-31 4:09 ` [PATCH v2 0/2] irqchip: add MSM8x60 MPM wakeup interrupt controller Herman van Hazendonk
2026-05-31 4:09 ` [PATCH v2 1/2] dt-bindings: interrupt-controller: qcom: add msm8660-mpm Herman van Hazendonk
2026-05-31 4:20 ` sashiko-bot
2026-05-31 8:01 ` Krzysztof Kozlowski
2026-05-31 4:09 ` [PATCH v2 2/2] irqchip: add MSM8x60 MPM wakeup interrupt controller driver Herman van Hazendonk
2026-05-31 4:32 ` sashiko-bot [this message]
2026-06-01 7:25 ` Sebastian Andrzej Siewior
2026-06-03 15:12 ` Thomas Gleixner
2026-05-31 15:36 ` [PATCH 0/2] clk: qcom: add MSM8x60 LPASS Clock Controller Dmitry Baryshkov
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=20260531043213.D18801F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=github.com@herrie.org \
--cc=robh@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.