Linux GPIO subsystem development
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: move GPIO IRQ setup into request_resources
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
@ 2026-10-19 13:46 ` Sasha Levin
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: fix debounce register selection Sasha Levin
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
  To: patches, stable
  Cc: Tomer Maimon, Linus Walleij, Sasha Levin, andrew, avifishman70,
	tali.perry1, openbmc, linux-gpio, linux-kernel

From: Tomer Maimon <tmaimon77@gmail.com>

[ Upstream commit b8edfde12e355030e708394c0fa11632559c7ac5 ]

npcmgpio_irq_startup() calls pinctrl_gpio_direction_input(), which may
sleep while taking the pinctrl core mutex. That makes IRQ startup trip
lockdep when CONFIG_PROVE_LOCKING is enabled.

Move the direction change into irq_request_resources() and keep startup
limited to the ack and unmask operations that are safe in atomic
context.

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is **v7.3-rc4** (`7.3.0-rc4`). The NPCM8XX pinctrl driver
is present, and this change is a real sleep-in-atomic IRQ fix, not a
feature add.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

Step 1.1: PARSE THE SUBJECT LINE
Record: **[pinctrl/npcm8xx] [move] move GPIO IRQ setup into
request_resources**
Subsystem `pinctrl: npcm8xx`. Verb is “move”, but the body is a
correctness fix: take a may-sleep call out of `irq_startup`.

Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Tomer Maimon `<tmaimon77@gmail.com>` (author; NPCM
  maintainer)
- Signed-off-by: Linus Walleij `<linusw@kernel.org>` (pinctrl
  maintainer)
- No Fixes, Reported-by, Tested-by, Reviewed-by, Acked-by, Link, or Cc:
  stable
Absence of Fixes/Cc: stable is expected for this review and is not a
negative signal.

Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: `npcmgpio_irq_startup()` calls `pinctrl_gpio_direction_input()`,
  which takes the pinctrl mutex and may sleep.
- Symptom: lockdep splat with `CONFIG_PROVE_LOCKING` on IRQ startup.
- Root cause: IRQ startup runs in atomic context; mutex_lock there is
  illegal.
- Fix: do the direction change in `irq_request_resources()`; leave
  startup as ack+unmask only.
- No version range, stack trace, or reproducer in the message.

Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a hidden fix. It is an explicit locking/context bug. Cover
letter of the v1 series called the set a “cleanup” from a Nuvoton tree
comparison, but this patch itself describes a real sleep-in-atomic
problem.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` (+23 / -6, 29 lines)
- Functions: `npcmgpio_irq_startup` (changed),
  `npcmgpio_irq_request_resources` (added),
  `npcmgpio_irq_release_resources` (added), `npcmgpio_irqchip` (changed)
- Scope: single-file surgical irqchip callback change

Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: `irq_startup` called `npcmgpio_direction_input()` then
  ack/unmask. Resource helpers came from `GPIOCHIP_IRQ_RESOURCE_HELPERS`
  (`gpiochip_irq_reqres` / `gpiochip_irq_relres`).
- After: `irq_startup` only ack+unmask. New `irq_request_resources` does
  `npcmgpio_direction_input()` then `gpiochip_reqres_irq()`. New
  `irq_release_resources` calls `gpiochip_relres_irq()`. Macro helpers
  removed because custom callbacks replace them.
- Path: GPIO `request_irq()` setup, not a probe-only path.

Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **Synchronization / illegal sleep in atomic context**
`irq_startup()` is invoked from `__setup_irq()` while `desc->lock` is
held via `raw_spin_lock_irqsave()` (`kernel/irq/manage.c`: lock at 1589,
`irq_startup()` at 1766, unlock at 1807).
`pinctrl_gpio_direction_input()` takes `pinctrldev_list_mutex` and
`pctldev->mutex` (`drivers/pinctrl/core.c`). Mutex in that context is
sleep-in-atomic. `irq_request_resources()` runs before that spinlock and
is allowed to sleep.

Step 2.4: ASSESS THE FIX QUALITY
Record: Quality is high. Same pattern as `pinctrl-ingenic.c` and
`pinctrl-st.c`. Resource get/put is preserved. Direction-input errors
are now returned instead of ignored. Regression risk is low: startup no
longer re-applies input on later startups, which matches other drivers;
first `request_irq()` still sets input before unmask. No API or data-
structure change.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

Step 3.1: BLAME THE CHANGED LINES
Record: Buggy `npcmgpio_irq_startup()` / `GPIOCHIP_IRQ_RESOURCE_HELPERS`
came from `acf4884a571709` (“pinctrl: nuvoton: add NPCM8XX pinctrl and
GPIO driver”, 2023-08-28), first in **v6.7-rc1**. The bug is as old as
the driver.

Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Introducer is the original driver commit above.
`git merge-base --is-ancestor acf4884a571709 HEAD` is true in this tree.

Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Submitted as **[PATCH v1 6/8]** “pinctrl: npcm8xx: fix pinmuxing
and configuration handling”. Siblings (bmcuart1 pins, RMII, RG2 drive
strength, event clear, rename, JM1/SMB7 flags, debounce) do not change
the irqchip callbacks this patch needs. Standalone. No follow-up on
these IRQ helpers after this commit.

Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Tomer Maimon is listed under ARM/NUVOTON NPCM ARCHITECTURE in
MAINTAINERS. Recent npcm8xx work is this same 8-patch set plus earlier
pin-table updates. Maintainer-authored.

Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Needs existing `gpiochip_reqres_irq` / `gpiochip_relres_irq` and
`GPIOCHIP_IRQ_RESOURCE_HELPERS`, both present here. No series
prerequisite for this hunk. Can apply standalone to this driver.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record: `b4 dig -c b8edfde12e355` →
https://patch.msgid.link/20260715122923.1938327-7-tmaimon77@gmail.com
Only **v1**. Lore HTTP fetch returned 403; full thread was saved with
`b4 dig -m`. Linus Walleij (24 Jul 2026): “No comments so patches
applied.” No NAK, no stable nomination, no requested respin.

Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: `b4 dig -w` To/Cc: Tomer Maimon, Andrew Jeffery, Linus Walleij,
Bartosz Golaszewski, openbmc, linux-gpio, linux-kernel, Avi Fishman,
Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair. Right lists and
maintainers. Only explicit reply is Walleij applying the series.

Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by, syzbot, or bugzilla. Issue was found by
comparing upstream with Nuvoton’s tree. Symptom claimed is lockdep with
`CONFIG_PROVE_LOCKING`. No public user crash report found.

Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: 8-patch pinmux/config series. This IRQ move does not depend on
the others. npcm7xx still calls `npcmgpio_direction_input()` from
`irq_startup()` — same class of bug, different driver, not a dependency.

Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search via curl returned 403. UNVERIFIED
whether stable@ already discussed this. No evidence in the gpio thread
of a stable NAK.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `npcmgpio_irq_startup`, `npcmgpio_irq_request_resources`,
`npcmgpio_irq_release_resources`, plus `npcmgpio_irqchip` initializer.

Step 5.2: TRACE CALLERS
Record:
- irqchip ops invoked from IRQ core: `irq_request_resources()` /
  `irq_release_resources()` / `irq_startup()` in `kernel/irq/manage.c`
  and `kernel/irq/chip.c`
- Chip registered in `npcm8xx_gpio_register()` via `girq->chip`
- Reachable from `request_irq()` / `gpiod_to_irq()` users on NPCM8XX
  GPIO banks

Step 5.3: TRACE CALLEES
Record: `npcmgpio_direction_input` → `pinctrl_gpio_direction_input`
(mutex) + generic `bank->direction_input`; `npcmgpio_irq_ack` / `unmask`
(MMIO); `gpiochip_reqres_irq` / `gpiochip_relres_irq`.

Step 5.4: FOLLOW THE CALL CHAIN
Record: userspace or driver `request_irq` on a GPIO line → `__setup_irq`
→ `irq_request_resources` (sleep OK) →
`raw_spin_lock_irqsave(&desc->lock)` → `irq_startup` (atomic). Path is
reachable whenever GPIO IRQs are used (BMC buttons, hotplug, etc.). Not
an obscure config-only path if `PINCTRL_NPCM8XX` is enabled (`depends on
ARCH_NPCM || COMPILE_TEST`).

Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same “direction_input in irq_request_resources” pattern in
ingenic and ST pinctrl. Sibling `pinctrl-npcm7xx.c` still has the old
startup-time `direction_input` call.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Driver is `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c`.
Introduced v6.7 (`acf4884a571709`). `git merge-base --is-ancestor
acf4884a571709 HEAD` succeeded. Pre-fix startup still present at parent
`b8edfde12e355^`. Local kernel: **v7.3-rc4** (`7.3.0-rc4`).

Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Expected apply: **clean**. Hunks are local to the irqchip struct
and two small callbacks. `GPIOCHIP_IRQ_RESOURCE_HELPERS` and
`gpiochip_reqres_irq()` exist here. Reverse-apply of the committed diff
checked cleanly against current file.

Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No earlier alternate fix for this irq_startup sleep. Current
HEAD already contains `b8edfde12e355` because this checkout is mainline
after the pinctrl-v7.3 pull; that is the upstream commit under review,
not a prior independent fix. No later corrective commit.

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **pinctrl / GPIO irqchip for Nuvoton NPCM8XX (Arbel BMC)**.
Criticality: **PERIPHERAL** for general kernels, **IMPORTANT** for
OpenBMC/NPCM845 systems. Not mm/fs/net core.

Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: File is actively updated (pin tables, debounce, RMII, this IRQ
fix). Driver is mature since v6.7, not brand-new staging code.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

Step 8.1: DETERMINE WHO IS AFFECTED
Record: **driver-specific / platform-specific**: NPCM8XX
(`CONFIG_PINCTRL_NPCM8XX`), typically OpenBMC on NPCM845. Not universal.

Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger is GPIO IRQ request (`request_irq` / irqchip startup).
Common for BMC GPIO IRQs. Unprivileged userspace can hit it if a GPIO
irq is exported; typical path is kernel drivers during bring-up. Not a
rare race: with lockdep it fires on every such startup. Mutex contention
can turn it into a real sleep-under-spinlock.

Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Failure mode: mutex_lock while `desc->lock` is held and IRQs are
off.
- With `CONFIG_PROVE_LOCKING` / `DEBUG_ATOMIC_SLEEP`: lockdep/WARN
  (always)
- If `pctldev->mutex` is contended: **scheduling while atomic** → BUG
Severity: **HIGH** (illegal atomic sleep; crash if contended), not a
silent data-corruption bug.

Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: medium-high for NPCM8XX/OpenBMC (correct IRQ request, no
  lockdep/sleep-in-atomic); zero for other platforms
- Risk: **low** (~20 net lines, irqchip callbacks only, established
  pattern)
- Ratio: favorable

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real sleep-in-atomic: `pinctrl_gpio_direction_input()` takes mutexes;
  `irq_startup()` runs under `raw_spin_lock_irqsave(&desc->lock)`
- Deterministic on GPIO IRQ request with lockdep
- Can BUG if the pinctrl mutex is contended
- Small, obviously correct, matches ingenic/ST
- Keeps `gpiochip_reqres_irq` / `gpiochip_relres_irq`
- Driver exists in this tree since v6.7
- Author is NPCM maintainer; applied by Linus Walleij
- Standalone vs the rest of the 8-patch series

AGAINST:
- No user crash report / syzbot / Fixes tag
- Author framed the user-visible issue as lockdep, not production oops
- NPCM8XX-only
- Cover letter called the series a vendor-tree cleanup
- npcm7xx still has the same pattern (does not make this patch wrong)

UNRESOLVED:
- lore.kernel.org HTTP 403; stable@ discussion not independently fetched
  (thread itself was retrieved via b4)

Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — context split is the
   documented irqchip model; applied by pinctrl maintainer. No extra
   Tested-by.
2. Fixes a real bug that affects users? **PASS** — illegal mutex in IRQ
   startup on GPIO `request_irq`.
3. Important issue? **PASS** — sleep-in-atomic / lockdep; possible BUG
   if mutex contended. Not a new feature.
4. Small and contained? **PASS** — one file, ~29 lines.
5. No new features or APIs? **PASS** — only irqchip callback placement.
6. Can apply to the local tree? **PASS** — driver and helpers exist;
   hunks match.

Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID, quirk, DT, build, or docs-only change).
Qualifies as a normal bugfix.

Step 9.4: MAKE YOUR DECISION
This tree has the NPCM8XX driver and the buggy startup path. The patch
is a small, correct move of a may-sleep call to
`irq_request_resources()`, which is the sleepable side of
`request_irq()`. That meets stable rules for this checkout.

Verification:
- [Phase 1] Tags: only Tomer Maimon and Linus Walleij SOBs; no
  Fixes/Reported-by/stable Cc
- [Phase 2] Diff: 23 insertions, 6 deletions in `pinctrl-npcm8xx.c`;
  direction_input moved; GPIOCHIP_IRQ_RESOURCE_HELPERS replaced by
  custom reqres/relres
- [Phase 2] `pinctrl_gpio_direction()` locks `pctldev->mutex`;
  `pinctrl_get_device_gpio_range()` locks `pinctrldev_list_mutex`
- [Phase 2] `__setup_irq()`: `irq_request_resources()` before
  `desc->lock`; `irq_startup()` while lock held (`manage.c` 1574–1766,
  unlock 1807)
- [Phase 3] Blame: bug from `acf4884a571709` (v6.7-rc1); `git merge-base
  --is-ancestor` true for intro and for `b8edfde12e355`
- [Phase 3] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; `make
  kernelversion`: 7.3.0-rc4
- [Phase 3] Series 1/8–8/8 identified; this patch does not depend on the
  others
- [Phase 4] `b4 dig -c b8edfde12e355`: lore msgid
  20260715122923.1938327-7; v1 only
- [Phase 4] `b4 dig -w`: Walleij, Golaszewski, Andrew Jeffery, openbmc,
  linux-gpio
- [Phase 4] mbox: Walleij “No comments so patches applied”; no
  NAK/stable Cc
- [Phase 4] UNVERIFIED: stable@ archive (HTTP 403)
- [Phase 5] Same pattern in `ingenic_gpio_irq_request` and
  `st_gpio_irq_request_resources`; npcm7xx still uses startup-time
  direction_input
- [Phase 6] File present; reverse `git apply --check` of the commit diff
  succeeded
- [Phase 8] Failure mode: lockdep always; scheduling-while-atomic if
  mutex contended — HIGH for this SoC, not universal
- UNVERIFIED: whether an unprivileged gpiochip ioctl is the common
  trigger vs kernel drivers (both reach `request_irq`)

**YES**

 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 29 ++++++++++++++++++-----
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 28464463ff833..0347a471f9226 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -295,17 +295,33 @@ static void npcmgpio_irq_unmask(struct irq_data *d)
 
 static unsigned int npcmgpio_irq_startup(struct irq_data *d)
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	unsigned int gpio = irqd_to_hwirq(d);
-
-	/* active-high, input, clear interrupt, enable interrupt */
-	npcmgpio_direction_input(gc, gpio);
 	npcmgpio_irq_ack(d);
 	npcmgpio_irq_unmask(d);
 
 	return 0;
 }
 
+static int npcmgpio_irq_request_resources(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	unsigned int gpio = irqd_to_hwirq(d);
+	int ret;
+
+	ret = npcmgpio_direction_input(gc, gpio);
+	if (ret)
+		return ret;
+
+	return gpiochip_reqres_irq(gc, gpio);
+}
+
+static void npcmgpio_irq_release_resources(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	unsigned int gpio = irqd_to_hwirq(d);
+
+	gpiochip_relres_irq(gc, gpio);
+}
+
 static struct irq_chip npcmgpio_irqchip = {
 	.name = "NPCM8XX-GPIO-IRQ",
 	.irq_ack = npcmgpio_irq_ack,
@@ -313,8 +329,9 @@ static struct irq_chip npcmgpio_irqchip = {
 	.irq_mask = npcmgpio_irq_mask,
 	.irq_set_type = npcmgpio_set_irq_type,
 	.irq_startup = npcmgpio_irq_startup,
+	.irq_request_resources = npcmgpio_irq_request_resources,
+	.irq_release_resources = npcmgpio_irq_release_resources,
 	.flags =  IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
-	GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
 static const int gpi36_pins[] = { 36 };
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: fix debounce register selection
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: move GPIO IRQ setup into request_resources Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip Sasha Levin
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
  To: patches, stable
  Cc: Tomer Maimon, Linus Walleij, Sasha Levin, andrew, avifishman70,
	tali.perry1, openbmc, linux-gpio, linux-kernel

From: Tomer Maimon <tmaimon77@gmail.com>

[ Upstream commit 602ee6c9447e4382c7e145b26a1c940813f2a144 ]

Each DBNCS register programs debounce source selection for 16 GPIOs.
The current offset calculation advances the register address every four
GPIOs, so offsets 4-15 and 20-31 end up touching the wrong selector
register.

Advance the DBNCS offset per 16 GPIOs so each line uses the debounce
selector bank that matches the hardware layout.

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local checkout is **v7.3-rc4** (mainline 7.3.0-rc4). The candidate
is a one-line DBNCS offset fix in the Nuvoton NPCM8XX pinctrl driver;
the buggy formula has been in this file since the driver landed in v6.7.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[pinctrl/npcm8xx] [fix] [debounce DBNCS register offset is
wrong for most GPIOs in a bank]**

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Tomer Maimon \<tmaimon77@gmail.com\> (author; original
  NPCM8XX pinctrl driver author)
- Signed-off-by: Linus Walleij \<linusw@kernel.org\> (pinctrl
  maintainer; applied the patch)
- No Fixes:, Reported-by, Tested-by, Reviewed-by, Acked-by, Link:, or
  Cc: stable (absence of Fixes/Cc:stable is expected for this review)

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Each DBNCS register selects debounce source for 16 GPIOs. The
  driver advanced the register pointer every four GPIOs (`gpio / 4`
  bytes).
- **Symptom:** GPIOs 4–15 and 20–31 program the wrong selector register
  (and, for most of those, an unaligned address).
- **Root cause:** Integer-division “simplification”: `(gpio / 16) * 4`
  is not `gpio / 4`.
- **Version info:** None in the message. Driver introduced in v6.7-rc1.
- **Failure mode:** Hardware debounce source is programmed into the
  wrong MMIO location.

**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. Subject and body describe a register-
selection bug. The 2022 pre-merge driver used `gpio / 16` with a `* 4`
stride; mainline shipped the broken `gpio / 4` form.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` (+2/−1)
- Function: `debounce_timing_setting()`
- Scope: single-file surgical fix (one expression)

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Hardware: `NPCM8XX_GP_N_DBNCS0` at 0x80, `DBNCS1` at 0x84; 2 bits per
  GPIO; 16 GPIOs per 32-bit register. Bit index `(gpio % 16) * 2` was
  already correct.
- Before: `base + 0x80 + (gpio / 4)`
  - gpio 0–3: 0x80 (DBNCS0, aligned)
  - gpio 4–7: 0x81, 8–11: 0x82, 12–15: 0x83 (unaligned, inside DBNCS0)
  - gpio 16–19: 0x84 (DBNCS1, accidentally correct)
  - gpio 20–31: 0x85–0x87 (unaligned; 32-bit RMW can overlap DBNCP0 at
    0x88)
- After: `base + 0x80 + (gpio / 16) * 4` → 0x80 for 0–15, 0x84 for
  16–31.
- Path: pinconf set of `PIN_CONFIG_INPUT_DEBOUNCE` only (not a
  probe/error-path change).

**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Logic / hardware programming]** Wrong MMIO offset. Matches
the bit-field layout already in the same function. `npcm_gpio_set()`
does `iowrite32(ioread32(reg) | pinmask, reg)` on that pointer.

**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct against DBNCS0/DBNCS1 at 0x80/0x84 and `(gpio
% 16) * 2`. Minimal. Regression risk is very low: only the register
address changes; GPIOs 0–3 and 16–19 keep the same address.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

**Step 3.1: BLAME THE CHANGED LINES**
Record: Buggy line introduced in **acf4884a57170** (“pinctrl: nuvoton:
add NPCM8XX pinctrl and GPIO driver”, Tomer Maimon, 2023-09-11),
contained in **v6.7-rc1**. Present until 602ee6c9447e4.

**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Bug is in the original driver merge, not a later
regression.

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same-author series merged via `pinctrl-v7.3-1` (drop RTS/CTS,
RMII, RG2 drive strength, pending GPIO events, IRQ setup, pin flags,
this debounce fix). This hunk does not depend on those other patches.
Only other debounce commit on this path is the original driver add.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Tomer Maimon is the Nuvoton/NPCM pinctrl author. Linus Walleij
applied the series. Recent npcm8xx work is a mix of pin-map corrections
and one feature (RG2 drive strength). This commit is the debounce
correctness fix.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. Uses `NPCM8XX_GP_N_DBNCS0` and
`debounce_timing_setting()` as they existed at driver introduction. No
new helpers or struct fields.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 602ee6c9447e4` →
  https://patch.msgid.link/20260715122923.1938327-9-tmaimon77@gmail.com
- Subject: `[PATCH v1 8/8] pinctrl: npcm8xx: fix debounce register
  selection` (2026-07-15)
- `b4 dig -a`: only **v1**; applied version matches v1
- lore.kernel.org fetches returned **403**; patch text confirmed via
  LKML/openwall mirrors. No replies were visible on those mirror pages.

**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): linusw@kernel.org, brgl@kernel.org,
andrew@codeconstruct.com.au, linux-gpio, openbmc, Nuvoton/Google BMC
CCs. No Reviewed-by on the commit; maintainer SOB is Linus Walleij.

**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by, bugzilla, or syzbot link. Author-found hardware
mapping error.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Patch 8/8 of an npcm8xx pin/group cleanup series. Other patches
change groups, IRQ setup, or add RG2 drive strength. This offset change
does not require them. Pre-merge 2022 v2 driver used `int DBNCS_offset =
gpio / 16` and `DBNCS0 + (DBNCS_offset * 4)` — the correct formula this
commit restores.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search was not usable (403). No evidence
this was discussed on stable@ from the mirrors that did load.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `debounce_timing_setting()` only.

**Step 5.2: TRACE CALLERS**
Record:
- `debounce_timing_setting()` ← `npcm_set_debounce()` ←
  `npcm8xx_config_set_one()` on `PIN_CONFIG_INPUT_DEBOUNCE` ←
  `npcm8xx_config_set()` (`pinconf_ops.pin_config_set`)
- DT generic pinconf maps `input-debounce` to that param (`pinconf-
  generic.c`).
- **GPIO cdev debounce does not hit this path here:**
  `gpio_generic_chip_init()` does not set `gc->set_config`, and this
  driver never assigns `gpiochip_generic_config`. `gpio_do_set_config()`
  returns `-ENOTSUPP`; gpiolib-cdev then uses software debounce.

**Step 5.3: TRACE CALLEES**
Record: `npcm_gpio_set()` (32-bit RMW), `iowrite32` of DBNCPx period
registers, `DIV_ROUND_CLOSEST` for custom periods.

**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Reachable when a pinctrl state applies `input-debounce` (boot DT
or pin_config_set). No in-tree dts/dtsi uses `input-debounce`
(verified). OpenBMC board DTs are often out of tree. Not a syscall hot
path on this driver as wired today.

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: npcm7xx has PIN_CONFIG_INPUT_DEBOUNCE cases but no DBNCS
registers (NPCM8XX-specific adjustable debounce). No sibling copy of
this bug.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` is present.
Pre-image at 602ee6c9447e4^ is `+ (gpio / 4)`. Bug since v6.7. This
checkout already contains the fix (expected for a mainline candidate
tree). `PINCTRL_NPCM8XX` depends on `ARCH_NPCM || COMPILE_TEST`.

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply on the debounce formula. Surrounding gpio-generic
API churn does not affect this one line. Expected backport difficulty:
**clean apply** on any tree that still has `(gpio / 4)` in
`debounce_timing_setting`.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier debounce-offset fix. `git log --grep=debounce --
drivers/pinctrl/nuvoton/` only shows the original add and this commit.

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **[pinctrl / Nuvoton NPCM8XX GPIO] [PERIPHERAL]** — Arbel BMC
(ARM64 Cortex-A35), used on OpenBMC server BMCs. Not core mm/fs/net.

**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature driver (v6.7), recent concentrated npcm8xx pin-map/IRQ
fixes in the 7.3 pinctrl pull. Debounce math had been unchanged since
introduction.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Platform-specific:** NPCM8XX BMC boards that set pinctrl
`input-debounce`. Not universal. No in-tree DT consumers found.

**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Applying hardware debounce via pinconf. Not every boot unless DT
requests it. Unprivileged GPIO debounce ioctl does **not** reach this
function on this driver (no `set_config`). Privilege/DT-dependent.

**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Primary (author): wrong DBNCS register → debounce source not applied
  to the intended line; possible corruption of neighboring DBNCS/DBNCP
  fields via unaligned 32-bit RMW.
- Unaligned `ioread32`/`iowrite32` on ARM64 Device mappings *can*
  alignment-fault; **no crash was reported**. Treat crash as possible,
  not verified.
- Severity: **MEDIUM** for functional debounce / adjacent-register
  corruption on this SoC; not a demonstrated panic/UAF/security hole.

**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Makes hardware debounce match the documented 16-GPIO
  DBNCS banks for NPCM8XX users who enable it.
- **Risk:** Very low (one address expression; GPIOs that already hit
  0x80/0x84 unchanged).
- **Ratio:** Favorable. Small correctness fix, not a feature.

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

**Step 9.1: COMPILE THE EVIDENCE**

FOR backporting:
- Real hardware programming bug, present since the driver was added
  (v6.7).
- Restores the mapping the author’s 2022 submission already used (`gpio
  / 16` × 4-byte stride).
- Matches DBNCS0/DBNCS1 at 0x80/0x84 and the existing `(gpio % 16) * 2`
  bit layout.
- 3-line, single-function, no API/feature change.
- Author is the driver writer; pinctrl maintainer applied it.
- Standalone; other 8/8 series patches not required.
- Applies on this tree’s pre-image without surrounding refactor.

AGAINST:
- Peripheral BMC pinctrl, not a core crash/security/corruption class as
  described.
- No Fixes/Cc:stable, no Reported-by/Tested-by (tags not required, but
  no field report).
- No in-tree `input-debounce` DT users; GPIO cdev debounce does not call
  this code.
- Series also contains non-stable material (e.g. RG2 drive strength);
  this patch itself is independent.

UNRESOLVED:
- Full lore thread (reviews/NAKs) unverified due to lore 403.
- Whether any OpenBMC DT actually sets `input-debounce` (not in this
  tree).
- Whether unaligned MMIO actually oopses on NPCM8XX (not reported).

**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — formula matches register
   layout; maintainer applied. No extra Tested-by.
2. Fixes a real bug that affects users? **PASS** — wrong DBNCS bank for
   24/32 lines per bank when hardware debounce is configured.
3. Important issue (crash, security, corruption, deadlock)? **PASS**
   (borderline) — wrong MMIO and possible adjacent-register RMW; not a
   documented oops. Still a hardware-feature break on a production BMC
   SoC, which stable routinely takes in pinctrl/gpio.
4. Small and contained? **PASS** — +2/−1, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — same file/function; pre-image
   is the buggy line.

**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary small
driver correctness fix.

**Step 9.4: MAKE YOUR DECISION**
This tree has the NPCM8XX driver and the long-standing `gpio / 4` bug.
The patch is a minimal, obviously correct register-index fix with no
dependencies. Benefit is limited to NPCM8XX debounce configuration, but
the risk of taking it is negligible and the bug is real. That meets
stable criteria for this checkout.

------------------------------------------------
What the commit solves, for stable users
------------------------------------------------
Hardware debounce on NPCM8XX is supposed to use DBNCS0 for GPIOs 0–15
and DBNCS1 for 16–31. Integer division turned `(gpio / 16) * 4` into
`gpio / 4`, so most lines wrote the wrong (often unaligned) address.
Boards that set pinctrl `input-debounce` would not get the intended
debounce source and could disturb neighboring debounce-period registers.
The fix is one address expression.

Risk vs benefit: very low risk, modest but real benefit for NPCM8XX BMC
GPIO debounce. No series dependencies.

Verification:
- [Phase 1] Parsed commit 602ee6c9447e4: SOB Tomer Maimon + Linus
  Walleij; no Fixes/Reported-by/Cc:stable
- [Phase 2] Diff: one expression in `debounce_timing_setting()`;
  DBNCS0=0x80, DBNCS1=0x84 confirmed in this file
- [Phase 2] `npcm_gpio_set()` is 32-bit RMW at the computed pointer
  (lines 124–129)
- [Phase 3] `git blame` on parent: acf4884a57170 (v6.7-rc1) introduced
  `(gpio / 4)`
- [Phase 3] `git merge-base --is-ancestor acf4884a57170 HEAD` → yes; fix
  is ancestor of HEAD
- [Phase 3] `git log --grep=debounce -- drivers/pinctrl/nuvoton/` → only
  driver add + this fix
- [Phase 4] `b4 dig -c 602ee6c9447e4` → msgid 20260715122923.1938327-9;
  v1 8/8; recipients linusw, brgl, openbmc
- [Phase 4] Pre-merge 2022 v2 used `gpio / 16` and `* 4`
  (lists.ozlabs.org OpenBMC archive)
- [Phase 4] lore.kernel.org 403 — full review thread UNVERIFIED;
  LKML/openwall showed the patch text only
- [Phase 5] Callers: `npcm_set_debounce` ← `npcm8xx_config_set_one`
  PIN_CONFIG_INPUT_DEBOUNCE
- [Phase 5] This driver has no `gc->set_config`; GPIO cdev debounce does
  not reach this function
- [Phase 5] `rg input-debounce` on dts/dtsi: no matches
- [Phase 6] `git describe HEAD` → v7.3-rc4-27-gf0100363d8c37; `make
  kernelversion` → 7.3.0-rc4
- [Phase 6] Parent of fix still has `(gpio / 4)`; apply is clean
- [Phase 8] Failure mode: wrong debounce MMIO; crash via unaligned
  access UNVERIFIED
- UNVERIFIED: OpenBMC out-of-tree DT debounce use; stable@ discussion;
  review NAKs

**YES**

 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 22cc87d43ea69..28464463ff833 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -2135,7 +2135,8 @@ static const struct pinmux_ops npcm8xx_pinmux_ops = {
 static int debounce_timing_setting(struct npcm8xx_gpio *bank, u32 gpio,
 				   u32 nanosecs)
 {
-	void __iomem *DBNCS_offset = bank->base + NPCM8XX_GP_N_DBNCS0 + (gpio / 4);
+	void __iomem *DBNCS_offset = bank->base + NPCM8XX_GP_N_DBNCS0 +
+				     (gpio / 16) * 4;
 	int gpio_debounce = (gpio % 16) * 2, debounce_select, i;
 	u32 dbncp_val, dbncp_val_mod;
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: move GPIO IRQ setup into request_resources Sasha Levin
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: fix debounce register selection Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
  2026-10-19 14:27   ` sashiko-bot
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] gpio: mvebu: keep resume masks within the irqchip cache Sasha Levin
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
  To: patches, stable
  Cc: Maulik Shah, Sneh Mankad, Linus Walleij, Navya Malempati,
	Bartosz Golaszewski, Sasha Levin, andersson, brgl, linux-arm-msm,
	linux-gpio, linux-kernel

