* Re: [PATCH v3] arm64: errata: Workaround NVIDIA Olympus device store/load ordering erratum
From: Jason Gunthorpe @ 2026-06-11 17:49 UTC (permalink / raw)
To: Will Deacon
Cc: Shanker Donthineni, Catalin Marinas, Vladimir Murzin,
linux-arm-kernel, Mark Rutland, linux-kernel, linux-doc,
Vikram Sethi, Jason Sequeira
In-Reply-To: <aiq5VigmtZq9GlAm@willie-the-truck>
On Thu, Jun 11, 2026 at 02:34:14PM +0100, Will Deacon wrote:
> I still reckon you should do something with the memcpy-to-io routines.
> A simple option could be to make dgh() a dmb on parts with the erratum?
> That at least moves the barrier out of the loop.
AFAIK only callers that know they are using WC memory should be
calling dgh() and in that case we know it is NORMAL-NC and we don't
need a different barrier
Other random users calling memcpy_to_io functions on real IO don't
have to do dgh(), and AFAIK it doesn't do anything on the Device
memory types?
Jason
^ permalink raw reply
* Re: [PATCH v2 3/3] arm64: escalate smp_send_stop() to an SDEI NMI as a last resort
From: Kiryl Shutsemau @ 2026-06-11 17:47 UTC (permalink / raw)
To: Doug Anderson
Cc: Catalin Marinas, Will Deacon, James Morse, Mark Rutland,
Marc Zyngier, Petr Mladek, Thomas Gleixner, Andrew Morton,
Baoquan He, Puranjay Mohan, Usama Arif, Breno Leitao,
Julien Thierry, Lecopzer Chen, Sumit Garg, kernel-team, kexec,
linux-arm-kernel, linux-kernel
In-Reply-To: <CAD=FV=VLoJBMhDjb=3XAOCZWDBACn_=KdnkL0J6-Ch4uKrHjNA@mail.gmail.com>
On Wed, Jun 10, 2026 at 03:50:32PM -0700, Doug Anderson wrote:
> Hi,
>
> On Tue, Jun 9, 2026 at 6:58 AM Kiryl Shutsemau <kirill@shutemov.name> wrote:
> >
> > @@ -910,6 +911,35 @@ static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs
> > #endif
> > }
> >
> > +#ifdef CONFIG_ARM_SDEI_NMI
> > +/*
> > + * Stop entry for the SDEI cross-CPU NMI service: its event-0 handler
> > + * lands here when this CPU was asked to stop. The bookkeeping mirrors
> > + * the IPI_CPU_STOP{,_NMI} handling; the park happens inside the SDEI
> > + * event, which is never completed -- completing it would have firmware
> > + * resume the interrupted (typically wedged) context. No PSCI CPU_OFF
> > + * either: powering off a PE that EL3 still considers mid-event invites
> > + * firmware trouble.
> > + */
> > +void __noreturn arm64_nmi_cpu_stop(struct pt_regs *regs)
> > +{
> > + unsigned int cpu = smp_processor_id();
> > +
> > + local_daif_mask();
> > +
> > + if (IS_ENABLED(CONFIG_KEXEC_CORE) && crash_stop)
> > + crash_save_cpu(regs, cpu);
> > +
> > + /* the ack the stop requester polls for */
> > + set_cpu_online(cpu, false);
> > +
> > + sdei_mask_local_cpu();
> > +
> > + cpu_park_loop();
> > +}
> > +NOKPROBE_SYMBOL(arm64_nmi_cpu_stop);
> > +#endif
>
> Can we combine everything into one function so we don't have to keep
> all the different stop functionality in sync? Like this (untested):
>
Okay. Look good to me. See the patch below.
void __noreturn arm64_nmi_cpu_stop(struct pt_regs *regs, bool die_on_crash)
The stop IPI handlers call it with die_on_crash=true, the SDEI handler
and panic_smp_self_stop() with false. Pretty much your sketch, with the
crash = IS_ENABLED(CONFIG_KEXEC_CORE) && crash_stop discriminator inside.
> FWIW, I'm not totally sure I followed the logic for why "die_on_crash"
> needs to be "false" for the SDEI case,
It's not about kexec mechanics, it's about the SDEI dispatch state.
The SDEI stop handler parks inside an SDEI event that it deliberately
never completes — completing it makes firmware resume the wedged
context, which is the opposite of what we want. PSCI CPU_OFF from inside
that not-yet-completed event silently wedges EL3 on at least one
production firmware (still root-causing on the firmware side), so the
SDEI path saves the crashed context and parks instead of powering off.
The only consequence is that an SMP capture kernel can't re-online that
CPU. The dump itself is complete. I've left "power the SDEI-stopped CPU
off too" as a follow-up and called it out in the cover letter. The IPI
crash path is unaffected and still does CPU_OFF, exactly as before.
> Perhaps when doing that you'd stop unconditionally getting the cpu in
> do_handle_IPI() and just call it for `IPI_KGDB_ROUNDUP` since it would
> now be the only consumer of that local variable.
I kept the local cpu — after the change it's still used by the
IPI_KGDB_ROUNDUP case and the default: pr_crit(), so it didn't become
single-use.
> > @@ -1263,6 +1293,29 @@ void smp_send_stop(void)
> > udelay(1);
> > }
> >
> > + /*
> > + * If CPUs are *still* online, try the SDEI cross-CPU NMI. Firmware
> > + * delivers it regardless of the target's DAIF state, so it reaches
> > + * a CPU spinning with interrupts masked, which neither rung above
> > + * could (without pseudo-NMI there is no NMI rung at all). Allow
> > + * 100ms: a firmware round-trip per CPU, with headroom.
> > + */
> > + if (num_other_online_cpus()) {
> > + /* re-snapshot after the rungs above took CPUs offline */
> > + smp_rmb();
> > + cpumask_copy(&mask, cpu_online_mask);
> > + cpumask_clear_cpu(smp_processor_id(), &mask);
> > +
> > + if (sdei_nmi_stop_cpus(&mask)) {
> > + pr_info("SMP: retry stop with SDEI NMI for CPUs %*pbl\n",
> > + cpumask_pr_args(&mask));
>
> Perhaps it's being a bit pedantic, but it's a little weird that you're
> printing a message that sounds like "I'm going to retry with SDEI"
> after you've already done it. It feels like it would be nominally
> cleaner (and more parellel with the pseudo-NMI case) if you could
> separately test if SDEI is available. Then sdei_nmi_stop_cpus() would
> just return void?
Fixed. There's now a sdei_nmi_active() predicate; the rung tests it,
prints, then calls sdei_nmi_stop_cpus(), which is now void. It mirrors
the pseudo-NMI rung's check-then-act shape.
>
>
> > @@ -59,8 +64,45 @@ static bool sdei_nmi_available;
> >
> > #define SDEI_NMI_EVENT 0
> >
> > +/*
> > + * Stop-request dispatch lives on the same SDEI event 0 as everything
> > + * else. The requesting CPU sets each target's bit in sdei_nmi_stop_mask
> > + * before signalling event 0; the target's handler test-and-clears its
> > + * bit and hands the CPU to arm64_nmi_cpu_stop(), which saves crash
> > + * state when the stop is a kdump crash-stop, marks the CPU offline
> > + * (which is what the requester polls for) and parks it.
> > + *
> > + * This mirrors the cpumask the framework's nmi_cpu_backtrace() consults
> > + * just below, and a shared mask rather than a separate SDEI event avoids
> > + * extra registrations from firmware.
> > + */
>
> Do you have any reasoning for why you don't pick a separate EVENT ID
> for "backtrace" vs. "stop". If you absolutely have to share an ID
> because they're a limited resource then I guess it's fine, but it
> would make the code easier to understand / reason about if they were
> separate IDs.
>
> If you had a separate EVENT ID, then it seems like you could
> completely eliminate the (potentially large) `sdei_nmi_stop_mask`
> variable, right? Any time a "STOP" event fires you can unconditionally
> consider it to be a stop w/ no globals needed, right?
Separate event IDs aren't available: SDEI_EVENT_SIGNAL only ever signals
event 0 — it's the one architecturally software-signalled event. Every
other event number is an interrupt-bound event that firmware has to
define and bind, which is the firmware dependency this series is
specifically trying not to add. So backtrace and stop are stuck sharing
event 0.
But you're right that the mask should go — just not via a second event. A
stop is terminal and system-wide (sdei_nmi_stop_cpus() is only reached
from smp_send_stop(), which never returns), so once a stop is requested
every later event-0 fire is a stop too. I replaced the cpumask with a
single write-once flag the handler reads; a backtrace that races in
after a stop has begun just stops that CPU, which is fine. So the
(potentially large) variable is gone.
> > @@ -115,6 +157,35 @@ bool sdei_nmi_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu)
> > return true;
> > }
> >
> > +/*
> > + * Last rung of the stop escalation in smp_send_stop() (see
> > + * arch/arm64/kernel/smp.c). The caller runs the regular stop IPI (and
> > + * the pseudo-NMI stop IPI, where available) first; @mask holds whatever
> > + * stayed online through those -- typically CPUs wedged with interrupts
> > + * masked, unreachable by an IPI. Set each target's stop-request flag and
> > + * signal event 0 at it; a target acks by marking itself offline, which
> > + * the caller polls for.
> > + *
> > + * Returns false when SDEI isn't active, so the caller can skip the wait.
> > + */
> > +bool sdei_nmi_stop_cpus(const cpumask_t *mask)
> > +{
> > + unsigned int cpu;
> > +
> > + if (!sdei_nmi_available)
> > + return false;
> > +
> > + cpumask_or(&sdei_nmi_stop_mask, &sdei_nmi_stop_mask, mask);
>
> As per above, hopefully we can get rid of `sdei_nmi_stop_mask`. ...but
> if we keep it, I'm curious why "or" and not "copy"?
It doesn't matter anymore. Mask is gone.
Thanks for the feedback! Any other comments?
--------------------------------8<-----------------------------------------------
From c25c32428c5f4fd896815acec5633240326e810c Mon Sep 17 00:00:00 2001
From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
Date: Tue, 2 Jun 2026 15:28:10 +0100
Subject: [PATCHv2.1 3/3] arm64: escalate smp_send_stop() to an SDEI NMI as a last
resort
A CPU wedged with interrupts masked ignores the stop IPI, and without
pseudo-NMI there is no NMI IPI to escalate to: a reboot proceeds with
the CPU still running, and a kdump misses its registers.
Add a third rung to smp_send_stop(): once the IPI (and pseudo-NMI IPI,
if enabled) rungs have run, signal SDEI event 0 at whatever stayed
online. Firmware delivers it regardless of the target's DAIF, so it
reaches a CPU a plain IPI cannot; the target acks by going offline,
which the caller already polls for.
Fold the stop bookkeeping into one arm64_nmi_cpu_stop(regs,
die_on_crash), shared by the stop IPI handlers, panic_smp_self_stop()
and the SDEI handler, replacing the near-duplicate local_cpu_stop() and
ipi_cpu_crash_stop(). @die_on_crash is the only difference: the IPI
handlers pass true and PSCI CPU_OFF the CPU on a crash stop so a capture
kernel can reclaim it; the SDEI handler and self-stop pass false and
park. The SDEI park is required, not conservative -- its handler runs
inside an SDEI event that is never completed (completing it resumes the
wedged context), and a CPU_OFF from that unfinished-event context wedges
EL3 on some firmware (left as a follow-up). The dump is unaffected; only
re-onlining the CPU in an SMP capture kernel is lost.
Suggested-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
---
arch/arm64/include/asm/nmi.h | 24 +++++++
arch/arm64/kernel/smp.c | 109 +++++++++++++++++++++-----------
drivers/firmware/Kconfig | 2 +
drivers/firmware/arm_sdei_nmi.c | 75 ++++++++++++++++++++++
4 files changed, 172 insertions(+), 38 deletions(-)
diff --git a/arch/arm64/include/asm/nmi.h b/arch/arm64/include/asm/nmi.h
index 9366be419d18..2e8974ff8d63 100644
--- a/arch/arm64/include/asm/nmi.h
+++ b/arch/arm64/include/asm/nmi.h
@@ -4,21 +4,45 @@
#include <linux/cpumask.h>
+struct pt_regs;
+
/*
* Cross-CPU NMI provider hooks, consulted by the arm64 arch code before
* its regular-IRQ / pseudo-NMI IPI paths. The SDEI provider in
* drivers/firmware/arm_sdei_nmi.c implements them when active; a future
* FEAT_NMI provider could slot in here too. The stubs let callers stay
* unconditional when ARM_SDEI_NMI is off.
+ *
+ * sdei_nmi_active() lets a caller test for the service before committing
+ * to (and waiting on) the SDEI stop rung; sdei_nmi_stop_cpus() then signals
+ * the targets, which ack by going offline.
*/
#ifdef CONFIG_ARM_SDEI_NMI
bool sdei_nmi_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu);
+bool sdei_nmi_active(void);
+void sdei_nmi_stop_cpus(const cpumask_t *mask);
#else
static inline bool sdei_nmi_trigger_cpumask_backtrace(const cpumask_t *mask,
int exclude_cpu)
{
return false;
}
+
+static inline bool sdei_nmi_active(void)
+{
+ return false;
+}
+
+static inline void sdei_nmi_stop_cpus(const cpumask_t *mask) { }
#endif
+/*
+ * The common "stop this CPU" entry every arm64 stop path funnels through:
+ * the regular/pseudo-NMI stop IPI handlers, panic_smp_self_stop(), and the
+ * SDEI cross-CPU NMI handler. @die_on_crash powers the CPU off on the kdump
+ * crash path (IPI handlers) instead of parking it (SDEI / self-stop).
+ * Defined in arch/arm64/kernel/smp.c.
+ */
+void __noreturn arm64_nmi_cpu_stop(struct pt_regs *regs, bool die_on_crash);
+
#endif /* __ASM_NMI_H */
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index a670434a8cae..e85a4ba18d5c 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -33,6 +33,7 @@
#include <linux/kernel_stat.h>
#include <linux/kexec.h>
#include <linux/kgdb.h>
+#include <linux/kprobes.h>
#include <linux/kvm_host.h>
#include <linux/nmi.h>
@@ -862,14 +863,58 @@ void arch_irq_work_raise(void)
}
#endif
-static void __noreturn local_cpu_stop(unsigned int cpu)
+/*
+ * Bring the local CPU to a stop, saving its register state into the vmcore
+ * on the kdump crash path first. The single point every arm64 stop path
+ * funnels through, so the bookkeeping (mask interrupts, mark offline, mask
+ * SDEI, optionally power off) lives in one place:
+ *
+ * - the regular IPI_CPU_STOP and pseudo-NMI IPI_CPU_STOP_NMI handlers;
+ * - panic_smp_self_stop(), a CPU parking itself on a parallel panic();
+ * - the SDEI cross-CPU NMI handler (drivers/firmware/arm_sdei_nmi.c),
+ * which reaches CPUs the stop IPIs could not.
+ *
+ * @regs is the register state to record in the vmcore on a crash stop; NULL
+ * means "capture the current context". @die_on_crash decides the kdump crash
+ * path: the IPI stop handlers pass true and power the CPU off (PSCI CPU_OFF,
+ * via __cpu_try_die()) so a capture kernel can reclaim it. The SDEI handler
+ * and panic_smp_self_stop() pass false and only park. For SDEI that is
+ * required, not just conservative: it runs inside an SDEI event that is
+ * deliberately never completed (completing it has firmware resume the wedged
+ * context), and a CPU_OFF from that not-yet-completed context wedges EL3 on
+ * some firmware -- a documented follow-up. Parking also matches this path's
+ * own fallback when CPU_OFF is unavailable.
+ */
+void __noreturn arm64_nmi_cpu_stop(struct pt_regs *regs, bool die_on_crash)
{
+ unsigned int cpu = smp_processor_id();
+ bool crash = IS_ENABLED(CONFIG_KEXEC_CORE) && crash_stop;
+
+ /*
+ * Use local_daif_mask() instead of local_irq_disable() to make sure
+ * that pseudo-NMIs are disabled. The "stop" code starts with an IRQ
+ * and falls back to NMI (which might be pseudo). If the IRQ finally
+ * goes through right as we're timing out then the NMI could interrupt
+ * us. It's better to prevent the NMI and let the IRQ finish since the
+ * pt_regs will be better.
+ */
+ local_daif_mask();
+
+ if (crash)
+ crash_save_cpu(regs, cpu);
+
+ /* the ack a stop requester (e.g. smp_send_stop()) polls for */
set_cpu_online(cpu, false);
- local_daif_mask();
sdei_mask_local_cpu();
+
+ if (crash && die_on_crash)
+ __cpu_try_die(cpu);
+
+ /* just in case */
cpu_park_loop();
}
+NOKPROBE_SYMBOL(arm64_nmi_cpu_stop);
/*
* We need to implement panic_smp_self_stop() for parallel panic() calls, so
@@ -878,36 +923,7 @@ static void __noreturn local_cpu_stop(unsigned int cpu)
*/
void __noreturn panic_smp_self_stop(void)
{
- local_cpu_stop(smp_processor_id());
-}
-
-static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
-{
-#ifdef CONFIG_KEXEC_CORE
- /*
- * Use local_daif_mask() instead of local_irq_disable() to make sure
- * that pseudo-NMIs are disabled. The "crash stop" code starts with
- * an IRQ and falls back to NMI (which might be pseudo). If the IRQ
- * finally goes through right as we're timing out then the NMI could
- * interrupt us. It's better to prevent the NMI and let the IRQ
- * finish since the pt_regs will be better.
- */
- local_daif_mask();
-
- crash_save_cpu(regs, cpu);
-
- set_cpu_online(cpu, false);
-
- sdei_mask_local_cpu();
-
- if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
- __cpu_try_die(cpu);
-
- /* just in case */
- cpu_park_loop();
-#else
- BUG();
-#endif
+ arm64_nmi_cpu_stop(NULL, false);
}
static void arm64_send_ipi(const cpumask_t *mask, unsigned int nr)
@@ -984,12 +1000,7 @@ static void do_handle_IPI(int ipinr)
case IPI_CPU_STOP:
case IPI_CPU_STOP_NMI:
- if (IS_ENABLED(CONFIG_KEXEC_CORE) && crash_stop) {
- ipi_cpu_crash_stop(cpu, get_irq_regs());
- unreachable();
- } else {
- local_cpu_stop(cpu);
- }
+ arm64_nmi_cpu_stop(get_irq_regs(), true);
break;
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
@@ -1263,6 +1274,28 @@ void smp_send_stop(void)
udelay(1);
}
+ /*
+ * If CPUs are *still* online, try the SDEI cross-CPU NMI. Firmware
+ * delivers it regardless of the target's DAIF state, so it reaches
+ * a CPU spinning with interrupts masked, which neither rung above
+ * could (without pseudo-NMI there is no NMI rung at all). Allow
+ * 100ms: a firmware round-trip per CPU, with headroom.
+ */
+ if (num_other_online_cpus() && sdei_nmi_active()) {
+ /* re-snapshot after the rungs above took CPUs offline */
+ smp_rmb();
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
+
+ pr_info("SMP: retry stop with SDEI NMI for CPUs %*pbl\n",
+ cpumask_pr_args(&mask));
+
+ sdei_nmi_stop_cpus(&mask);
+ timeout = USEC_PER_MSEC * 100;
+ while (num_other_online_cpus() && timeout--)
+ udelay(1);
+ }
+
if (num_other_online_cpus()) {
smp_rmb();
cpumask_copy(&mask, cpu_online_mask);
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6501087ff90d..ab0ee36d46e7 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -46,6 +46,8 @@ config ARM_SDEI_NMI
- arch_trigger_cpumask_backtrace() (sysrq-l, RCU stalls,
hardlockup_all_cpu_backtrace, soft-lockup secondary dumps,
hung-task auxiliary dumps)
+ - smp_send_stop() escalation (reboot/halt and the
+ panic / kdump crash stop)
The driver registers a handler for the SDEI software-signalled
event (event 0) and reaches a target CPU by signalling it with
diff --git a/drivers/firmware/arm_sdei_nmi.c b/drivers/firmware/arm_sdei_nmi.c
index a82776e7b55a..b2a69be6008f 100644
--- a/drivers/firmware/arm_sdei_nmi.c
+++ b/drivers/firmware/arm_sdei_nmi.c
@@ -29,6 +29,11 @@
* hardlockup_all_cpu_backtrace, soft-lockup/hung-task secondary
* dumps all reach interrupt-masked CPUs.
*
+ * - sdei_nmi_stop_cpus() — the last rung of smp_send_stop()'s
+ * escalation (reboot/halt and the panic/kdump crash stop alike),
+ * reaching CPUs that ignored the stop IPIs; on the kdump path the
+ * wedged context is captured into the vmcore before the CPU parks.
+ *
* Delivery uses the standard SDEI software-signalled event (event 0) and
* SDEI_EVENT_SIGNAL. We register a handler for event 0, enable it, and
* poke a target CPU with sdei_event_signal(0, mpidr): firmware makes
@@ -59,8 +64,51 @@ static bool sdei_nmi_available;
#define SDEI_NMI_EVENT 0
+/*
+ * Backtrace and stop both ride SDEI event 0. That is not a chosen economy:
+ * event 0 is the only architecturally software-signalled event -- the sole
+ * event SDEI_EVENT_SIGNAL can target at an arbitrary PE. Every other event
+ * number is a firmware/platform interrupt-bound event, not something the
+ * kernel can raise cross-CPU, so a dedicated "stop" event would need
+ * firmware to define and bind it -- exactly the firmware dependency this
+ * driver sets out to avoid.
+ *
+ * Sharing one event means the handler must tell a stop apart from a
+ * backtrace. A stop is terminal and system-wide -- sdei_nmi_stop_cpus() is
+ * only reached from smp_send_stop() (reboot/halt/panic/kdump), which never
+ * returns -- so once a stop is requested, every later event-0 fire is a
+ * stop too. A single write-once flag therefore carries as much as a
+ * per-CPU mask would: sdei_nmi_stop_cpus() sets it before signalling, and
+ * the handler reads a set flag as "stop this CPU" and a clear flag as
+ * "backtrace" (handled by nmi_cpu_backtrace(), which self-gates on the
+ * framework's backtrace mask). A backtrace fire that races in after a stop
+ * has begun just stops that CPU instead -- harmless, it is going down.
+ */
+static bool sdei_nmi_stopping;
+
static int sdei_nmi_handler(u32 event, struct pt_regs *regs, void *arg)
{
+ if (READ_ONCE(sdei_nmi_stopping)) {
+ /*
+ * Never returns, and deliberately never completes the SDEI
+ * event: SDEI_EVENT_COMPLETE has firmware restore the
+ * interrupted context, which would land the CPU back in
+ * the wedged loop (or in do_idle, which BUGs at
+ * cpuhp_report_idle_dead once it sees itself offline).
+ * Returning a modified pt_regs doesn't help --
+ * arch/arm64/kernel/sdei.c::do_sdei_event only honours a PC
+ * override via its IRQ-state heuristic and otherwise hands
+ * EL3 its own saved-context slot back.
+ *
+ * Trade-off: EL3 retains ~one saved-context slot per parked
+ * CPU until the next hardware reset (~hundreds of bytes per
+ * CPU). Recoverability is unchanged versus an IPI-stopped
+ * CPU: neither comes back without a reset.
+ */
+ arm64_nmi_cpu_stop(regs, false);
+ /* unreachable */
+ }
+
/*
* nmi_cpu_backtrace() no-ops unless this CPU's bit is set in the
* global backtrace mask (driven by nmi_trigger_cpumask_backtrace()),
@@ -115,6 +163,33 @@ bool sdei_nmi_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu)
return true;
}
+bool sdei_nmi_active(void)
+{
+ return sdei_nmi_available;
+}
+
+/*
+ * Last rung of the stop escalation in smp_send_stop() (see
+ * arch/arm64/kernel/smp.c). The caller runs the regular stop IPI (and
+ * the pseudo-NMI stop IPI, where available) first; @mask holds whatever
+ * stayed online through those -- typically CPUs wedged with interrupts
+ * masked, unreachable by an IPI. Mark the stop in progress and signal
+ * event 0 at each target; a target acks by marking itself offline, which
+ * the caller polls for. The caller has already confirmed sdei_nmi_active().
+ */
+void sdei_nmi_stop_cpus(const cpumask_t *mask)
+{
+ unsigned int cpu;
+
+ WRITE_ONCE(sdei_nmi_stopping, true);
+
+ /* Publish the flag before the SMCs make targets read it */
+ smp_wmb();
+
+ for_each_cpu(cpu, mask)
+ sdei_nmi_fire(cpu);
+}
+
/*
* device_initcall (after arch_initcall(sdei_init), so the SDEI subsystem
* is up): probe the firmware, register the event, and turn on the
--
Kiryl Shutsemau / Kirill A. Shutemov
^ permalink raw reply related
* Re: [PATCH RFC 1/2] dt-bindings: pinctl: amlogic,pinctrl-a4: Add gpio irq property
From: Conor Dooley @ 2026-06-11 17:39 UTC (permalink / raw)
To: xianwei.zhao
Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
linux-amlogic, linux-gpio, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <20260611-gpio-to-irq-v1-1-12201716f23f@amlogic.com>
[-- Attachment #1: Type: text/plain, Size: 1305 bytes --]
On Thu, Jun 11, 2026 at 07:54:33AM +0000, Xianwei Zhao via B4 Relay wrote:
> From: Xianwei Zhao <xianwei.zhao@amlogic.com>
>
> Add the hw-irq property for each GPIO bank and enable interrupt-parent
> for pinctrl so that gpiod_to_irq() can translate GPIO lines to IRQs.
Uhhhhh, what? Why can't you just use the normal interrupts property?
>
> Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
> ---
> Documentation/devicetree/bindings/pinctrl/amlogic,pinctrl-a4.yaml | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/amlogic,pinctrl-a4.yaml b/Documentation/devicetree/bindings/pinctrl/amlogic,pinctrl-a4.yaml
> index b69db1b95345..65ec9121300e 100644
> --- a/Documentation/devicetree/bindings/pinctrl/amlogic,pinctrl-a4.yaml
> +++ b/Documentation/devicetree/bindings/pinctrl/amlogic,pinctrl-a4.yaml
> @@ -37,6 +37,8 @@ properties:
>
> ranges: true
>
> + interrupt-parent: true
> +
> patternProperties:
> "^gpio@[0-9a-f]+$":
> type: object
> @@ -65,6 +67,9 @@ patternProperties:
> gpio-ranges:
> maxItems: 1
>
> + hw-irq:
> + $ref: /schemas/types.yaml#/definitions/uint32
> +
> required:
> - reg
> - reg-names
>
> --
> 2.52.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: spi: nuvoton,ma35d1-qspi: Add Nuvoton MA35D1 QSPI
From: Conor Dooley @ 2026-06-11 17:34 UTC (permalink / raw)
To: Chi-Wen Weng
Cc: broonie, robh, krzk+dt, conor+dt, linux-arm-kernel, linux-spi,
devicetree, linux-kernel, cwweng
In-Reply-To: <20260611091246.2070485-2-cwweng.linux@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2626 bytes --]
On Thu, Jun 11, 2026 at 05:12:45PM +0800, Chi-Wen Weng wrote:
> From: Chi-Wen Weng <cwweng@nuvoton.com>
>
> Add a devicetree binding for the Quad SPI controller found in
> Nuvoton MA35D1 SoCs.
>
> The controller supports SPI memory devices such as SPI NOR and SPI NAND
> flashes. It has one register range, one clock input and one reset line,
> and supports up to two chip selects.
>
> Signed-off-by: Chi-Wen Weng <cwweng@nuvoton.com>
> ---
> .../bindings/spi/nuvoton,ma35d1-qspi.yaml | 62 +++++++++++++++++++
> 1 file changed, 62 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml
>
> diff --git a/Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml b/Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml
> new file mode 100644
> index 000000000000..d3b36e612eb0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml
> @@ -0,0 +1,62 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/spi/nuvoton,ma35d1-qspi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Nuvoton MA35D1 Quad SPI Controller
> +
> +maintainers:
> + - Chi-Wen Weng <cwweng@nuvoton.com>
> +
> +allOf:
> + - $ref: /schemas/spi/spi-controller.yaml#
> +
> +properties:
> + compatible:
> + const: nuvoton,ma35d1-qspi
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + resets:
> + maxItems: 1
> +
> + num-cs:
> + maximum: 2
Missing a default of 2, unless you make the property required.
FWIW, your driver doesn't appear to read this value.
pw-bot: changes-requested
Cheers,
Conor.
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - resets
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
> + #include <dt-bindings/reset/nuvoton,ma35d1-reset.h>
> +
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + spi@40680000 {
> + compatible = "nuvoton,ma35d1-qspi";
> + reg = <0 0x40680000 0 0x100>;
> + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clk QSPI0_GATE>;
> + resets = <&sys MA35D1_RESET_QSPI0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> + };
> +
> --
> 2.25.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v3] media: bcm2835-unicam: Fix log status runtime access
From: Laurent Pinchart @ 2026-06-11 17:34 UTC (permalink / raw)
To: Eugen Hristev
Cc: Raspberry Pi Kernel Maintenance, Mauro Carvalho Chehab,
Florian Fainelli, Broadcom internal kernel review list, Ray Jui,
Scott Branden, Dave Stevenson, Hans Verkuil, Sakari Ailus,
Jean-Michel Hautbois, Naushir Patuck, linux-media,
linux-rpi-kernel, linux-arm-kernel, linux-kernel
In-Reply-To: <3b142d52-53d1-4942-bb45-1cb9645c164b@kernel.org>
On Thu, Jun 11, 2026 at 08:18:10PM +0300, Eugen Hristev wrote:
> On 6/11/26 11:03, Laurent Pinchart wrote:
> > On Thu, Jun 11, 2026 at 08:29:55AM +0300, Eugen Hristev wrote:
> >> When requesting log status, the block might be powered off, but registers
> >> are being read.
> >> Avoid reading the registers if the device is not resumed, thus also avoid
> >> powering up the device just for log status.
> >>
> >> Fixes: 392cd78d495f ("media: bcm2835-unicam: Add support for CCP2/CSI2 camera interface")
> >> Signed-off-by: Eugen Hristev <ehristev@kernel.org>
> >> ---
> >> Changes in v3:
> >> - Changed to check return value of pm_runtime_get_if_active() and only call
> >> pm_runtime_put() if the device is active.
> >> - Link to v2: https://patch.msgid.link/20260522-bcmpipm-v2-1-a3da66cbc9f0@kernel.org
> >>
> >> Changes in v2:
> >> - changed to use pm_runtime_get_if_active()
> >> - add corresponding put()
> >> - Link to v1: https://patch.msgid.link/20260521-bcmpipm-v1-1-3eba88d88045@kernel.org
> >>
> >> To: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
> >> To: Mauro Carvalho Chehab <mchehab@kernel.org>
> >> To: Florian Fainelli <florian.fainelli@broadcom.com>
> >> To: Ray Jui <rjui@broadcom.com>
> >> To: Scott Branden <sbranden@broadcom.com>
> >> To: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
> >> To: Sakari Ailus <sakari.ailus@linux.intel.com>
> >> To: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
> >> To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> To: Hans Verkuil <hverkuil@kernel.org>
> >> To: Naushir Patuck <naush@raspberrypi.com>
> >> Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>
> >> Cc: linux-media@vger.kernel.org
> >> Cc: linux-rpi-kernel@lists.infradead.org
> >> Cc: linux-arm-kernel@lists.infradead.org
> >> Cc: linux-kernel@vger.kernel.org
> >> ---
> >> drivers/media/platform/broadcom/bcm2835-unicam.c | 12 ++++++++++++
> >> 1 file changed, 12 insertions(+)
> >>
> >> diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c
> >> index 8d28ba0b59a3..96b51e29bba4 100644
> >> --- a/drivers/media/platform/broadcom/bcm2835-unicam.c
> >> +++ b/drivers/media/platform/broadcom/bcm2835-unicam.c
> >> @@ -2043,6 +2043,7 @@ static int unicam_log_status(struct file *file, void *fh)
> >> struct unicam_node *node = video_drvdata(file);
> >> struct unicam_device *unicam = node->dev;
> >> u32 reg;
> >> + int pm_active;
> >>
> >> /* status for sub devices */
> >> v4l2_device_call_all(&unicam->v4l2_dev, 0, core, log_status);
> >> @@ -2052,6 +2053,14 @@ static int unicam_log_status(struct file *file, void *fh)
> >> node->fmt.fmt.pix.width, node->fmt.fmt.pix.height);
> >> dev_info(unicam->dev, "V4L2 format: %08x\n",
> >> node->fmt.fmt.pix.pixelformat);
> >> +
> >> + pm_active = pm_runtime_get_if_active(unicam->dev);
> >> + if (!pm_active) {
> >> + dev_info(unicam->dev,
> >> + "Live data N/A due to device inactive\n");
> >> + return 0;
> >> + }
> >> +
> >> reg = unicam_reg_read(unicam, UNICAM_IPIPE);
> >> dev_info(unicam->dev, "Unpacking/packing: %u / %u\n",
> >> unicam_get_field(reg, UNICAM_PUM_MASK),
> >> @@ -2065,6 +2074,9 @@ static int unicam_log_status(struct file *file, void *fh)
> >> dev_info(unicam->dev, "Write pointer: %08x\n",
> >> unicam_reg_read(unicam, UNICAM_IBWP));
> >>
> >> + if (pm_active == 1)
> >> + pm_runtime_put(unicam->dev);
> >
> > As far as I understand, the discussion on v2 concluded there was no need
> > to test pm_active here. Did I miss anything ?
>
> Sorry, I saw the message from Sakari and he was pretty confident on the
> right way, he even mentioned that all sensors should be fixed, and has
> not come up with a follow up since.
> If v2 is the right way, please disregard this v3
Let's see what Sakari has to say :-)
> >> +
> >> return 0;
> >> }
> >>
> >>
> >> ---
> >> base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83
> >> change-id: 20260521-bcmpipm-6c578e73239c
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: [PATCH 1/4] dt-bindings: mfd: mediatek: mt6397: add mt6323 PMIC EFUSE
From: Conor Dooley @ 2026-06-11 17:22 UTC (permalink / raw)
To: rva333
Cc: Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Srinivas Kandagatla, Andy Shevchenko,
Jonathan Cameron, linux-pm, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, Ben Grisdale
In-Reply-To: <20260611-mt6323-nvmem-v1-1-b5e1b9ce51f2@protonmail.com>
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: {Spam?} Re: [PATCH] media: bcm2835-unicam: Fix querycap multiple caps
From: Eugen Hristev @ 2026-06-11 17:19 UTC (permalink / raw)
To: Jean-Michel Hautbois, Raspberry Pi Kernel Maintenance,
Mauro Carvalho Chehab, Florian Fainelli, Ray Jui, Scott Branden,
Broadcom internal kernel review list, Sakari Ailus,
Dave Stevenson, Laurent Pinchart, Naushir Patuck
Cc: Hans Verkuil, linux-media, linux-rpi-kernel, linux-arm-kernel,
linux-kernel
In-Reply-To: <b549ea8a-76cc-4a7a-bab6-710fddeaeebd@yoseli.org>
On 6/11/26 09:51, Jean-Michel Hautbois wrote:
> Hi Eugen,
>
> Thank you for the patch.
>
> Two issues with this one, I'm afraid.
>
> Le 11/06/2026 à 08:09, Eugen Hristev a écrit :
>> The unicam exposes two video nodes, one for image, another for metadata.
>> Querycap should return the right caps for the respective node, not both.
>>
>> video0:
>>
>> Capabilities : 0xa4200001
>> Video Capture
>> I/O MC
>> Streaming
>> Extended Pix Format
>> Device Capabilities
>> Device Caps : 0x24200001
>> Video Capture
>> I/O MC
>> Streaming
>> Extended Pix Format
>>
>> video1:
>>
>> Capabilities : 0xa4a00000
>> Metadata Capture
>> I/O MC
>> Streaming
>> Extended Pix Format
>> Device Capabilities
>> Device Caps : 0x24a00000
>> Metadata Capture
>> I/O MC
>> Streaming
>> Extended Pix Format
>>
>> Fixes: 392cd78d495f ("media: bcm2835-unicam: Add support for CCP2/CSI2 camera interface")
>> Signed-off-by: Eugen Hristev <ehristev@kernel.org>
>> ---
>> drivers/media/platform/broadcom/bcm2835-unicam.c | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c
>> index 8d28ba0b59a3..4bf36ce80047 100644
>> --- a/drivers/media/platform/broadcom/bcm2835-unicam.c
>> +++ b/drivers/media/platform/broadcom/bcm2835-unicam.c
>> @@ -1833,7 +1833,10 @@ static int unicam_querycap(struct file *file, void *priv,
>> strscpy(cap->driver, UNICAM_MODULE_NAME, sizeof(cap->driver));
>> strscpy(cap->card, UNICAM_MODULE_NAME, sizeof(cap->card));
>>
>> - cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE;
>> + if (is_image_node(node))
>
> First, it does not compile, as node is not declared here.
> 'struct unicam_node *node = video_drvdata(file);' would be needed.
Sorry, my brain must have been sleeping
>
>> + cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE;
>> + else
>> + cap->capabilities |= V4L2_CAP_META_CAPTURE;
>>
>> return 0;
>> }
>>
>
> Second, and more important, I don't think the current behaviour is a bug.
> Documentation/userspace-api/media/v4l/vidioc-querycap.rst states about
> the 'capabilities' field:
>
> "The capabilities field should contain a union of all capabilities
> available around the several V4L2 devices exported to userspace.
> For all those devices the capabilities field returns the same set of
> capabilities."
>
> Per-node differentiation is the job of 'device_caps', which unicam
> already sets correctly when registering each video device (your
> v4l2-ctl output shows the Device Caps are already right).
>
> So this looks like working as intended to me, and the patch should be
> dropped.
Thanks for taking the time to explain.
Let's drop the patch.
Eugen
>
> Thanks,
> JM
>
>> ---
>> base-commit: a87737435cfa134f9cdcc696ba3080759d04cf72
>> change-id: 20260611-bcmpiqcap-f893a9ea2da9
>>
>> Best regards,
>> --
>> Eugen Hristev <ehristev@kernel.org>
>>
>
^ permalink raw reply
* Re: [PATCH v3] media: bcm2835-unicam: Fix log status runtime access
From: Eugen Hristev @ 2026-06-11 17:18 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Raspberry Pi Kernel Maintenance, Mauro Carvalho Chehab,
Florian Fainelli, Broadcom internal kernel review list, Ray Jui,
Scott Branden, Dave Stevenson, Hans Verkuil, Sakari Ailus,
Jean-Michel Hautbois, Naushir Patuck, linux-media,
linux-rpi-kernel, linux-arm-kernel, linux-kernel
In-Reply-To: <20260611080348.GC1758601@killaraus.ideasonboard.com>
On 6/11/26 11:03, Laurent Pinchart wrote:
> On Thu, Jun 11, 2026 at 08:29:55AM +0300, Eugen Hristev wrote:
>> When requesting log status, the block might be powered off, but registers
>> are being read.
>> Avoid reading the registers if the device is not resumed, thus also avoid
>> powering up the device just for log status.
>>
>> Fixes: 392cd78d495f ("media: bcm2835-unicam: Add support for CCP2/CSI2 camera interface")
>> Signed-off-by: Eugen Hristev <ehristev@kernel.org>
>> ---
>> Changes in v3:
>> - Changed to check return value of pm_runtime_get_if_active() and only call
>> pm_runtime_put() if the device is active.
>> - Link to v2: https://patch.msgid.link/20260522-bcmpipm-v2-1-a3da66cbc9f0@kernel.org
>>
>> Changes in v2:
>> - changed to use pm_runtime_get_if_active()
>> - add corresponding put()
>> - Link to v1: https://patch.msgid.link/20260521-bcmpipm-v1-1-3eba88d88045@kernel.org
>>
>> To: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
>> To: Mauro Carvalho Chehab <mchehab@kernel.org>
>> To: Florian Fainelli <florian.fainelli@broadcom.com>
>> To: Ray Jui <rjui@broadcom.com>
>> To: Scott Branden <sbranden@broadcom.com>
>> To: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
>> To: Sakari Ailus <sakari.ailus@linux.intel.com>
>> To: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
>> To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> To: Hans Verkuil <hverkuil@kernel.org>
>> To: Naushir Patuck <naush@raspberrypi.com>
>> Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>
>> Cc: linux-media@vger.kernel.org
>> Cc: linux-rpi-kernel@lists.infradead.org
>> Cc: linux-arm-kernel@lists.infradead.org
>> Cc: linux-kernel@vger.kernel.org
>> ---
>> drivers/media/platform/broadcom/bcm2835-unicam.c | 12 ++++++++++++
>> 1 file changed, 12 insertions(+)
>>
>> diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c
>> index 8d28ba0b59a3..96b51e29bba4 100644
>> --- a/drivers/media/platform/broadcom/bcm2835-unicam.c
>> +++ b/drivers/media/platform/broadcom/bcm2835-unicam.c
>> @@ -2043,6 +2043,7 @@ static int unicam_log_status(struct file *file, void *fh)
>> struct unicam_node *node = video_drvdata(file);
>> struct unicam_device *unicam = node->dev;
>> u32 reg;
>> + int pm_active;
>>
>> /* status for sub devices */
>> v4l2_device_call_all(&unicam->v4l2_dev, 0, core, log_status);
>> @@ -2052,6 +2053,14 @@ static int unicam_log_status(struct file *file, void *fh)
>> node->fmt.fmt.pix.width, node->fmt.fmt.pix.height);
>> dev_info(unicam->dev, "V4L2 format: %08x\n",
>> node->fmt.fmt.pix.pixelformat);
>> +
>> + pm_active = pm_runtime_get_if_active(unicam->dev);
>> + if (!pm_active) {
>> + dev_info(unicam->dev,
>> + "Live data N/A due to device inactive\n");
>> + return 0;
>> + }
>> +
>> reg = unicam_reg_read(unicam, UNICAM_IPIPE);
>> dev_info(unicam->dev, "Unpacking/packing: %u / %u\n",
>> unicam_get_field(reg, UNICAM_PUM_MASK),
>> @@ -2065,6 +2074,9 @@ static int unicam_log_status(struct file *file, void *fh)
>> dev_info(unicam->dev, "Write pointer: %08x\n",
>> unicam_reg_read(unicam, UNICAM_IBWP));
>>
>> + if (pm_active == 1)
>> + pm_runtime_put(unicam->dev);
>
> As far as I understand, the discussion on v2 concluded there was no need
> to test pm_active here. Did I miss anything ?
Sorry, I saw the message from Sakari and he was pretty confident on the
right way, he even mentioned that all sensors should be fixed, and has
not come up with a follow up since.
If v2 is the right way, please disregard this v3
Eugen
>
>> +
>> return 0;
>> }
>>
>>
>> ---
>> base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83
>> change-id: 20260521-bcmpipm-6c578e73239c
>
^ permalink raw reply
* Re: [PATCH v7 24/30] drm/vc4: hdmi: Use common TMDS char rate constants
From: Dave Stevenson @ 2026-06-11 17:14 UTC (permalink / raw)
To: Cristian Ciocaltea
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Sandy Huang, Heiko Stübner, Andy Yan, Daniel Stone,
Maíra Canal, Raspberry Pi Kernel Maintenance, kernel,
dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260602-dw-hdmi-qp-scramb-v7-24-445eb54ee1ed@collabora.com>
On Mon, 1 Jun 2026 at 23:45, Cristian Ciocaltea
<cristian.ciocaltea@collabora.com> wrote:
>
> Replace HDMI_14_MAX_TMDS_CLK defined locally with
> HDMI_1_3_TMDS_CHAR_RATE_MAX_HZ provided by linux/hdmi.h. Note this
> incorrectly referenced HDMI 1.4, as the 340 MHz maximum TMDS character
> rate was actually introduced in HDMI 1.3.
>
> Similarly, use HDMI_2_0_TMDS_CHAR_RATE_MAX_HZ instead of the 600000000
> magic number.
>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> ---
^ permalink raw reply
* Re: [PATCH] power: supply: macsmc: Support macOS 27 SMC firmware
From: Sven Peter @ 2026-06-11 17:09 UTC (permalink / raw)
To: Sasha Finkelstein, Janne Grunau, Neal Gompa, Sebastian Reichel
Cc: asahi, linux-arm-kernel, linux-pm, linux-kernel
In-Reply-To: <20260611-gate-power-v1-1-8a62721086c7@chaosmail.tech>
On 11.06.26 18:49, Sasha Finkelstein wrote:
> The SMC firmware included in macOS 27 changed the size of BCF0 key from
> 4 to 1 bytes. This key is used for indicating that battery state is
> critically low.
>
> Signed-off-by: Sasha Finkelstein <k@chaosmail.tech>
> ---
> drivers/power/supply/macsmc-power.c | 34 +++++++++++++++++++++++++++++++---
> 1 file changed, 31 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/power/supply/macsmc-power.c b/drivers/power/supply/macsmc-power.c
> index 33ca07460f3a..650dc8740f71 100644
> --- a/drivers/power/supply/macsmc-power.c
> +++ b/drivers/power/supply/macsmc-power.c
> @@ -86,6 +86,7 @@ struct macsmc_power {
> bool has_ch0i; /* Force discharge (Older firmware) */
> bool has_ch0c; /* Inhibit charge (Older firmware) */
> bool has_chte; /* Inhibit charge (Modern firmware) */
> + bool bcf0_1byte; /* Battery critical */
The comment is a bit misleading, maybe "Battery critical key is 1
instead of 4 bytes" or "Battery critical key is 1 byte (Modern
firmware)" instead?
With that changed:
Reviewed-by: Sven Peter <sven@kernel.org>
Best,
Sven
^ permalink raw reply
* Re: [PATCH v7 5/6] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device
From: Suzuki K Poulose @ 2026-06-11 17:06 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm), linux-coco, linux-arm-kernel,
linux-kernel
Cc: Catalin Marinas, Greg KH, Jeremy Linton, Jonathan Cameron,
Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Will Deacon,
Steven Price, Andre Przywara
In-Reply-To: <20260611130429.295516-6-aneesh.kumar@kernel.org>
On 11/06/2026 14:04, Aneesh Kumar K.V (Arm) wrote:
> The Arm CCA guest TSM provider currently binds through the arm-cca-dev
> platform device. Like arm-smccc-trng, this device is not an independent
> platform resource; it is a software representation of the RSI firmware
> service discovered through SMCCC.
>
> Move RSI discovery into the SMCCC firmware driver. When the SMCCC conduit
> is SMC and if RSI ABI version call is supported, create an arm-rsi-dev
> SMCCC device. Convert the Arm CCA guest TSM provider to an SMCCC driver so
> it binds to that discovered RSI service and keeps module autoloading
> through the SMCCC device id table.
>
> Keep the old arm-cca-dev platform-device registration for now. Userspace
> has used that device as a Realm-guest indicator, so removing it is left to
> a follow-up patch that adds a replacement sysfs ABI.
>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> ---
> arch/arm64/include/asm/rsi.h | 2 -
> arch/arm64/kernel/rsi.c | 2 +-
> drivers/firmware/smccc/smccc.c | 7 +++
> drivers/virt/coco/arm-cca-guest/Kconfig | 1 +
> drivers/virt/coco/arm-cca-guest/arm-cca.c | 56 +++++++++++------------
> include/linux/arm-smccc-rsi.h | 2 +
> 6 files changed, 39 insertions(+), 31 deletions(-)
>
> diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
> index 88b50d660e85..5f9c8623183d 100644
> --- a/arch/arm64/include/asm/rsi.h
> +++ b/arch/arm64/include/asm/rsi.h
> @@ -10,8 +10,6 @@
> #include <linux/jump_label.h>
> #include <asm/rsi_cmds.h>
>
> -#define RSI_PDEV_NAME "arm-cca-dev"
> -
> DECLARE_STATIC_KEY_FALSE(rsi_present);
>
> void __init arm64_rsi_init(void);
> diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
> index 92160f2e57ff..da440f71bb64 100644
> --- a/arch/arm64/kernel/rsi.c
> +++ b/arch/arm64/kernel/rsi.c
> @@ -161,7 +161,7 @@ void __init arm64_rsi_init(void)
> }
>
> static struct platform_device rsi_dev = {
> - .name = RSI_PDEV_NAME,
> + .name = "arm-cca-dev",
> .id = PLATFORM_DEVID_NONE
> };
>
> diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
> index a47696f3a5de..7127af3dbe5c 100644
> --- a/drivers/firmware/smccc/smccc.c
> +++ b/drivers/firmware/smccc/smccc.c
> @@ -10,6 +10,7 @@
> #include <linux/arm-smccc.h>
> #include <linux/kernel.h>
> #include <linux/arm-smccc-bus.h>
> +#include <linux/arm-smccc-rsi.h>
>
> #include <asm/archrandom.h>
>
> @@ -94,6 +95,12 @@ static const struct smccc_device_info smccc_devices[] __initconst = {
> .requires_smc = false,
> .device_name = "arm-smccc-trng",
> },
> +
> + {
> + .func_id = SMC_RSI_ABI_VERSION,
> + .requires_smc = true,
> + .device_name = RSI_DEV_NAME,
> + },
> };
>
> static bool __init smccc_probe_smccc_device(const struct smccc_device_info *smccc_dev)
> diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/arm-cca-guest/Kconfig
> index 3f0f013f03f1..ad7538750c5a 100644
> --- a/drivers/virt/coco/arm-cca-guest/Kconfig
> +++ b/drivers/virt/coco/arm-cca-guest/Kconfig
> @@ -1,6 +1,7 @@
> config ARM_CCA_GUEST
> tristate "Arm CCA Guest driver"
> depends on ARM64
> + depends on HAVE_ARM_SMCCC_DISCOVERY
> select TSM_REPORTS
> help
> The driver provides userspace interface to request and
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/arm-cca-guest/arm-cca.c
> index 0bbd1fa53ee4..4f9289ccf498 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/arm-smccc.h>
> +#include <linux/arm-smccc-bus.h>
> #include <linux/cc_platform.h>
> #include <linux/kernel.h>
> #include <linux/mod_devicetable.h>
> @@ -189,16 +190,12 @@ static const struct tsm_report_ops arm_cca_tsm_report_ops = {
> .report_new = arm_cca_report_new,
> };
>
> -/**
> - * arm_cca_guest_init - Register with the Trusted Security Module (TSM)
> - * interface.
> - *
> - * Return:
> - * * %0 - Registered successfully with the TSM interface.
> - * * %-ENODEV - The execution context is not an Arm Realm.
> - * * %-EBUSY - Already registered.
> - */
> -static int __init arm_cca_guest_init(void)
> +static void unregister_cca_tsm_report(void *data)
> +{
> + tsm_report_unregister(&arm_cca_tsm_report_ops);
> +}
> +
> +static int cca_tsm_probe(struct arm_smccc_device *sdev)
> {
> int ret;
>
> @@ -206,30 +203,33 @@ static int __init arm_cca_guest_init(void)
> return -ENODEV;
>
> ret = tsm_report_register(&arm_cca_tsm_report_ops, NULL);
> - if (ret < 0)
> - pr_err("Error %d registering with TSM\n", ret);
> + if (ret < 0) {
> + dev_err_probe(&sdev->dev, ret, "Error registering with TSM\n");
> + return ret;
> + }
>
> - return ret;
> -}
> -module_init(arm_cca_guest_init);
> + ret = devm_add_action_or_reset(&sdev->dev, unregister_cca_tsm_report,
> + NULL);
> + if (ret < 0) {
> + dev_err_probe(&sdev->dev, ret, "Error registering devm action\n");
> + return ret;
> + }
>
> -/**
> - * arm_cca_guest_exit - unregister with the Trusted Security Module (TSM)
> - * interface.
> - */
> -static void __exit arm_cca_guest_exit(void)
> -{
> - tsm_report_unregister(&arm_cca_tsm_report_ops);
> + return 0;
> }
> -module_exit(arm_cca_guest_exit);
>
> -/* modalias, so userspace can autoload this module when RSI is available */
> -static const struct platform_device_id arm_cca_match[] __maybe_unused = {
> - { RSI_PDEV_NAME, 0},
> - { }
> +static const struct arm_smccc_device_id cca_tsm_id_table[] = {
> + { .name = RSI_DEV_NAME },
> + {}
> };
> +MODULE_DEVICE_TABLE(arm_smccc, cca_tsm_id_table);
>
> -MODULE_DEVICE_TABLE(platform, arm_cca_match);
> +static struct arm_smccc_driver cca_tsm_driver = {
> + .name = KBUILD_MODNAME,
> + .probe = cca_tsm_probe,
> + .id_table = cca_tsm_id_table,
> +};
> +module_arm_smccc_driver(cca_tsm_driver);
> MODULE_AUTHOR("Sami Mujawar <sami.mujawar@arm.com>");
> MODULE_DESCRIPTION("Arm CCA Guest TSM Driver");
> MODULE_LICENSE("GPL");
> diff --git a/include/linux/arm-smccc-rsi.h b/include/linux/arm-smccc-rsi.h
> index fddb77986f70..ae663aa8fd7f 100644
> --- a/include/linux/arm-smccc-rsi.h
> +++ b/include/linux/arm-smccc-rsi.h
> @@ -8,6 +8,8 @@
>
> #include <linux/arm-smccc.h>
>
> +#define RSI_DEV_NAME "arm-rsi-dev"
This shouldn't be here ? This is not part of the SMCCC RSI standard, but
a linux thing. May be in drivers/firmware/../rsi.h ?
Rest looks fine.
Suzuki
> +
> /*
> * This file describes the Realm Services Interface (RSI) Application Binary
> * Interface (ABI) for SMC calls made from within the Realm to the RMM and
^ permalink raw reply
* [PATCH] power: supply: macsmc: Support macOS 27 SMC firmware
From: Sasha Finkelstein @ 2026-06-11 16:49 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Neal Gompa, Sebastian Reichel
Cc: asahi, linux-arm-kernel, linux-pm, linux-kernel,
Sasha Finkelstein
The SMC firmware included in macOS 27 changed the size of BCF0 key from
4 to 1 bytes. This key is used for indicating that battery state is
critically low.
Signed-off-by: Sasha Finkelstein <k@chaosmail.tech>
---
drivers/power/supply/macsmc-power.c | 34 +++++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/power/supply/macsmc-power.c b/drivers/power/supply/macsmc-power.c
index 33ca07460f3a..650dc8740f71 100644
--- a/drivers/power/supply/macsmc-power.c
+++ b/drivers/power/supply/macsmc-power.c
@@ -86,6 +86,7 @@ struct macsmc_power {
bool has_ch0i; /* Force discharge (Older firmware) */
bool has_ch0c; /* Inhibit charge (Older firmware) */
bool has_chte; /* Inhibit charge (Modern firmware) */
+ bool bcf0_1byte; /* Battery critical */
u8 num_cells;
int nominal_voltage_mv;
@@ -273,6 +274,18 @@ static int macsmc_battery_get_date(const char *s, int *out)
return 0;
}
+static int macsmc_battery_read_bcf0(struct macsmc_power *power, u32 *val)
+{
+ u8 tval;
+ int ret;
+
+ if (!power->bcf0_1byte)
+ return apple_smc_read_u32(power->smc, SMC_KEY(BCF0), val);
+ ret = apple_smc_read_u8(power->smc, SMC_KEY(BCF0), &tval);
+ *val = tval;
+ return ret;
+}
+
static int macsmc_battery_get_capacity_level(struct macsmc_power *power)
{
bool flag;
@@ -280,7 +293,7 @@ static int macsmc_battery_get_capacity_level(struct macsmc_power *power)
int ret;
/* Check for emergency shutdown condition */
- if (apple_smc_read_u32(power->smc, SMC_KEY(BCF0), &val) >= 0 && val)
+ if (macsmc_battery_read_bcf0(power, &val) >= 0 && val)
return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
/* Check AC status for whether we could boot in this state */
@@ -577,7 +590,7 @@ static void macsmc_power_critical_work(struct work_struct *wrk)
* Check if SMC flagged the battery as empty.
* We trigger a graceful shutdown to let the OS save data.
*/
- if (apple_smc_read_u32(power->smc, SMC_KEY(BCF0), &bcf0) == 0 && bcf0 != 0) {
+ if (macsmc_battery_read_bcf0(power, &bcf0) == 0 && bcf0 != 0) {
power->orderly_shutdown_triggered = true;
dev_crit(power->dev, "Battery critical (empty flag set). Triggering orderly shutdown.\n");
orderly_poweroff(true);
@@ -616,6 +629,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
struct power_supply_config psy_cfg = {};
+ struct apple_smc_key_info info;
struct macsmc_power *power;
bool has_battery = false;
bool has_ac_adapter = false;
@@ -714,6 +728,20 @@ static int macsmc_power_probe(struct platform_device *pdev)
if (apple_smc_key_exists(smc, SMC_KEY(CH0I)))
power->has_ch0i = true;
+ ret = apple_smc_get_key_info(power->smc, SMC_KEY(BCF0), &info);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to determine BCF0 key size\n");
+ return ret;
+ }
+ if (info.size == 1)
+ power->bcf0_1byte = true;
+ else if (info.size == 4)
+ power->bcf0_1byte = false;
+ else {
+ dev_err(&pdev->dev, "Unexpected BCF0 key size %d\n", info.size);
+ return -EIO;
+ }
+
/* Reset "Optimised Battery Charging" flags to default state */
if (power->has_chte)
apple_smc_write_u32(smc, SMC_KEY(CHTE), 0);
@@ -766,7 +794,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
power->nominal_voltage_mv = MACSMC_NOMINAL_CELL_VOLTAGE_MV * power->num_cells;
/* Enable critical shutdown notifications by reading status once */
- apple_smc_read_u32(power->smc, SMC_KEY(BCF0), &val32);
+ macsmc_battery_read_bcf0(power, &val32);
psy_cfg.drv_data = power;
power->batt = devm_power_supply_register(dev, &power->batt_desc, &psy_cfg);
---
base-commit: 9716c086c8e8b141d35aa61f2e96a2e83de212a7
change-id: 20260611-gate-power-cfd726dc0d7f
Best regards,
--
Sasha Finkelstein <k@chaosmail.tech>
^ permalink raw reply related
* Re: [PATCH v22 08/13] mfd: core: Add firmware-node support to MFD cells
From: Shivendra Pratap @ 2026-06-11 16:44 UTC (permalink / raw)
To: Lee Jones
Cc: Bartosz Golaszewski, Sebastian Reichel, Mark Rutland,
Lorenzo Pieralisi, Rafael J. Wysocki, Daniel Lezcano,
Christian Loehle, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Arnd Bergmann,
Souvik Chakravarty, Andy Yan, Matthias Brugger, John Stultz,
Moritz Fischer, Sudeep Holla, linux-pm, linux-kernel,
linux-arm-msm, linux-arm-kernel, devicetree, Florian Fainelli,
Krzysztof Kozlowski, Dmitry Baryshkov, Mukesh Ojha, Andre Draszik,
Greg Kroah-Hartman, Kathiravan Thirumoorthy, Srinivas Kandagatla,
Bartosz Golaszewski
In-Reply-To: <20260611164211.GD1212816@google.com>
On 11-06-2026 22:12, Lee Jones wrote:
> /* Sashiko Automation: Reviewed (0 Findings) */
>
> On Thu, 04 Jun 2026, Shivendra Pratap wrote:
>
>>
>>
>> On 25-05-2026 15:04, Shivendra Pratap wrote:
>>>
>>>
>>> On 22-05-2026 14:38, Bartosz Golaszewski wrote:
>>>> On Thu, May 21, 2026 at 6:27 PM Lee Jones <lee@kernel.org> wrote:
>>>>>
>>>>> On Thu, 21 May 2026, Bartosz Golaszewski wrote:
>>>>>
>>>>>> On Thu, May 21, 2026 at 3:24 PM Lee Jones <lee@kernel.org> wrote:
>>>>>>>
>>>>>>>>
>>>>>>>> I suggested it because of its flexibility. The alternative I had in
>>>>>>>> mind is something like a new field in mfd_cell:
>>>>>>>>
>>>>>>>> const char *cell_node_name;
>>>>>>>>
>>>>>>>> Which - if set - would tell MFD to look up an fwnode
>>>>>>>> that's a child of
>>>>>>>> the parent device's node by name - as it may not have a compatible.
>>>>>>>
>>>>>>> Remind me why the chlid device can't look-up its own fwnode?
>>>>>>>
>>>>>>
>>>>>> Oh sure it can, but should it? I'm not sure it's logically sound to
>>>>>> have the child device reach into the parent, look up the fwnode and
>>>>>> then assign it to itself after it's already attached to the driver.
>>>>>> This should be done at the subsystem level before the device is
>>>>>> registered.
>>>>>
>>>>> Leaf drivers reach back into the parent all the time.
>>>>>
>>>>
>>>> But drivers don't generally assign firmware nodes to devices they are
>>>> already bound to. This is racy as in probe() the device is already
>>>> visible to the system. There's no synchronization of device property
>>>> access - properties are assumed to be read-only for a registered
>>>> device.
>>>
>>> thanks Bart/Lee. Any pointers to take this from here?
>>
>> Hi Lee,
>>
>> To take this patchset forward, it would be helpful to get your views on
>> fwnode based addition in mfd-core. Maybe, a member like "*named_fwnode" in
>> mfd-core and then a lookup logic, or any alternatives?
>
> Can you please make your best pick and resubmit the set please?
>
> I'll comment on a fresh set with fresh eyes.
sure. thanks.
thanks,
Shivendra
^ permalink raw reply
* Re: [PATCH v22 08/13] mfd: core: Add firmware-node support to MFD cells
From: Lee Jones @ 2026-06-11 16:42 UTC (permalink / raw)
To: Shivendra Pratap
Cc: Bartosz Golaszewski, Sebastian Reichel, Mark Rutland,
Lorenzo Pieralisi, Rafael J. Wysocki, Daniel Lezcano,
Christian Loehle, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Arnd Bergmann,
Souvik Chakravarty, Andy Yan, Matthias Brugger, John Stultz,
Moritz Fischer, Sudeep Holla, linux-pm, linux-kernel,
linux-arm-msm, linux-arm-kernel, devicetree, Florian Fainelli,
Krzysztof Kozlowski, Dmitry Baryshkov, Mukesh Ojha, Andre Draszik,
Greg Kroah-Hartman, Kathiravan Thirumoorthy, Srinivas Kandagatla,
Bartosz Golaszewski
In-Reply-To: <81680397-3bbd-4f66-9166-546c8fe753fc@oss.qualcomm.com>
/* Sashiko Automation: Reviewed (0 Findings) */
On Thu, 04 Jun 2026, Shivendra Pratap wrote:
>
>
> On 25-05-2026 15:04, Shivendra Pratap wrote:
> >
> >
> > On 22-05-2026 14:38, Bartosz Golaszewski wrote:
> > > On Thu, May 21, 2026 at 6:27 PM Lee Jones <lee@kernel.org> wrote:
> > > >
> > > > On Thu, 21 May 2026, Bartosz Golaszewski wrote:
> > > >
> > > > > On Thu, May 21, 2026 at 3:24 PM Lee Jones <lee@kernel.org> wrote:
> > > > > >
> > > > > > >
> > > > > > > I suggested it because of its flexibility. The alternative I had in
> > > > > > > mind is something like a new field in mfd_cell:
> > > > > > >
> > > > > > > const char *cell_node_name;
> > > > > > >
> > > > > > > Which - if set - would tell MFD to look up an fwnode
> > > > > > > that's a child of
> > > > > > > the parent device's node by name - as it may not have a compatible.
> > > > > >
> > > > > > Remind me why the chlid device can't look-up its own fwnode?
> > > > > >
> > > > >
> > > > > Oh sure it can, but should it? I'm not sure it's logically sound to
> > > > > have the child device reach into the parent, look up the fwnode and
> > > > > then assign it to itself after it's already attached to the driver.
> > > > > This should be done at the subsystem level before the device is
> > > > > registered.
> > > >
> > > > Leaf drivers reach back into the parent all the time.
> > > >
> > >
> > > But drivers don't generally assign firmware nodes to devices they are
> > > already bound to. This is racy as in probe() the device is already
> > > visible to the system. There's no synchronization of device property
> > > access - properties are assumed to be read-only for a registered
> > > device.
> >
> > thanks Bart/Lee. Any pointers to take this from here?
>
> Hi Lee,
>
> To take this patchset forward, it would be helpful to get your views on
> fwnode based addition in mfd-core. Maybe, a member like "*named_fwnode" in
> mfd-core and then a lookup logic, or any alternatives?
Can you please make your best pick and resubmit the set please?
I'll comment on a fresh set with fresh eyes.
--
Lee Jones
^ permalink raw reply
* Re: [PATCH v7 4/8] mfd: khadas-mcu: Add support for VIM4 MCU variant
From: Lee Jones @ 2026-06-11 16:40 UTC (permalink / raw)
To: linux-kernel-dev
Cc: Neil Armstrong, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Andi Shyti, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Beniamino Galvani, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Liam Girdwood, Mark Brown, linux-amlogic, devicetree,
linux-kernel, linux-i2c, linux-arm-kernel, linux-pm
In-Reply-To: <20260603-add-mcu-fan-khadas-vim4-v7-4-594ba8a965d8@aliel.fr>
/* Sashiko Automation: Reviewed (0 Findings) */
On Wed, 03 Jun 2026, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
>
> Refactor probe() to use per-variant values
> instead of hardcoded globals.
>
> Add dedicated regmap configuration for the VIM4 MCU,
> with its own volatile/writeable registers.
>
> Add the fan control register
> (0–100 levels vs 0–3 for previous supported boards).
>
> Add a new compatible string "khadas,vim4-mcu".
>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
> drivers/mfd/khadas-mcu.c | 115 ++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 99 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
> index ba981a7886921..1bf260729d73b 100644
> --- a/drivers/mfd/khadas-mcu.c
> +++ b/drivers/mfd/khadas-mcu.c
> @@ -75,47 +75,129 @@ static const struct regmap_config khadas_mcu_regmap_config = {
> .cache_type = REGCACHE_MAPLE,
> };
>
> -static struct mfd_cell khadas_mcu_fan_cells[] = {
> +static const struct khadas_mcu_fan_pdata khadas_mcu_fan_pdata = {
> + .fan_reg = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
> + .max_level = 3, /* Fan speed: 0 = off, 1 = low, 2 = medium, 3 = high */
Instead of this comment, you could always just define the value(s)?
> +};
> +
> +static const struct mfd_cell khadas_mcu_fan_cells[] = {
> /* VIM1/2 Rev13+ and VIM3 only */
> - { .name = "khadas-mcu-fan-ctrl", },
> + {
> + .name = "khadas-mcu-fan-ctrl",
> + .platform_data = &khadas_mcu_fan_pdata,
> + .pdata_size = sizeof(khadas_mcu_fan_pdata),
No need to attempt to align the '=' like this, please.
> + },
> };
>
> -static struct mfd_cell khadas_mcu_cells[] = {
> +static const struct mfd_cell khadas_mcu_cells[] = {
> { .name = "khadas-mcu-user-mem", },
> };
>
> +static bool khadas_mcu_vim4_reg_volatile(struct device *dev, unsigned int reg)
> +{
> + switch (reg) {
> + case KHADAS_MCU_PWR_OFF_CMD_REG:
> + case KHADAS_MCU_VIM4_REST_CONF_REG:
> + case KHADAS_MCU_WOL_INIT_START_REG:
> + case KHADAS_MCU_VIM4_LED_ON_RAM_REG:
> + case KHADAS_MCU_VIM4_FAN_CTRL_REG:
> + case KHADAS_MCU_VIM4_WDT_EN_REG:
> + case KHADAS_MCU_VIM4_SYS_RST_REG:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> +static bool khadas_mcu_vim4_reg_writeable(struct device *dev, unsigned int reg)
> +{
> + switch (reg) {
> + case KHADAS_MCU_VERSION_0_REG:
> + case KHADAS_MCU_VERSION_1_REG:
> + case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
> + return false;
> + default:
> + return true;
> + }
> +}
> +
> +static const struct regmap_config khadas_mcu_vim4_regmap_config = {
> + .reg_bits = 8,
> + .reg_stride = 1,
> + .val_bits = 8,
> + .max_register = KHADAS_MCU_VIM4_SYS_RST_REG,
> + .volatile_reg = khadas_mcu_vim4_reg_volatile,
> + .writeable_reg = khadas_mcu_vim4_reg_writeable,
> + .cache_type = REGCACHE_MAPLE,
> +};
> +
> +static const struct khadas_mcu_fan_pdata khadas_vim4_fan_pdata = {
> + .fan_reg = KHADAS_MCU_VIM4_FAN_CTRL_REG,
> + .max_level = 0x64,
> +};
> +
> +static const struct mfd_cell khadas_mcu_vim4_cells[] = {
> + {
> + .name = "khadas-mcu-fan-ctrl",
> + .platform_data = &khadas_vim4_fan_pdata,
> + .pdata_size = sizeof(khadas_vim4_fan_pdata),
> + },
> +};
> +
> static int khadas_mcu_probe(struct i2c_client *client)
> {
> + const struct mfd_cell *cells, *fan_cells;
> + const struct regmap_config *regmap_cfg;
> struct device *dev = &client->dev;
> + int ncells, nfan_cells, ret;
> struct khadas_mcu *ddata;
> - int ret;
>
> ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
> if (!ddata)
> return -ENOMEM;
>
> + switch ((uintptr_t)i2c_get_match_data(client)) {
> + case KHADAS_MCU_GENERIC:
> + regmap_cfg = &khadas_mcu_regmap_config;
> + cells = khadas_mcu_cells;
> + ncells = ARRAY_SIZE(khadas_mcu_cells);
> + fan_cells = khadas_mcu_fan_cells;
> + nfan_cells = ARRAY_SIZE(khadas_mcu_fan_cells);
> + break;
> + case KHADAS_MCU_VIM4:
> + regmap_cfg = &khadas_mcu_vim4_regmap_config;
> + cells = NULL;
> + ncells = 0;
> + fan_cells = khadas_mcu_vim4_cells;
> + nfan_cells = ARRAY_SIZE(khadas_mcu_vim4_cells);
I'm not as offended by this as I thought I would be!
> + break;
> + default:
> + return -ENODEV;
> + }
> +
> i2c_set_clientdata(client, ddata);
>
> ddata->dev = dev;
>
> - ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
> + ddata->regmap = devm_regmap_init_i2c(client, regmap_cfg);
> if (IS_ERR(ddata->regmap)) {
> ret = PTR_ERR(ddata->regmap);
> - dev_err(dev, "Failed to allocate register map: %d\n", ret);
> - return ret;
> + return dev_err_probe(dev, ret, "Failed to allocate register map\n");
> }
>
> - ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
> - khadas_mcu_cells,
> - ARRAY_SIZE(khadas_mcu_cells),
> - NULL, 0, NULL);
> - if (ret)
> - return ret;
> + if (cells && ncells) {
> + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
> + cells,
> + ncells,
> + NULL, 0, NULL);
> + if (ret)
> + return ret;
> + }
>
> if (of_property_present(dev->of_node, "#cooling-cells"))
> return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
> - khadas_mcu_fan_cells,
> - ARRAY_SIZE(khadas_mcu_fan_cells),
> + fan_cells,
> + nfan_cells,
> NULL, 0, NULL);
>
> return 0;
> @@ -123,7 +205,8 @@ static int khadas_mcu_probe(struct i2c_client *client)
>
> #ifdef CONFIG_OF
> static const struct of_device_id khadas_mcu_of_match[] = {
> - { .compatible = "khadas,mcu", },
> + { .compatible = "khadas,mcu", .data = (void *)KHADAS_MCU_GENERIC },
> + { .compatible = "khadas,vim4-mcu", .data = (void *)KHADAS_MCU_VIM4 },
> {},
> };
> MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);
>
> --
> 2.49.0
>
>
--
Lee Jones
^ permalink raw reply
* Re: [PATCH 3/4] mfd: mt6397-core: add mt6323 AUXADC support
From: Lee Jones @ 2026-06-11 16:37 UTC (permalink / raw)
To: rva333
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, Ben Grisdale
In-Reply-To: <20260602-mt6323-adc-v1-3-68ec737508ee@protonmail.com>
Interesting. Has this been considered?
/* Sashiko Automation: Issues Found (1 Findings) */
On Tue, 02 Jun 2026, Roman Vivchar via B4 Relay wrote:
> From: Roman Vivchar <rva333@protonmail.com>
>
> The mt6323 PMIC includes an AUXADC. Register the AUXADC in the mt6323
> devices array to allow the corresponding driver to probe using compatible
> string.
>
> Tested-by: Ben Grisdale <bengris32@protonmail.ch> # Amazon Echo Dot (2nd Generation)
> Signed-off-by: Roman Vivchar <rva333@protonmail.com>
> ---
> drivers/mfd/mt6397-core.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
> index 3e58d0764c7e..013b0857fb54 100644
> --- a/drivers/mfd/mt6397-core.c
> +++ b/drivers/mfd/mt6397-core.c
> @@ -125,6 +125,9 @@ static const struct resource mt6323_pwrc_resources[] = {
>
> static const struct mfd_cell mt6323_devs[] = {
> {
> + .name = "mt6323-auxadc",
> + .of_compatible = "mediatek,mt6323-auxadc",
[Severity: High]
Does adding this compatible string expose an unhandled edge case in the
auxadc driver?
If this device is instantiated directly from a Device Tree without an MFD
parent (e.g., at the DT root), dev->parent could be the platform bus
(which has a NULL parent) or NULL itself.
Looking at mt6323_auxadc_probe() in drivers/iio/adc/mt6323-auxadc.c:
regmap = dev_get_regmap(dev->parent->parent, NULL);
Could blindly dereferencing dev->parent->parent here, or passing a NULL
device to dev_get_regmap() (which calls devres_find()), result in a
kernel oops if probed as a root node?
> + }, {
> .name = "mt6323-rtc",
> .num_resources = ARRAY_SIZE(mt6323_rtc_resources),
> .resources = mt6323_rtc_resources,
>
> --
> 2.54.0
>
>
--
Lee Jones
^ permalink raw reply
* Re: [PATCH v3 2/3] dt-bindings: mfd: syscon: Drop custom select for older dtschema
From: Rob Herring @ 2026-06-11 16:31 UTC (permalink / raw)
To: Conor Dooley
Cc: Krzysztof Kozlowski, Lee Jones, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno, Jacky Huang,
Shan-Chun Hung, Geert Uytterhoeven, Magnus Damm, Heiko Stuebner,
Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros,
Tony Lindgren, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, linux-renesas-soc, linux-rockchip, linux-omap
In-Reply-To: <20260609-vertical-antarctic-e18a7ec91685@spud>
On Tue, Jun 09, 2026 at 05:28:21PM +0100, Conor Dooley wrote:
> On Mon, Jun 08, 2026 at 10:44:25PM +0200, Krzysztof Kozlowski wrote:
> > Older dtschema <2024.02 required custom select to avoid applying this
> > binding to anything having "syscon" compatible. That's not the case
> > anymore and this additional select has two headaches:
> >
> > 1. Duplicates all the compatibles listed in the schema.
> >
> > 2. Is error-prone, because it requires contributor to add the compatible
> > in two places, otherwise the schema will be silently ignored.
> > The select list already misses mentioning compatibles:
> > mediatek,mt8365-infracfg-nao and renesas,r9a08g046-lvds-cmn (with the
> > latter being reverted for different reasons).
> >
> > This requires bumping minimum dtschema requirement to v2024.04, which
> > feels old enough to be a safe requirement.
>
> I agree, seems reasonable enough given it's a jump from 2023.09 and not
> some large jump.
> The diff is nice too!
> I assume Rob will be taking it, but just in case..
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
I expect Lee to take this. I suspect syscon.yaml has other conflicting
changes.
Rob
^ permalink raw reply
* Re: iio: adc: KASAN wild-memory-access in complete() on early IRQ
From: Jonathan Cameron @ 2026-06-11 16:22 UTC (permalink / raw)
To: Jaeyoung Chung
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Vladimir Zapolskiy,
Piotr Wojtaszczyk, linux-iio, linux-arm-kernel, linux-kernel,
Sangyun Kim, Kyungwook Boo
In-Reply-To: <20260610115700.774689-1-jjy600901@snu.ac.kr>
On Wed, 10 Jun 2026 20:57:00 +0900
Jaeyoung Chung <jjy600901@snu.ac.kr> wrote:
> Hi,
>
> lpc32xx_adc_probe() in drivers/iio/adc/lpc32xx_adc.c and
> spear_adc_probe() in drivers/iio/adc/spear_adc.c register their
> interrupt handler with devm_request_irq() before they initialize
> st->completion with init_completion(). If an interrupt arrives after
> devm_request_irq() and before init_completion(), the handler calls
> complete() on an uninitialized completion, causing a kernel panic.
>
> The probe path, in lpc32xx_adc_probe():
>
> iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); /* st kzalloc-zeroed */
> ...
> retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
> LPC32XXAD_NAME, st); /* register handler */
> ...
> init_completion(&st->completion); /* initialize completion */
>
> spear_adc_probe() has the same ordering: devm_request_irq() for
> spear_adc_isr() before init_completion(&st->completion).
>
> Both interrupt handlers, lpc32xx_adc_isr() and spear_adc_isr(), call
> complete():
>
> complete(&st->completion);
>
> If the device raises an interrupt before init_completion() runs,
> complete() acquires the uninitialized wait.lock and walks the zeroed
> task_list in swake_up_locked(). The zeroed task_list makes list_empty()
> return false, so swake_up_locked() dereferences a NULL list entry,
> triggering a KASAN wild-memory-access.
>
> Suggested fix: move init_completion(&st->completion) above
> devm_request_irq(), so the completion is valid before the handler can run.
>
> Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
> Reported-by: Kyungwook Boo <bookyungwook@gmail.com>
Hi I think the report is valid, but I'm curious to whether you ran these
drivers given the hardware is pretty obscure! If not how did KASAN detect
anything (unless there is a static analysis version I'm not aware of)
Given age of drivers and that this only occurs if a spurious IRQ turns
up I'm not going to rush to fix this. However, I'd certainly welcome
patches.
Thanks,
Jonathan
>
> Thanks,
> Jaeyoung Chung
^ permalink raw reply
* Re: [PATCHv2] PCI: mvebu: Use fixed-width interrupt masks
From: Bjorn Helgaas @ 2026-06-11 16:17 UTC (permalink / raw)
To: Rosen Penev
Cc: linux-pci, Thomas Petazzoni, Pali Rohár, Lorenzo Pieralisi,
linusw, Krzysztof Wilczyński, Manivannan Sadhasivam,
Rob Herring, Bjorn Helgaas,
moderated list:PCI DRIVER FOR MVEBU (Marvell Armada 370 and Ar...),linusw@kernel.org,
open list
In-Reply-To: <20260526044016.1025613-1-rosenp@gmail.com>
On Mon, May 25, 2026 at 09:40:16PM -0700, Rosen Penev wrote:
> Use u32-typed BIT and GENMASK helpers for PCIe interrupt register
> masks. This keeps inverted masks in the same width as the registers
> and avoids truncation warnings on 64-bit compile-test builds.
>
> Fixes this and similar warnings:
>
> drivers/pci/controller/pci-mvebu.c:316:21: error: implicit conversion from
> 'unsigned long' to 'u32' (aka 'unsigned int') changes value from
> 18446744069414584320 to 0 [-Werror,-Wconstant-conversion]
> 316 | mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF);
>
> Assisted-by: Codex:GPT-5.5
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
> v2: remove sys_to_pcie change
> drivers/pci/controller/pci-mvebu.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
> index e568528bad85..f5a3f7370552 100644
> --- a/drivers/pci/controller/pci-mvebu.c
> +++ b/drivers/pci/controller/pci-mvebu.c
> @@ -57,9 +57,9 @@
> #define PCIE_CONF_DATA_OFF 0x18fc
> #define PCIE_INT_CAUSE_OFF 0x1900
> #define PCIE_INT_UNMASK_OFF 0x1910
> -#define PCIE_INT_INTX(i) BIT(24+i)
> -#define PCIE_INT_PM_PME BIT(28)
> -#define PCIE_INT_ALL_MASK GENMASK(31, 0)
> +#define PCIE_INT_INTX(i) BIT_U32(24 + (i))
> +#define PCIE_INT_PM_PME BIT_U32(28)
> +#define PCIE_INT_ALL_MASK GENMASK_U32(31, 0)
This looks like something that could be an issue in dozens of drivers.
Is it? If so, I'd prefer to fix them all at once in a single patch
instead of a slow trickle.
^ permalink raw reply
* Re: [PATCH 2/4] nvmem: add mt6323 PMIC EFUSE driver
From: Andy Shevchenko @ 2026-06-11 16:13 UTC (permalink / raw)
To: rva333
Cc: Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Srinivas Kandagatla, Andy Shevchenko,
Jonathan Cameron, linux-pm, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, Ben Grisdale
In-Reply-To: <20260611-mt6323-nvmem-v1-2-b5e1b9ce51f2@protonmail.com>
On Thu, Jun 11, 2026 at 1:21 PM Roman Vivchar via B4 Relay
<devnull+rva333.protonmail.com@kernel.org> wrote:
>
> Add support for the EFUSE controller found in the Mediatek MT6323 PMIC.
> The MT6323 EFUSE stores 24 bytes of hardware-related data, such as
> thermal sensor calibration values.
Reviewed-by: Andy Shevchenko <andy@kernel.org>
...
> +static int mt6323_efuse_read(void *context, unsigned int offset, void *val,
> + size_t bytes)
> +{
> + struct regmap *map = context;
> + u32 tmp;
> + u16 *buf = val;
> + int ret;
Perhaps reversed xmas tree order? And it's actually better to see
assignments first.
> + /*
> + * A manual loop using regmap_read is required because PWRAP is not
> + * a continuous MMIO space, but rather a FSM that doesn't implement the
> + * necessary read callback for the regmap_read_raw and regmap_read_bulk
> + * functions.
> + */
> + for (size_t i = 0; i < bytes; i += sizeof(*buf)) {
> + ret = regmap_read(map, MT6323_EFUSE_DOUT_BASE + offset + i, &tmp);
> + if (ret)
> + return ret;
> +
> + *buf++ = tmp;
> + }
> +
> + return 0;
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH] net: ethernet: mediatek: fix refcount leak in mtk_probe()
From: Simon Horman @ 2026-06-11 16:11 UTC (permalink / raw)
To: Wentao Liang
Cc: nbd, lorenzo, andrew+netdev, davem, edumazet, kuba, pabeni,
matthias.bgg, angelogioacchino.delregno, netdev, linux-kernel,
linux-arm-kernel, linux-mediatek, stable
In-Reply-To: <20260609081300.208168-1-vulab@iscas.ac.cn>
On Tue, Jun 09, 2026 at 08:13:00AM +0000, Wentao Liang wrote:
> If mtk_sgmii_init() fails after successfully creating some PCS
> instances, it returns an error without cleaning up the partially
> created ones. mtk_pcs_lynxi_create() increments the fwnode
> refcount for each PCS it creates, but this refcount is never
> released because mtk_probe() uses a plain "return err" instead of
> a goto to the err_destroy_sgmii label. This leaks both the PCS
> devices and their fwnode references.
>
> Fix the leak by jumping to the existing err_destroy_sgmii path
> which calls mtk_sgmii_destroy() to safely release all allocated
> resources.
>
> Cc: stable@vger.kernel.org
> Fixes: 9ffee4a8276c ("net: ethernet: mediatek: Extend SGMII related functions")
> Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
I think that a better approach would be, on error, for mtk_sgmii_init()
to release any resources it has allocated before returning.
Also, I'm not convinced this is stable material
as I'm not sure it's bothering anyone.
...
^ permalink raw reply
* Re: iio: adc: KASAN wild-memory-access in complete() on early IRQ
From: Maxwell Doose @ 2026-06-11 16:07 UTC (permalink / raw)
To: Jaeyoung Chung
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Vladimir Zapolskiy, Piotr Wojtaszczyk, linux-iio,
linux-arm-kernel, linux-kernel, Sangyun Kim, Kyungwook Boo
In-Reply-To: <20260610115700.774689-1-jjy600901@snu.ac.kr>
On Wed, Jun 10, 2026 at 7:04 AM Jaeyoung Chung <jjy600901@snu.ac.kr> wrote:
>
> Hi,
>
> lpc32xx_adc_probe() in drivers/iio/adc/lpc32xx_adc.c and
> spear_adc_probe() in drivers/iio/adc/spear_adc.c register their
> interrupt handler with devm_request_irq() before they initialize
> st->completion with init_completion(). If an interrupt arrives after
> devm_request_irq() and before init_completion(), the handler calls
> complete() on an uninitialized completion, causing a kernel panic.
>
> The probe path, in lpc32xx_adc_probe():
>
> iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); /* st kzalloc-zeroed */
> ...
> retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
> LPC32XXAD_NAME, st); /* register handler */
> ...
> init_completion(&st->completion); /* initialize completion */
>
> spear_adc_probe() has the same ordering: devm_request_irq() for
> spear_adc_isr() before init_completion(&st->completion).
>
> Both interrupt handlers, lpc32xx_adc_isr() and spear_adc_isr(), call
> complete():
>
> complete(&st->completion);
>
> If the device raises an interrupt before init_completion() runs,
> complete() acquires the uninitialized wait.lock and walks the zeroed
> task_list in swake_up_locked(). The zeroed task_list makes list_empty()
> return false, so swake_up_locked() dereferences a NULL list entry,
> triggering a KASAN wild-memory-access.
>
> Suggested fix: move init_completion(&st->completion) above
> devm_request_irq(), so the completion is valid before the handler can run.
>
> Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
> Reported-by: Kyungwook Boo <bookyungwook@gmail.com>
>
Thanks for reporting this; I can start working on a fix shortly
(assuming nobody else is already working on it).
--
best regards,
max
^ permalink raw reply
* Re: [PATCH v7 3/6] firmware: smccc: Move RSI definitions to include/linux
From: Suzuki K Poulose @ 2026-06-11 16:04 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm), linux-coco, linux-arm-kernel,
linux-kernel
Cc: Catalin Marinas, Greg KH, Jeremy Linton, Jonathan Cameron,
Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Will Deacon,
Steven Price, Andre Przywara
In-Reply-To: <20260611130429.295516-4-aneesh.kumar@kernel.org>
On 11/06/2026 14:04, Aneesh Kumar K.V (Arm) wrote:
> The RSI SMCCC function IDs describe a firmware ABI and are not arm64
> architecture specific definitions. Follow-up changes need to use them from
> non-arch code, including drivers/firmware/smccc and the Arm CCA guest
> driver.
>
> Move the RSI SMCCC definitions from arch/arm64/include/asm/ to
> include/linux/ so they can be shared with the driver code. This also
> keeps the firmware interface outside architecture code, as requested [1].
Please could we also mention about moving the "wrappers" only used by
drivers accordingly ?
>
> [1] https://lore.kernel.org/all/agsNO9cc7H-b0H8L@willie-the-truck
>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> ---
> arch/arm64/include/asm/rsi_cmds.h | 74 +---------------
> .../virt/coco/arm-cca-guest/arm-cca-guest.c | 2 +
> drivers/virt/coco/arm-cca-guest/rsi.h | 84 +++++++++++++++++++
> .../linux/arm-smccc-rsi.h | 6 +-
> 4 files changed, 90 insertions(+), 76 deletions(-)
> create mode 100644 drivers/virt/coco/arm-cca-guest/rsi.h
> rename arch/arm64/include/asm/rsi_smc.h => include/linux/arm-smccc-rsi.h (98%)
>
> diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi_cmds.h
> index 2c8763876dfb..633123a4e5d5 100644
> --- a/arch/arm64/include/asm/rsi_cmds.h
> +++ b/arch/arm64/include/asm/rsi_cmds.h
> @@ -8,10 +8,9 @@
>
> #include <linux/arm-smccc.h>
> #include <linux/string.h>
> +#include <linux/arm-smccc-rsi.h>
super minor nit: Please keep them in the alphabetical order.
With that:
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Suzuki
> #include <asm/memory.h>
>
> -#include <asm/rsi_smc.h>
> -
> #define RSI_GRANULE_SHIFT 12
> #define RSI_GRANULE_SIZE (_AC(1, UL) << RSI_GRANULE_SHIFT)
>
> @@ -88,75 +87,4 @@ static inline long rsi_set_addr_range_state(phys_addr_t start,
> return res.a0;
> }
>
> -/**
> - * rsi_attestation_token_init - Initialise the operation to retrieve an
> - * attestation token.
> - *
> - * @challenge: The challenge data to be used in the attestation token
> - * generation.
> - * @size: Size of the challenge data in bytes.
> - *
> - * Initialises the attestation token generation and returns an upper bound
> - * on the attestation token size that can be used to allocate an adequate
> - * buffer. The caller is expected to subsequently call
> - * rsi_attestation_token_continue() to retrieve the attestation token data on
> - * the same CPU.
> - *
> - * Returns:
> - * On success, returns the upper limit of the attestation report size.
> - * Otherwise, -EINVAL
> - */
> -static inline long
> -rsi_attestation_token_init(const u8 *challenge, unsigned long size)
> -{
> - struct arm_smccc_1_2_regs regs = { 0 };
> -
> - /* The challenge must be at least 32bytes and at most 64bytes */
> - if (!challenge || size < 32 || size > 64)
> - return -EINVAL;
> -
> - regs.a0 = SMC_RSI_ATTESTATION_TOKEN_INIT;
> - memcpy(®s.a1, challenge, size);
> - arm_smccc_1_2_smc(®s, ®s);
> -
> - if (regs.a0 == RSI_SUCCESS)
> - return regs.a1;
> -
> - return -EINVAL;
> -}
> -
> -/**
> - * rsi_attestation_token_continue - Continue the operation to retrieve an
> - * attestation token.
> - *
> - * @granule: {I}PA of the Granule to which the token will be written.
> - * @offset: Offset within Granule to start of buffer in bytes.
> - * @size: The size of the buffer.
> - * @len: The number of bytes written to the buffer.
> - *
> - * Retrieves up to a RSI_GRANULE_SIZE worth of token data per call. The caller
> - * is expected to call rsi_attestation_token_init() before calling this
> - * function to retrieve the attestation token.
> - *
> - * Return:
> - * * %RSI_SUCCESS - Attestation token retrieved successfully.
> - * * %RSI_INCOMPLETE - Token generation is not complete.
> - * * %RSI_ERROR_INPUT - A parameter was not valid.
> - * * %RSI_ERROR_STATE - Attestation not in progress.
> - */
> -static inline unsigned long rsi_attestation_token_continue(phys_addr_t granule,
> - unsigned long offset,
> - unsigned long size,
> - unsigned long *len)
> -{
> - struct arm_smccc_res res;
> -
> - arm_smccc_1_1_invoke(SMC_RSI_ATTESTATION_TOKEN_CONTINUE,
> - granule, offset, size, 0, &res);
> -
> - if (len)
> - *len = res.a1;
> - return res.a0;
> -}
> -
> #endif /* __ASM_RSI_CMDS_H */
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> index 66d00b6ceb78..8b6854e7a188 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> @@ -14,6 +14,8 @@
>
> #include <asm/rsi.h>
>
> +#include "rsi.h"
> +
> /**
> * struct arm_cca_token_info - a descriptor for the token buffer.
> * @challenge: Pointer to the challenge data
> diff --git a/drivers/virt/coco/arm-cca-guest/rsi.h b/drivers/virt/coco/arm-cca-guest/rsi.h
> new file mode 100644
> index 000000000000..f7303f4bce17
> --- /dev/null
> +++ b/drivers/virt/coco/arm-cca-guest/rsi.h
> @@ -0,0 +1,84 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2026 ARM Ltd.
> + */
> +
> +#ifndef _VIRT_COCO_RSI_H_
> +#define _VIRT_COCO_RSI_H_
> +
> +#include <linux/arm-smccc-rsi.h>
> +
> +/**
> + * rsi_attestation_token_init - Initialise the operation to retrieve an
> + * attestation token.
> + *
> + * @challenge: The challenge data to be used in the attestation token
> + * generation.
> + * @size: Size of the challenge data in bytes.
> + *
> + * Initialises the attestation token generation and returns an upper bound
> + * on the attestation token size that can be used to allocate an adequate
> + * buffer. The caller is expected to subsequently call
> + * rsi_attestation_token_continue() to retrieve the attestation token data on
> + * the same CPU.
> + *
> + * Returns:
> + * On success, returns the upper limit of the attestation report size.
> + * Otherwise, -EINVAL
> + */
> +static inline long
> +rsi_attestation_token_init(const u8 *challenge, unsigned long size)
> +{
> + struct arm_smccc_1_2_regs regs = { 0 };
> +
> + /* The challenge must be at least 32bytes and at most 64bytes */
> + if (!challenge || size < 32 || size > 64)
> + return -EINVAL;
> +
> + regs.a0 = SMC_RSI_ATTESTATION_TOKEN_INIT;
> + memcpy(®s.a1, challenge, size);
> + arm_smccc_1_2_smc(®s, ®s);
> +
> + if (regs.a0 == RSI_SUCCESS)
> + return regs.a1;
> +
> + return -EINVAL;
> +}
> +
> +/**
> + * rsi_attestation_token_continue - Continue the operation to retrieve an
> + * attestation token.
> + *
> + * @granule: {I}PA of the Granule to which the token will be written.
> + * @offset: Offset within Granule to start of buffer in bytes.
> + * @size: The size of the buffer.
> + * @len: The number of bytes written to the buffer.
> + *
> + * Retrieves up to a RSI_GRANULE_SIZE worth of token data per call. The caller
> + * is expected to call rsi_attestation_token_init() before calling this
> + * function to retrieve the attestation token.
> + *
> + * Return:
> + * * %RSI_SUCCESS - Attestation token retrieved successfully.
> + * * %RSI_INCOMPLETE - Token generation is not complete.
> + * * %RSI_ERROR_INPUT - A parameter was not valid.
> + * * %RSI_ERROR_STATE - Attestation not in progress.
> + */
> +static inline unsigned long rsi_attestation_token_continue(phys_addr_t granule,
> + unsigned long offset,
> + unsigned long size,
> + unsigned long *len)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RSI_ATTESTATION_TOKEN_CONTINUE,
> + granule, offset, size, 0, &res);
> +
> + if (len)
> + *len = res.a1;
> + return res.a0;
> +}
> +
> +
> +
> +#endif
> diff --git a/arch/arm64/include/asm/rsi_smc.h b/include/linux/arm-smccc-rsi.h
> similarity index 98%
> rename from arch/arm64/include/asm/rsi_smc.h
> rename to include/linux/arm-smccc-rsi.h
> index e19253f96c94..fddb77986f70 100644
> --- a/arch/arm64/include/asm/rsi_smc.h
> +++ b/include/linux/arm-smccc-rsi.h
> @@ -3,8 +3,8 @@
> * Copyright (C) 2023 ARM Ltd.
> */
>
> -#ifndef __ASM_RSI_SMC_H_
> -#define __ASM_RSI_SMC_H_
> +#ifndef __LINUX_ARM_SMCCC_RSI_H_
> +#define __LINUX_ARM_SMCCC_RSI_H_
>
> #include <linux/arm-smccc.h>
>
> @@ -190,4 +190,4 @@ struct realm_config {
> */
> #define SMC_RSI_HOST_CALL SMC_RSI_FID(0x199)
>
> -#endif /* __ASM_RSI_SMC_H_ */
> +#endif /* __LINUX_ARM_SMCCC_RSI_H_ */
^ permalink raw reply
* Re: [PATCH v3] arm64: errata: Workaround NVIDIA Olympus device store/load ordering erratum
From: Shanker Donthineni @ 2026-06-11 16:00 UTC (permalink / raw)
To: Vladimir Murzin, Will Deacon
Cc: Catalin Marinas, Jason Gunthorpe, linux-arm-kernel, Mark Rutland,
linux-kernel, linux-doc, Vikram Sethi, Jason Sequeira
In-Reply-To: <aee00047-81b9-4562-be47-500b2643f7f6@arm.com>
Hi Vladimir,
On 6/11/2026 10:08 AM, Vladimir Murzin wrote:
> External email: Use caution opening links or attachments
>
>
> Hi,
>
> On 6/11/26 14:34, Will Deacon wrote:
>> On Wed, Jun 10, 2026 at 11:48:22AM -0500, Shanker Donthineni wrote:
>>> On systems with NVIDIA Olympus cores, a Device-nGnR* load can be
>>> observed by a peripheral before an older, non-overlapping Device-nGnR*
>>> store to the same peripheral. This breaks the program-order guarantee
>>> that software expects for Device-nGnR* accesses and can leave a
>>> peripheral in an incorrect state, as a load is observed before an
>>> earlier store takes effect.
>>>
>>> The erratum can occur only when all of the following apply:
>>>
>>> - A PE executes a Device-nGnR* store followed by a younger
>>> Device-nGnR* load.
>>> - The store is not a store-release.
>>> - The accesses target the same peripheral and do not overlap in bytes.
>>> - There is at most one intervening Device-nGnR* store in program
>>> order, and there are no intervening Device-nGnR* loads.
>>> - There is no DSB, and no DMB that orders loads, between the store and
>>> the load.
>>> - Specific micro-architectural and timing conditions occur.
>>>
>>> Promote the raw MMIO store helpers (__raw_writeb/w/l/q) from plain str*
>>> to stlr* (Store-Release), which removes the "store is not a
>>> store-release" condition for every device write the kernel issues.
>>> Because writel() and writel_relaxed() are both built on __raw_writel()
>>> in asm-generic/io.h, patching the raw variants covers both the
>>> non-relaxed and relaxed APIs without touching the higher layers. Note
>>> that writel()'s own barrier sits before the store, so it does not order
>>> the store against a subsequent readl(); the store-release promotion is
>>> what provides that ordering.
>>>
>>> Like ARM64_ERRATUM_832075 on the load side, the change is gated on a new
>>> ARM64_WORKAROUND_DEVICE_STORE_RELEASE capability and only activated on
>>> parts that match MIDR_NVIDIA_OLYMPUS, so unaffected CPUs continue to use
>>> the plain str* sequence.
>>>
>>> Note: stlr* only supports base-register addressing, so affected CPUs use
>>> a base-register stlr* path. Unaffected CPUs keep the original
>>> offset-addressed str* sequence introduced by commit d044d6ba6f02
>>> ("arm64: io: permit offset addressing").
>>>
>>> The __const_memcpy_toio_aligned32() and __const_memcpy_toio_aligned64()
>>> helpers are left unchanged. These helpers are intended for
>>> write-combining mappings, which are Normal-NC on arm64. Replacing their
>>> contiguous str* groups would defeat the write-combining behavior used to
>>> improve store performance.
>>>
>>> Co-developed-by: Vikram Sethi <vsethi@nvidia.com>
>>> Signed-off-by: Vikram Sethi <vsethi@nvidia.com>
>>> Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
>>> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>>> ---
>>> Changes since v2:
>>> - Reworked the raw MMIO write helpers so unaffected CPUs keep the
>>> existing offset-addressed STR sequence, while affected CPUs use the
>>> base-register STLR path.
>>> - Updated the commit message to match the code changes.
>>> - Rebased on top of the arm64 for-next/errata branch:
>>> https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/errata
>>>
>>> Changes since v1:
>>> - Updated the commit message based on feedback from Vladimir Murzin.
>>>
>>> Documentation/arch/arm64/silicon-errata.rst | 2 ++
>>> arch/arm64/Kconfig | 23 ++++++++++++++++
>>> arch/arm64/include/asm/io.h | 30 +++++++++++++++++++++
>>> arch/arm64/kernel/cpu_errata.c | 8 ++++++
>>> arch/arm64/tools/cpucaps | 1 +
>>> 5 files changed, 64 insertions(+)
>>>
>>> diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
>>> index ad09bbb10da80..fc45125dc2f80 100644
>>> --- a/Documentation/arch/arm64/silicon-errata.rst
>>> +++ b/Documentation/arch/arm64/silicon-errata.rst
>>> @@ -298,6 +298,8 @@ stable kernels.
>>> +----------------+-----------------+-----------------+-----------------------------+
>>> | NVIDIA | Carmel Core | N/A | NVIDIA_CARMEL_CNP_ERRATUM |
>>> +----------------+-----------------+-----------------+-----------------------------+
>>> +| NVIDIA | Olympus core | T410-OLY-1027 | NVIDIA_OLYMPUS_1027_ERRATUM |
>>> ++----------------+-----------------+-----------------+-----------------------------+
>>> | NVIDIA | Olympus core | T410-OLY-1029 | ARM64_ERRATUM_4118414 |
>>> +----------------+-----------------+-----------------+-----------------------------+
>>> | NVIDIA | T241 GICv3/4.x | T241-FABRIC-4 | N/A |
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index c65cef81be86a..d633eb70de1ac 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -564,6 +564,29 @@ config ARM64_ERRATUM_832075
>>>
>>> If unsure, say Y.
>>>
>>> +config NVIDIA_OLYMPUS_1027_ERRATUM
>>> + bool "NVIDIA Olympus: device store/load ordering erratum"
>>> + default y
>>> + help
>>> + This option adds an alternative code sequence to work around an
>>> + NVIDIA Olympus core erratum where a Device-nGnR* store can be
>>> + observed by a peripheral after a younger Device-nGnR* load to the
>>> + same peripheral. This breaks the program order that drivers rely
>>> + on for MMIO and can leave a device in an incorrect state.
>>> +
>>> + The workaround promotes the raw MMIO store helpers
>>> + (__raw_writeb/w/l/q) to Store-Release (STLR), which restores the
>>> + required ordering. Because writel() and writel_relaxed() are built
>>> + on __raw_writel(), both are covered without changes to the higher
>>> + layers.
>>> +
>>> + The fix is applied through the alternatives framework, so enabling
>>> + this option does not by itself activate the workaround: it is
>>> + patched in only when an affected CPU is detected, and is a no-op on
>>> + unaffected CPUs.
>>> +
>>> + If unsure, say Y.
>>> +
>>> config ARM64_ERRATUM_834220
>>> bool "Cortex-A57: 834220: Stage 2 translation fault might be incorrectly reported in presence of a Stage 1 fault (rare)"
>>> depends on KVM
>>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>>> index 8cbd1e96fd50b..801223e754c90 100644
>>> --- a/arch/arm64/include/asm/io.h
>>> +++ b/arch/arm64/include/asm/io.h
>>> @@ -22,10 +22,22 @@
>>> /*
>>> * Generic IO read/write. These perform native-endian accesses.
>>> */
>>> +static __always_inline bool arm64_needs_device_store_release(void)
>>> +{
>>> + return alternative_has_cap_unlikely(
>>> + ARM64_WORKAROUND_DEVICE_STORE_RELEASE);
>>> +}
>>> +
>>> #define __raw_writeb __raw_writeb
>>> static __always_inline void __raw_writeb(u8 val, volatile void __iomem *addr)
>>> {
>>> volatile u8 __iomem *ptr = addr;
>>> +
>>> + if (arm64_needs_device_store_release()) {
>>> + asm volatile("stlrb %w0, [%1]" : : "rZ" (val), "r" (addr));
>>> + return;
>>> + }
>>> +
>>> asm volatile("strb %w0, %1" : : "rZ" (val), "Qo" (*ptr));
>>> }
>> Use an 'else' clause instead of the early return? (similarly for the other
>> changes).
> Perhaps I'm missing something, but it is not clear to me why all that
> complexity is required.
>
> IIUC, benefits coming with d044d6ba6f02 ("arm64: io: permit offset
> addressing") are from better code generation, so we:
> - save code
> - open opportunity for write-combining
>
> d044d6ba6f02 ("arm64: io: permit offset addressing") comes with simple
> benchmark to measure effect of code generation:
>
> | void writeq_zero_8_times(void *ptr)
> | {
> | writeq_relaxed(0, ptr + 8 * 0);
> | writeq_relaxed(0, ptr + 8 * 1);
> | writeq_relaxed(0, ptr + 8 * 2);
> | writeq_relaxed(0, ptr + 8 * 3);
> | writeq_relaxed(0, ptr + 8 * 4);
> | writeq_relaxed(0, ptr + 8 * 5);
> | writeq_relaxed(0, ptr + 8 * 6);
> | writeq_relaxed(0, ptr + 8 * 7);
> | }
>
> which compiles to
>
> | <writeq_zero_8_times>:
> | str xzr, [x0]
> | str xzr, [x0, #8]
> | str xzr, [x0, #16]
> | str xzr, [x0, #24]
> | str xzr, [x0, #32]
> | str xzr, [x0, #40]
> | str xzr, [x0, #48]
> | str xzr, [x0, #56]
>
>
> v1/v2 compiles to
>
> | <writeq_zero_8_times>:
> | str xzr, [x0]
> | add x1, x0, #0x8
> | str xzr, [x1]
> | add x1, x0, #0x10
> | str xzr, [x1]
> | add x1, x0, #0x18
> | str xzr, [x1]
> | add x1, x0, #0x20
> | str xzr, [x1]
> | add x1, x0, #0x28
> | str xzr, [x1]
> | add x1, x0, #0x30
> | str xzr, [x1]
> | add x0, x0, #0x38
> | str xzr, [x0]
>
> were alternatives are swapping str with stlr. In other words, we are
> rolling back to the pre-d044d6ba6f02 implementation.
>
> v3 compiles to:
>
> | <writeq_zero_8_times>:
> | nop
> | str xzr, [x0]
> | add x1, x0, #0x8
> | nop
> | str xzr, [x1]
> | add x1, x0, #0x10
> | nop
> | str xzr, [x1]
> | add x1, x0, #0x18
> | nop
> | str xzr, [x1]
> | add x1, x0, #0x20
> | nop
> | str xzr, [x1]
> | add x1, x0, #0x28
> | nop
> | str xzr, [x1]
> | add x1, x0, #0x30
> | nop
> | str xzr, [x1]
> | add x0, x0, #0x38
> | nop
> | str xzr, [x0]
> | ret
>
> where static branch swapping nop with branch to stlr and back to add.
>
> So it looks to me that we're losing an opportunity for write
> combining, but in terms of code size, v1/v2 seems to be the lesser of
> two evils.
Thanks, that makes sense.
My intent with the v3 change was to keep the offset-addressed STR sequence on
unaffected CPUs and use the base-register STLR sequence only on affected CPUs.
However, as you point out, because STLR only supports base-register addressing,
the affected path still forces the address to be materialized in a register, and
the alternative_has_cap_unlikely() check adds another instruction at each write
site. So the generated code no longer preserves the benefit from d044d6ba6f02 in
practice.
Given that, I agree the extra complexity is not justified. I’ll simplify the raw
MMIO write helpers back to the direct ALTERNATIVE() form from v1/v2, where both
the STR and STLR paths use base-register addressing. That is still a regression
from the offset-addressed STR sequence on unaffected CPUs, but it avoids the
additional static-branch/nop overhead and is the smaller of the two options.
-Shanker
^ permalink raw reply
* Re: [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device
From: Heikki Krogerus @ 2026-06-11 15:48 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Andy Shevchenko, Greg Kroah-Hartman, Daniel Scally, Sakari Ailus,
Rafael J. Wysocki, Danilo Krummrich, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Alan Stern, linux-acpi, driver-core,
linux-pm, linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam, Chen-Yu Tsai
In-Reply-To: <CAMRc=MdRN7YitmMX8PknbzLh+MdsWm+dDg0MLtCVYOorqNobTw@mail.gmail.com>
On Thu, Jun 11, 2026 at 11:35:13AM +0200, Bartosz Golaszewski wrote:
> On Thu, Jun 11, 2026 at 10:37 AM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> >
> > On Thu, Jun 11, 2026 at 04:20:58AM -0400, Bartosz Golaszewski wrote:
> > > On Wed, 10 Jun 2026 16:16:12 +0200, Andy Shevchenko
> > > <andriy.shevchenko@linux.intel.com> said:
> > > > On Wed, Jun 10, 2026 at 04:40:39PM +0800, Chen-Yu Tsai wrote:
> > > >> When a USB hub port is connected to a connector in a firmware node
> > > >> graph, the port itself has a node in the graph.
> > > >>
> > > >> Associate the port's firmware node with the USB port's device,
> > > >> usb_port::dev. This is used in later changes for the M.2 slot power
> > > >> sequencing provider to match against the requesting port.
> > > >
> > > > Okay, would this affect ACPI-based systems? if so, how?
> > > > Can you elaborate on that, please?
> > >
> > > Is it possible that there's an ACPI device node associated with the port like
> > > on some DT systems? I don't think so and there should be no impact IMO but I
> > > also don't know enough about ACPI.
There are device nodes for the USB ports in ACPI, and I think they get
always assigned in drivers/usb/core/usb-acpi.c.
> > The API is agnostic. There is a possibility to have software nodes associated
> > with the port. I think the best is to be sure that ACPI-aware people who are
> > experts in USB will check this (Heikki?).
I can't say what's the impact from this patch - I'm not an expert with
this side of USB. Is there a danger that we end up overwriting the
ACPI node for the port, or something else?
> Even if there is a software node - it shouldn't really matter. It will
> just be assigned to the port device.
thanks,
--
heikki
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox