From: Ioana Ciornei <[email protected]>

[ Upstream commit 208858b1b48eba83d073542372329cf8ed606526 ]

There are use cases in which the Management Complex firmware boot
process is started by the bootloader which does not wait for the boot to
complete. This is mainly done in order to reduce the overall boot time
of a DPAA2 based SoC.

In this kind of circumstance, the fsl-mc bus driver needs to make sure
that the MC firmware boot process is finished before proceeding to the
usual operations such as interrogating the firmware to gather all
existent DPAA2 objects, creating the fsl-mc devices on the bus etc.

Add this kind of check early in the boot process of the fsl-mc bus and
defer the probe in case the firmware is still in its boot process.

Signed-off-by: Ioana Ciornei <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Christophe Leroy (CS GROUP) <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit Message Forensics

### Step 1.1: Subject Line
**Record:** `[bus: fsl-mc]` `[wait]` — Ensure the Management Complex
(MC) firmware has finished booting before the fsl-mc bus driver proceeds
with DPAA2 enumeration.

### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Ioana Ciornei `<[email protected]>` (author)
- **Link:** https://lore.kernel.org/r/20260401144508.3062019-1-
  [email protected]
- **Signed-off-by:** Christophe Leroy (CS GROUP) `<[email protected]>`
  (committer/ack)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, or Cc:
  stable tags
- Notable: NXP author, FSL maintainer committer; no fuzzer or user bug
  reports

### Step 1.3: Body Analysis
**Record:**
- **Bug:** Bootloaders on DPAA2 SoCs may start MC firmware boot
  asynchronously (to shorten boot time) without waiting for completion.
- **Symptom:** `fsl_mc_bus_probe()` talks to MC firmware (version query,
  DPRC enumeration, device creation) before firmware is ready → MC I/O
  fails.
- **Failure mode:** Without `-EPROBE_DEFER`, probe fails permanently;
  DPAA2 networking/storage/crypto does not come up.
- **Root cause:** Driver assumed MC firmware was ready at probe time; no
  GSR (Global Status Register) boot-complete check.
- **Version info:** None in message; fix targets all trees with the
  existing probe path.

### Step 1.4: Hidden Bug Fix Detection
**Record:** Yes — described as a synchronization improvement, but it
fixes a real boot race. Without it, `mc_get_version()` and later MC
portal calls run against firmware still booting, causing hard probe
failure instead of deferred retry.

---

## Phase 2: Diff Analysis

### Step 2.1: Inventory
**Record:**
- **Files:** `drivers/bus/fsl-mc/fsl-mc-bus.c` only (+46 lines, 0
  removed)
- **Functions added:** `fsl_mc_read_gsr()`, `fsl_mc_firmware_check()`
- **Function modified:** `fsl_mc_bus_probe()` — adds call after GCR1
  resume
- **Scope:** Single-file, surgical fix

### Step 2.2: Code Flow Change
**Record:**
- **Hunk 1 (defines):** Adds `FSL_MC_GSR` (offset 0x8) and bit masks for
  boot-done, MCS status, and boot code.
- **Hunk 2 (`fsl_mc_firmware_check`):**
  - Before: No firmware readiness check.
  - After: Reads GSR; if boot code `0xDD` → `-EOPNOTSUPP` (DPL never
    started); if `BOOT_DONE` clear → `-EPROBE_DEFER`; if MCS error bits
    set → `-EINVAL`.
- **Hunk 3 (`fsl_mc_bus_probe`):**
  - Before: After GCR1 resume, immediately opens MC portal and calls
    `mc_get_version()`.
  - After: Calls `fsl_mc_firmware_check()` first; only proceeds on
    success.

### Step 2.3: Bug Mechanism
**Record:** **Category:** Logic / timing race (boot synchronization).
**Mechanism:** Probe races ahead of asynchronous MC firmware boot
started by the bootloader. Fix polls hardware GSR and uses
`-EPROBE_DEFER` so the driver core retries once firmware is ready.

### Step 2.4: Fix Quality
**Record:** Fix is minimal and follows established kernel patterns
(`EPROBE_DEFER`, hardware status register). Low regression risk on real
DPAA2 hardware (GSR register is part of the existing MC control register
block at `IORESOURCE_MEM` index 1). Minor note:
`fsl_mc_firmware_check()` is called outside `if (mc->fsl_mc_regs)` —
would NULL-deref if register resource 1 is absent, but all in-tree DPAA2
DT bindings provide both `reg` regions and the same resource is already
required for GCR1 pause/resume logic.

---

## Phase 3: Git History Investigation