From: Maulik Shah <maulik.shah@oss.qualcomm.com>

[ Upstream commit 1860fb0be224dec0e4d170f46d1cbbc77e25e09e ]

MPM irqchip monitors the interrupts during SoC sleep state and after wakeup
replays the edge interrupt by making it pending at respective irqchip by
invoking irq_set_irqchip_state() API. The msm gpio irqchip however do not
implement this function making it impossible to replay the gpio interrupt
on any MPM irqchip based SoC.

Add the missing irq_get/set_irqchip_state() APIs. Implement only
IRQCHIP_STATE_PENDING case which MPM irqchip uses.

Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
Signed-off-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Acked-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Navya Malempati <navya.malempati@oss.qualcomm.com>
Link: https://patch.msgid.link/20260424-pinctrl_irqchip_states-v1-1-85286f078916@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is **7.3.0-rc4**. This commit fills in missing MSM GPIO
irqchip ops so MPM can replay edge GPIOs after deep sleep. That is a
real resume bug on Qualcomm MPM SoCs, and the change is small enough to
be a stable candidate.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[pinctrl/qcom] [Add] Implement missing
irq_get/set_irqchip_state() on the MSM GPIO irqchip`

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Fixes:` — none (expected)
- `Reported-by:` — none
- `Tested-by:` — none
- `Reviewed-by: Navya Malempati <navya.malempati@oss.qualcomm.com>`
- `Acked-by: Linus Walleij <linusw@kernel.org>` (pinctrl maintainer)
- `Link: https://patch.msgid.link/20260424-pinctrl_irqchip_states-v1-1-
  85286f078916@oss.qualcomm.com`
- `Cc: stable@vger.kernel.org` — none (expected)
- `Signed-off-by: Maulik Shah` (author)
- `Signed-off-by: Sneh Mankad` (submitter)
- `Signed-off-by: Bartosz Golaszewski` (Qualcomm pinctrl maintainer)
- Ignore pipeline `Signed-off-by: Sasha Levin`

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** After SoC sleep, MPM replays edge IRQs with
  `irq_set_irqchip_state(..., IRQCHIP_STATE_PENDING, true)`. The MSM
  GPIO irqchip did not implement that op, so GPIO edges cannot be
  replayed on MPM SoCs.
- **Symptom:** Lost GPIO edge interrupts after deep sleep / resume
  (wakeup events never delivered to the GPIO irqchip).
- **Root cause:** Missing `irq_chip.irq_{get,set}_irqchip_state` on
  `msmgpio`.
- **Versions:** None stated. MPM has called this API since it was added
  (2022).

**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. Subject says “Add”, but the body
describes a real missing-op bug. Implementing existing irqchip callbacks
is a completeness/correctness fix, not a new userspace API.

---

## PHASE 2: DIFF ANALYSIS

**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pinctrl/qcom/pinctrl-msm.c` — **+39 / -0**
- New: `msm_gpio_irq_set_irqchip_state()`,
  `msm_gpio_irq_get_irqchip_state()`
- Wired into `msm_gpio_irq_chip`
- Scope: single-file, surgical

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `irq_set_irqchip_state()` walks the hierarchy from
  `msmgpio`. That chip had no callback, so it walked to MPM (also no
  callback). GPIO-only MPM pins disconnect GIC, so the call returns
  `-EINVAL` and the edge is never made pending.
- **After:** `msmgpio` writes/reads TLMM `intr_status` for
  `IRQCHIP_STATE_PENDING`. Other states and `skip_wake_irqs` pins (PDC-
  owned) return `-EINVAL`.
- Path: resume / MPM handler, not probe.

**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Logic / correctness (missing irqchip op)**, with a hardware-
wakeup workaround flavor.
Mechanism: MPM’s `qcom_mpm_handler()` does
`irq_set_irqchip_state(d->irq, IRQCHIP_STATE_PENDING, true)` for non-
level IRQs. Without the GPIO callback, replay is impossible. The fix
writes the GPIO status register (bit 0; `intr_status_bit` is 0 on all
GPIO pingroups).

**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Quality: sufficient for the MPM case. Only `IRQCHIP_STATE_PENDING`;
  PDC pins are rejected via `skip_wake_irqs`.
- Nits (not blockers): bool written as the full status register (OK
  because status bit is 0); no `pctrl->lock` (single `writel`/`readl`);
  redundant `g` assignment in get; get is unused by MPM but harmless.
- `intr_ack_high` platforms (msm8660/8960, ipq8064, …) would invert set
  vs ack; those SoCs do not use MPM.
- For `skip_wake_irqs` (PDC), the walk now stops at `msmgpio` and
  returns `-EINVAL` instead of forwarding to PDC/GIC. PDC SoCs do not
  use MPM replay; this is conservative, not the MPM bug.
- Regression risk: **low–medium**. Writing pending can inject an IRQ;
  that is the intended replay. Pinctrl maintainer initially called it
  “super dangerous”, then acked after Qualcomm review.

---

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: BLAME THE CHANGED LINES**
Record: These callbacks are new. The irqchip struct dates to
`69b78b8de65b` (2014) / immutable chip `14dbe186b9d4` (2022).
`skip_wake_irqs` dates to `e35a6ae0eb3a` (2019). MPM (`a6199bb514d8`,
2022-03-11, ~v5.18) is what started calling `irq_set_irqchip_state()` on
wakeup.

**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Bug is omission vs MPM, not a regression from a
later commit.

**Step 3.3: CHECK FILE HISTORY**
Record: No prerequisite series. `v1-1` is standalone. No later commit in
this tree patches these new functions.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Maulik Shah is a regular Qualcomm pinctrl/irqchip contributor
(PDC, wakeup, irqchip flags). Related work is Qualcomm wakeup IRQ
handling, not a hard dependency of this patch.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Uses existing `msm_readl/writel_intr_status`, `skip_wake_irqs`,
and `irq_chip` ops. Can apply standalone to this file.

---

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- Lore: https://patch.msgid.link/20260424-pinctrl_irqchip_states-v1-1-
  85286f078916@oss.qualcomm.com
- Single revision **v1** (no v2/v3).
- Linus Walleij (28 Apr 2026): “smart and also **super dangerous**” —
  wanted Qualcomm ACK/test before merge.
- Navya Malempati (16 Jul 2026): `Reviewed-by`.
- Linus (25 Jul 2026): `Acked-by`; asked Bartosz to queue it.
- Bartosz (27 Jul 2026): Applied as `[1/1]`.
- No `Cc: stable`, no NAK after Qualcomm review.

**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: To/Cc: Bjorn Andersson, Linus Walleij, linux-arm-msm, linux-
gpio, linux-kernel, Maulik Shah. Right lists and maintainers.

**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot, bugzilla, or public user report. Qualcomm-internal
hardware knowledge. Severity from the message: **GPIO edges cannot be
replayed after sleep on any MPM SoC**.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone 1/1. Same 7.3 pinctrl-qcom pull also had PDC work;
this patch does not depend on those.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: No stable@ discussion found. Merged via “Qualcomm pinctrl
updates for v7.3-rc1”.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: KEY FUNCTIONS**
Record: `msm_gpio_irq_set_irqchip_state`,
`msm_gpio_irq_get_irqchip_state`; `msm_gpio_irq_chip` updated.

**Step 5.2: TRACE CALLERS**
Record:
- IRQ core: `irq_set_irqchip_state()` / `irq_get_irqchip_state()`
  (`kernel/irq/manage.c`) start at the leaf chip (`msmgpio`).
- Primary caller: `qcom_mpm_handler()` in `drivers/irqchip/irq-qcom-
  mpm.c` (RPM wakeup IRQ, resume).
- Also: `irq_inject_interrupt()` (debug), KVM vgic (unrelated host
  IRQs).

**Step 5.3: TRACE CALLEES**
Record: `msm_writel_intr_status` / `msm_readl_intr_status` — MMIO to
TLMM per-pin status.

**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Sleep → MPM latches wakeup GPIO → resume → `qcom_mpm_handler` →
`irq_set_irqchip_state(PENDING)` → **now** TLMM status. Triggered by
hardware wakeup, not a raw syscall. User-visible: GPIO clients (keys,
modem, sensors) miss the edge after suspend.

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: PDC already has `irq_chip_{get,set}_parent_state`. GIC
implements these ops. `skip_wake_irqs` is set only when parent is PDC
(`IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP`). MPM parent does **not** set that
flag, so TLMM keeps handling those GPIOs — which is why MSM GPIO must
implement the ops.

---

## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: **v7.3-rc4-27-gf0100363d8c37**, `VERSION=7 PATCHLEVEL=3
  SUBLEVEL=0 EXTRAVERSION=-rc4`.
- Driver, MPM (`CONFIG_QCOM_MPM`), `skip_wake_irqs`, and accessors all
  exist.
- Commit `1860fb0be224` **is already an ancestor of HEAD** (7.3 merge
  window). Unfixed code is not on HEAD; the same files still need this
  on any branch that predates 7.3.
- Bug present since MPM (v5.18), not introduced after 7.3 branched.

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** onto this `pinctrl-msm.c`. One file, two new
functions, two irq_chip pointers. `skip_wake_irqs` and status accessors
are old.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No other fix for “MPM cannot replay GPIO pending”. No follow-up
on these functions after `1860fb0be224`.

---

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: `drivers/pinctrl/qcom` + Qualcomm MPM irqchip. **IMPORTANT**
(platform GPIO/wakeup), not core mm/vfs. Affects Qualcomm MPM boards
(sdm660, sm6115/6125/6375, msm8996/8998, qcm2290, …), not PDC phones.

**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Actively maintained (Bartosz / Qualcomm). This is a targeted
irqchip-ops fill-in, not a refactor.

---

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: WHO IS AFFECTED**
Record: **Platform-specific** — `CONFIG_PINCTRL_MSM*` +
`CONFIG_QCOM_MPM`. Not universal. Still real products (older/mid
Qualcomm, IoT, embedded).

**Step 8.2: TRIGGER CONDITIONS**
Record: SoC deep sleep, then an edge GPIO that MPM monitored. Common on
suspend/resume. Not an unprivileged syscall exploit path.

**Step 8.3: FAILURE MODE SEVERITY**
Record: Lost GPIO edge after resume (keys, wake sources, peripherals).
Not oops/UAF/corruption. **MEDIUM–HIGH** functional/suspend-resume, not
CRITICAL crash.

**Step 8.4: RISK-BENEFIT RATIO**
Record:
- **Benefit:** High for MPM Qualcomm users (resume GPIO actually fires).
- **Risk:** Low–medium (39 lines, pending-bit write). Mitigated by
  PENDING-only and `skip_wake_irqs`. No lock/API/data-structure change.
- **Ratio:** Benefit outweighs risk for trees that still lack the ops.

---

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: COMPILE THE EVIDENCE**

FOR:
- Concrete bug: MPM cannot replay GPIO edges after sleep.
- User-visible resume failure on MPM SoCs.
- Small, one-file, existing irqchip API only.
- Prerequisites present here for years.
- Qualcomm `Reviewed-by`, Walleij `Acked-by`, Bartosz merged.
- No follow-up fix in this tree.
- Same class as hardware/suspend quirks that stable takes.

AGAINST:
- Worded as “Add”; implements new irqchip methods.
- Not crash/UAF/security.
- No public reporter / `Tested-by`.
- Walleij first called it “super dangerous”.
- Minor implementation nits.

UNRESOLVED:
- No public repro log (Qualcomm-described).
- lore HTTP 403; thread recovered via `b4 dig -m`.

**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — PENDING-only, skip PDC pins;
   reviewed/acked. Initial “dangerous” concern addressed in review. No
   `Tested-by`, but mechanism matches MPM code.
2. Fixes a real bug that affects users? **PASS** — lost GPIO IRQs after
   sleep on MPM SoCs.
3. Important issue? **PASS** — suspend/resume IRQ loss (serious
   functional), not oops/CVE.
4. Small and contained? **PASS** — +39 lines, one file.
5. No new features or APIs? **PASS** — no new uAPI; fills existing
   `irq_chip` ops the core already calls.
6. Can apply to the local tree? **PASS** — same file/helpers; applies
   cleanly.

**Step 9.3: EXCEPTION CATEGORIES**
Record: Not a device-ID/DT/build/doc exception. Closest: **hardware
wakeup workaround** (missing irqchip op so existing MPM hardware works
after sleep).

**Step 9.4: DECISION**
This tree has the MSM GPIO irqchip, MPM, and `skip_wake_irqs`. The bug
is missing ops, present since MPM (~v5.18), not a 7.3-only feature. The
patch is a small, review-vetted fix for lost edge GPIOs after deep
sleep. That meets stable rules for this checkout.

---

### What it solves for stable users
On Qualcomm MPM SoCs, an edge GPIO during sleep is latched in always-on
MPM. On resume, MPM marks the leaf irqchip pending. Without these ops,
`msmgpio` cannot accept that, so the edge is dropped. Users can miss
keys, modem/Wi-Fi wake, sensors, etc. after suspend.

### Stable rules
Small, obviously aimed at one hardware path, no new uAPI, real resume
bug. Risk is writing the GPIO pending bit; the patch limits that to
`IRQCHIP_STATE_PENDING` and non-PDC pins.

### Risk vs benefit
Benefit is real on MPM platforms. Risk is contained. Quality nits do not
break the MPM case (`intr_status_bit == 0`).

---

### Verification
- **[Phase 1]** Tags: Reviewed-by Navya, Acked-by Walleij, Link to
  msgid; no Fixes/Reported-by/Cc:stable.
- **[Phase 2]** Diff: +39 in `pinctrl-msm.c`; two callbacks + irq_chip
  pointers; `msm_writel_intr_status(val)` with bool; `intr_status_bit`
  is 0 on GPIO groups (verified across pinctrl-qcom).
- **[Phase 2]** `qcom_mpm_handler` confirmed to call
  `irq_set_irqchip_state(..., IRQCHIP_STATE_PENDING, true)` for non-
  level IRQs.
- **[Phase 2]** `irq_set_irqchip_state()` in `kernel/irq/manage.c` walks
  until a chip implements the op; `qcom_mpm_chip` does not.
- **[Phase 3]** MPM added `a6199bb514d8` (2022); `skip_wake_irqs` from
  `e35a6ae0eb3a` (2019); no later fix to these functions.
- **[Phase 3]** `git merge-base --is-ancestor 1860fb0be224 HEAD` → yes
  (commit is in this 7.3-rc4 history). Decision is on technical merit,
  not “already selected”.
- **[Phase 4]** `b4 dig -c 1860fb0be224` → v1 only; Walleij “super
  dangerous” then Acked-by; Bartosz applied 1/1.
- **[Phase 4]** `b4 dig -w`: linux-gpio, linux-arm-msm, Walleij,
  Andersson.
- **[Phase 4]** lore.kernel.org WebFetch 403; thread read from
  `/tmp/pinctrl-irqchip.mbox`.
- **[Phase 5]** PDC sets `IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP` →
  `skip_wake_irqs`; MPM sets `IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP` and does
  not skip TLMM.
- **[Phase 6]** `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`;
  `make kernelversion` = `7.3.0-rc4`.
- **[Phase 8]** Failure: dropped GPIO edge after MPM wakeup; severity
  MEDIUM–HIGH functional, not crash.
- **UNVERIFIED:** Public reproducer / which exact board Qualcomm used
  (not in the thread).

The patch is a contained fix for a real resume IRQ-loss bug on hardware
this tree already supports.

**YES**

 drivers/pinctrl/qcom/pinctrl-msm.c | 39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 424b14bc29e96..015c9b2f086da 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1289,6 +1289,43 @@ static int msm_gpio_irq_set_affinity(struct irq_data *d,
 	return -EINVAL;
 }
 
+static int msm_gpio_irq_set_irqchip_state(struct irq_data *d,
+					  enum irqchip_irq_state which, bool val)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+	const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq];
+
+	if (which != IRQCHIP_STATE_PENDING)
+		return -EINVAL;
+
+	if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
+		return -EINVAL;
+
+	msm_writel_intr_status(val, pctrl, g);
+
+	return 0;
+}
+
+static int msm_gpio_irq_get_irqchip_state(struct irq_data *d,
+					  enum irqchip_irq_state which, bool *val)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
+	const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq];
+
+	if (which != IRQCHIP_STATE_PENDING)
+		return -EINVAL;
+
+	if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
+		return -EINVAL;
+
+	g = &pctrl->soc->groups[d->hwirq];
+	*val = msm_readl_intr_status(pctrl, g);
+
+	return 0;
+}
+
 static int msm_gpio_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -1377,6 +1414,8 @@ static const struct irq_chip msm_gpio_irq_chip = {
 	.irq_request_resources	= msm_gpio_irq_reqres,
 	.irq_release_resources	= msm_gpio_irq_relres,
 	.irq_set_affinity	= msm_gpio_irq_set_affinity,
+	.irq_set_irqchip_state = msm_gpio_irq_set_irqchip_state,
+	.irq_get_irqchip_state = msm_gpio_irq_get_irqchip_state,
 	.irq_set_vcpu_affinity	= msm_gpio_irq_set_vcpu_affinity,
 	.flags			= (IRQCHIP_MASK_ON_SUSPEND |
 				   IRQCHIP_SET_TYPE_MASKED |
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] gpio: mvebu: keep resume masks within the irqchip cache
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (2 preceding siblings ...)
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
  2026-10-19 14:37   ` sashiko-bot
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-6.6] gpio: pca9570: Use I2C match data Sasha Levin
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
  To: patches, stable
  Cc: Rosen Penev, Bartosz Golaszewski, Sasha Levin, linusw, brgl,
	linux-gpio, linux-kernel

