From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Jonathan Cameron <jonathan.cameron@huawei.com>,
Will Deacon <will@kernel.org>, Sasha Levin <sashal@kernel.org>,
mark.rutland@arm.com, clrkwllms@kernel.org, rostedt@goodmis.org,
linux-cxl@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-perf-users@vger.kernel.org, linux-rt-devel@lists.linux.dev
Subject: [PATCH AUTOSEL 6.19-6.6] perf/cxlpmu: Replace IRQF_ONESHOT with IRQF_NO_THREAD
Date: Wed, 11 Feb 2026 07:30:41 -0500 [thread overview]
Message-ID: <20260211123112.1330287-31-sashal@kernel.org> (raw)
In-Reply-To: <20260211123112.1330287-1-sashal@kernel.org>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
[ Upstream commit ab26d9c85554c4ff1d95ca8341522880ed9219d6 ]
Passing IRQF_ONESHOT ensures that the interrupt source is masked until
the secondary (threaded) handler is done. If only a primary handler is
used then the flag makes no sense because the interrupt can not fire
(again) while its handler is running.
The flag also disallows force-threading of the primary handler and the
irq-core will warn about this.
The intention here was probably not allowing forced-threading.
Replace IRQF_ONESHOT with IRQF_NO_THREAD.
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now I have gathered all the information I need for a thorough analysis.
Let me compile my findings.
---
## Complete Analysis: `perf/cxlpmu: Replace IRQF_ONESHOT with
IRQF_NO_THREAD`
### 1. COMMIT MESSAGE ANALYSIS
The commit, authored by Sebastian Andrzej Siewior
(bigeasy@linutronix.de) — one of the PREEMPT_RT core maintainers —
replaces `IRQF_ONESHOT` with `IRQF_NO_THREAD` in the CXL PMU driver's
interrupt registration. The commit message explains:
- `IRQF_ONESHOT` ensures the interrupt source is masked until the
threaded (secondary) handler finishes
- This driver only has a **primary** handler (`cxl_pmu_irq`) and no
threaded handler
- Therefore `IRQF_ONESHOT` makes no sense here — the interrupt can't
fire while its hardirq handler is running anyway
- The flag also **disables force-threading** of the primary handler
- The "irq-core will warn about this" (via lockdep assertions)
- The **intended** semantics were to prevent forced-threading, so
`IRQF_NO_THREAD` is the correct replacement
### 2. CODE CHANGE ANALYSIS
The change is a **single flag swap** on one line:
```880:881:drivers/perf/cxl_pmu.c
rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED |
IRQF_ONESHOT,
irq_name, info);
```
becomes:
```880:881:drivers/perf/cxl_pmu.c
rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED |
IRQF_NO_THREAD,
irq_name, info);
```
#### What `IRQF_ONESHOT` does here (incorrectly):
Looking at `irq_setup_forced_threading()` in `kernel/irq/manage.c`:
```1291:1296:kernel/irq/manage.c
static int irq_setup_forced_threading(struct irqaction *new)
{
if (!force_irqthreads())
return 0;
if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
return 0;
```
Both `IRQF_NO_THREAD` and `IRQF_ONESHOT` cause
`irq_setup_forced_threading()` to bail out early, preventing the
interrupt from being force-threaded. However, `IRQF_ONESHOT` has an
**additional side effect**: it tells the IRQ core to mask the interrupt
line until a threaded handler completes. Since there is no threaded
handler here, this masking behavior is semantically wrong.
#### Why `IRQF_NO_THREAD` is the correct flag:
The `cxl_pmu_irq` handler is a PMU overflow interrupt handler that:
1. Reads the overflow register via `readq()`
2. Processes each overflowed counter via `__cxl_pmu_read()`
3. Clears the overflow status via `writeq()`
This handler interacts with perf core internals. As the arm-ccn PMU fix
(commit `0811ef7e2f54`) established, **PMU interrupt handlers must not
be force-threaded** because the perf core relies on strict CPU affinity
and interrupt disabling for mutual exclusion. Force-threading a PMU
interrupt handler would break these synchronization guarantees.
#### The actual bugs:
**Bug 1 — PREEMPT_RT / `threadirqs` warning:** When the kernel is booted
with `threadirqs` command-line parameter or PREEMPT_RT is enabled, the
IRQ core's lockdep infrastructure marks handlers as `hardirq_threaded`
if they can be force-threaded. In `kernel/irq/handle.c`:
```199:201:kernel/irq/handle.c
if (irq_settings_can_thread(desc) &&
!(action->flags & (IRQF_NO_THREAD | IRQF_PERCPU |
IRQF_ONESHOT)))
lockdep_hardirq_threaded();
```
Because `IRQF_ONESHOT` is already set, this particular path won't
trigger the threaded annotation, but the **masking semantics** of
ONESHOT are incorrect for a primary-only handler. In the `IRQF_ONESHOT`
path, the IRQ core does:
```1726:1727:kernel/irq/manage.c
if (new->flags & IRQF_ONESHOT)
desc->istate |= IRQS_ONESHOT;
```
This causes the interrupt line to be masked during the handler and
unmask logic depends on `desc->threads_oneshot` — but there's no thread
to clear this mask, so it depends on the
`cond_unmask_irq`/`cond_unmask_eoi_irq` fallback path.
**Bug 2 — IRQF_SHARED conflict potential:** The interrupt uses
`IRQF_SHARED`. When sharing interrupts, all handlers on the same line
must agree on `IRQF_ONESHOT`. If another driver on the shared line
doesn't use `IRQF_ONESHOT`, `request_threaded_irq()` will fail with
`-EINVAL` at the mismatch check:
```1606:1607:kernel/irq/manage.c
else if ((old->flags ^ new->flags) & IRQF_ONESHOT)
goto mismatch;
```
This is a real failure mode for shared interrupts — CXL PMU's incorrect
use of `IRQF_ONESHOT` could prevent other handlers from sharing the same
IRQ line.
### 3. CLASSIFICATION
This is a **bug fix** — it corrects incorrect IRQ flag usage that:
1. Applies semantically wrong masking behavior (ONESHOT without a
thread)
2. Can trigger warnings/assertions under PREEMPT_RT or `threadirqs`
3. Could cause shared IRQ registration failures
4. Prevents force-threading in the wrong way (the intention is correct,
but the mechanism is wrong)
### 4. SCOPE AND RISK ASSESSMENT
- **Lines changed:** 1 line (single flag change)
- **Files touched:** 1 (`drivers/perf/cxl_pmu.c`)
- **Complexity:** Minimal — straightforward flag replacement
- **Risk:** Extremely low. `IRQF_NO_THREAD` is the semantically correct
flag for the intended purpose. The interrupt handler is a hardirq-only
handler that performs only register I/O and atomic operations — it
should never be threaded.
- **Subsystem:** CXL PMU performance monitoring driver (PCI-based)
### 5. USER IMPACT
- **PREEMPT_RT users:** On PREEMPT_RT kernels, `IRQF_ONESHOT` without a
thread handler causes the interrupt line to be masked with incorrect
oneshot semantics. This could lead to lockdep warnings or subtle
interrupt masking issues.
- **Shared IRQ users:** CXL devices sharing PCI MSI/MSI-X vectors with
other devices could experience IRQ registration failures due to
ONESHOT flag mismatch.
- **General users:** The CXL PMU driver is used for performance
monitoring on CXL 3.0 memory devices — an increasingly important
hardware platform for servers and data centers.
### 6. STABILITY INDICATORS
- **Author:** Sebastian Andrzej Siewior — PREEMPT_RT core maintainer,
expert on IRQ threading
- **Reviewer:** Jonathan Cameron — CXL maintainer
- **Signed-off-by:** Will Deacon — ARM architecture and perf subsystem
maintainer
- **Pattern:** This is the same fix Sebastian has applied to multiple
drivers (i2c-exynos5, i2c-hix5hd2) with proven track record
- **Precedent:** The arm-ccn PMU used exactly this fix
(`IRQF_NO_THREAD`) for the same class of issue
### 7. DEPENDENCY CHECK
- No dependencies on other commits
- The driver exists in stable kernels 6.6.y and later (introduced in
v6.5-rc1)
- The change is self-contained — just a flag change in
`devm_request_irq()`
### 8. CONCLUSION
This is a small, surgical, well-understood bug fix that corrects
incorrect IRQ flag usage in the CXL PMU driver. The `IRQF_ONESHOT` flag
was semantically wrong for a primary-only interrupt handler and could
cause:
- Incorrect interrupt line masking behavior
- Shared IRQ registration failures
- Issues on PREEMPT_RT kernels
The replacement with `IRQF_NO_THREAD` correctly expresses the intended
behavior (prevent force-threading of this PMU interrupt handler) without
the incorrect side effects. The fix is trivial, low-risk, authored by a
world-class IRQ threading expert, and reviewed by CXL and ARM
maintainers.
**YES**
drivers/perf/cxl_pmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
index d094030220bf2..68a54d97d2a8a 100644
--- a/drivers/perf/cxl_pmu.c
+++ b/drivers/perf/cxl_pmu.c
@@ -877,7 +877,7 @@ static int cxl_pmu_probe(struct device *dev)
if (!irq_name)
return -ENOMEM;
- rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_ONESHOT,
+ rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_NO_THREAD,
irq_name, info);
if (rc)
return rc;
--
2.51.0
next prev parent reply other threads:[~2026-02-11 12:32 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-11 12:30 [PATCH AUTOSEL 6.19-5.10] s390/perf: Disable register readout on sampling events Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] arm64: Add support for TSV110 Spectre-BHB mitigation Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] xenbus: Use .freeze/.thaw to handle xenbus devices Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] s390/purgatory: Add -Wno-default-const-init-unsafe to KBUILD_CFLAGS Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.18] s390/boot: " Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.1] perf/arm-cmn: Support CMN-600AE Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.18] ntfs: ->d_compare() must not block Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.12] ACPI: x86: s2idle: Invoke Microsoft _DSM Function 9 (Turn On Display) Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.12] block: decouple secure erase size limit from discard size limit Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] sparc: don't reference obsolete termio struct for TC* constants Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] EFI/CPER: don't go past the ARM processor CPER record buffer Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19] ACPI: scan: Use async schedule function in acpi_scan_clear_dep_fn() Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.6] cpufreq: dt-platdev: Block the driver from probing on more QC platforms Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] EFI/CPER: don't dump the entire memory region Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.12] ACPI: battery: fix incorrect charging status when current is zero Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.18] rust: cpufreq: always inline functions using build_assert with arguments Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.18] blk-mq-sched: unify elevators checking for async requests Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] x86/xen/pvh: Enable PAE mode for 32-bit guest only when CONFIG_X86_PAE is set Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.12] APEI/GHES: ARM processor Error: don't go past allocated memory Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.18] md raid: fix hang when stopping arrays with metadata through dm-raid Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] tools/power cpupower: Reset errno before strtoull() Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] sparc: Synchronize user stack on fork and clone Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] blk-mq-debugfs: add missing debugfs_mutex in blk_mq_debugfs_register_hctxs() Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] rnbd-srv: Zero the rsp buffer before using it Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.12] alpha: fix user-space corruption during memory compaction Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] ACPICA: Abort AML bytecode execution when executing AML_FATAL_OP Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19] arm64: mte: Set TCMA1 whenever MTE is present in the kernel Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.18] tools/cpupower: Fix inverted APERF capability check Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.15] ACPI: processor: Fix NULL-pointer dereference in acpi_processor_errata_piix4() Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.12] ACPI: resource: Add JWIPC JVC9100 to irq1_level_low_skip_override[] Sasha Levin
2026-02-11 12:30 ` Sasha Levin [this message]
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.6] md-cluster: fix NULL pointer dereference in process_metadata_update Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-5.10] APEI/GHES: ensure that won't go past CPER allocated record Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.12] powercap: intel_rapl: Add PL4 support for Ice Lake Sasha Levin
2026-02-11 12:30 ` [PATCH AUTOSEL 6.19-6.18] io_uring/timeout: annotate data race in io_flush_timeouts() Sasha Levin
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=20260211123112.1330287-31-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=bigeasy@linutronix.de \
--cc=clrkwllms@kernel.org \
--cc=jonathan.cameron@huawei.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=mark.rutland@arm.com \
--cc=patches@lists.linux.dev \
--cc=rostedt@goodmis.org \
--cc=stable@vger.kernel.org \
--cc=will@kernel.org \
/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