### Step 3.1: Blame
**Record:** Probe path without GSR check dates to Jakub Kicinski merge
`e7fa5c80defe0` (Jan 2021). GCR1 pause/resume added by Laurentiu Tudor
`f8cfa9bbab338b` / `8c97a4fc1b348` (Jul 2021). Buggy “assume firmware
ready” behavior has been present since probe was written; async-
bootloader scenario was never handled.

### Step 3.2: Fixes: Tag
**Record:** N/A — no Fixes: tag.

### Step 3.3: Related File History
**Record:** Recent stable-tree changes to this file include error-
handling fixes (`b662f91e216fd`), UAF fix (`1d6bd6183e723`),
`platform_get_resource()` check (`25f526507b8cc`). Commit
`208858b1b48eb` is standalone (v1 only, no series). On mainline but not
yet in `stable/linux-6.18.y`.

### Step 3.4: Author Context
**Record:** Ioana Ciornei is an active NXP contributor to fsl-mc
(endpoint, userspace support, command whitelist commits visible in this
tree). Christophe Leroy is the FSL/soc maintainer who applied the patch.

### Step 3.5: Dependencies
**Record:** No prerequisites. Uses existing `mc->fsl_mc_regs`,
`platform_get_drvdata()`, and `readl()`. Applies cleanly to this tree
(`git apply --check` passed). Standalone.

---

## Phase 4: Mailing List and External Research

### Step 4.1: Original Discussion
**Record:** `b4 dig -c 208858b1b48eb` →
https://patch.msgid.link/[email protected].
Single v1 submission (Apr 1, 2026). Maintainer reply: “Applied, thanks!”
— no NAKs, no stable nomination, no review objections.

### Step 4.2: Reviewers
**Record:** `b4 dig -w`: To/Cc included `[email protected]`, `linuxppc-
[email protected]`, `[email protected]`. Appropriate
maintainers CC'd.

### Step 4.3: Bug Report
**Record:** N/A — no Reported-by or external bug link. Issue is
described as a known bootloader optimization use case from NXP.

### Step 4.4: Related Patches
**Record:** Standalone patch, not part of a multi-patch series. Related
historical context: 2021 GCR1 pause/resume series addressed the opposite
timing problem (MC running too early before IOMMU).

### Step 4.5: Stable List
**Record:** Not searched on lore stable list; no stable nomination found
in the patch thread.

---

## Phase 5: Code Semantic Analysis

### Step 5.1: Key Functions
**Record:** `fsl_mc_firmware_check()`, `fsl_mc_read_gsr()`,
`fsl_mc_bus_probe()`

### Step 5.2: Callers
**Record:** `fsl_mc_bus_probe()` is the `platform_driver.probe` callback
for `fsl_mc_bus_driver` — invoked during platform device enumeration at
boot on DPAA2 SoCs (DT: `fsl,qoriq-mc`; ACPI: `NXP0008`).

### Step 5.3: Callees
**Record:** `readl()` on `mc->fsl_mc_regs + FSL_MC_GSR`;
`platform_get_drvdata()`; `dev_err()` / `dev_dbg()`.

### Step 5.4: Reachability
**Record:** Triggered on every boot of DPAA2 hardware when
`CONFIG_FSL_MC_BUS=y/m`. Bootloader async MC start is the trigger
condition. Affects init path, not a hot path. Userspace cannot directly
trigger, but all DPAA2 I/O depends on successful probe.

### Step 5.5: Similar Patterns
**Record:** Existing `EPROBE_DEFER` usage in same file for ACPI DMA
deferral (`f8cfa9bbab338b`, line 1053). GCR1 pause/resume in bus
notifier and probe handles complementary MC/IOMMU timing. This fix
completes the boot-synchronization story for the async-bootloader case.

---

## Phase 6: Cross-Reference Against Local Tree

### Step 6.1: Buggy Code Present?
**Record:** **Yes.** Local tree is **v6.18.43** (`stable/linux-6.18.y`).
`fsl_mc_firmware_check` / `FSL_MC_GSR` are **not** present (grep found
no matches). `fsl_mc_bus_probe()` at lines 1069–1091 proceeds directly
from GCR1 resume to `fsl_create_mc_io()` / `mc_get_version()` with no
boot-complete check.

### Step 6.2: Backport Complications
**Record:** **Clean apply** — `git apply --check` on commit
`208858b1b48eb` succeeded with no conflicts. Probe structure matches
mainline.