From: Rosen Penev <rosenp@gmail.com>

[ Upstream commit 02af7eac17bc62a72335c1fc8c4af4471654f6cc ]

mvebu_gpio_resume() writes the edge/level mask registers saved at
suspend time straight back to hardware, bypassing the irqchip's
mask_cache_priv.  genirq skips mask_irq() for a line it already
considers masked, so restoring a bit in hardware that genirq thinks
is still masked leaves that line unmasked behind genirq's back.  An
asserted level line then has nobody to ack it, and the moment
interrupts are re-enabled the chained handler storms, hanging resume.

AND the restored mask values with the matching irqchip mask cache so
only lines genirq currently considers unmasked are unmasked again.
Read the caches under gc->lock to keep them consistent with the
mask/unmask handlers.

Tested on Helios4 (armhf): 5 suspend cycles woken by magic packet,
no hang; mvebu_gpio_resume() returns in 6 usecs.

Assisted-by: LLM
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://patch.msgid.link/20260915004406.115230-1-rosenp@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This is a real resume hang in `gpio-mvebu`: restoring stale mask bits
can unmask a level line behind genirq and storm the chained handler. The
buggy restore is in this 6.18.57 tree and the patch is small enough to
backport.

## Phase 1: Commit message forensics

**Step 1.1 — Subject**
- Record: `[gpio/mvebu] [keep/prevent] keep resume masks within the
  irqchip cache` — stop `mvebu_gpio_resume()` from writing suspend-time
  mask bits that genirq still considers masked.

**Step 1.2 — Tags**
- Record:
  - `Assisted-by: LLM`
  - `Signed-off-by: Rosen Penev <rosenp@gmail.com>` (author)
  - `Link:
    https://patch.msgid.link/20260915004406.115230-1-rosenp@gmail.com`
  - `Signed-off-by: Bartosz Golaszewski
    <bartosz.golaszewski@oss.qualcomm.com>` (GPIO maintainer)
  - No `Fixes:`, `Reported-by:`, `Tested-by:`, `Cc: stable` (absence
    expected)
  - Ignore `[Upstream commit 02af7eac17bc...]` and `Signed-off-by: Sasha
    Levin`

**Step 1.3 — Body**
- Record:
  - **Bug:** `mvebu_gpio_resume()` writes saved edge/level mask
    registers straight to hardware, bypassing `mask_cache_priv`.
  - **Symptom:** resume hang — an asserted level line is unmasked while
    genirq still thinks it is masked, so nobody acks it and the chained
    handler storms once IRQs are live.
  - **Root cause (author):** `mask_irq()` is skipped when genirq already
    considers the line masked (`irqd_irq_masked`).
  - **Fix:** AND restored values with the irqchip mask cache; read
    caches under `gc->lock`.
  - **Testing:** Helios4 (armhf), 5 suspend cycles woken by magic
    packet, no hang; `mvebu_gpio_resume()` ~6 µs.
  - **Versions:** none named.

**Step 1.4 — Hidden bug fix?**
- Record: Not hidden. The subject uses “keep … within” but the body
  describes a resume hang from an IRQ storm. This is an explicit
  correctness fix.

## Phase 2: Diff analysis

**Step 2.1 — Inventory**
- Record:
  - File: `drivers/gpio/gpio-mvebu.c` (+27 / −6)
  - Function: `mvebu_gpio_resume()` only
  - Classification: single-file surgical fix

**Step 2.2 — Control flow**
- Record:
  - **Before:** restore `edge_mask_regs[]` / `level_mask_regs[]`
    verbatim to hardware.
  - **After:** if `mvchip->domain` is set, snapshot
    `gc->chip_types[0].mask_cache_priv` (level) and `[1]` (edge) under
    `gc->lock`, drop the lock, then write `saved & cache`. If there is
    no domain, caches stay `~0U` so behavior is unchanged.
  - Path: system resume of the GPIO platform device, after
    `resume_device_irqs()`.

**Step 2.3 — Bug mechanism**
- Record: **Logic / interrupt-state desync** that produces a **level IRQ
  storm / resume hang**.
  - `mask_irq()` returns immediately if `irqd_irq_masked()` is already
    set (`kernel/irq/chip.c`).
  - `handle_level_irq()` does `mask_ack_irq()` then `irq_can_handle()`.
    If the line is disabled, it returns without running the handler.
    Level GPIO has no separate ack; masking is the ack.
  - Blind restore can put 1s in the HW mask while genirq still has
    `IRQD_IRQ_MASKED`. The chained handler (`mvebu_gpio_irq_handler`)
    keeps seeing `data_in & level_mask` and storms.

**Step 2.4 — Fix quality**
- Record: Minimal and locally correct. `chip_types[0]` is level and
  `[1]` is edge in `mvebu_gpio_probe()` in this tree, matching the
  snapshot. Unlock-before-`regmap_write` is required because
  `regmap_write()` can take a sleepable lock on PREEMPT_RT (`gc->lock`
  is a `raw_spinlock_t`).
- Regression risk: low. AND can only clear extra bits, never unmask more
  than both the snapshot and genirq allow. The `saved==0 && cache==1`
  “lost IRQ” case already wrote 0 before this patch. Remaining TOCTOU
  after dropping the lock is the same class of window v1 tried to close
  by holding the lock across `regmap_write`, which is illegal on RT; v2
  is the applied compromise.

## Phase 3: Git history

**Step 3.1 — Blame**
- Record: Resume save/restore added by `b5b7b487431b0` (“gpio: mvebu:
  add suspend/resume support”, Thomas Petazzoni, 2014-10-24), first in
  **v3.19-rc1**. Present for a long time; this is not new 6.18-only
  code.

**Step 3.2 — Fixes: tag**
- Record: None. Buggy pattern is the 2014 suspend/resume support, not a
  recent regression commit.

**Step 3.3 — Related file history**
- Record:
  - `6136c1474db88` gpio: mvebu: fix NULL pointer dereference in
    suspend/resume (PWM NULL) — related path, different bug.
  - `3bfcce441c552` gpio: mvebu: free generic chips on unbind — same
    author, teardown leak, not a prerequisite.
  - No later follow-up on this file after the candidate (`git log
    cb5b039e115ea..HEAD -- drivers/gpio/gpio-mvebu.c` is empty).

**Step 3.4 — Author**
- Record: Rosen Penev is a regular contributor, not the GPIO maintainer.
  Two mvebu commits in this tree. Maintainer (Bartosz) applied it; Linus
  Walleij reviewed v1.

**Step 3.5 — Dependencies**
- Record: Standalone. Uses `irq_get_domain_generic_chip()`,
  `mask_cache_priv`, `gc->lock`, and `mvchip->domain`, all already in
  this tree. Not patch X/Y.

## Phase 4: Mailing list / external

**Step 4.1 — Original discussion**
- Record:
  - Lore / msgid:
    https://patch.msgid.link/20260915004406.115230-1-rosenp@gmail.com
  - **v1:**
    https://patch.msgid.link/20260912221937.71403-1-rosenp@gmail.com —
    held `gc->lock` across `regmap_write`.
  - **v2 (applied):** unlock before `regmap_write` (changelog: “Unlock
    spinlock before regmap_write”).
  - `b4 dig -a` found only v1 and v2. `b4 mbox -c` did not find a newer
    revision.
  - Linus Walleij: `Reviewed-by` on v1.
  - Bartosz: “Applied, thanks!”
  - Sebastian Andrzej Siewior (RT): asked why the mask changes after
    suspend; later “This looks like a hack with no explanation about the
    root cause.” Not a NAK of the hang; complaint about the write-up.
  - Rosen, after apply: “I had a v3 ready … to fix sashiko’s issue. I
    guess I’ll send it separately.” No v3 found in this tree or via
    `b4`.
  - Sashiko bot flagged a TOCTOU after dropping the lock, and a pre-
    existing `saved & cache` lost-IRQ case. The lost-IRQ case is not
    made worse (see 2.4). No reviewer nominated `Cc: stable`.

**Step 4.2 — Recipients (`b4 dig -w`)**
- Record: `linux-gpio@vger.kernel.org`, Linus Walleij, Bartosz
  Golaszewski, linux-kernel; v2 also CC’d Sebastian Siewior, Clark
  Williams, Steven Rostedt, `linux-rt-devel` because of the PREEMPT_RT
  lock/sleep issue.

**Step 4.3 — Bug report**
- Record: No syzbot/bugzilla link. Author reports Helios4 magic-packet
  wakeup hangs without the patch.
  `arch/arm/boot/dts/marvell/armada-388-helios4.dts` is in this tree.

**Step 4.4 — Series**
- Record: Standalone one-patch series. Not 2/3.

**Step 4.5 — Stable list**
- Record: lore.kernel.org/stable search returned HTTP 403. No stable
  discussion found via `b4`. **UNVERIFIED:** whether anyone already
  requested or rejected this on stable@.

## Phase 5: Semantic / call graph

**Step 5.1 — Functions**
- Record: only `mvebu_gpio_resume()`.

**Step 5.2 — Callers**
- Record: `platform_driver.mvebu_gpio_driver.resume`. Reachable from
  system suspend/resume (`dpm_resume` → driver `.resume`), not from a
  syscall on a hot path.

**Step 5.3 — Callees**
- Record: `irq_get_domain_generic_chip()`,
  `raw_spin_lock_irqsave`/`unlock`, `regmap_write()`, optional
  `mvebu_pwm_resume()`.

**Step 5.4 — Reachability**
- Record: Userspace triggers via `/sys/power/state` (or equivalent).
  Helios4 WOL GPIO is a typical level wakeup. `CONFIG_GPIO_MVEBU` is
  `default y` on `ARCH_MVEBU`/`PLAT_ORION`.

**Step 5.5 — Similar patterns**
- Record: No other gpio driver in this tree ANDs resume masks with
  `mask_cache_priv`. This is mvebu-specific because it saves/restores
  mask registers itself instead of using generic irqchip suspend/resume.

## Phase 6: This tree (6.18.y)

**Step 6.1 — Does the bug exist here?**
- Record: **Yes.** `make kernelversion` / Makefile: **6.18.57**. `git
  describe HEAD`: `v6.18.57-155-gcdf239ca885b2`.
- `v6.18.57:drivers/gpio/gpio-mvebu.c` `mvebu_gpio_resume()` writes
  `mvchip->edge_mask_regs[]` / `level_mask_regs[]` with **no** cache
  AND. Diff of that function vs the candidate’s parent is empty.
- Probe in v6.18.57 already has `chip_types[0]` level, `chip_types[1]`
  edge, and `mvchip->domain`.

**Step 6.2 — Backport difficulty**
- Record: **Clean apply.** Same resume function, same irqchip layout,
  same APIs.

**Step 6.3 — Related fixes already here?**
- Record: PWM NULL check in suspend/resume is present and different.
  Nothing else intersects mask-cache vs HW restore.

## Phase 7: Subsystem context

**Step 7.1**
- Record: `drivers/gpio/gpio-mvebu.c` — Marvell Orion/EBU GPIO irqchip.
  **IMPORTANT** for ARCH_MVEBU (Armada 370/XP/38x/8K, Helios4, Clearfog,
  etc.), not core mm/VFS.

**Step 7.2**
- Record: Mature driver (suspend/resume since 2014). Recent commits are
  small fixes, not a rewrite.

## Phase 8: Impact and risk

**Step 8.1 — Who is affected**
- Record: Platform-specific: `CONFIG_GPIO_MVEBU` (default on Marvell
  EBU). Users who suspend/resume, especially with GPIO/level wakeup
  (WOL).

**Step 8.2 — Trigger**
- Record: System suspend then resume with an asserted level GPIO
  (author: magic packet on Helios4). Not unprivileged-exploit in the
  syzbot sense; any user who can suspend can hit it. Timing-sensitive
  around genirq vs HW mask.

**Step 8.3 — Failure mode**
- Record: Chained IRQ storm → resume hang. **CRITICAL** for affected
  boards.

**Step 8.4 — Risk/benefit**
- Record: **Benefit high** (unhang resume on real hardware). **Risk
  low** (one function, conservative AND, tested, GPIO maintainer
  applied). Remaining TOCTOU is a small window required for RT, not a
  reason to keep the hang.

## Phase 9: Synthesis

**Step 9.1 — Evidence**

FOR:
- Resume hang / IRQ storm is a real user-visible failure.
- Author reproduced and tested on Helios4 (DT in this tree).
- Mechanism matches genirq: `mask_irq()` skip + `handle_level_irq()` +
  chained GPIO handler.
- Buggy restore is in **this** 6.18.57 tree; bug dates to v3.19.
- +27/−6, one function, no new API.
- Applies cleanly.
- Reviewed by Linus Walleij; applied by Bartosz Golaszewski.

AGAINST:
- Sebastian Siewior called the explanation a hack (write-up, not a
  demonstrated regression).
- Author mentioned an unsent v3 for a TOCTOU sashiko flagged; not in
  this tree.
- No `Fixes:` / syzbot / stable Cc (not a negative per the rules).
- Driver-specific, not universal.

UNRESOLVED:
- Stable@ discussion (lore 403).
- Whether v3 was ever posted after 2026-09-17.

**Step 9.2 — Stable rules**
1. Obviously correct and tested? **PASS** — AND with irqchip cache;
   Helios4 test; maintainer applied.
2. Real bug affecting users? **PASS** — resume hang on Marvell EBU
   boards.
3. Important (crash/hang/corruption/deadlock)? **PASS** — resume hang /
   IRQ storm.
4. Small and contained? **PASS** — one function, ~30 lines.
5. No new features/APIs? **PASS**.
6. Can apply to this tree? **PASS** — v6.18.57 resume path matches the
   parent.

**Step 9.3 — Exceptions**
- Record: None (not a device ID / quirk / DT / build / docs exception).
  Ordinary driver bugfix.

**Step 9.4 — Decision**
Backport to this 6.18.57 tree. The hang is in-tree, the fix is surgical,
and the remaining RT lock-drop window is weaker than leaving resume
broken.

### What the commit solves for this tree
On 6.18.57, `mvebu_gpio_resume()` still restores suspend-time EDGE/LEVEL
mask registers blindly. If genirq has since masked a line (lazy disable,
wakeup handling, in-progress level IRQ), that write unmasks hardware
while `mask_irq()` is a no-op. An asserted level GPIO then has no ack
path; `mvebu_gpio_irq_handler` storms and resume hangs. AND-ing with
`mask_cache_priv` keeps hardware from going beyond what genirq currently
has unmasked.

### Risk vs benefit
Benefit is an unhang of suspend/resume on in-tree Marvell EBU platforms
(Helios4 and similar). Risk is a short snapshot-vs-write window
(required so `regmap_write` is not called under a raw spinlock on
PREEMPT_RT) and a theoretically more conservative mask; both are
preferable to the current hang.

## Verification
- [Phase 1] Parsed tags: author Rosen Penev; Link msgid
  20260915004406.115230-1; Bartosz SOB; no Fixes/Reported-by/stable Cc.
- [Phase 2] Diff: +27/−6 in `mvebu_gpio_resume()` only; AND saved masks
  with `mask_cache_priv`.
- [Phase 2] Probe in this tree: `chip_types[0]` level, `chip_types[1]`
  edge (`drivers/gpio/gpio-mvebu.c` ~1291–1305).
- [Phase 2] `mask_irq()` skips if `irqd_irq_masked()`
  (`kernel/irq/chip.c:428–431`).
- [Phase 2] `handle_level_irq()` → `mask_ack_irq()` then
  `irq_can_handle()`; disabled lines are not handled (`chip.c:686–697`,
  `544–552`).
- [Phase 2] `gc->lock` is `raw_spinlock_t`
  (`include/linux/irq.h:1052–1053`).
- [Phase 3] Blame: resume path from `b5b7b487431b0`, contained in
  v3.19-rc1; ancestor of HEAD.
- [Phase 3] No follow-up on `gpio-mvebu.c` after this candidate.
- [Phase 4] `b4 dig -c 02af7eac17bc...`: v1 + v2; applied version is v2.
- [Phase 4] `b4 dig -w`: gpio lists + RT CCs on v2.
- [Phase 4] mbox: Linus Walleij Reviewed-by (v1); Bartosz applied;
  Siewior “hack” comment; Rosen mentioned unsent v3.
- [Phase 4] `b4 mbox -c`: no newer revision found.
- [Phase 4] lore.kernel.org WebFetch: 403. UNVERIFIED: stable@ thread.
- [Phase 5] Resume hooked from `mvebu_gpio_driver.resume`;
  `CONFIG_GPIO_MVEBU` default on ARCH_MVEBU
  (`drivers/gpio/Kconfig:509–514`).
- [Phase 6] `make kernelversion`: 6.18.57; `git describe HEAD`:
  v6.18.57-155-gcdf239ca885b2.
- [Phase 6] `git show v6.18.57:drivers/gpio/gpio-mvebu.c` resume ==
  candidate parent (clean apply).
- [Phase 6] Helios4 DT present:
  `arch/arm/boot/dts/marvell/armada-388-helios4.dts`.
- [Phase 8] Failure mode: chained level IRQ storm → resume hang,
  severity CRITICAL for mvebu boards.

**YES**

 drivers/gpio/gpio-mvebu.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 39a7ad6585f25..c613d74ed48d0 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -1006,6 +1006,8 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
 static int mvebu_gpio_resume(struct platform_device *pdev)
 {
 	struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
+	u32 edge_cache = ~0U, level_cache = ~0U;
+	unsigned long flags;
 	int i;
 
 	regmap_write(mvchip->regs, GPIO_OUT_OFF + mvchip->offset,
@@ -1017,32 +1019,51 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
 	regmap_write(mvchip->regs, GPIO_IN_POL_OFF + mvchip->offset,
 		     mvchip->in_pol_reg);
 
+	/*
+	 * genirq skips mask_irq() for a line it already considers masked, so
+	 * unmasking one behind its back leaves an asserted level line that
+	 * nobody masks. Restore only bits the irqchip cache still has set.
+	 *
+	 * Snapshot the caches under the raw spinlock, but release it before
+	 * the regmap writes below: regmap_write() takes a sleepable lock on
+	 * PREEMPT_RT.
+	 */
+	if (mvchip->domain) {
+		struct irq_chip_generic *gc;
+
+		gc = irq_get_domain_generic_chip(mvchip->domain, 0);
+		raw_spin_lock_irqsave(&gc->lock, flags);
+		level_cache = gc->chip_types[0].mask_cache_priv;
+		edge_cache = gc->chip_types[1].mask_cache_priv;
+		raw_spin_unlock_irqrestore(&gc->lock, flags);
+	}
+
 	switch (mvchip->soc_variant) {
 	case MVEBU_GPIO_SOC_VARIANT_ORION:
 	case MVEBU_GPIO_SOC_VARIANT_A8K:
 		regmap_write(mvchip->regs, GPIO_EDGE_MASK_OFF + mvchip->offset,
-			     mvchip->edge_mask_regs[0]);
+			     mvchip->edge_mask_regs[0] & edge_cache);
 		regmap_write(mvchip->regs, GPIO_LEVEL_MASK_OFF + mvchip->offset,
-			     mvchip->level_mask_regs[0]);
+			     mvchip->level_mask_regs[0] & level_cache);
 		break;
 	case MVEBU_GPIO_SOC_VARIANT_MV78200:
 		for (i = 0; i < 2; i++) {
 			regmap_write(mvchip->regs,
 				     GPIO_EDGE_MASK_MV78200_OFF(i),
-				     mvchip->edge_mask_regs[i]);
+				     mvchip->edge_mask_regs[i] & edge_cache);
 			regmap_write(mvchip->regs,
 				     GPIO_LEVEL_MASK_MV78200_OFF(i),
-				     mvchip->level_mask_regs[i]);
+				     mvchip->level_mask_regs[i] & level_cache);
 		}
 		break;
 	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
 		for (i = 0; i < 4; i++) {
 			regmap_write(mvchip->regs,
 				     GPIO_EDGE_MASK_ARMADAXP_OFF(i),
-				     mvchip->edge_mask_regs[i]);
+				     mvchip->edge_mask_regs[i] & edge_cache);
 			regmap_write(mvchip->regs,
 				     GPIO_LEVEL_MASK_ARMADAXP_OFF(i),
-				     mvchip->level_mask_regs[i]);
+				     mvchip->level_mask_regs[i] & level_cache);
 		}
 		break;
 	default:
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-6.6] gpio: pca9570: Use I2C match data
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (3 preceding siblings ...)
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] gpio: mvebu: keep resume masks within the irqchip cache Sasha Levin
@ 2026-10-19 13:49 ` Sasha Levin
  2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-6.1] gpio: sifive: add missing MODULE_DEVICE_TABLE() Sasha Levin
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:49 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Bartosz Golaszewski, Sasha Levin, linusw, brgl,
	linux-gpio, linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit 415c63896b76fd98883e190bc7518383cb01779c ]

The driver stores chip metadata in both the OF match table and the I2C
id table, but probe currently reads it with device_get_match_data().
That helper only returns firmware-node match data, so an I2C-id/modalias
match can leave chip_data NULL before the driver dereferences it to read
ngpio.

Use i2c_get_match_data() so the I2C id table driver_data is consumed
when firmware match data is not present.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260624053744.72612-1-pengpeng@iscas.ac.cn
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit message forensics

**Step 1.1: Subject line**
- Record: `[gpio/pca9570] [Use] Switch probe from firmware-only match
  data to I2C match data so I2C-id/modalias binds get chip metadata`

**Step 1.2: Tags**
- Record:
  - `Fixes:`: none (expected for this review)
  - `Reported-by:`: none
  - `Tested-by:`: none
  - `Reviewed-by:`: none
  - `Acked-by:`: none
  - `Link:` `https://patch.msgid.link/20260624053744.72612-1-
    pengpeng@iscas.ac.cn`
  - `Cc: stable`: none (expected)
  - `Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>` (author)
  - `Signed-off-by: Bartosz Golaszewski
    <bartosz.golaszewski@oss.qualcomm.com>` (GPIO maintainer)
  - Pipeline `Signed-off-by: Sasha Levin` / `[Upstream commit
    415c63896b76...]` ignored per instructions

**Step 1.3: Body**
- Record: `[Bug] Probe uses device_get_match_data() while chip metadata
  lives in both OF and I2C id tables. That helper only returns firmware-
  node data.` `[Symptom] I2C-id/modalias bind leaves chip_data NULL;
  probe then reads chip_data->ngpio.` `[Versions] None stated.` `[Root
  cause] Wrong match-data helper; I2C id table driver_data is never
  consumed.`

**Step 1.4: Hidden bug fix?**
- Record: This is an explicit bug fix, not cleanup. The subject says
  “Use” rather than “fix”, but the body describes a NULL dereference on
  probe.

## Phase 2: Diff analysis

**Step 2.1: Inventory**
- Record: `[Files] drivers/gpio/gpio-pca9570.c: 1 insertion, 1 deletion`
  `[Function] pca9570_probe()` `[Scope] Single-file, one-line surgical
  change`

The candidate as applied on this tree is exactly that one-line swap.
Mainline context around `devm_mutex_init()` is not in 6.18.y
(`mutex_init()` is still used here); it does not affect the hunk.

**Step 2.2: Code flow**
- Record: `[Before] gpio->chip_data =
  device_get_match_data(&client->dev); then gpio->chip.ngpio =
  gpio->chip_data->ngpio;` `[After] Same dereference, but chip_data
  comes from i2c_get_match_data(client).` Path: probe / initialization,
  not an error path.

**Step 2.3: Bug mechanism**
- Record: `[Category] Memory safety — NULL pointer dereference`
  `[Mechanism] device_get_match_data() is fwnode-only
  (drivers/base/property.c). i2c_device_match() can still bind via
  i2c_match_id() when there is no OF/ACPI data. Probe then dereferences
  NULL. i2c_get_match_data() tries firmware data first, then
  id_table->driver_data.`

Verified helper:

```121:137:drivers/i2c/i2c-core-base.c
const void *i2c_get_match_data(const struct i2c_client *client)
{
        struct i2c_driver *driver = to_i2c_driver(client->dev.driver);
        const struct i2c_device_id *match;
        const void *data;

        data = device_get_match_data(&client->dev);
        if (!data) {
                match = i2c_match_id(driver->id_table, client);
                if (!match)
                        return NULL;

                data = (const void *)match->driver_data;
        }

        return data;
}
```

The id table already stores the pointers probe needs:

```158:163:drivers/gpio/gpio-pca9570.c
static const struct i2c_device_id pca9570_id_table[] = {
        { "pca9570", (kernel_ulong_t)&pca9570_gpio},
        { "pca9571", (kernel_ulong_t)&pca9571_gpio },
        { "slg7xl45106", (kernel_ulong_t)&slg7xl45106_gpio },
        { /* sentinel */ }
};
```

**Step 2.4: Fix quality**
- Record: `[Quality] Obviously correct; this is the I2C-core helper used
  by pca953x/pcf857x in this tree.` `[Regression risk] Very low.
  Firmware path is unchanged (helper still calls device_get_match_data
  first). No locking, API, or data-structure change. Still no NULL check
  after the lookup; that is not a regression versus the OF path.`

## Phase 3: Git history

**Step 3.1: Blame**
- Record: `[Introduced] Pointer dereference of match data: b8a34582c7f7f
  (“gpio: pca9570: add a platform data structure”, 2022-10-27, contained
  in v6.2-rc1).` Before that, 16d44b6085c1d (2020) used
  `(uintptr_t)device_get_match_data()`, so a missing firmware match set
  `ngpio = 0` instead of oopsing. The crash exists from v6.2 onward.
  Helper `i2c_get_match_data()`: 564d73c4d9201, contained in v6.5-rc1;
  present in this tree.

**Step 3.2: Fixes: tag**
- Record: No `Fixes:` tag. Buggy commit `b8a34582c7f7f` is an ancestor
  of HEAD.

**Step 3.3: File history**
- Record: Recent file commits are GPIO callback renames, kerneldoc,
  probe-style switch, chip_data rename, slg7xl45106/pca9571 support. No
  prerequisite refactor is required for this one-line swap. Standalone,
  not patch X/Y.

**Step 3.4: Author**
- Record: Pengpeng Hou has several GPIO fixes on this branch
  (MODULE_DEVICE_TABLE, probe-failure handling). Not the GPIO
  maintainer. Maintainer Bartosz Golaszewski applied the patch.

**Step 3.5: Dependencies**
- Record: Depends only on `i2c_get_match_data()`, which exists in
  v6.18.53 (`include/linux/i2c.h` and `drivers/i2c/i2c-core-base.c`).
  Can apply standalone. Applied commit `f191ba12096a2` is a clean 2-line
  change on this tree.

## Phase 4: Mailing list / external

**Step 4.1: Original discussion**
- Record: `[Lore]
  https://patch.msgid.link/20260624053744.72612-1-pengpeng@iscas.ac.cn`
  `[Revisions] v1 only, single patch` `[Feedback] Maintainer reply:
  “Applied, thanks!” No NAK, no requested changes, no Cc: stable
  suggestion.` Direct lore.kernel.org fetch returned 403; full thread
  recovered via `b4 dig -m`.

**Step 4.2: Recipients (`b4 dig -w`)**
- Record: Linus Walleij, Bartosz Golaszewski, linux-gpio@, linux-
  kernel@. Correct GPIO maintainers and list. Applied by Bartosz.

**Step 4.3: Bug report**
- Record: No Reported-by / bugzilla / syzbot. Bug is deduced from the
  code: I2C-id bind + firmware-only helper.

**Step 4.4: Series**
- Record: Standalone v1. Sibling GPIO conversions already in this tree:
  `ea05787136256` (pca953x) and `db3b16dcc7e4f` (pcf857x). Not
  prerequisites.

**Step 4.5: Stable list**
- Record: Original submission did not Cc stable. lore.kernel.org/stable
  search could not be fetched (HTTP 403). No stable-specific discussion
  in the recovered thread.

## Phase 5: Semantic analysis

**Step 5.1: Functions**
- Record: `pca9570_probe()` only.

**Step 5.2: Callers**
- Record: Only `pca9570_driver.probe`. Invoked from I2C core on client
  bind (boot DT, ACPI, `i2c_new_client_device()`, sysfs `new_device`).
  Not IRQ/hot-path.

**Step 5.3: Callees**
- Record: After the lookup, probe still uses `chip_data->ngpio`,
  `devm_mutex_init`/`mutex_init`, `pca9570_read`,
  `devm_gpiochip_add_data`. The only behavioral change is where match
  data comes from.

**Step 5.4: Reachability**
- Record: DT boards with `compatible = "nxp,pca9570"` (imx95-15x15-evk,
  imx8mp-dhcom-pdk3, stm32mp157c-lxa-tac-gen1) already get firmware
  match data and do not hit the bug. The broken path is I2C-id/modalias:
  sysfs `new_device`, board-info, or any client without a firmware node.
  That is a supported I2C instantiation method (`new_device_store` in
  i2c-core). Needs privileges to write sysfs; still a deterministic
  probe oops for that path.

**Step 5.5: Similar patterns**
- Record: Same class of I2C GPIO expanders already use
  `i2c_get_match_data()` (`gpio-pca953x.c`, `gpio-pcf857x.c`). pca953x
  also NULL-checks; this patch does not add that check.

## Phase 6: Local tree (this checkout only)

**Step 6.1: Does the bug exist here?**
- Record: Local tree is **6.18.53** (`git describe HEAD`:
  `v6.18.53-5049-g0f0bdc2b0dffb`; Makefile `VERSION=6 PATCHLEVEL=18
  SUBLEVEL=53`). At `v6.18.53`, probe still does
  `device_get_match_data()` then `chip_data->ngpio`. Bug present.
  Candidate is **not** an ancestor of `v6.18.53`. Crash-introducing
  commit `b8a34582c7f7f` (v6.2) is in this tree.

**Step 6.2: Backport difficulty**
- Record: Clean apply. On this tree the change is exactly one call swap;
  no `devm_mutex_init` conflict.

**Step 6.3: Related fixes already here?**
- Record: No earlier pca9570 match-data fix. pca953x/pcf857x already
  converted; this driver was left on the firmware-only helper.

## Phase 7: Subsystem context

**Step 7.1**
- Record: `[Subsystem] drivers/gpio (I2C GPO expander)` `[Criticality]
  PERIPHERAL / driver-specific` — NXP PCA9570/PCA9571 and Dialog
  SLG7XL45106. Not core MM/VFS, but in-tree boards and
  `CONFIG_GPIO_PCA9570` users exist.

**Step 7.2**
- Record: GPIO I2C expanders are mature. This file is low-churn except
  callback API updates. Long-standing bug (since v6.2), not churn from a
  new subsystem.

## Phase 8: Impact and risk

**Step 8.1: Who is affected**
- Record: Driver-specific / config-specific (`CONFIG_GPIO_PCA9570`). DT
  users are fine. Users instantiating via I2C id/modalias oops in probe.

**Step 8.2: Trigger**
- Record: `[Trigger] Bind pca9570/pca9571/slg7xl45106 without firmware
  match data.` `[Likelihood] Uncommon vs DT, but 100% on that path (not
  a race).` `[Unprivileged?] No; sysfs new_device is privileged. Not a
  local-priv-esc issue.`

**Step 8.3: Failure mode**
- Record: `[Failure] NULL deref in pca9570_probe → kernel oops`
  `[Severity] HIGH (crash on probe for a supported bind method). Not
  data corruption or unprivileged security.`

**Step 8.4: Risk vs benefit**
- Record: `[Benefit] Prevents a deterministic probe oops; makes the
  existing I2C id table actually work.` `[Risk] Very low: one line,
  established helper, firmware path unchanged.` `[Ratio] Favorable.`

## Phase 9: Synthesis

**Step 9.1: Evidence**

For:
- Real NULL deref when I2C-id matching; helper and dereference verified
  in this tree
- One-line, obviously correct; GPIO maintainer applied v1 with no
  objections
- `i2c_get_match_data()` already in 6.18.y; applies cleanly
- Same pattern already used by sibling GPIO I2C expanders
- In-tree DT users exist, so the driver is not dead; the I2C id table
  with `driver_data` is currently unused/wrong

Against:
- No user/syzbot report
- In-tree boards use DT, so they do not hit it
- Peripheral driver, not core
- Probe still does not NULL-check `chip_data` (pre-existing)

Unresolved:
- lore.kernel.org HTTP 403 for live HTML; thread recovered via b4 mbox
- No stable@ discussion found

**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — one helper swap; maintainer
   applied; helper semantics verified
2. Fixes a real bug that affects users? **PASS** — NULL deref on a
   supported I2C bind path
3. Important (crash/security/corruption/deadlock)? **PASS** — probe oops
   (HIGH, not universal CRITICAL)
4. Small and contained? **PASS** — 1 line, one file
5. No new features/APIs? **PASS**
6. Can apply to this tree? **PASS** — clean on 6.18.53; helper present

**Step 9.3: Exception category**
- Record: None (not a device ID/quirk/DT/build/docs exception). It is a
  normal small crash fix.

**Step 9.4: Decision**
This belongs in this 6.18.y tree: the buggy code is here, the helper is
here, and the fix is a one-line swap that stops a NULL deref on I2C-id
probe.

## What the commit solves

`pca9570_probe()` treats `device_get_match_data()` as the source of
`struct pca9570_chip_data`, then immediately reads `->ngpio`. That
helper only consults firmware nodes. I2C matching can still succeed from
`id_table` (sysfs `new_device`, board info, modalias). `chip_data` is
then NULL and probe oopses. `i2c_get_match_data()` keeps the DT path and
consumes the id-table pointers this driver already stores.

For 6.18 stable users this is a small crash fix, not a feature. DT
boards keep working; non-firmware instantiation stops oopsing.

## Verification
- [Phase 1] Parsed tags: author + GPIO maintainer SOB, lore Link; no
  Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: 1 line in `pca9570_probe()`; `device_get_match_data` →
  `i2c_get_match_data`
- [Phase 2] `device_get_match_data()` is fwnode-only
  (`drivers/base/property.c:1346`)
- [Phase 2] `i2c_get_match_data()` falls back to `id_table->driver_data`
  (`i2c-core-base.c:121`)
- [Phase 2] `i2c_device_match()` binds OF, then ACPI, then I2C id
  (`i2c-core-base.c:140`)
- [Phase 3] Blame: crash introduced by `b8a34582c7f7f` (v6.2-rc1);
  helper from `564d73c4d9201` (v6.5-rc1)
- [Phase 3] `git merge-base --is-ancestor b8a34582c7f7f HEAD` → yes;
  helper ancestor → yes
- [Phase 4] `b4 dig -c 415c63896b76`: v1 only; recipients GPIO
  maintainers; mbox: “Applied, thanks!”
- [Phase 4] lore.kernel.org WebFetch: HTTP 403; used b4 mbox instead
- [Phase 5] `pca9570_probe` only used as `i2c_driver.probe`
- [Phase 5] DT users: imx95-15x15-evk, imx8mp-dhcom-pdk3,
  stm32mp157c-lxa-tac-gen1
- [Phase 6] `git describe HEAD` → `v6.18.53-5049-g0f0bdc2b0dffb`; `make
  kernelversion` → 6.18.53
- [Phase 6] `v6.18.53:drivers/gpio/gpio-pca9570.c` still uses
  `device_get_match_data`; candidate not in `v6.18.53`
- [Phase 6] Applied form on this branch: clean 2-line change
  (`f191ba12096a2`)
- [Phase 8] Failure mode: NULL deref in probe → oops; DT path unaffected
- UNVERIFIED: live lore.kernel.org/stable HTML search (HTTP 403)

The patch is obviously correct, fixes a real probe oops, is one line,
and applies cleanly to this 6.18.y tree.

**YES**

 drivers/gpio/gpio-pca9570.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-pca9570.c b/drivers/gpio/gpio-pca9570.c
index c5a1287079a06..f7cc3fbf45336 100644
--- a/drivers/gpio/gpio-pca9570.c
+++ b/drivers/gpio/gpio-pca9570.c
@@ -128,7 +128,7 @@ static int pca9570_probe(struct i2c_client *client)
 	gpio->chip.get = pca9570_get;
 	gpio->chip.set = pca9570_set;
 	gpio->chip.base = -1;
-	gpio->chip_data = device_get_match_data(&client->dev);
+	gpio->chip_data = i2c_get_match_data(client);
 	gpio->chip.ngpio = gpio->chip_data->ngpio;
 	gpio->chip.can_sleep = true;
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-6.1] gpio: sifive: add missing MODULE_DEVICE_TABLE()
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (4 preceding siblings ...)
  2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-6.6] gpio: pca9570: Use I2C match data Sasha Levin