### Step 6.3: Related Fixes Already Present?
**Record:** No equivalent GSR boot-check fix in this tree. Prerequisite
infrastructure (`fsl_mc_regs`, GCR1 defines, bus notifier) all present
since 2021.

---

## Phase 7: Subsystem and Maintainer Context

### Step 7.1: Subsystem Criticality
**Record:** **Subsystem:** `drivers/bus/fsl-mc` (NXP QorIQ DPAA2 bus).
**Criticality:** IMPORTANT for DPAA2 platforms — root bus for all DPAA2
objects (DPMAC networking, DPNI, DPIO, crypto, etc.). Not universal, but
essential on affected enterprise/embedded SoCs (LS1088, LS2088, LX2160,
etc.).

### Step 7.2: Subsystem Activity
**Record:** Moderately active — recent stable fixes include UAF, double-
free, error-handling. MC/IOMMU boot synchronization has been an ongoing
concern since 2021.

---

## Phase 8: Impact and Risk Assessment

### Step 8.1: Who Is Affected
**Record:** Platform-specific — users of NXP QorIQ DPAA2 SoCs with
bootloaders that start MC firmware boot without waiting. All
DPAA2-dependent functionality is affected when the race loses.

### Step 8.2: Trigger Conditions
**Record:** Boot-time race when bootloader optimizes boot time by not
waiting for MC firmware. Reasonably likely on newer/fast-boot
configurations. Not userspace-triggerable; not a security issue.

### Step 8.3: Failure Severity
**Record:** **Probe failure → DPAA2 subsystem non-functional** (no
network, no DPAA2 devices enumerated). Without `-EPROBE_DEFER`, failure
is permanent for that boot. **Severity: HIGH** for affected platforms
(functional boot failure of core I/O subsystem).

### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH for DPAA2 users with async-boot bootloaders —
  restores reliable boot.
- **Risk:** LOW — 46 lines, hardware register read, standard defer
  pattern, applies cleanly.
- **Ratio:** Strong benefit, low risk.

---

## Phase 9: Final Synthesis

### Step 9.1: Evidence Summary

**FOR backport:**
- Fixes real boot race on DPAA2 SoCs
- Prevents permanent probe failure and broken DPAA2 I/O
- Small, self-contained, applies cleanly to v6.18.43
- Uses standard `-EPROBE_DEFER` mechanism
- Buggy code confirmed present in this tree since 2021
- NXP developer + FSL maintainer authorship
- Analogous to prior stable-worthy MC/IOMMU boot timing fixes

**AGAINST backport:**
- Platform-specific (DPAA2 only) — but stable routinely takes such fixes
- No syzbot/user bug report — but mechanism is clear from code and
  commit message
- `fsl_mc_firmware_check()` called even when `mc->fsl_mc_regs` may be
  NULL — mitigated by all real DPAA2 bindings providing resource index 1

**Unresolved:** No independent user crash reports; impact verified by
code analysis and NXP description only.

### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — hardware GSR check +
   EPROBE_DEFER is standard; maintainer applied without objection.
2. Fixes a real bug? **PASS** — boot race causes MC I/O failure before
   firmware ready.
3. Important issue? **PASS** — HIGH: DPAA2 probe failure, core I/O
   broken on affected SoCs.
4. Small and contained? **PASS** — 46 lines, one file.
5. No new features/APIs? **PASS** — synchronization fix only.
6. Can apply to local tree? **PASS** — clean apply verified.

### Step 9.3: Exception Categories
**Record:** None (not device ID, quirk, DT, build, or docs). Qualifies
as a hardware boot-synchronization bug fix.

### Step 9.4: Decision Rationale
For **linux-6.18.y (v6.18.43)**, the fsl-mc bus driver lacks any MC
firmware boot-complete check. When bootloaders start MC firmware
asynchronously, probe races ahead and fails MC portal operations —
without `-EPROBE_DEFER` this is a permanent boot failure for the entire
DPAA2 subsystem. The fix is small, obviously correct, self-contained,
and applies cleanly. Platform-specific scope is normal for stable DPAA2
fixes.

---

## Verification

- **[Phase 1]** Parsed commit message and tags from `git show
  208858b1b48eb`
- **[Phase 1]** Confirmed no Fixes:/Reported-by:/Cc: stable tags
- **[Phase 2]** Full diff analyzed: +46 lines in `fsl-mc-bus.c`, two new
  functions, one probe call site
- **[Phase 3]** `git describe HEAD` → v6.18.43; tree on
  `stable/linux-6.18.y`
- **[Phase 3]** `git blame` on probe area: core probe from
  `e7fa5c80defe0` (2021), GCR1 logic from `f8cfa9bbab338b` (2021)