@ 2026-10-19 13:50 ` Sasha Levin
  2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] pinctrl: sx150x: " Sasha Levin
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:50 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Bartosz Golaszewski, Sasha Levin, linusw, brgl, pjw,
	samuel.holland, linux-gpio, linux-riscv, linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit 8fe6fa0f223f44b8b869319d1b9c383749aa147b ]

The driver has an OF match table wired to .of_match_table, but does
not export the table with MODULE_DEVICE_TABLE().

Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias
information is generated for OF based module autoloading.

This is a source-level fix.  It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the platform driver, and the missing module alias publication.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260704122230.75964-1-pengpeng@iscas.ac.cn
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

I have the local-tree identity, the one-line diff, and the mailing-list
thread, including the GPIO maintainer asking for a `Fixes:`/`Cc: stable`
resend. Compiling the nine-phase verdict next.

## Phase 1: Commit message forensics

**Step 1.1: Subject line**
- Record: `[gpio] [add] add missing MODULE_DEVICE_TABLE() so OF module
  aliases are generated`

**Step 1.2: Tags**
- Record:
  - `Fixes:` — none (expected)
  - `Reported-by:` — none
  - `Tested-by:` — none
  - `Reviewed-by:` — none on the applied commit
  - `Acked-by:` — none
  - `Link: https://patch.msgid.link/20260704122230.75964-1-
    pengpeng@iscas.ac.cn`
  - `Cc: stable@vger.kernel.org` — none (expected)
  - `Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>` (author)
  - `Signed-off-by: Bartosz Golaszewski
    <bartosz.golaszewski@oss.qualcomm.com>` (GPIO maintainer, committer)
  - Notable: no syzbot, no user crash report. Maintainer SOB is a
    quality signal.

**Step 1.3: Body**
- Record: **Bug:** `sifive_gpio_match[]` is wired to `.of_match_table`
  but not published via `MODULE_DEVICE_TABLE()`, so modpost does not
  emit OF aliases. **Symptom:** `gpio-sifive.ko` does not autoload from
  DT compatible strings (`sifive,gpio0`, `sifive,fu540-c000-gpio`).
  **Version info:** none in the message. **Root cause:** missing module-
  alias publication, not a runtime logic error in probe. The “source-
  level fix / no dynamic hardware reproduction” wording is extra
  justification, not a different bug.

**Step 1.4: Hidden bug fix?**
- Record: Not hidden. This is an explicit autoload fix. “Add missing
  MODULE_DEVICE_TABLE” is a standard class of real functional bugs for
  `tristate` OF drivers.

## Phase 2: Diff analysis

**Step 2.1: Inventory**
- Record: `drivers/gpio/gpio-sifive.c` — **+1 / -0**. One insertion
  after `sifive_gpio_match[]`. No functions changed. **Scope:** single-
  file surgical fix.

**Step 2.2: Code flow**
- Record: **Before:** OF match table exists and is used by
  `platform_driver.driver.of_match_table`, so a *already loaded* driver
  still binds. No `__mod_device_table__*` alias is emitted, so kmod/udev
  cannot load the module from DT. **After:** `MODULE_DEVICE_TABLE(of,
  sifive_gpio_match)` creates a used alias to that table;
  `scripts/mod/file2alias.c` (`do_of_entry`) emits
  `of:N*T*Csifive,gpio0` / `sifive,fu540-c000-gpio` aliases. **Path
  affected:** build-time modpost / userspace autoload only. Probe and
  IRQ setup are unchanged.

**Step 2.3: Bug mechanism**
- Record: **Category:** hardware enablement / missing module alias
  (logic/correctness at the module-loading boundary). **Mechanism:**
  `CONFIG_GPIO_SIFIVE=m` never autoloads; GPIO controller stays unbound
  unless `modprobe` is done by hand. Same class as device-ID additions:
  existing driver, existing hardware, missing match publication.

**Step 2.4: Fix quality**
- Record: Obviously correct one-liner; this is the documented way to
  export OF aliases. No locking, no API, no data-structure change.
  **Regression risk:** negligible. For `=y` it is a no-op at runtime. No
  new userspace ABI beyond standard `modules.alias` entries.

## Phase 3: Git history

**Step 3.1: Blame**
- Record: Match table introduced in `96868dce644d0` (“gpio/sifive: Add
  GPIO driver for SiFive SoCs”, 2019; in `v5.5-rc4`). Originally `bool`
  + `builtin_platform_driver()`, so `MODULE_DEVICE_TABLE` was not
  required. Bug became real in `6b4c76ded35826` (“gpio: sifive: Allow
  building the driver as a module”, 2023-07-25) which switched Kconfig
  to `tristate` and `module_platform_driver()` **without** adding
  `MODULE_DEVICE_TABLE`. That commit is in `v6.6-rc1` and later.
  `of_match_table = sifive_gpio_match` confirmed via blame
  (`6ae42529547a4f` dropped `of_match_ptr` in 2023).

**Step 3.2: Fixes: tag**
- Record: No `Fixes:` on the candidate. The implicit Fixes target is
  `6b4c76ded35826`, which **is** an ancestor of this tree (`git merge-
  base --is-ancestor` succeeded). GPIO maintainer Bartosz said the same
  on list (Phase 4).

**Step 3.3: File history**
- Record: Recent `gpio-sifive.c` work is generic-chip API
  (`8e1c8ccc1df8b`) and the modular conversion. No prerequisite series
  for this one line. Standalone.

**Step 3.4: Author**
- Record: Pengpeng Hou is not the GPIO maintainer; same-day sibling
  `975a1d61260cf` (“gpio: vf610: add missing MODULE_DEVICE_TABLE()”).
  Samuel Holland (SiFive, author of the modular conversion) sent the
  identical one-line change earlier (Oct 2025) as “Support module
  autoloading”.

**Step 3.5: Dependencies**
- Record: Needs `sifive_gpio_match[]`, `module_platform_driver()`, and
  `MODULE_DEVICE_TABLE(of, ...)`. All exist in this checkout. Applies
  standalone.

## Phase 4: Mailing list / external

**Step 4.1: Original discussion**
- Record: `b4 dig -c 8fe6fa0f223f44` matched patch-id to:
  - v1 (applied):
    https://patch.msgid.link/20260704122230.75964-1-pengpeng@iscas.ac.cn
    (2026-07-04, Pengpeng Hou)
  - Same diff, earlier: https://patch.msgid.link/20251016003631.3912523-
    1-samuel.holland@sifive.com (2025-10-15, Samuel Holland)
- Single revision of Pengpeng’s patch. Bartosz: “Applied, thanks!”
  (2026-07-06). No NAK.
- On Samuel’s earlier post, Bartosz wrote it should have been part of
  `6b4c76ded358` and asked him to **resend with `Fixes:` and `Cc:
  stable`**. That resend did not land; Pengpeng’s later patch (without
  those tags) was applied instead.

**Step 4.2: Recipients (`b4 dig -w`)**
- Record: Pengpeng Hou, Linus Walleij, Bartosz Golaszewski, Paul
  Walmsley, Samuel Holland, `linux-gpio`, `linux-riscv`, `linux-kernel`.
  GPIO maintainers were on To/Cc.

**Step 4.3: Bug report**
- Record: No syzbot/bugzilla. Evidence is source-level plus vendor
  (SiFive) sending the same patch. No count of field reports.

**Step 4.4: Series**
- Record: Standalone 1/1. Sibling vf610 fix is a separate driver, not a
  dependency.

**Step 4.5: Stable list**
- Record: lore.kernel.org via WebFetch returned 403. Stable-list search
  **UNVERIFIED** by HTTP. Maintainer request for `Cc: stable` is from
  `linux-gpio` mbox, not from `stable@`.

## Phase 5: Semantic analysis

**Step 5.1: Functions**
- Record: No functions modified. Added `MODULE_DEVICE_TABLE(of,
  sifive_gpio_match)` after `sifive_gpio_match[]`. Related symbols:
  `sifive_gpio_probe`, `sifive_gpio_driver`.

**Step 5.2: Callers**
- Record: `sifive_gpio_probe` is the platform `.probe`. Driver core
  calls it when OF compatible matches **and the module is already
  loaded**. Autoload is userspace (kmod) using aliases from
  `MODULE_DEVICE_TABLE`. Not IRQ/hot-path.

**Step 5.3: Callees**
- Record: Unchanged. Probe still uses generic GPIO + irqchip
  registration.

**Step 5.4: Reachability**
- Record: Reachable on SiFive FU540/FU740 and Canaan K210 DT
  (`compatible = "sifive,gpio0"` / `"sifive,fu540-c000-gpio"`).
  Userspace-visible: without aliases, GPIO never appears unless the
  module is forced. Not a syscall crash path.

**Step 5.5: Similar patterns**
- Record: Same pattern in-tree: `gpio: lpc32xx: fix module autoloading`,
  `gpio: modepin: Enable module autoloading`, `gpio: vf610: add missing
  MODULE_DEVICE_TABLE()`, `gpio: cadence: Add missing
  MODULE_DEVICE_TABLE`. Established GPIO-subsystem practice.

## Phase 6: Local tree (this checkout only)

**Step 6.1: Buggy code in this tree?**
- Record: Checkout is **Linus `origin/master`**, `git describe` =
  `v7.3-rc4-27-gf0100363d8c37`, Makefile **7.3.0-rc4**. `gpio-sifive.c`,
  `sifive_gpio_match[]`, `tristate GPIO_SIFIVE`, and
  `module_platform_driver()` are all present. Modular conversion
  `6b4c76ded35826` is an ancestor. The one-line alias export belongs on
  this code. In-tree DT: `arch/riscv/boot/dts/sifive/fu540-c000.dtsi`,
  `fu740-c000.dtsi`, `arch/riscv/boot/dts/canaan/k210.dtsi`. Defconfigs
  (`arch/riscv/configs/defconfig`, K210 defconfigs) set
  `CONFIG_GPIO_SIFIVE=y`, so *default* RISC-V configs do not hit
  autoload; `=m` (the reason the driver was made modular: multiplatform
  image size) does.

**Step 6.2: Backport difficulty**
- Record: Clean apply. Only needs the `of_device_id` table name
  `sifive_gpio_match`. No conflict with later generic-chip changes.

**Step 6.3: Related fixes already here**
- Record: No earlier alternate autoload fix. This is the first
  `MODULE_DEVICE_TABLE` on this file.

## Phase 7: Subsystem context

**Step 7.1**
- Record: **Subsystem:** GPIO (`drivers/gpio/`). **Criticality:**
  IMPORTANT for SiFive/K210 boards (GPIO is a board-level dependency),
  PERIPHERAL vs core mm/net. Not staging.

**Step 7.2**
- Record: GPIO is actively maintained (Bartosz). This driver is mature
  (since v5.5); the modular hole is from v6.6, not new experimental
  code.

## Phase 8: Impact and risk

**Step 8.1: Who is affected**
- Record: Driver-specific, config-specific: `CONFIG_GPIO_SIFIVE=m` on DT
  platforms with those compatibles. Not universal.

**Step 8.2: Trigger**
- Record: Boot / device enumeration with the module not preloaded.
  Common for multiplatform modular kernels (the stated goal of
  `6b4c76ded358`). Unprivileged users do not trigger a crash; the
  controller simply never binds. Not a race.

**Step 8.3: Failure mode**
- Record: GPIO chip (and its irqchip) never registers if the module is
  not loaded. Dependent LEDs, resets, keys, hog lines fail. **Severity:
  MEDIUM** functionally (hardware dead until `modprobe`), not panic/UAF.
  For those boards that is user-visible breakage, not cosmetic.

**Step 8.4: Risk-benefit**
- Record: **Benefit:** high for `=m` SiFive/K210 users; restores the
  modular conversion’s purpose. **Risk:** very low (1 line, build-time
  alias only). **Ratio:** strongly favorable. Matches the device-ID /
  hardware-enablement exception.

## Phase 9: Synthesis

**Step 9.1: Evidence**
- **For:** Real autoload bug; 1-line obviously correct; GPIO maintainer
  asked for `Fixes:` + `Cc: stable` on the identical diff; SiFive
  engineer sent that diff; driver is `tristate` since v6.6; DT hardware
  exists; zero runtime regression surface; same pattern already used
  across GPIO.
- **Against:** Not a crash/security/corruption issue; in-tree defconfigs
  use `=y`; no `Reported-by`; Pengpeng’s applied patch omitted the
  `Fixes:`/`Cc: stable` Bartosz asked for.
- **Unresolved:** Stable-list archive (lore HTTP 403). No field bugzilla
  count.

**Step 9.2: Stable rules**
1. Obviously correct and tested? **PASS** — canonical
   `MODULE_DEVICE_TABLE(of, …)`; maintainer applied it.
2. Real bug affecting users? **PASS** — `=m` never autoloads; modular
   conversion is pointless without it.
3. Important (crash/security/corruption/deadlock)? **PASS** as hardware-
   enablement (GPIO controller never binds), same bar as new device IDs
   / missing aliases — not a panic, but the device does not work.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features/APIs? **PASS** — aliases for existing compatibles.
6. Can apply to this tree? **PASS** — table, tristate Kconfig, and
   `module_platform_driver()` are here.

**Step 9.3: Exception category**
- Record: Closest to **device ID / hardware enablement**: publishing
  existing OF IDs so the existing driver autoloads. Not a new driver or
  API.

**Step 9.4: Decision**
This tree has the SiFive GPIO driver as a module-capable OF platform
driver with a match table that was never exported. That is a real,
contained autoload bug. The GPIO maintainer already treated the
identical change as stable material. It should be backported here.

### What the commit solves for this tree
Without `MODULE_DEVICE_TABLE(of, sifive_gpio_match)`, `modpost` never
writes OF aliases, so `gpio-sifive.ko` will not load from
`"sifive,gpio0"` / `"sifive,fu540-c000-gpio"`. On `CONFIG_GPIO_SIFIVE=m`
the GPIO (and irq) controller never appears unless someone `modprobe`s
it. That undercuts `6b4c76ded358` (“Allow building the driver as a
module”) on multiplatform kernels. Built-in `=y` is unaffected; the one-
liner is still correct and harmless.

### Risk vs benefit
Benefit is restoring autoload for real FU540/FU740/K210 hardware when
the driver is modular. Risk is a single build-time alias with no
probe/locking/API change.

### Concerns
No `Fixes:` on the applied commit (should be `6b4c76ded35826`); that
does not block backport. In-tree defconfigs use `=y`, so default images
already work; the users who need this are modular/multiplatform configs,
which is exactly who the tristate change was for.

Verification:
- [Phase 1] Parsed tags: Link to msgid
  `20260704122230.75964-1-pengpeng@iscas.ac.cn`; SOB Pengpeng Hou and
  Bartosz Golaszewski; no Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: +1 line `MODULE_DEVICE_TABLE(of, sifive_gpio_match)`
  in `drivers/gpio/gpio-sifive.c`; probe unchanged
- [Phase 2] Confirmed `MODULE_DEVICE_TABLE` in `include/linux/module.h`
  and OF alias emission via `scripts/mod/file2alias.c` `do_of_entry`
- [Phase 3] `git blame`: match table from `96868dce644d0` (v5.5-rc4);
  modular bug from `6b4c76ded35826` (in v6.6-rc1); `git merge-base --is-
  ancestor 6b4c76ded35826 HEAD` succeeded
- [Phase 3] `git show 6b4c76ded35826`: bool→tristate +
  `builtin_platform_driver` → `module_platform_driver` without
  MODULE_DEVICE_TABLE
- [Phase 3] Author log: sibling vf610 commit `975a1d61260cf`
- [Phase 4] `b4 dig -c 8fe6fa0f223f44`: Pengpeng v1 applied; same patch-
  id as Samuel Holland Oct 2025
- [Phase 4] `b4 dig -a`: single Pengpeng revision; `b4 dig -w`: GPIO
  maintainers + linux-gpio/linux-riscv
- [Phase 4] mbox: Bartosz asked Samuel for Fixes: + Cc: stable; later
  “Applied, thanks!” on Pengpeng’s patch
- [Phase 4] WebFetch lore.kernel.org: 403 — UNVERIFIED via HTTP; thread
  recovered with b4 mbox
- [Phase 5] Callers: platform probe + OF match table; autoload is
  userspace/kmod, not a kernel hot path
- [Phase 5] Similar GPIO autoload fixes: `11baa36d31732`,
  `a5135526426df`, `e6382fcf98907`
- [Phase 6] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37; `make
  kernelversion` = 7.3.0-rc4; detached `origin/master`
- [Phase 6] Kconfig `GPIO_SIFIVE` is `tristate`; DT nodes present;
  defconfigs use `=y`
- [Phase 8] Failure mode: module not autoloaded → GPIO controller
  absent; severity MEDIUM functional / hardware-enablement
- UNVERIFIED: whether this exact commit was discussed on
  `stable@vger.kernel.org` (lore HTTP 403)
- UNVERIFIED: how many distro configs set `CONFIG_GPIO_SIFIVE=m`

**YES**

 drivers/gpio/gpio-sifive.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
index 94ef2efbd14f5..e9a992cd4b9cd 100644
--- a/drivers/gpio/gpio-sifive.c
+++ b/drivers/gpio/gpio-sifive.c
@@ -260,6 +260,7 @@ static const struct of_device_id sifive_gpio_match[] = {
 	{ .compatible = "sifive,fu540-c000-gpio" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, sifive_gpio_match);
 
 static struct platform_driver sifive_gpio_driver = {
 	.probe		= sifive_gpio_probe,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] pinctrl: sx150x: add missing MODULE_DEVICE_TABLE()
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (5 preceding siblings ...)
  2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-6.1] gpio: sifive: add missing MODULE_DEVICE_TABLE() Sasha Levin
@ 2026-10-19 13:51 ` Sasha Levin
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: enable RMII outputs from RMII groups Sasha Levin
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:51 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Linus Walleij, Sasha Levin, linux-gpio,
	linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit 5fe4b12c087db3e565f53b87f1dafdf2f0d1ee0f ]

The driver has a match table for the i2c bus wired into its driver
structure, but the table is not exported with MODULE_DEVICE_TABLE().

Add the missing MODULE_DEVICE_TABLE() entry so module alias information
is generated for automatic module loading.

This is a source-level fix.  It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the driver registration structure, and the missing module alias
publication.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

I have enough to judge this: a one-line I2C alias export on a driver
that is modular in this tree, with OF autoload already working.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: PARSE THE SUBJECT LINE**

Record: **[pinctrl/sx150x] [add] [export the existing I2C match table
via MODULE_DEVICE_TABLE() so module aliases are generated]**

- Subsystem prefix: `pinctrl: sx150x:`
- Action verb: **add**
- Claimed intent: publish missing I2C module aliases for automatic
  loading

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**

Commit: `5fe4b12c087db3e565f53b87f1dafdf2f0d1ee0f`

Record:
- **Fixes:** none (expected)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** none
- **Acked-by:** none
- **Link:** none in the git commit (lore exists; see Phase 4)
- **Cc: stable:** none (expected)
- **Signed-off-by:** Pengpeng Hou `<pengpeng@iscas.ac.cn>` (author);
  Linus Walleij `<linusw@kernel.org>` (pinctrl maintainer)
- Ignored pipeline markers: none present on this commit

Notable pattern: no user/syzbot report; maintainer SOB only.

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**

Record:
- **Bug:** `sx150x_id[]` is wired as `sx150x_driver.id_table` but not
  exported with `MODULE_DEVICE_TABLE(i2c, ...)`.
- **Symptom:** depmod/udev never get `i2c:sx1501q` … `i2c:sx1509q`
  aliases, so the module does not autoload for I2C-name instantiation.
- **Version info:** none in the message.
- **Root cause (author):** match table is used at registration but not
  published for `file2alias` / modules.alias.
- Author states this is a **source-level** finding with **no hardware
  reproduction**.

**Step 1.4: DETECT HIDDEN BUG FIXES**

Record: **Not a disguised cleanup.** It is an explicit autoload/metadata
fix. The “source-level” wording means the author inferred the bug from
the missing macro, not from a crash.

---

## PHASE 2: DIFF ANALYSIS

**Step 2.1: INVENTORY THE CHANGES**

Record:
- File: `drivers/pinctrl/pinctrl-sx150x.c` — **+1 / −0**
- Function/data: none; one statement after `sx150x_id[]`
- Scope: **single-file surgical fix**

```850:856:drivers/pinctrl/pinctrl-sx150x.c
        { .name = "sx1509q", .driver_data =
(kernel_ulong_t)&sx1509q_device_data },
        { }
};
MODULE_DEVICE_TABLE(i2c, sx150x_id);
```

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**

Record:
- **Before:** OF table already had `MODULE_DEVICE_TABLE(of,
  sx150x_of_match)`. I2C table was registered via `.id_table` but not
  aliased.
- **After:** `scripts/mod/file2alias.c` `do_i2c_entry()` emits
  `i2c:<name>` aliases (`I2C_MODULE_PREFIX` is `"i2c:"`).
- Path affected: **module build / depmod / udev autoload**, not
  probe/runtime logic.

**Step 2.3: IDENTIFY THE BUG MECHANISM**

Record:
- **Category:** hardware enablement / module autoload (same family as
  device-ID publication)
- **Mechanism:** without `MODULE_DEVICE_TABLE(i2c, sx150x_id)`,
  `file2alias` never sees the I2C table. DT devices still autoload via
  OF aliases (`i2c_device_uevent()` prefers
  `of_device_uevent_modalias()`). Non-DT instantiation (`new_device`,
  i2c-USB, board info) emits `MODALIAS=i2c:<name>` and would fail to
  autoload.

**Step 2.4: ASSESS THE FIX QUALITY**

Record:
- Obviously correct: matches `Documentation/i2c/writing-clients.rst`.
- Minimal: one line, no API/locking/data-structure change.
- Regression risk: **very low** (modinfo aliases only; no runtime path
  change).
- Red flags: none.

---

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: BLAME THE CHANGED LINES**

Record:
- `sx150x_id[]` introduced in `9e80f9064e73f` (**2016**, v4.10-era):
  “pinctrl: Add SX150X GPIO Extender Pinctrl Driver”. That commit
  **removed** `MODULE_DEVICE_TABLE` because the driver was `bool`
  (citing gpio-sx150x `module.h` cleanup).
- I2C `MODULE_DEVICE_TABLE` added only by this commit (`5fe4b12c087db`,
  2026-07-10).
- Modularization: `fe2e8f17a56fe` (2025-08-19) made `PINCTRL_SX150X`
  **tristate** and added **only** `MODULE_DEVICE_TABLE(of, ...)`.

**Step 3.2: FOLLOW THE FIXES: TAG**

Record: **No Fixes: tag.** Buggy omission is from `fe2e8f17a56fe`
(incomplete modularization), not from a tagged regression.
`fe2e8f17a56fe` is an ancestor of this HEAD.

**Step 3.3: CHECK FILE HISTORY**

Record:
- Related: `fe2e8f17a56fe` (tristate + OF aliases); `dbbb19b8e412f`
  (allow `depends on I2C` so it can be `=m` when I2C is a module, landed
  later in 7.3).
- Standalone one-liner; not patch X/Y.
- Prerequisite for *meaning*: driver must be buildable as a module
  (`fe2e8f17a56fe`). That is in this tree.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**

Record: Pengpeng Hou is **not** the pinctrl maintainer. Large sweep of
“add missing MODULE_DEVICE_TABLE()” across
rtc/vdpa/watchdog/clk/soc/etc. This is a systematic metadata sweep,
applied here by Linus Walleij.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**

Record: No new helpers. Applies anywhere `sx150x_id[]` exists (since
2016). Standalone. User-visible only when `PINCTRL_SX150X=m`.

---

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**

Record:
- **Lore:**
  https://patch.msgid.link/20260704152230.51188-1-pengpeng@iscas.ac.cn
- **Revisions:** v1 only (`b4 dig -a`)
- Thread (mbox via `b4 dig -m`): submission + Linus Walleij **“Patch
  applied!”**
- No NAK, no review changes, **no Cc: stable** from author or maintainer
- WebFetch of lore.kernel.org returned **403**; discussion read from the
  saved mbox instead

**Step 4.2: CHECK WHO REVIEWED THE PATCH**

Record (`b4 dig -w`): To Linus Walleij; Cc linux-gpio, linux-kernel.
Maintainer applied it. No other reviewers.

**Step 4.3: SEARCH FOR THE BUG REPORT**

Record: **No bugzilla/syzbot/user report.** Author: source-level only.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**

Record: Standalone v1. Same author has many sibling MODULE_DEVICE_TABLE
patches; none are prerequisites for this hunk.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**

Record: **UNVERIFIED** on lore.kernel.org/stable (HTTP 403). No `Cc:
stable` in commit or mbox.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: KEY FUNCTIONS**

Record: No functions changed. Touches `sx150x_id[]` publication.
Related: `sx150x_driver`, `sx150x_init()` → `i2c_add_driver()`.

**Step 5.2: TRACE CALLERS**

Record:
- `sx150x_init()` is `subsys_initcall` / module init; only caller of
  `i2c_add_driver(&sx150x_driver)`.
- `sx150x_probe()` is the I2C probe (line 1123). Bound via OF match or
  `id_table`.
- Not IRQ/hot-path; device enumeration / module autoload.

**Step 5.3: TRACE CALLEES**

Record: `MODULE_DEVICE_TABLE` is a build-time alias for `file2alias`. No
allocations, locks, or I/O.

**Step 5.4: FOLLOW THE CALL CHAIN**

Record:
- DT boards (qcs615-ride, imx8mp-aristainetos3, kirkwood-l-50,
  vf610-zii, at91-natte, …): uevent uses **OF** modalias; already
  covered.
- Non-DT: `i2c_device_uevent()` falls through to
  `MODALIAS=i2c:<client->name>`. Original 2016 commit tested **x86_64
  I2C-USB** as well as BeagleBone DT — that path needs I2C aliases.
- Userspace `new_device` can also trigger it.
- Reachable: yes, from device enumeration / sysfs, not a syscall crash
  path.

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**

Record: Same missing-macro pattern across many drivers in this cycle. OF
table in this file already had the macro; I2C table was the gap.

semcode MCP: **not available**; used git/grep/read.

---

## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**

Record:
- Local tree: **`v7.3-rc4-27-gf0100363d8c37`**, `make kernelversion` =
  **7.3.0-rc4**, detached HEAD on mainline.
- Driver file present; Kconfig is `tristate`; both MODULE_DEVICE_TABLE
  lines present **because this commit is already in HEAD**.
- Bug existed in this lineage from `fe2e8f17a56fe` (in v6.18) until
  `5fe4b12c087db` (first in **v7.3-rc1**).
- `git merge-base --is-ancestor 5fe4b12c087db HEAD` → **yes**.

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**

Record: **Clean apply.** Single line after `sx150x_id[]`. Pre-fix parent
still has the table and OF `MODULE_DEVICE_TABLE`. Context around named
initializers (`84c0fe4a2085f`) does not affect the added line.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**

Record: OF aliases already added by `fe2e8f17a56fe`. No other I2C alias
fix. This is the remaining hole, not a duplicate.

---

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

**Step 7.1: SUBSYSTEM AND CRITICALITY**

Record: **pinctrl / I2C GPIO expander driver**
(`drivers/pinctrl/pinctrl-sx150x.c`). Criticality: **PERIPHERAL**
(specific Semtech SX150x chips on a handful of boards). Not mm/fs/net
core.

**Step 7.2: SUBSYSTEM ACTIVITY**

Record: pinctrl is actively developed (frequent 7.3 merges). This driver
is mature (2016); the modularization is recent (6.18).

---

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: WHO IS AFFECTED**

Record: **Driver-specific / config-specific:**
`CONFIG_PINCTRL_SX150X=m`, and instantiation **without** a working OF
(or ACPI) modalias — I2C name match. DT users already autoload via OF.

**Step 8.2: TRIGGER CONDITIONS**

Record:
- Trigger: module not loaded; I2C client named `sx1501q`…`sx1509q`
  appears (sysfs `new_device`, non-DT board, I2C-USB).
- Commonness: **low** on in-tree DT boards; **real** for the non-OF path
  the driver was written to support.
- Unprivileged trigger: no (needs device creation / root sysfs).

**Step 8.3: FAILURE MODE SEVERITY**

Record:
- Failure: GPIO/pinctrl expander **does not bind** until manual
  `modprobe`. No oops, deadlock, or corruption.
- Severity: **MEDIUM** for affected modular non-DT users; **LOW** for
  typical DT boards.
- Not CRITICAL.

**Step 8.4: RISK-BENEFIT RATIO**

Record:
- **Benefit:** modest — restores I2C autoload for a modular driver that
  documents non-OF use.
- **Risk:** very low — one compile-time alias line.
- **Ratio:** favorable. Same class as publishing device IDs.

---

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: COMPILE THE EVIDENCE**

**FOR backporting:**
- Real autoload bug once the driver is a module (this tree: tristate).
- One line, obviously correct, maintainer-applied.
- Zero runtime regression risk.
- Same user-visible class as device-ID additions (module aliases).
- I2C `id_table` is actually used (`.id_table = sx150x_id`); OF aliases
  do not cover the i2c: modalias path.
- Original driver was tested on non-OF x86 I2C-USB.

**AGAINST:**
- Not a crash/UAF/security/corruption/deadlock issue.
- No user report; author says source-level only.
- DT autoload already works via OF `MODULE_DEVICE_TABLE`.
- Peripheral expander, small user set.
- Automated MODULE_DEVICE_TABLE sweep, not a targeted production
  incident.

**UNRESOLVED:**
- Whether stable@ already discussed this (lore 403).
- How many distros set `PINCTRL_SX150X=m` vs `=y`.

**Step 9.2: STABLE RULES CHECKLIST**

1. Obviously correct and tested? **PASS** — correct by construction;
   maintainer applied. Hardware test not claimed.
2. Fixes a real bug that affects users? **PASS** — missing I2C aliases
   prevent autoload for non-DT / `i2c:` modalias.
3. Important issue? **PASS** (as device-ID / enablement, not as crash).
   User-visible: device never probes until manual modprobe. Stable text
   allows “add a device ID”; this publishes existing IDs.
4. Small and contained? **PASS** — +1 line, one file.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — applies cleanly; this
   checkout already contains the equivalent change.

**Step 9.3: EXCEPTION CATEGORIES**

Record: **Device ID / module alias publication** (not a new driver).
Closest exception: adding/exporting IDs on an existing driver so
hardware binds automatically.

**Step 9.4: DECISION**

This tree is **7.3-rc4 mainline**, where `PINCTRL_SX150X` is tristate
and the I2C table is live. The patch does not change runtime logic; it
only emits the aliases `file2alias` needs for `i2c:sx150*q`. That is a
real, contained autoload fix with essentially no regression risk. DT
boards already worked; the I2C table still matters for the non-OF path
this driver has supported since 2016.

It meets stable rules as a small, obviously correct hardware-binding
fix, not as a crash fix.

---

### What the commit solves (for this tree)

When built as a module, udev/modprobe cannot match
`MODALIAS=i2c:sx1509q` (and siblings) because those aliases were never
generated. Probe itself was fine if the module was loaded by hand or via
OF. The one-line `MODULE_DEVICE_TABLE(i2c, sx150x_id)` closes that gap.

### Risk vs benefit

Benefit is autoload for modular, non-DT (or sysfs-instantiated) SX150x
users. Risk is negligible. That trade-off is acceptable for stable.

### Concerns

No `Fixes:`/`Cc: stable` (not a negative by itself). Impact is not a
panic. Prerequisite modularization is already in this lineage. No
backport rework needed.

---

### Verification

- **[Phase 1]** Parsed `5fe4b12c087db`: subject/body/SOBs; no
  Fixes/Reported-by/stable Cc
- **[Phase 2]** Diff: +1 `MODULE_DEVICE_TABLE(i2c, sx150x_id)` in
  `pinctrl-sx150x.c`
- **[Phase 2]** Confirmed OF table already has `MODULE_DEVICE_TABLE(of,
  sx150x_of_match)` (line 870)
- **[Phase 2]** Confirmed `.id_table = sx150x_id` (line 1281)
- **[Phase 3]** `git blame`: table from `9e80f9064e73f` (2016); OF macro
  from `fe2e8f17a56fe`; I2C macro from this commit
- **[Phase 3]** `git show fe2e8f17a56fe`: tristate + OF
  MODULE_DEVICE_TABLE + MODULE_LICENSE; I2C table omitted
- **[Phase 3]** `git log --author=Pengpeng Hou`: many sibling
  MODULE_DEVICE_TABLE commits
- **[Phase 4]** `b4 dig -c 5fe4b12c087db`: lore msgid
  `20260704152230.51188-1-pengpeng@iscas.ac.cn`
- **[Phase 4]** `b4 dig -a`: v1 only
- **[Phase 4]** `b4 dig -w`: Linus Walleij + linux-gpio
- **[Phase 4]** mbox: “Patch applied!”; no NAK; no stable nomination
- **[Phase 4]** WebFetch lore/stable: **403 UNVERIFIED**
- **[Phase 5]** `i2c_device_uevent`: OF, then ACPI, then `i2c:` name
  (`drivers/i2c/i2c-core-base.c:163-176`)
- **[Phase 5]** `do_i2c_entry` emits `i2c:%s`
  (`scripts/mod/file2alias.c:855-860`)
- **[Phase 5]** In-tree DTS uses `semtech,sx150xq` compatibles
- **[Phase 5]** No ACPI table in this driver
- **[Phase 6]** `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`;
  `kernelversion` 7.3.0-rc4
- **[Phase 6]** `git merge-base --is-ancestor 5fe4b12c087db HEAD` → yes
- **[Phase 6]** Tags: fix first in v7.3-rc1; tristate in v6.18; missing
  in v7.2
- **[Phase 6]** Kconfig in this tree: `tristate` `depends on I2C`
- **[Phase 8]** Failure mode: module not autoloaded; severity
  MEDIUM/LOW, not crash
- **UNVERIFIED:** stable@ archive discussion; distro `=m` vs `=y`
  prevalence
- **UNVERIFIED:** semcode MCP not present

The fix is small, surgical, and meets stable criteria as module-alias /
device-ID enablement.

**YES**

 drivers/pinctrl/pinctrl-sx150x.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index 1d6760ffe809a..f1647d9114e3b 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -850,6 +850,7 @@ static const struct i2c_device_id sx150x_id[] = {
 	{"sx1509q", (kernel_ulong_t) &sx1509q_device_data },
 	{}
 };
+MODULE_DEVICE_TABLE(i2c, sx150x_id);
 
 static const struct of_device_id sx150x_of_match[] = {
 	{ .compatible = "semtech,sx1501q", .data = &sx1501q_device_data },
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: enable RMII outputs from RMII groups
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (6 preceding siblings ...)
  2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] pinctrl: sx150x: " Sasha Levin
@ 2026-10-19 13:52 ` Sasha Levin
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: clear pending GPIO events during init Sasha Levin
  2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-5.10] gpio: vf610: add missing MODULE_DEVICE_TABLE() Sasha Levin
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:52 UTC (permalink / raw)
  To: patches, stable
  Cc: Tomer Maimon, Linus Walleij, Sasha Levin, andrew, avifishman70,
	tali.perry1, openbmc, linux-gpio, linux-kernel

From: Tomer Maimon <tmaimon77@gmail.com>

[ Upstream commit c6ccdc305589dd7c7976116e0870a23f291c5fa9 ]

NPCM8xx uses GCR_INTCR4 bits to release the R1, R2 and RMII3
transmit outputs from Hi-Z.

Those bits need to follow the mandatory r1, r2 and rmii3 pin
groups. The R1_OEn, R2_OEn and R3_OEn side groups are optional and
should not be required just to enable RMII transmit outputs.

Program the INTCR4 bits when the corresponding RMII groups are
selected and clear them again when those pins switch back to GPIO or
another shared function.

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This is a real NPCM8xx hardware-programming bug (RMII TX left in Hi-Z),
and the local 7.3 tree already has the driver and the affected mux path.

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[pinctrl/npcm8xx] [enable] [program INTCR4 so RMII TX leaves
Hi-Z when r1/r2/rmii3 groups are selected]`

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Tomer Maimon `<tmaimon77@gmail.com>` (author; Nuvoton)
- Signed-off-by: Linus Walleij `<linusw@kernel.org>` (pinctrl
  maintainer)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
  or Cc: stable
- Absence of Fixes/Cc-stable is expected for this review and is not a
  negative signal

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: NPCM8xx GCR_INTCR4 bits 12–14 release R1/R2/RMII3 transmit pads
  from Hi-Z. The driver muxed the mandatory `r1`/`r2`/`rmii3` groups but
  never programmed those bits.
- Symptom: RMII TX stays tri-stated, so those Ethernet ports cannot
  transmit.
- Root cause: INTCR4 was (incorrectly) treated as belonging to optional
  `R1_OEn`/`R2_OEn`/`R3_OEn` side groups; those groups are separate pins
  and do not program INTCR4.
- Version info: none in the message. Driver itself arrived in v6.7-rc1.

**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. The cover letter of the series calls
the set a “cleanup,” but this patch is explicit hardware-correctness: TX
is stuck in Hi-Z until INTCR4 is programmed. That is a functional bug,
not a style change.

## PHASE 2: DIFF ANALYSIS

**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` (+61 / −0)
- New helpers: `npcm8xx_rmii_output_enable_mask()`,
  `npcm8xx_set_rmii_output_enable()`
- Modified: `npcm8xx_setfunc()` (one call at the end)
- New defines: `NPCM8XX_GCR_INTCR4`,
  `NPCM8XX_INTCR4_R1_RMII_EN/R2_RMII_EN/RMII3_EN`
- Scope: single-file surgical change

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: `npcm8xx_setfunc()` only updated MFSEL/I2CSEGSEL bits from
  `pincfg[]`. INTCR4 was never written.
- After: after that mux, INTCR4 bits 12–14 are set iff the selected mode
  is `fn_r1`/`fn_r2`/`fn_rmii3` for pins in those groups; they are
  cleared when those pins go back to GPIO or another function.
- Paths: pinmux set (`npcm8xx_pinmux_set_mux`) and GPIO request
  (`npcm8xx_gpio_request_enable`). Normal mux/GPIO path, not an error
  path.

**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: `[Hardware programming / logic correctness]` Incomplete mux:
existing RMII groups did not drive the SoC output-enable bits, so TX
pads stayed Hi-Z. Fix programs those bits from the same `setfunc()` path
that already muxes the groups. Pin lists match `r1_pins[]`, `r2_pins[]`,
and `rmii3_pins[]` exactly.

**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Quality: obviously correct against the driver’s own group tables; no
  API/data-structure change.
- Regression risk: low–medium. Linux now writes INTCR4 bits that used to
  be left at firmware values. Clearing the whole R1/R2/RMII3 enable when
  a single pin in that group is requested as GPIO is the stated intent,
  but it can drop TX for the rest of that RMII if one pad is taken as
  GPIO. No deadlock/locking change.

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: BLAME THE CHANGED LINES**
Record: `npcm8xx_setfunc()` comes from `acf4884a57170` (“pinctrl:
nuvoton: add NPCM8XX pinctrl and GPIO driver”, 2023-08-28; first in
**v6.7-rc1**). INTCR4 handling is new in this commit. The bug is
“missing programming since the driver was added,” not a recent
regression.

**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Not applicable. The incomplete mux has been there
since the original driver.

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same-day 8-patch series from Tomer, merged via `pinctrl-v7.3-1`:
1. drop RTS/CTS from bmcuart1
2. **this commit**
3. RG2 drive strength
4. clear pending GPIO events
5. rename GPIO7 IOX2
6. move GPIO IRQ setup
7. JM1/SMB7 flags
8. debounce register selection
This patch does not depend on the others. No later follow-up on INTCR4.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Tomer Maimon is the original npcm8xx/npcm7xx pinctrl author
(Nuvoton). That is a strong subsystem-author signal, not a drive-by
change.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. Uses existing `npcm8xx_setfunc()`,
`fn_r1`/`fn_r2`/`fn_rmii3`, and `regmap_update_bits()` on the GCR
syscon. No new helpers from other patches.

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c c6ccdc305589d` →
  https://patch.msgid.link/20260715122923.1938327-3-tmaimon77@gmail.com
- Series: `[PATCH v1 0/8] pinctrl: npcm8xx: fix pinmuxing and
  configuration handling` (2026-07-15)
- Only v1; no v2/v3
- Cover letter: issues found by comparing upstream with the newer
  Nuvoton tree
- Linus Walleij: “No comments so patches applied.”
- No Cc: stable, no NAKs

**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc included Linus Walleij, Bartosz Golaszewski,
Andrew Jeffery, linux-gpio, openbmc, and Google/Nuvoton BMC people. Only
the maintainer reply is in the thread; no Reviewed-by/Tested-by.

**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by, bugzilla, or syzbot. Evidence is the author’s
hardware description (Hi-Z TX), not a user crash report.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Patch 2/8. Independent of 1/8 (UART pins) and 3/8 (RG2 drive
strength). Safe to take alone.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable returned 403. UNVERIFIED whether stable@
discussed this commit. The mbox has no stable nomination.

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: KEY FUNCTIONS**
Record: `npcm8xx_rmii_output_enable_mask`,
`npcm8xx_set_rmii_output_enable`, `npcm8xx_setfunc`

**Step 5.2: TRACE CALLERS**
Record:
- `npcm8xx_setfunc` ← `npcm8xx_pinmux_set_mux` (DT/pinctrl mux) and
  `npcm8xx_gpio_request_enable` (GPIO request)
- Reachable when a consumer selects `r1`/`r2`/`rmii3` or when those pads
  are claimed as GPIO
- Not IRQ/hot-path

**Step 5.3: TRACE CALLEES**
Record: `regmap_update_bits()` on GCR INTCR4. Side effect is only those
three bits.

**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Device-tree pinctrl for NPCM8xx RMII groups → pinmux → `setfunc`
→ INTCR4. Userspace cannot trigger it without those pins being muxed.
In-tree `nuvoton-npcm845-evb.dts` only enables UART/watchdog, but
`nuvoton-common-npcm8xx.dtsi` already defines `r1`/`r2`/`rmii3` mux
nodes for board DTs (typical OpenBMC).

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: npcm7xx pinctrl has no INTCR4 RMII enable. This is npcm8xx-
specific. No sibling copy-paste bug.

## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. Local tree is **v7.3-rc4** (`7.3.0-rc4`). `PINCTRL_NPCM8XX`
and `npcm8xx_setfunc()` are present. `git merge-base --is-ancestor
c6ccdc305589d HEAD` is true (the fix is already in this checkout). The
pre-fix mux without INTCR4 existed from v6.7 through this series.

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply on this file’s `setfunc()`/GCR-define region. Those
sites were stable from the original driver until this commit. Later 7.3
include churn (`mod_devicetable.h`) is unrelated.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: This is the only INTCR4/RMII-output change. No alternate fix.

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

**Step 7.1: SUBSYSTEM AND CRITICALITY**
Record: `[drivers/pinctrl/nuvoton] [PERIPHERAL]` — Nuvoton NPCM8xx BMC
pinmux. Important for that BMC’s RMII, not a core mm/fs/net path.

**Step 7.2: SUBSYSTEM ACTIVITY**
Record: Mature driver (v6.7) with a 2026 vendor-sync series. Not a
brand-new subsystem.

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: WHO IS AFFECTED**
Record: NPCM8xx (Arbel) BMC boards that mux `r1`/`r2`/`rmii3`. Config:
`PINCTRL_NPCM8XX` / `ARCH_NPCM`. Not universal.

**Step 8.2: TRIGGER CONDITIONS**
Record: Selecting those RMII pin groups (boot pinctrl). Common on boards
that use RMII Ethernet; unused if those groups are never muxed. Not a
userspace-triggered security path.

**Step 8.3: FAILURE MODE SEVERITY**
Record: `[RMII TX held in Hi-Z → no Ethernet transmit] [MEDIUM, HIGH for
BMC management if that port is the OOB NIC]`. Not a panic, UAF, or
filesystem corruption.

**Step 8.4: RISK-BENEFIT RATIO**
Record:
- Benefit: BMC RMII actually transmits when the existing groups are
  selected; firmware no longer has to paper over Linux.
- Risk: ~61 lines, three GCR bits, no locking. Behavior change vs “leave
  INTCR4 to firmware.”
- Ratio: favorable for trees that already ship this driver.

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: COMPILE THE EVIDENCE**

FOR:
- Concrete hardware bug: TX pads stay Hi-Z without INTCR4
- Existing pin groups; this completes mux, it does not add a new
  function/API
- 61 lines, one file, pin lists match group arrays
- No series dependencies
- Driver author + pinctrl maintainer
- Driver and bug exist in this tree (since v6.7)
- Hardware-workaround exception (broken/incomplete SoC programming)

AGAINST:
- Not crash/security/corruption/deadlock
- Cover letter is a Nuvoton-tree sync, no user report or Tested-by
- In-tree EVB DTS does not enable Ethernet
- Writes INTCR4 that firmware may already own
- Part of an 8-patch “cleanup” series (this patch is still self-
  contained)

UNRESOLVED:
- Could not query lore.kernel.org/stable (HTTP 403)
- Could not confirm how many shipping boards rely on firmware vs Linux
  for INTCR4

**Step 9.2: STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — matches group tables;
   maintainer applied v1. Tested-by is missing, but the change is
   inspectable.
2. Fixes a real bug that affects users? **PASS** — RMII TX does not
   leave Hi-Z.
3. Important issue? **PASS** (MEDIUM, hardware-workaround exception) —
   dead BMC Ethernet TX, not a kernel oops.
4. Small and contained? **PASS** — 61 lines, one driver.
5. No new features or APIs? **PASS** — no new userspace API; programs a
   register the existing groups already required.
6. Can apply to the local tree? **PASS** — `pinctrl-npcm8xx.c` and
   `npcm8xx_setfunc()` are here; the patch is already an ancestor of
   HEAD.

**Step 9.3: EXCEPTION CATEGORIES**
Record: Hardware workaround / incomplete mux for existing NPCM8xx RMII
groups. Not a new driver.

**Step 9.4: DECISION**
This tree is 7.3 and already contains NPCM8xx pinctrl. The bug is real:
selecting the documented RMII groups never released TX from Hi-Z. The
fix is small, local, and does not need the rest of the series. That is
the same class of change as a hardware quirk: the existing function does
not work until the SoC bit is programmed. Benefit outweighs the INTCR4
behavior change.

Verification:
- [Phase 1] Parsed tags: only author + Linus Walleij SOBs; no
  Fixes/Reported-by/stable
- [Phase 2] Diff: +61 lines in pinctrl-npcm8xx.c; INTCR4 helpers + call
  from setfunc
- [Phase 2] Pin lists verified equal to r1_pins/r2_pins/rmii3_pins
- [Phase 3] git describe HEAD: v7.3-rc4-27-gf0100363d8c37; make
  kernelversion 7.3.0-rc4
- [Phase 3] git merge-base --is-ancestor c6ccdc305589d HEAD: yes
- [Phase 3] Driver added acf4884a57170, first contained in v6.7-rc1
- [Phase 3] git blame setfunc: original driver except the new INTCR4
  call
- [Phase 3] No Fixes: tag; no INTCR4 history before this commit
- [Phase 4] b4 dig -c: lore/msgid 20260715122923.1938327-3; series v1
  2/8
- [Phase 4] b4 dig -a: only v1
- [Phase 4] b4 dig -w: linusw, brgl, andrew, openbmc, linux-gpio, Google
  BMC CCs
- [Phase 4] mbox: Linus “No comments so patches applied”; no NAK; no Cc:
  stable
- [Phase 4] lore.kernel.org HTTP 403 for WebFetch; stable-list search
  UNVERIFIED
- [Phase 5] Callers: pinmux_set_mux and gpio_request_enable only
- [Phase 6] Buggy mux without INTCR4 present from v6.7 until this commit
- [Phase 6] In-tree EVB DTS has no ethernet node; common dtsi still
  defines r1/r2/rmii3 muxes
- [Phase 8] Failure mode: RMII TX Hi-Z, severity MEDIUM (BMC NIC)

**YES**

 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 61 +++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 0aae1a2534594..c94441b2acdae 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -26,6 +26,7 @@
 #define NPCM8XX_GCR_SRCNT	0x068
 #define NPCM8XX_GCR_FLOCKR1	0x074
 #define NPCM8XX_GCR_DSCNT	0x078
+#define NPCM8XX_GCR_INTCR4	0x0c0
 #define NPCM8XX_GCR_I2CSEGSEL	0x0e0
 #define NPCM8XX_GCR_MFSEL1	0x260
 #define NPCM8XX_GCR_MFSEL2	0x264
@@ -78,6 +79,9 @@
 #define NPCM8XX_GPIO_PER_BANK	32
 #define NPCM8XX_GPIO_BANK_NUM	8
 #define NPCM8XX_GCR_NONE	0
+#define NPCM8XX_INTCR4_R1_RMII_EN	BIT(12)
+#define NPCM8XX_INTCR4_R2_RMII_EN	BIT(13)
+#define NPCM8XX_INTCR4_RMII3_EN	BIT(14)
 
 #define NPCM8XX_DEBOUNCE_MAX		4
 #define NPCM8XX_DEBOUNCE_NSEC		40
@@ -1796,6 +1800,61 @@ static const struct pinctrl_pin_desc npcm8xx_pins[] = {
 	PINCTRL_PIN(251, "JM2/CP1_GPIO"),
 	};
 
+static u32 npcm8xx_rmii_output_enable_mask(unsigned int pin)
+{
+	switch (pin) {
+	case 178:
+	case 179:
+	case 180:
+	case 181:
+	case 182:
+	case 193:
+	case 201:
+		return NPCM8XX_INTCR4_R1_RMII_EN;
+	case 84:
+	case 85:
+	case 86:
+	case 87:
+	case 88:
+	case 89:
+	case 200:
+		return NPCM8XX_INTCR4_R2_RMII_EN;
+	case 110:
+	case 111:
+	case 209:
+	case 210:
+	case 211:
+	case 214:
+	case 215:
+		return NPCM8XX_INTCR4_RMII3_EN;
+	default:
+		return 0;
+	}
+}
+
+static void npcm8xx_set_rmii_output_enable(struct regmap *gcr_regmap,
+					   const unsigned int *pin,
+					   int pin_number, int mode)
+{
+	u32 mask = 0;
+	u32 val = 0;
+	u32 bit;
+	int i;
+
+	for (i = 0; i < pin_number; i++) {
+		bit = npcm8xx_rmii_output_enable_mask(pin[i]);
+		mask |= bit;
+
+		if ((mode == fn_r1 && bit == NPCM8XX_INTCR4_R1_RMII_EN) ||
+		    (mode == fn_r2 && bit == NPCM8XX_INTCR4_R2_RMII_EN) ||
+		    (mode == fn_rmii3 && bit == NPCM8XX_INTCR4_RMII3_EN))
+			val |= bit;
+	}
+
+	if (mask)
+		regmap_update_bits(gcr_regmap, NPCM8XX_GCR_INTCR4, mask, val);
+}
+
 /* Enable mode in pin group */
 static void npcm8xx_setfunc(struct regmap *gcr_regmap, const unsigned int *pin,
 			    int pin_number, int mode)
@@ -1834,6 +1893,8 @@ static void npcm8xx_setfunc(struct regmap *gcr_regmap, const unsigned int *pin,
 						   BIT(cfg->bit4) : 0);
 		}
 	}