- **[Phase 3]** `git log stable/linux-6.18.y..origin/master --
  drivers/bus/fsl-mc/fsl-mc-bus.c`: commit `208858b1b48eb` not in stable
- **[Phase 3]** `git apply --check` on patch: **clean apply**
- **[Phase 4]** `b4 dig -c 208858b1b48eb`: found lore thread
- **[Phase 4]** `b4 dig -a`: single v1, no revisions
- **[Phase 4]** `b4 dig -w`: chleroy, linuxppc-dev, linux-kernel CC'd
- **[Phase 4]** `b4 dig -m /tmp/fsl_mc.mbox`: maintainer “Applied,
  thanks!” — no NAKs or stable discussion
- **[Phase 5]** `grep fsl_mc_bus_probe`: only platform driver probe
  callback
- **[Phase 5]** Read current `fsl_mc_bus_probe()` lines 1014–1096:
  confirms no GSR check before `mc_get_version()`
- **[Phase 5]** DT check `fsl-lx2160a.dtsi`: two `reg` entries for fsl-
  mc (portal + control registers)
- **[Phase 6]** `grep FSL_MC_GSR fsl_mc_firmware_check`: **not present**
  in local tree
- **[Phase 6]** Confirmed buggy probe path exists at lines 1069–1091
- **[Phase 6]** Patch applies cleanly to v6.18.43
- **[Phase 7]** `Kconfig`: `FSL_MC_BUS` depends on OF && (LAYERSCAPE ||
  COMPILE_TEST)
- **[Phase 8]** Failure mode: `mc_get_version()` error → `goto
  error_cleanup_mc_io` → non-defer probe failure

**YES**

 drivers/bus/fsl-mc/fsl-mc-bus.c | 46 +++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 996379ace3764..21eb0a3c190fc 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -66,6 +66,13 @@ struct fsl_mc_addr_translation_range {
 #define GCR1_P1_STOP   BIT(31)
 #define GCR1_P2_STOP   BIT(30)
 
+#define FSL_MC_GSR             0x8
+#define FSL_MC_GSR_BOOT_DONE   BIT(0)
+#define FSL_MC_GSR_MCS_MASK    GENMASK(7, 0)
+#define FSL_MC_GSR_MCS_ERR_MASK        GENMASK(7, 1)
+#define FSL_MC_GSR_BC_MASK     GENMASK(15, 8)
+#define FSL_MC_GSR_BC_SHIFT    8
+
 #define FSL_MC_FAPR    0x28
 #define MC_FAPR_PL     BIT(18)
 #define MC_FAPR_BMT    BIT(17)
@@ -1007,6 +1014,41 @@ static int get_mc_addr_translation_ranges(struct device 
*dev,
        return 0;
 }
 
+static u32 fsl_mc_read_gsr(struct fsl_mc *mc)
+{
+       return readl(mc->fsl_mc_regs + FSL_MC_GSR);
+}
+
+static int fsl_mc_firmware_check(struct platform_device *pdev)
+{
+       struct fsl_mc *mc = platform_get_drvdata(pdev);
+       u32 gsr, boot_done, boot_code, mcs;
+
+       gsr = fsl_mc_read_gsr(mc);
+       boot_code = (gsr & FSL_MC_GSR_BC_MASK) >> FSL_MC_GSR_BC_SHIFT;
+       if (boot_code == 0xDD) {
+               dev_err(&pdev->dev,
+                       "fsl-mc: DPL processing was not started, DPAA2 will not 
work!\n");
+               return -EOPNOTSUPP;
+       }
+
+       boot_done = gsr & FSL_MC_GSR_BOOT_DONE;
+       if (!boot_done) {
+               dev_dbg(&pdev->dev,
+                       "fsl-mc: DPL processing in progress, defer probe\n");
+               return -EPROBE_DEFER;
+       }
+
+       mcs = gsr & FSL_MC_GSR_MCS_MASK;
+       if (mcs & FSL_MC_GSR_MCS_ERR_MASK) {
+               dev_err(&pdev->dev,
+                       "fsl-mc: MC boot completed with error 0x%x\n", mcs);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
  * fsl_mc_bus_probe - callback invoked when the root MC bus is being
  * added
@@ -1071,6 +1113,10 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
                       mc->fsl_mc_regs + FSL_MC_GCR1);
        }
 
+       error = fsl_mc_firmware_check(pdev);
+       if (error)
+               return error;
+
        /*
         * Get physical address of MC portal for the root DPRC:
         */
-- 
2.53.0


Reply via email to