+
+	npcm8xx_set_rmii_output_enable(gcr_regmap, pin, pin_number, mode);
 }
 
 static int npcm8xx_get_slew_rate(struct npcm8xx_gpio *bank,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: clear pending GPIO events during init
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (7 preceding siblings ...)
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: enable RMII outputs from RMII groups Sasha Levin
@ 2026-10-19 13:52 ` Sasha Levin
  2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-5.10] gpio: vf610: add missing MODULE_DEVICE_TABLE() Sasha Levin
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:52 UTC (permalink / raw)
  To: patches, stable
  Cc: Tomer Maimon, Linus Walleij, Sasha Levin, andrew, avifishman70,
	tali.perry1, openbmc, linux-gpio, linux-kernel

From: Tomer Maimon <tmaimon77@gmail.com>

[ Upstream commit cd39cce4cfd499f555eb8b8252636609c3468f57 ]

A bank may retain pending event status across resets of the GPIO block.
If probe leaves the old state in place, the chained IRQ handler can see
spurious events as soon as the irqchip is registered.

Disable event generation and clear EVST before wiring each GPIO bank
into gpiolib so the driver starts from a known state.

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The local tree is **7.3.0-rc4** (`v7.3-rc4-27-gf0100363d8c37`). The
NPCM8XX pinctrl/GPIO driver is present, the leftover EVEN/EVST init gap
is real on this path, and the change is a 3-line hardware init fix that
belongs here.

===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================

**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[pinctrl/npcm8xx] [clear] [clear leftover GPIO event
enable/status before irqchip registration]**

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Tomer Maimon \<tmaimon77@gmail.com\> (author; original
  NPCM8XX driver author)
- Signed-off-by: Linus Walleij \<linusw@kernel.org\> (pinctrl
  maintainer)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
  or Cc: stable (absence is expected)

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** GPIO bank EVEN/EVST can survive GPIO-block reset
  (bootloader/firmware leftover).
- **Symptom:** chained IRQ handler sees spurious events as soon as the
  irqchip is registered at probe.
- **Root cause:** probe never disables event generation or W1C-clears
  EVST before `gpiochip_add_data()`.
- **Fix:** write EVEN=0, then EVST=0xffffffff, per bank, before gpiolib
  wiring.
- **Versions:** none stated. Bug is an omission since the driver was
  added.

**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not disguised. Subject/body describe a real init-time IRQ bug.
Cover letter of the v1 8-patch series called the series a vendor-tree
cleanup, but this patch is a concrete spurious-IRQ fix, not style-only.

===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================

**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` (+3 / −0)
- Function: `npcm8xx_gpio_fw()`
- Scope: single-file surgical init fix

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** after `fwnode_irq_get()`, the bank’s EVEN/EVST were left
  as hardware left them; later `npcm8xx_gpio_register()` set
  `girq->parent_handler = npcmgpio_irq_handler` and called
  `devm_gpiochip_add_data()`.
- **After:** EVEN is forced to 0 (no event generation), then EVST is
  W1C-cleared with `0xffffffff`, still before irqchip registration.
- Path: probe/init only (`npcm8xx_pinctrl_probe` → `npcm8xx_gpio_fw`).

**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** hardware leftover interrupt state / spurious IRQ (init
  hygiene, same class as a quirk).
- **Mechanism:** `npcmgpio_irq_handler()` does `sts = EVST; en = EVEN;
  sts &= en;` then `generic_handle_domain_irq()` for set bits. If
  firmware left EVEN and EVST non-zero, the first chained invocation
  dispatches IRQs for lines that were never requested. Parent bank IRQs
  in DT are **GIC_SPI, IRQ_TYPE_LEVEL_HIGH**; leftover asserted status
  can keep the parent line high (storm / “nobody cared”).
  `npcmgpio_irq_ack()` writes `BIT(gpio)` to EVST, confirming EVST is
  write-1-to-clear; writing `0xffffffff` is the correct all-clear.
  Disabling EVEN first avoids a new event sneaking in between the two
  writes.

**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: disable, then W1C-clear, before the handler is
  installed.
- Minimal: two MMIO writes, no API/struct/locking changes.
- Regression risk: very low. Linux GPIO IRQs must be requested through
  gpiolib; inheriting bootloader unmasks is not a supported ABI.
  Starting masked+cleared is the normal irqchip model.

===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================

**Step 3.1: BLAME THE CHANGED LINES**
Record: The surrounding `npcm8xx_gpio_fw()` bank setup comes from
**acf4884a57170** (“pinctrl: nuvoton: add NPCM8XX pinctrl and GPIO
driver”, 2023-08-28), first in **v6.7-rc1**. The bug is missing init,
present for the lifetime of the driver.

**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. N/A. Introduced-by is the original driver commit
above. `git merge-base --is-ancestor acf4884a57170 HEAD` is implicit:
the file exists on this 7.3 tree.

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Same-day series (2026-07-15) in this file:
1. drop RTS/CTS from bmcuart1
2. enable RMII outputs
3. RG2 drive strength
4. **this commit**
5. rename GPIO7 IOX2
6. move IRQ setup into `request_resources`
7. JM1/SMB7 pin flags
8. debounce register selection

This patch does not use symbols or structure from 1–3 or 5–8.
Standalone.

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Tomer Maimon is the Nuvoton driver author
(`MODULE_AUTHOR("tomer.maimon@nuvoton.com")`) and added both NPCM7XX and
NPCM8XX pinctrl drivers. Weight: high.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None. Uses existing `NPCM8XX_GP_N_EVEN` / `NPCM8XX_GP_N_EVST`
and `iowrite32()`. Applies standalone.

===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c cd39cce4cfd499f555eb8b8252636609c3468f57` →
  https://patch.msgid.link/20260715122923.1938327-5-tmaimon77@gmail.com
- v1 only (`b4 dig -a`): **[PATCH v1 4/8]** in “pinctrl: npcm8xx: fix
  pinmuxing and configuration handling”
- Cover letter: issues found by comparing upstream with the Nuvoton
  tree; this patch is called out as clearing stale GPIO events at probe.
- Linus Walleij (2026-07-24): “No comments so patches applied.” No NAK,
  no requested respin.
- Applied version is v1 (only revision).

**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc included linusw@kernel.org (pinctrl
maintainer), brgl@kernel.org (GPIO), andrew@codeconstruct.com.au,
openbmc@lists.ozlabs.org, linux-gpio, Nuvoton/Google OpenBMC people.
Maintainer applied the series. No Reviewed-by tags on the commit.

**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No Reported-by, bugzilla, or syzbot. Trigger is SoC/firmware
leftover state, not a fuzzer path. Author is the vendor driver owner;
that is how this class of BMC GPIO bugs usually surfaces.

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: 8-patch v1 series. Other patches are pinmux/drive-
strength/rename/lockdep-IRQ-startup/debounce — not prerequisites. This
3-line hunk is self-contained.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned HTTP 403. **UNVERIFIED:**
no confirmation of prior stable-list discussion. gpio list mbox had no
“Cc: stable” and no objection.

===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================

**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `npcm8xx_gpio_fw()` (modified). Related, not edited:
`npcmgpio_irq_handler()`, `npcm8xx_gpio_register()`,
`npcm8xx_pinctrl_probe()`.

**Step 5.2: TRACE CALLERS**
Record:
- `npcm8xx_gpio_fw()` ← `npcm8xx_pinctrl_probe()` only (platform probe,
  `arch_initcall`).
- `npcmgpio_irq_handler()` ← chained parent handler for each of 8 GPIO
  banks.
- Context: boot/probe, then hardirq for bank SPI 116–123.

**Step 5.3: TRACE CALLEES**
Record: `iowrite32()` to EVEN and EVST. No alloc, no locks. Later
`npcm8xx_gpio_register()` → `devm_gpiochip_add_data()`.

**Step 5.4: FOLLOW THE CALL CHAIN**
Record: DT `compatible = "nuvoton,npcm845-pinctrl"` with 8
`gpio@f001x000` nodes, each `interrupts = <GIC_SPI 11x
IRQ_TYPE_LEVEL_HIGH>`. Reachable on every NPCM845/NPCM8XX boot
(OpenBMC). Not a syscall fuzzer path; userspace GPIO IRQ consumers can
be hit by the spurious events if leftover enables match those lines.

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: NPCM7XX has the same EVEN/EVST handler and **does not** clear
them at init (same latent class, out of scope). `pinctrl-owl.c` also
clears pending GPIO IRQs in its handler path. Pattern is established.

===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. `drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c` is in this
7.3-rc4 tree. Driver since v6.7. Without the two writes,
`npcm8xx_gpio_fw()` still maps banks and `npcm8xx_gpio_register()` still
installs `npcmgpio_irq_handler`. Bug introduced with the driver, long
before 7.3.

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply. Hunk sits immediately after `fwnode_irq_get()` in
`npcm8xx_gpio_fw()`, which exists here. No structural mismatch.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No earlier equivalent EVEN/EVST init. This is the first such
clear on this file (`git log --grep='pending GPIO'` / `'spurious'` on
that path only hits this commit).

===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================

**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **pinctrl/GPIO, Nuvoton NPCM8XX (BMC SoC).** Criticality:
**PERIPHERAL** for the kernel as a whole, **IMPORTANT** for NPCM845
OpenBMC/server BMC users. `CONFIG_PINCTRL_NPCM8XX` depends on `ARCH_NPCM
|| COMPILE_TEST`.

**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature driver (v6.7), with a burst of vendor fixes in the 7.3
window. Not staging.

===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================

**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific / platform-specific: Nuvoton NPCM8XX (e.g.
NPCM845) systems using this pinctrl driver. Typical population: OpenBMC
on that SoC.

**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Boot/probe, when firmware or a partial GPIO-block reset left
EVEN/EVST non-zero. Common on BMCs (bootloader uses GPIOs). Not
unprivileged-syscall; it is default hardware bring-up.

**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Spurious chained IRQs at probe.
- Parent IRQs are **level-high**; leftover enable+status can hold the
  line → IRQ storm, “nobody cared”, hung boot.
- `generic_handle_domain_irq()` on never-requested lines (this driver
  defaults `girq->handler = handle_level_irq`, not `handle_bad_irq`).
- **Severity: HIGH** (boot IRQ storm / spurious IRQs on BMC GPIO). Not a
  universal panic, but a real stability failure on affected boards.

**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** high for NPCM8XX (known-state IRQ init; prevents probe-
  time storms).
- **Risk:** very low (2 MMIO writes, probe only).
- **Ratio:** strongly in favor of applying.

===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================

**Step 9.1: COMPILE THE EVIDENCE**

FOR:
- Real leftover-hardware IRQ bug, not a refactor.
- Level-triggered parent IRQs make leftover EVST/EVEN a boot storm risk.
- 3 lines, obviously correct (mask then W1C-clear before handler
  install).
- Author is the vendor driver owner; pinctrl maintainer applied it.
- Driver and insertion point exist in this 7.3 tree; no prerequisites.
- Same class as accepted GPIO “clear pending at init” fixes.

AGAINST:
- No user/syzbot report; found via vendor-tree comparison.
- Affects one BMC SoC family, not core kernel.
- No Cc: stable (not a negative by itself).
- Series mixed in feature/rename patches (this hunk does not depend on
  them).

UNRESOLVED:
- Could not search lore.kernel.org/stable (HTTP 403).
- No independent Tested-by.

**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — two register writes,
   maintainer applied; no test robot/NAK. Formal Tested-by absent, but
   the change is reviewable from the handler and DT IRQ type.
2. Fixes a real bug that affects users? **PASS** — leftover EVEN/EVST →
   spurious chained IRQs on NPCM8XX probe.
3. Important issue? **PASS** — boot-time spurious/level IRQ storm on BMC
   GPIO, not cosmetic.
4. Small and contained? **PASS** — +3 lines, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — file, registers, and
   `npcm8xx_gpio_fw()` insertion point are here.

**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Hardware init/workaround (clear stale IRQ state). Not a new ID,
but the same “make existing hardware boot cleanly” exception.

**Step 9.4: MAKE YOUR DECISION**
This is a small, correct, self-contained fix for leftover GPIO event
state that can fire the chained handler as soon as the irqchip is
registered. The buggy path exists in this 7.3 tree. It should be applied
here.

What the commit solves: NPCM8XX GPIO banks can keep EVEN/EVST across
GPIO-block reset. Probe used to register the chained handler on that
dirty state, so leftover enables × pending status become spurious (and,
with level-high parents, potentially stuck) interrupts at boot.

Stable rules: obviously correct, real bug, important for that platform,
tiny, no new API, applies cleanly.

Risk vs benefit: two MMIO writes at probe vs boot IRQ storms on OpenBMC
NPCM845. Benefit dominates.

Concerns: no public reproducer; NPCM7XX still has the same gap (does not
block this fix). No extra backports required.

Verification:
- [Phase 1] Parsed tags: only Tomer Maimon + Linus Walleij SOBs; no
  Fixes/Reported-by/stable
- [Phase 2] Diff: +3 lines in `npcm8xx_gpio_fw()`; EVEN=0 then
  EVST=0xffffffff
- [Phase 2] Handler at lines 210–227 ANDs EVST with EVEN then
  `generic_handle_domain_irq()`
- [Phase 2] `npcmgpio_irq_ack()` writes `BIT(gpio)` to EVST → W1C
  confirmed
- [Phase 3] Driver added in acf4884a57170 (v6.7-rc1); blame of
  surrounding init is that commit
- [Phase 3] `git merge-base --is-ancestor` of the fix vs HEAD: commit is
  in this 7.3 history; code path exists either way
- [Phase 3] Standalone vs 8-patch series: no shared symbols with
  neighboring patches
- [Phase 4] `b4 dig -c cd39cce4cfd49`: lore msgid
  20260715122923.1938327-5; v1 4/8
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: linusw, brgl, openbmc, linux-gpio
- [Phase 4] mbox: Linus Walleij “No comments so patches applied.”; no
  NAK; no Cc: stable
- [Phase 4] Cover letter (LKML archive): vendor-tree comparison; this
  patch listed as stale-event clear
- [Phase 4] lore.kernel.org/stable: 403, UNVERIFIED
- [Phase 5] Callers: `npcm8xx_pinctrl_probe` only; 8 DT GPIO banks,
  GIC_SPI 116–123 level-high
- [Phase 6] `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37; `make
  kernelversion`: 7.3.0-rc4
- [Phase 6] File and `fwnode_irq_get` insertion point present; apply
  would be clean
- [Phase 8] Failure mode: spurious chained GPIO IRQs / possible level-
  triggered storm at probe; HIGH on NPCM8XX, not core-wide
- UNVERIFIED: stable@ list discussion; independent user reports

**YES**

 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index c94441b2acdae..22cc87d43ea69 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -2412,6 +2412,9 @@ static int npcm8xx_gpio_fw(struct npcm8xx_pinctrl *pctrl)
 		if (ret < 0)
 			return dev_err_probe(dev, ret, "Failed to retrieve IRQ for bank %u\n", id);
 
+		iowrite32(0, pctrl->gpio_bank[id].base + NPCM8XX_GP_N_EVEN);
+		iowrite32(0xffffffff, pctrl->gpio_bank[id].base + NPCM8XX_GP_N_EVST);
+
 		pctrl->gpio_bank[id].irq = ret;
 		pctrl->gpio_bank[id].irq_chip = npcmgpio_irqchip;
 		pctrl->gpio_bank[id].irqbase = id * NPCM8XX_GPIO_PER_BANK;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH AUTOSEL 6.18-5.10] gpio: vf610: add missing MODULE_DEVICE_TABLE()
       [not found] <20261019135441.1420968-1-sashal@kernel.org>
                   ` (8 preceding siblings ...)
  2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: clear pending GPIO events during init Sasha Levin
@ 2026-10-19 13:53 ` Sasha Levin
  9 siblings, 0 replies; 12+ messages in thread
From: Sasha Levin @ 2026-10-19 13:53 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Linus Walleij, Bartosz Golaszewski, Sasha Levin,
	brgl, linux-gpio, linux-kernel

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit 975a1d61260cf74d467f34898fade63165c80735 ]

The driver has an OF match table wired to .of_match_table, but does
not export the table with MODULE_DEVICE_TABLE().

Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias
information is generated for OF based module autoloading.

This is a source-level fix.  It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the platform driver, and the missing module alias publication.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260704122123.73004-1-pengpeng@iscas.ac.cn
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

I have the mailing-list thread, version mapping, and driver context.
Compiling the nine-phase analysis and verdict next.

---

## Phase 1: Commit message forensics

**Step 1.1: PARSE THE SUBJECT LINE**

Record: `[gpio: vf610:] [add] [missing MODULE_DEVICE_TABLE() so OF
module aliases are generated]`

- Subsystem: `gpio: vf610` (Freescale/NXP VF610 / i.MX GPIO driver)
- Action verb: **add** (missing export — a functional gap, not a new
  feature)
- Claimed intent: export the existing OF match table for module
  autoloading

**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**

Record:
- **Fixes:** none (expected; not a negative signal)
- **Reported-by:** none
- **Tested-by:** none
- **Reviewed-by:** Linus Walleij `<linusw@kernel.org>` (GPIO subsystem
  veteran / former GPIO maintainer)
- **Acked-by:** none
- **Link:**
  `https://patch.msgid.link/20260704122123.73004-1-pengpeng@iscas.ac.cn`
- **Cc: stable:** none (expected)
- **Signed-off-by:** Pengpeng Hou `<pengpeng@iscas.ac.cn>` (author)
- **Signed-off-by:** Bartosz Golaszewski
  `<bartosz.golaszewski@oss.qualcomm.com>` (current GPIO maintainer who
  applied it)

Ignored per instructions: any pipeline “Upstream commit” / Sasha Levin
SOB (none present on the real commit).

Notable: maintainer-applied, reviewed by a GPIO expert. No user/syzbot
report.

**Step 1.3: ANALYZE THE COMMIT BODY TEXT**

Record:
- **Bug:** `vf610_gpio_dt_ids` is wired to `.of_match_table` but is not
  published with `MODULE_DEVICE_TABLE(of, ...)`.
- **Symptom:** when `CONFIG_GPIO_VF610=m`, modpost does not emit
  `of:N*T*C...` aliases, so udev/modprobe will not autoload `gpio-vf610`
  from DT compatible strings (`fsl,vf610-gpio`, `fsl,imx7ulp-gpio`,
  `fsl,imx8ulp-gpio`).
- **Version info in message:** none
- **Root cause (author):** match table exists and is used by the
  platform driver; only the module-alias publication is missing. Author
  explicitly calls it a **source-level** fix with no dynamic hardware
  repro.

**Step 1.4: DETECT HIDDEN BUG FIXES**

Record: **Not a disguised cleanup.** It is an explicit missing-export
fix. The “add missing” wording is the standard pattern for module-
autoload bugs. It is not a refactor, API, or feature.

---

## Phase 2: Diff analysis

**Step 2.1: INVENTORY THE CHANGES**

Record:
- File: `drivers/gpio/gpio-vf610.c` — **+1 / −0**
- Function/object: file-scope `vf610_gpio_dt_ids[]` (not a function
  body)
- Scope: **single-file surgical fix** (one macro)

**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**

Record:
- **Before:** `vf610_gpio_dt_ids` is a `const struct of_device_id[]`
  used only as `vf610_gpio_driver.driver.of_match_table`. Runtime OF
  matching still works **if the module is already loaded or the driver
  is built-in**.
- **After:** `MODULE_DEVICE_TABLE(of, vf610_gpio_dt_ids)` creates a
  `__mod_of__vf610_gpio_dt_ids_device_table` alias (see
  `include/linux/module.h`) so `scripts/mod/file2alias.c` / modpost
  emits OF modaliases into `.modinfo`.
- Path affected: **build-time module metadata only**, not probe, IRQ, or
  GPIO runtime.

**Step 2.3: IDENTIFY THE BUG MECHANISM**

Record:
- **Category:** hardware enablement / module autoload (OF analogue of
  missing device IDs)
- **Mechanism:** without the alias, a modular driver is never bound to
  DT nodes unless something else loads it (`modprobe gpio-vf610`,
  initramfs list, etc.). GPIO chip never registers → pins/IRQs missing
  on affected boards.

**Step 2.4: ASSESS THE FIX QUALITY**

Record:
- **Quality:** obviously correct; this is the canonical one-line fix
  used across GPIO and many other subsystems.
- **Regression risk:** **very low**. The macro is `__attribute__((used,
  alias(...)))`; it does not change probe, locking, or exported APIs.
  Built-in builds ignore module aliases.

---

## Phase 3: Git history investigation

**Step 3.1: BLAME THE CHANGED LINES**

Record:
- Match table introduced with the driver in `7f2691a19627a8` (Stefan
  Agner, 2014) — originally **built-in only** (`bool` +
  `builtin_platform_driver`).
- Compatible entries updated later: `fsl,imx7ulp-gpio` (2017),
  `fsl,imx8ulp-gpio` (2023).
- **Bug became real** when the driver was made modular:

`73dc041f8a602` — `gpio: vf610: Allow building as a module` (Jindong
Yue, 2025-04-16; merged for **v6.16**)

That commit switched Kconfig to `tristate` and `builtin_platform_driver`
→ `module_platform_driver` **without** adding `MODULE_DEVICE_TABLE`.
Reason given: Android GKI cannot carry board-specific drivers built-in.

**Step 3.2: FOLLOW THE FIXES: TAG**

Record: **No Fixes: tag.** Investigated by history instead. Introducing
commit `73dc041f8a602` **is** an ancestor of this tree (`git merge-base
--is-ancestor` succeeded). It is **in v6.16+** including this 7.3-rc4
checkout. It is **not** in v6.15.

**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**

Record (recent `drivers/gpio/gpio-vf610.c`):
- `975a1d61260cf` — this fix
- `656dc0c6f725a` — generic GPIO chip API (unrelated)
- `73dc041f8a602` — allow module build (**prerequisite**)
- No later commits on this file after the fix (empty
  `975a1d61260cf..HEAD`)

Standalone; not “patch X/Y”. Same-day sibling: `8fe6fa0f223f4` `gpio:
sifive: add missing MODULE_DEVICE_TABLE()` (same author, same template).

**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**

Record: Pengpeng Hou is **not** the GPIO maintainer. This is part of a
mechanical sweep of missing `MODULE_DEVICE_TABLE()` across drivers
(gpio, rtc, vdpa, watchdog, hwmon, fbdev, soc, …). GPIO maintainer still
applied it after Walleij’s review, which keeps the change trustworthy.

**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**

Record: Runtime prerequisite is only “driver can be a module,” which
this tree has (`tristate`, `module_platform_driver`). The one-line macro
needs no extra APIs. **Can apply standalone** on any tree that already
has `vf610_gpio_dt_ids`.

---

## Phase 4: Mailing list and external research

**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**

Record:
- `b4 dig -c 975a1d61260cf`: matched
  `https://patch.msgid.link/20260704122123.73004-1-pengpeng@iscas.ac.cn`
- `b4 dig -a`: **v1 only** (no v2/v3)
- Thread (mbox): (1) patch from Hou, (2) **Reviewed-by: Linus Walleij**,
  (3) Bartosz: **“Applied, thanks!”** →
  `brgl/c/7a6426e72ab53c7cae34952528092efd2e26edc3`
- No NAK, no stable nomination, no reviewer risk flags

**Step 4.2: CHECK WHO REVIEWED THE PATCH**

Record (`b4 dig -w`): To/Cc were **Linus Walleij**, **Bartosz
Golaszewski**, `linux-gpio@vger.kernel.org`, `linux-
kernel@vger.kernel.org`. Right maintainers and list.

**Step 4.3: SEARCH FOR THE BUG REPORT**

Record: no Reported-by / bugzilla / syzbot. Evidence is the missing
export, not a field crash. Same class as other “fix module autoloading”
GPIO commits (e.g. `11baa36d31732` gpio-lpc32xx, `e6382fcf98907` gpio-
spacemit).

**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**

Record: standalone `[PATCH]`, not a numbered series. Parallel same-day
sifive fix is independent.

**Step 4.5: CHECK STABLE MAILING LIST HISTORY**

Record: **UNVERIFIED** — `lore.kernel.org` and `patch.msgid.link`
returned **HTTP 403** via WebFetch and curl. GPIO thread was obtained
via `b4 dig -m` (does not discuss stable).

---

## Phase 5: Code semantic analysis

**Step 5.1: KEY FUNCTIONS**

Record: no function body changed. Touches file-scope
`vf610_gpio_dt_ids[]`. Related symbols: `vf610_gpio_driver`,
`vf610_gpio_probe`, `module_platform_driver`.

**Step 5.2: TRACE CALLERS**

Record:
- `of_match_table = vf610_gpio_dt_ids` in `vf610_gpio_driver` (verified
  in-file at line 351)
- Bound via `module_platform_driver` → `platform_driver_register` at
  module init
- `MODULE_DEVICE_TABLE` is **not** a runtime caller graph; modpost
  consumes the alias at **build** time

semcode MCP: **not available** (namespace search returned no semcode
tools).

**Step 5.3: TRACE CALLEES**

Record: probe uses `device_get_match_data()` / GPIO chip registration.
Unchanged. New code allocates nothing, takes no locks, does no I/O.

**Step 5.4: FOLLOW THE CALL CHAIN**

Record: path is **reachable from userspace/boot** on NXP DT platforms
when the driver is a module: DT node with those compatibles → udev
`modalias` → `modprobe gpio-vf610`. The bug is that this chain is
**broken** without aliases. Unprivileged users do not need a special
exploit; missing GPIO is a boot/bring-up failure.

DT users verified under `arch/`:
- `arch/arm/boot/dts/nxp/vf/vfxxx.dtsi` — `fsl,vf610-gpio`
- `arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi` — `fsl,imx7ulp-gpio`
- `arch/arm64/boot/dts/freescale/imx8ulp.dtsi`, `imx91_93_common.dtsi`,
  `imx94.dtsi`, `imx95.dtsi`, `imx952.dtsi` — `fsl,imx8ulp-gpio`
  (including i.MX93/94/95)

**Step 5.5: SEARCH FOR SIMILAR PATTERNS**

Record: same missing-table pattern recently fixed in `gpio-sifive.c`,
and earlier in spacemit/lpc32xx/cadence/ath79/ts4800. Systematic, well-
understood class.

---

## Phase 6: Cross-referencing against the local tree

**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**

Record:
- Local tree: **`v7.3-rc4-27-gf0100363d8c37`**, `make kernelversion` =
  **7.3.0-rc4** (mainline, not an LTS branch)
- `CONFIG_GPIO_VF610` is **tristate**; `module_platform_driver` is
  present — the modular bug **does exist** in this lineage
- The **fix commit `975a1d61260cf` is already an ancestor of HEAD**
  (landed in **v7.3-rc1**; **not** in v7.2)
- Introducing modularization `73dc041f8a602` **is** in this tree (since
  v6.16)
- Current file already has `MODULE_DEVICE_TABLE(of, vf610_gpio_dt_ids)`
  at line 86

Approximate introduction of the **bug:** **v6.16** (April/July 2025).
Driver itself: **v3.x/v4.x era** (2014).

**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**

Record: **clean apply** on this tree’s driver — one line after the
existing `of_device_id` table. Match-table layout here matches the
commit hunk. No conflicting local changes.

**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**

Record: this exact fix **is already in HEAD**. No alternate/earlier
equivalent found (`git log --oneline --grep=MODULE_DEVICE_TABLE --
drivers/gpio/gpio-vf610.c` is this commit). No follow-up on the file
after it.

For **this checkout as a 7.3 baseline**, 7.3.y would inherit the fix
from rc1; the evaluation still asks whether the change is **stable-
worthy given that this tree’s driver is modular**.

---

## Phase 7: Subsystem and maintainer context

**Step 7.1: SUBSYSTEM AND CRITICALITY**

Record: `drivers/gpio/` — GPIO. **IMPORTANT** (not core mm/sched, but
platform GPIO is boot-critical on NXP i.MX/Vybrid: resets, IRQs,
regulators). Not staging.

**Step 7.2: SUBSYSTEM ACTIVITY**

Record: GPIO is actively maintained (Bartosz); this file still gets API
updates. The autoload hole is from the v6.16 modularization, not ancient
dead code.

---

## Phase 8: Impact and risk assessment

**Step 8.1: WHO IS AFFECTED**

Record: **driver-specific / config-specific**: `CONFIG_GPIO_VF610=m` on
`ARCH_MXC` (Vybrid VF610, i.MX7ULP, i.MX8ULP, and later i.MX9x that
compatible-string to `fsl,imx8ulp-gpio`). Built-in (`=y`) is unaffected.
Kconfig has `default y if SOC_VF610` only; i.MX7/8/9 do **not**
default-y on that symbol, so modular builds are realistic (explicitly
for **Android GKI**).

**Step 8.2: TRIGGER CONDITIONS**

Record:
- Trigger: boot/udev on DT platforms with `GPIO_VF610=m` and no explicit
  `modprobe`
- Commonness: every such boot, not a race
- Unprivileged exploit: **no**; availability/bring-up bug, not a
  sanitizer crash

**Step 8.3: FAILURE MODE SEVERITY**

Record:
- Failure: GPIO controller never probes → missing gpiochip, pin IRQs,
  board GPIOs
- Not oops/UAF/corruption
- Severity: **MEDIUM** functionally (hardware silent-fail), **HIGH** on
  boards that need those GPIOs at boot
- Fits “oh, that’s not good” plus the **device-ID / autoload** exception

**Step 8.4: RISK-BENEFIT RATIO**

Record:
- **Benefit:** restores autoload for an existing, in-tree driver on
  current NXP SoCs and GKI modular images
- **Risk:** **very low** (1 line, metadata only)
- **Ratio:** favorable for stable

---

## Phase 9: Final synthesis

**Step 9.1: COMPILE THE EVIDENCE**

**FOR backporting:**
- Real bug: OF module aliases never generated after v6.16 made the
  driver `tristate`
- One line, obviously correct, no runtime behavior change for built-in
- Same class as device-ID additions (explicitly allowed) and many
  historical “fix module autoloading” GPIO patches
- Used on VF610, i.MX7ULP, i.MX8ULP, i.MX93/94/95 DT
- Modularization was for Android GKI — the config where autoload matters
- Reviewed by Linus Walleij; applied by Bartosz Golaszewski
- Applies cleanly; no series dependencies
- This tree **has** the modular driver, so the bug class is applicable
  here

**AGAINST:**
- Not a crash, deadlock, corruption, or security hole
- No user/syzbot report; author labels it source-level
- Mechanical sweep by a non-maintainer
- `SOC_VF610` defaults the driver to `y` (Vybrid built-in path is fine)
- Workaround: load the module by name
- **Already in this 7.3-rc4 history** (since 7.3-rc1) — but that is
  expected for a mainline commit under review, not a reason to treat the
  fix as non-bugs

**UNRESOLVED:**
- lore.kernel.org/stable search (HTTP 403)
- Whether Android GKI already lists this module in a manual load list
  (unverified; aliases still help udev/modprobe)

**Step 9.2: STABLE RULES CHECKLIST**

1. Obviously correct and tested? **PASS** — canonical macro; reviewed
   and applied by GPIO maintainers
2. Fixes a real bug that affects users? **PASS** — modular OF autoload
   is broken; GKI/i.MX modular users hit it
3. Important issue? **PASS** (as device-ID/hardware-enablement / “oh,
   that’s not good”) — GPIO never appears; not a panic
4. Small and contained? **PASS** — +1 line, one file
5. No new features or APIs? **PASS** — publishes existing match table
6. Can apply to the local tree? **PASS** — code present; hunk matches;
   tree already contains the commit because it is mainline 7.3

**Step 9.3: EXCEPTION CATEGORIES**

Record: **Device ID / module alias publication for an existing driver**
(OF `MODULE_DEVICE_TABLE`). Not a new driver, not a new uAPI.

**Step 9.4: DECISION**

This tree is **mainline 7.3-rc4**, where `gpio-vf610` is modular.
Missing `MODULE_DEVICE_TABLE(of, ...)` is a real, user-visible autoload
bug on DT NXP platforms and GKI-style `=m` builds. The fix is one
obviously correct line with essentially no regression risk, which is the
same bar used for new device IDs in stable.

---

### What the commit solves (for stable users)

When `CONFIG_GPIO_VF610=m`, the kernel never announces OF aliases for
`fsl,vf610-gpio` / `fsl,imx7ulp-gpio` / `fsl,imx8ulp-gpio`. udev
therefore does not load the module, so the GPIO controller never probes.
That became a live bug in **v6.16** when the driver was switched from
`bool` to `tristate` for Android GKI. Adding `MODULE_DEVICE_TABLE(of,
vf610_gpio_dt_ids)` only restores the aliases the match table already
describes.

### Risk vs benefit

Benefit is working GPIO autoload on NXP boards that build this driver as
a module. Risk is negligible: module metadata only.

### Concerns

No field crash report; severity is bring-up rather than oops. That does
not outweigh the device-ID exception and the tiny, maintainer-acked
diff. No extra backports are required on this tree.

---

### Verification

- **[Phase 1]** Parsed tags: Reviewed-by Linus Walleij; Link msgid; SOB
  Hou + Bartosz; no Fixes/Reported-by/Cc:stable
- **[Phase 1]** Body: missing OF `MODULE_DEVICE_TABLE`; source-level, no
  hardware repro claimed
- **[Phase 2]** Diff: `drivers/gpio/gpio-vf610.c` +1 line after
  `vf610_gpio_dt_ids[]`
- **[Phase 2]** `include/linux/module.h:255-257`: macro is used+alias
  for file2alias; no runtime side effects
- **[Phase 3]** `git blame` lines 80–86: table from `7f2691a19627a8`
  (2014); MODULE_DEVICE_TABLE from `975a1d61260cf`
- **[Phase 3]** `git show 73dc041f8a602`: tristate +
  `module_platform_driver` without MODULE_DEVICE_TABLE; Android GKI
  rationale
- **[Phase 3]** `git merge-base --is-ancestor 73dc041f8a602 HEAD` → yes;
  `975a1d61260cf HEAD` → yes
- **[Phase 3]** Version tags: modular **in v6.16+**; fix **in
  v7.3-rc1+**, **not** in v7.2
- **[Phase 3]** `git log --oneline -20 -- drivers/gpio/gpio-vf610.c`: no
  series; sibling sifive commit same author
- **[Phase 3]** `git log 975a1d61260cf..HEAD -- drivers/gpio/gpio-
  vf610.c`: empty (no follow-up)
- **[Phase 4]** `b4 dig -c`: lore/msgid
  `20260704122123.73004-1-pengpeng@iscas.ac.cn`
- **[Phase 4]** `b4 dig -a`: v1 only
- **[Phase 4]** `b4 dig -w`: Walleij, Bartosz, linux-gpio, linux-kernel
- **[Phase 4]** `b4 dig -m`: Walleij Reviewed-by; Bartosz “Applied,
  thanks!”; no NAK; no Cc:stable in thread
- **[Phase 4]** WebFetch lore/msgid: **403** UNVERIFIED via HTTP; mbox
  used instead
- **[Phase 4]** lore.kernel.org/stable curl: **403** UNVERIFIED
- **[Phase 5]** semcode: **unavailable**
- **[Phase 5]** Read `gpio-vf610.c`: `of_match_table =
  vf610_gpio_dt_ids`; `module_platform_driver`
- **[Phase 5]** Grep DT: vfxxx, imx7ulp, imx8ulp, imx91/93, imx94,
  imx95, imx952
- **[Phase 6]** `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`;
  `make kernelversion` = 7.3.0-rc4
- **[Phase 6]** Kconfig: `tristate`, `default y if SOC_VF610` only
- **[Phase 8]** Failure mode: module not autoloaded → GPIO missing; not
  a panic
- **UNVERIFIED:** whether GKI already force-loads this `.ko` by name;
  stable@ thread beyond 403

The change is a one-line, maintainer-reviewed autoload fix for an
existing modular GPIO driver. That is appropriate stable material for
this tree’s code.

**YES**

 drivers/gpio/gpio-vf610.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index aa8586d8a787f..adfa2c2d5873d 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -83,6 +83,7 @@ static const struct of_device_id vf610_gpio_dt_ids[] = {
 	{ .compatible = "fsl,imx8ulp-gpio",	.data = &imx8ulp_data, },
 	{ /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, vf610_gpio_dt_ids);
 
 static inline void vf610_gpio_writel(u32 val, void __iomem *reg)
 {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip
  2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip Sasha Levin
@ 2026-10-19 14:27   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-19 14:27 UTC (permalink / raw)
  To: Sasha Levin; +Cc: linux-gpio

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] pinctrl: qcom: missing parent delegation in msm_gpio_irq_set_irqchip_state()
- [Medium] pinctrl: qcom: intr_ack_high ignored in msm_gpio_irq_set_irqchip_state()
--

commit 301c33b42ee8c08eddc97fb199477c476ddbf18c
Author: Maulik Shah <maulik.shah@oss.qualcomm.com>

pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip

This commit implements the .irq_get_irqchip_state and .irq_set_irqchip_state
callbacks for msm_gpio_irq_chip to support replaying edge interrupts for
IRQCHIP_STATE_PENDING after wakeup on MPM-based Qualcomm SoCs.

Link: https://patch.msgid.link/20260424-pinctrl_irqchip_states-v1-1-85286f078916@oss.qualcomm.com

> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
> index e99871b90ab9c..4804d5cba011c 100644
> --- a/drivers/pinctrl/qcom/pinctrl-msm.c
> +++ b/drivers/pinctrl/qcom/pinctrl-msm.c
> @@ -1289,6 +1289,43 @@ static int msm_gpio_irq_set_affinity(struct irq_data *d,
>  	return -EINVAL;
>  }
>  
> +static int msm_gpio_irq_set_irqchip_state(struct irq_data *d,
> +					  enum irqchip_irq_state which, bool val)
> +{
> +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> +	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
> +	const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq];
> +
> +	if (which != IRQCHIP_STATE_PENDING)
> +		return -EINVAL;
> +
> +	if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
> +		return -EINVAL;

[Severity: High]
Does returning -EINVAL here and in msm_gpio_irq_get_irqchip_state() break
parent interrupt state queries and updates on PDC-based Qualcomm SoCs?

In kernel/irq/manage.c, __irq_get_irqchip_state() and irq_set_irqchip_state()
walk up data->parent_data and stop at the first irq_chip that defines the
callback, without falling back to parent_data when -EINVAL is returned:

kernel/irq/manage.c:__irq_get_irqchip_state() {
    ...
    do {
        chip = irq_data_get_irq_chip(data);
        if (WARN_ON_ONCE(!chip))
            return -ENODEV;
        if (chip->irq_get_irqchip_state)
            break;
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
        data = data->parent_data;
#else
        data = NULL;
#endif
    } while (data);
    ...
}

On PDC-based SoCs (IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP), msm_gpio_init() sets
pctrl->skip_wake_irqs for wakeup-capable GPIOs because interrupt detection is
handled by the parent hierarchy (msmgpio -> PDC -> GICv3), and
qcom_pdc_gic_chip in drivers/irqchip/qcom-pdc.c explicitly wires:

    .irq_get_irqchip_state = irq_chip_get_parent_state,
    .irq_set_irqchip_state = irq_chip_set_parent_state,

Previously, msm_gpio_irq_chip left both callbacks NULL, so calls walked past
msmgpio to PDC and GICv3. With this change, when synchronize_irq(),
disable_irq(), or __free_irq() calls __synchronize_hardirq() ->
__irq_get_irqchip_state(irqd, IRQCHIP_STATE_ACTIVE, &inprogress), or when
KVM vgic, machine_kexec_mask_interrupts(), or irq_inject_interrupt() queries
or updates state on a PDC-routed GPIO, the walk stops at msmgpio and fails
with -EINVAL.

Should msm_gpio_irq_set_irqchip_state() and msm_gpio_irq_get_irqchip_state()
delegate to irq_chip_set_parent_state(d, which, val) and
irq_chip_get_parent_state(d, which, val) when d->parent_data &&
test_bit(d->hwirq, pctrl->skip_wake_irqs), similar to
msm_gpio_irq_set_affinity() and msm_gpio_irq_set_vcpu_affinity()?

> +
> +	msm_writel_intr_status(val, pctrl, g);
> +
> +	return 0;
> +}
> +
> +static int msm_gpio_irq_get_irqchip_state(struct irq_data *d,
> +					  enum irqchip_irq_state which, bool *val)
> +{
> +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> +	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
> +	const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq];
> +
> +	if (which != IRQCHIP_STATE_PENDING)
> +		return -EINVAL;
> +
> +	if (test_bit(d->hwirq, pctrl->skip_wake_irqs))
> +		return -EINVAL;
> +
> +	g = &pctrl->soc->groups[d->hwirq];
> +	*val = msm_readl_intr_status(pctrl, g);
> +
> +	return 0;
> +}

[Severity: Medium]
How does msm_gpio_irq_set_irqchip_state() behave on TLMM v2 SoCs where
g->intr_ack_high is set (such as apq8064, ipq8064, mdm9615, msm8660, and
msm8960), or if g->intr_status_bit is non-zero?

In drivers/pinctrl/qcom/pinctrl-msm.c, msm_ack_intr_status() clears a pending
interrupt by accounting for both g->intr_ack_high and g->intr_status_bit:

static void msm_ack_intr_status(struct msm_pinctrl *pctrl,
				const struct msm_pingroup *g)
{
	u32 val = g->intr_ack_high ? BIT(g->intr_status_bit) : 0;

	msm_writel_intr_status(val, pctrl, g);
}

By passing the raw boolean val directly to msm_writel_intr_status(val, pctrl, g),
won't calling irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true) on an
intr_ack_high platform acknowledge and clear the pending interrupt instead of
setting it pending, while passing false writes 0 and fails to clear it?

Also, in msm_gpio_irq_get_irqchip_state(), g = &pctrl->soc->groups[d->hwirq]
is initialized twice, and *val = msm_readl_intr_status(pctrl, g) converts the
full 32-bit register read to bool without masking with BIT(g->intr_status_bit)
(unlike msm_gpio_irq_handler()). Should both functions mask/shift with
BIT(g->intr_status_bit) and account for g->intr_ack_high?

[ ... ]

>
> -- 
> 2.34.1
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019135441.1420968-105-sashal@kernel.org?part=1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH AUTOSEL 6.18-5.10] gpio: mvebu: keep resume masks within the irqchip cache
  2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] gpio: mvebu: keep resume masks within the irqchip cache Sasha Levin
@ 2026-10-19 14:37   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-19 14:37 UTC (permalink / raw)
  To: Sasha Levin; +Cc: linux-gpio

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] gpio: mvebu: TOCTOU race in mvebu_gpio_resume() after dropping gc->lock
- [High] gpio: mvebu: wrong regmap used for Armada XP masks in mvebu_gpio_resume()
--

commit 3f933b6bd33ac55ae181080e42e681c5eace741e
Author: Rosen Penev <rosenp@gmail.com>

gpio: mvebu: keep resume masks within the irqchip cache

This commit updates mvebu_gpio_resume() to mask the saved edge and level
interrupt mask registers against the generic irqchip mask_cache_priv values
before writing them back to hardware on resume.

Link: https://patch.msgid.link/20260915004406.115230-1-rosenp@gmail.com

> diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
> index ac799fced950e..07af0f38252d6 100644
> --- a/drivers/gpio/gpio-mvebu.c
> +++ b/drivers/gpio/gpio-mvebu.c
> @@ -1006,6 +1006,8 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
>  static int mvebu_gpio_resume(struct platform_device *pdev)
>  {
>  	struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
> +	u32 edge_cache = ~0U, level_cache = ~0U;
> +	unsigned long flags;
>  	int i;
>  
>  	regmap_write(mvchip->regs, GPIO_OUT_OFF + mvchip->offset,
> @@ -1017,32 +1019,51 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
>  	regmap_write(mvchip->regs, GPIO_IN_POL_OFF + mvchip->offset,
>  		     mvchip->in_pol_reg);
>  
> +	/*
> +	 * genirq skips mask_irq() for a line it already considers masked, so
> +	 * unmasking one behind its back leaves an asserted level line that
> +	 * nobody masks. Restore only bits the irqchip cache still has set.
> +	 *
> +	 * Snapshot the caches under the raw spinlock, but release it before
> +	 * the regmap writes below: regmap_write() takes a sleepable lock on
> +	 * PREEMPT_RT.
> +	 */
> +	if (mvchip->domain) {
> +		struct irq_chip_generic *gc;
> +
> +		gc = irq_get_domain_generic_chip(mvchip->domain, 0);
> +		raw_spin_lock_irqsave(&gc->lock, flags);
> +		level_cache = gc->chip_types[0].mask_cache_priv;
> +		edge_cache = gc->chip_types[1].mask_cache_priv;
> +		raw_spin_unlock_irqrestore(&gc->lock, flags);
> +	}

[Severity: High]
Can dropping gc->lock and restoring local interrupts before writing the
hardware mask registers race with the irqchip mask and unmask callbacks?

The irqchip callbacks such as mvebu_gpio_level_irq_mask() and
mvebu_gpio_level_irq_unmask() hold gc->lock across both updating
ct->mask_cache_priv and updating the hardware mask register:

drivers/gpio/gpio-mvebu.c:mvebu_gpio_level_irq_mask() {
	guard(raw_spinlock)(&gc->lock);
	ct->mask_cache_priv &= ~mask;
	mvebu_gpio_write_level_mask(mvchip, ct->mask_cache_priv);
}

Since mvebu_gpio_resume() runs during dpm_resume() after dpm_resume_noirq() ->
resume_device_irqs() has re-enabled device interrupts, if a level GPIO
interrupt fires in the window between raw_spin_unlock_irqrestore() and
regmap_write(), the interrupt path:

  mvebu_gpio_irq_handler()
    -> handle_level_irq()
      -> mask_ack_irq()
        -> mvebu_gpio_level_irq_mask()

will clear the bit in ct->mask_cache_priv, mask the hardware register, and set
IRQD_IRQ_MASKED in genirq. When mvebu_gpio_resume() then calls regmap_write()
with its stale level_cache snapshot where the bit is still 1, won't it unmask
the asserted level line in hardware behind genirq's back and cause the same
unhandled level interrupt storm on resume?

Similarly, if an in-flight IRQF_ONESHOT threaded handler finishes via
irq_finalize_oneshot() -> unmask_threaded_irq() or another CPU calls
enable_irq() -> unmask_irq() during that window, the unmask callback will set
the bit in ct->mask_cache_priv and unmask the hardware register under
gc->lock. Won't mvebu_gpio_resume() then overwrite the hardware register with
a stale 0 bit from level_cache or edge_cache, leaving the interrupt
permanently masked in hardware while genirq considers it unmasked?

> +
>  	switch (mvchip->soc_variant) {
>  	case MVEBU_GPIO_SOC_VARIANT_ORION:
>  	case MVEBU_GPIO_SOC_VARIANT_A8K:
>  		regmap_write(mvchip->regs, GPIO_EDGE_MASK_OFF + mvchip->offset,
> -			     mvchip->edge_mask_regs[0]);
> +			     mvchip->edge_mask_regs[0] & edge_cache);
>  		regmap_write(mvchip->regs, GPIO_LEVEL_MASK_OFF + mvchip->offset,
> -			     mvchip->level_mask_regs[0]);
> +			     mvchip->level_mask_regs[0] & level_cache);
>  		break;
>  	case MVEBU_GPIO_SOC_VARIANT_MV78200:
>  		for (i = 0; i < 2; i++) {
>  			regmap_write(mvchip->regs,
>  				     GPIO_EDGE_MASK_MV78200_OFF(i),
> -				     mvchip->edge_mask_regs[i]);
> +				     mvchip->edge_mask_regs[i] & edge_cache);
>  			regmap_write(mvchip->regs,
>  				     GPIO_LEVEL_MASK_MV78200_OFF(i),
> -				     mvchip->level_mask_regs[i]);
> +				     mvchip->level_mask_regs[i] & level_cache);
>  		}
>  		break;
>  	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
>  		for (i = 0; i < 4; i++) {
>  			regmap_write(mvchip->regs,
>  				     GPIO_EDGE_MASK_ARMADAXP_OFF(i),
> -				     mvchip->edge_mask_regs[i]);
> +				     mvchip->edge_mask_regs[i] & edge_cache);
>  			regmap_write(mvchip->regs,
>  				     GPIO_LEVEL_MASK_ARMADAXP_OFF(i),
> -				     mvchip->level_mask_regs[i]);
> +				     mvchip->level_mask_regs[i] & level_cache);
>  		}
>  		break;

[Severity: High]
On MVEBU_GPIO_SOC_VARIANT_ARMADAXP, are these masked writes targeting the
wrong regmap in mvebu_gpio_resume() (and similarly in mvebu_gpio_suspend())?

In mvebu_gpioreg_edge_mask(), mvebu_gpioreg_level_mask(), and
mvebu_gpio_probe(), the per-CPU mask registers at
GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) and GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) live in
mvchip->percpu_regs rather than mvchip->regs:

drivers/gpio/gpio-mvebu.c:mvebu_gpioreg_edge_mask() {
	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
		cpu = smp_processor_id();
		*map = mvchip->percpu_regs;
		*offset = GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
		break;
}

drivers/gpio/gpio-mvebu.c:mvebu_gpio_probe() {
	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
		regmap_write(mvchip->regs, GPIO_EDGE_CAUSE_OFF, 0);
		regmap_write(mvchip->regs, GPIO_EDGE_MASK_OFF, 0);
		regmap_write(mvchip->regs, GPIO_LEVEL_MASK_OFF, 0);
		for (cpu = 0; cpu < 4; cpu++) {
			regmap_write(mvchip->percpu_regs,
				     GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu), 0);
			regmap_write(mvchip->percpu_regs,
				     GPIO_EDGE_MASK_ARMADAXP_OFF(cpu), 0);
			regmap_write(mvchip->percpu_regs,
				     GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu), 0);
		}
		break;
}

By passing mvchip->regs instead of mvchip->percpu_regs here, won't
mvebu_gpio_resume() leave the per-CPU mask registers in mvchip->percpu_regs
unupdated while writing the edge_cache and level_cache masked values over the
global GPIO registers at offsets 0x10..0x2c in mvchip->regs (such as
GPIO_EDGE_CAUSE_OFF at 0x14, GPIO_LEVEL_MASK_OFF at 0x1c, and
GPIO_BLINK_CNT_SELECT_OFF at 0x20)?

>  	default:

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019135441.1420968-150-sashal@kernel.org?part=1

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-10-19 14:37 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20261019135441.1420968-1-sashal@kernel.org>
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: move GPIO IRQ setup into request_resources Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: fix debounce register selection Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] pinctrl: qcom: Add irq_get/set_irqchip_state() for msm gpio irqchip Sasha Levin
2026-10-19 14:27   ` sashiko-bot
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] gpio: mvebu: keep resume masks within the irqchip cache Sasha Levin
2026-10-19 14:37   ` sashiko-bot
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-6.6] gpio: pca9570: Use I2C match data Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-6.1] gpio: sifive: add missing MODULE_DEVICE_TABLE() Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] pinctrl: sx150x: " Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: enable RMII outputs from RMII groups Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] pinctrl: npcm8xx: clear pending GPIO events during init Sasha Levin
2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-5.10] gpio: vf610: add missing MODULE_DEVICE_TABLE() Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox