* [PATCH 0/2] remoteproc: qcom: pas: Fix early_boot attach for not running and crashed remotes
@ 2026-10-06 3:35 Shawn Guo
2026-10-06 3:35 ` [PATCH 1/2] remoteproc: qcom: pas: Decide early_boot attach at probe time Shawn Guo
2026-10-06 3:35 ` [PATCH 2/2] remoteproc: qcom: pas: Don't fail attach if the remote has crashed Shawn Guo
0 siblings, 2 replies; 5+ messages in thread
From: Shawn Guo @ 2026-10-06 3:35 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Mathieu Poirier, Stephan Gerhold, Konrad Dybcio, Jingyi Wang,
Bartosz Golaszewski, linux-arm-msm, linux-remoteproc,
linux-kernel, Shawn Guo
The late attach support for early_boot subsystems has two problems.
1) A remote that the bootloader did not start is never booted. The
checks for that case live in qcom_pas_attach(), which marks the rproc
RPROC_OFFLINE and fails, but the core treats the failure as fatal and
never loads the firmware. This shows up on Nord, where newer XBL
firmware for the IoT variant leaves ADSP in reset for Linux to boot:
remoteproc remoteproc0: can't attach to rproc adsp: -19
Patch 1 moves the ready/stop-ack/shutdown-ack checks into probe, as
these signals are static until Linux interacts with the remote, and
only marks the rproc RPROC_DETACHED if the remote is running.
2) A remote found crashed at attach is recovered on top of the state the
failed attach has already unwound. Recovery leaves the rproc running
with a zero power refcount, so a following sysfs stop is a no-op and
start boots the firmware again on the running remote. Patch 2 lets
the attach succeed after reporting the crash, as the fatal interrupt
handler does, so recovery runs from the attached state.
This replaces the earlier patch dropping the early_boot flag from Nord
ADSP, following Konrad's and Stephan's comments [1]. With this series
the flag is kept, since the Nord Auto variant still has ADSP started by
XBL.
[1] https://lore.kernel.org/r/20260930020745.1940933-1-shengchao.guo@oss.qualcomm.com/
Shawn Guo (2):
remoteproc: qcom: pas: Decide early_boot attach at probe time
remoteproc: qcom: pas: Don't fail attach if the remote has crashed
drivers/remoteproc/qcom_q6v5_pas.c | 72 ++++++++++++++++--------------
1 file changed, 39 insertions(+), 33 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] remoteproc: qcom: pas: Decide early_boot attach at probe time
2026-10-06 3:35 [PATCH 0/2] remoteproc: qcom: pas: Fix early_boot attach for not running and crashed remotes Shawn Guo
@ 2026-10-06 3:35 ` Shawn Guo
2026-10-09 14:20 ` Stephan Gerhold
2026-10-06 3:35 ` [PATCH 2/2] remoteproc: qcom: pas: Don't fail attach if the remote has crashed Shawn Guo
1 sibling, 1 reply; 5+ messages in thread
From: Shawn Guo @ 2026-10-06 3:35 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Mathieu Poirier, Stephan Gerhold, Konrad Dybcio, Jingyi Wang,
Bartosz Golaszewski, linux-arm-msm, linux-remoteproc,
linux-kernel, Shawn Guo
For early_boot subsystems, probe unconditionally marks the rproc
RPROC_DETACHED and qcom_pas_attach() discovers from SMP2P whether the
bootloader actually started the remote. If it did not, attach sets the
state back to RPROC_OFFLINE and fails, expecting the core to boot the
firmware instead. The core does not do that: rproc_boot() treats the
attach failure as fatal and the remote is never started.
This is hit on Nord with firmware where XBL no longer brings ADSP out
of reset. The remote never publishes its inbound SMP2P entries, so the
very first state read fails (debug print below) and the ADSP stays down:
qcom_q6v5_pas 4c00000.remoteproc: Failed to get fatal_irq state: -19
remoteproc remoteproc0: can't attach to rproc adsp: -19
The ready, stop-ack and sysmon shutdown-ack signals cannot change while
Linux has not yet interacted with the remote, so there is no reason to
defer the decision to attach time. Check them in probe and only mark
the rproc RPROC_DETACHED when the remote is up and has not been asked
to stop; otherwise leave it RPROC_OFFLINE so the regular firmware boot
path is taken. The ready state is read first so that a missing SMP2P
entry -ENODEV is treated as "not running" before sysmon is queried.
qcom_pas_attach() keeps only the fatal check, since that is the one
signal that has to be acted upon once the rproc is attached.
Assisted-by: LLM
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
---
drivers/remoteproc/qcom_q6v5_pas.c | 64 +++++++++++++++---------------
1 file changed, 33 insertions(+), 31 deletions(-)
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 2e1e39826ffa..8f3d45c604c9 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -550,9 +550,7 @@ static unsigned long qcom_pas_panic(struct rproc *rproc)
static int qcom_pas_attach(struct rproc *rproc)
{
struct qcom_pas *pas = rproc->priv;
- bool ready_state;
bool crash_state;
- bool stop_state;
int ret;
pas->q6v5.handover_issued = true;
@@ -570,42 +568,46 @@ static int qcom_pas_attach(struct rproc *rproc)
goto disable_running;
}
- ret = irq_get_irqchip_state(pas->q6v5.stop_irq,
- IRQCHIP_STATE_LINE_LEVEL, &stop_state);
- if (ret)
- goto disable_running;
-
- if (stop_state || qcom_sysmon_shutdown_irq_state(pas->sysmon)) {
- dev_info(pas->dev, "Subsystem found stop state set. Falling back to start.\n");
- goto unroll_attach;
- }
-
- ret = irq_get_irqchip_state(pas->q6v5.ready_irq,
- IRQCHIP_STATE_LINE_LEVEL, &ready_state);
- if (ret)
- goto disable_running;
-
- if (unlikely(!ready_state)) {
- /*
- * The bootloader may not support early boot, mark the state as
- * RPROC_OFFLINE so that the PAS driver can load the firmware and
- * start the remoteproc.
- */
- dev_err(pas->dev, "Failed to get subsystem ready interrupt\n");
- goto unroll_attach;
- }
-
return 0;
-unroll_attach:
- pas->rproc->state = RPROC_OFFLINE;
- ret = -EINVAL;
disable_running:
pas->q6v5.running = false;
return ret;
}
+/*
+ * The bootloader may or may not have started the subsystem. Inspect the
+ * SMP2P state, which is static until Linux interacts with the remote, to
+ * decide whether to attach or to load and start the firmware.
+ */
+static bool qcom_pas_is_running(struct qcom_pas *pas)
+{
+ bool ready_state;
+ bool stop_state;
+ int ret;
+
+ /*
+ * Check ready first: if the remote never published its SMP2P
+ * entries the state read fails with -ENODEV.
+ */
+ ret = irq_get_irqchip_state(pas->q6v5.ready_irq,
+ IRQCHIP_STATE_LINE_LEVEL, &ready_state);
+ if (ret || !ready_state) {
+ dev_info(pas->dev, "Subsystem not running. Falling back to start.\n");
+ return false;
+ }
+
+ ret = irq_get_irqchip_state(pas->q6v5.stop_irq,
+ IRQCHIP_STATE_LINE_LEVEL, &stop_state);
+ if (ret || stop_state || qcom_sysmon_shutdown_irq_state(pas->sysmon)) {
+ dev_info(pas->dev, "Subsystem found stop state set. Falling back to start.\n");
+ return false;
+ }
+
+ return true;
+}
+
static void qcom_pas_coredump(struct rproc *rproc)
{
struct qcom_pas *pas = rproc->priv;
@@ -1024,7 +1026,7 @@ static int qcom_pas_probe(struct platform_device *pdev)
if (pas->dtb_pas_id)
pas->dtb_pas_ctx->use_tzmem = desc->needs_tzmem || rproc->has_iommu;
- if (desc->early_boot)
+ if (desc->early_boot && qcom_pas_is_running(pas))
pas->rproc->state = RPROC_DETACHED;
ret = qcom_pas_setup_tmd(pas, desc);
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] remoteproc: qcom: pas: Don't fail attach if the remote has crashed
2026-10-06 3:35 [PATCH 0/2] remoteproc: qcom: pas: Fix early_boot attach for not running and crashed remotes Shawn Guo
2026-10-06 3:35 ` [PATCH 1/2] remoteproc: qcom: pas: Decide early_boot attach at probe time Shawn Guo
@ 2026-10-06 3:35 ` Shawn Guo
2026-10-09 14:38 ` Stephan Gerhold
1 sibling, 1 reply; 5+ messages in thread
From: Shawn Guo @ 2026-10-06 3:35 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Mathieu Poirier, Stephan Gerhold, Konrad Dybcio, Jingyi Wang,
Bartosz Golaszewski, linux-arm-msm, linux-remoteproc,
linux-kernel, Shawn Guo
When qcom_pas_attach() finds the fatal SMP2P bit already set, it reports
a crash and then fails the attach. The core unwinds the attach while the
crash work is queued: rproc_boot() drops the power refcount back to 0,
and __rproc_attach()/rproc_attach() unprepare the subdevices, clean up
the resource table and disable the IOMMU. Once rproc_boot() releases
rproc->lock, the crash handler finds the rproc still RPROC_DETACHED,
marks it RPROC_CRASHED and runs rproc_boot_recovery() on top of that
torn-down state:
- the subdevices are unprepared a second time by rproc_stop(), so SSR
and sysmon notifiers see a duplicate shutdown;
- qcom_pas_stop() and the subsequent rproc_start() operate on resources
that rproc_attach() already released, e.g. iommu_unmap() on a
disabled domain for rproc->has_iommu;
- recovery leaves the rproc RPROC_RUNNING with power == 0. A later
"stop" via sysfs takes power to -1 and returns success without
stopping anything, so the remote stays running. A following "start"
then boots the firmware again on the running remote and fails to
re-add the still registered subdevices:
sysfs: cannot create duplicate filename '.../qcom_common.pd-mapper.0'
remoteproc remoteproc0: failed to prepare subdevices for adsp: -17
remoteproc remoteproc0: Boot failed: -17
A crash found at attach time is no different from one reported by the
fatal interrupt right after attaching. Treat it the same way as
q6v5_fatal_interrupt() does: clear q6v5.running, report the crash and
let the attach succeed. The core completes the attach with balanced
bookkeeping, and the crash handler then recovers the subsystem through
the regular RPROC_ATTACHED -> RPROC_CRASHED path. With running cleared,
qcom_q6v5_request_stop() does not wait for a stop ack the dead remote
cannot send, and handover_issued already prevents a spurious handover
on stop.
Assisted-by: LLM
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
---
drivers/remoteproc/qcom_q6v5_pas.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 8f3d45c604c9..0ecd7688a54d 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -562,10 +562,14 @@ static int qcom_pas_attach(struct rproc *rproc)
goto disable_running;
if (crash_state) {
+ /*
+ * Complete the attach and let the crash handler recover the
+ * subsystem from the attached state, as for a crash reported
+ * by the fatal interrupt.
+ */
dev_err(pas->dev, "Subsystem has crashed before driver probe\n");
+ pas->q6v5.running = false;
rproc_report_crash(rproc, RPROC_FATAL_ERROR);
- ret = -EINVAL;
- goto disable_running;
}
return 0;
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] remoteproc: qcom: pas: Decide early_boot attach at probe time
2026-10-06 3:35 ` [PATCH 1/2] remoteproc: qcom: pas: Decide early_boot attach at probe time Shawn Guo
@ 2026-10-09 14:20 ` Stephan Gerhold
0 siblings, 0 replies; 5+ messages in thread
From: Stephan Gerhold @ 2026-10-09 14:20 UTC (permalink / raw)
To: Shawn Guo
Cc: Bjorn Andersson, Mathieu Poirier, Konrad Dybcio, Jingyi Wang,
Bartosz Golaszewski, linux-arm-msm, linux-remoteproc,
linux-kernel
On Tue, Oct 06, 2026 at 11:35:49AM +0800, Shawn Guo wrote:
> For early_boot subsystems, probe unconditionally marks the rproc
> RPROC_DETACHED and qcom_pas_attach() discovers from SMP2P whether the
> bootloader actually started the remote. If it did not, attach sets the
> state back to RPROC_OFFLINE and fails, expecting the core to boot the
> firmware instead. The core does not do that: rproc_boot() treats the
> attach failure as fatal and the remote is never started.
>
> This is hit on Nord with firmware where XBL no longer brings ADSP out
> of reset. The remote never publishes its inbound SMP2P entries, so the
> very first state read fails (debug print below) and the ADSP stays down:
>
> qcom_q6v5_pas 4c00000.remoteproc: Failed to get fatal_irq state: -19
> remoteproc remoteproc0: can't attach to rproc adsp: -19
>
> The ready, stop-ack and sysmon shutdown-ack signals cannot change while
> Linux has not yet interacted with the remote, so there is no reason to
> defer the decision to attach time. Check them in probe and only mark
> the rproc RPROC_DETACHED when the remote is up and has not been asked
> to stop; otherwise leave it RPROC_OFFLINE so the regular firmware boot
> path is taken. The ready state is read first so that a missing SMP2P
> entry -ENODEV is treated as "not running" before sysmon is queried.
>
> qcom_pas_attach() keeps only the fatal check, since that is the one
> signal that has to be acted upon once the rproc is attached.
>
> Assisted-by: LLM
> Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
> ---
> drivers/remoteproc/qcom_q6v5_pas.c | 64 +++++++++++++++---------------
> 1 file changed, 33 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index 2e1e39826ffa..8f3d45c604c9 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -550,9 +550,7 @@ static unsigned long qcom_pas_panic(struct rproc *rproc)
> static int qcom_pas_attach(struct rproc *rproc)
> {
> struct qcom_pas *pas = rproc->priv;
> - bool ready_state;
> bool crash_state;
> - bool stop_state;
> int ret;
>
> pas->q6v5.handover_issued = true;
> @@ -570,42 +568,46 @@ static int qcom_pas_attach(struct rproc *rproc)
> goto disable_running;
> }
>
> - ret = irq_get_irqchip_state(pas->q6v5.stop_irq,
> - IRQCHIP_STATE_LINE_LEVEL, &stop_state);
> - if (ret)
> - goto disable_running;
> -
> - if (stop_state || qcom_sysmon_shutdown_irq_state(pas->sysmon)) {
> - dev_info(pas->dev, "Subsystem found stop state set. Falling back to start.\n");
> - goto unroll_attach;
> - }
> -
> - ret = irq_get_irqchip_state(pas->q6v5.ready_irq,
> - IRQCHIP_STATE_LINE_LEVEL, &ready_state);
> - if (ret)
> - goto disable_running;
> -
> - if (unlikely(!ready_state)) {
> - /*
> - * The bootloader may not support early boot, mark the state as
> - * RPROC_OFFLINE so that the PAS driver can load the firmware and
> - * start the remoteproc.
> - */
> - dev_err(pas->dev, "Failed to get subsystem ready interrupt\n");
> - goto unroll_attach;
> - }
> -
> return 0;
>
> -unroll_attach:
> - pas->rproc->state = RPROC_OFFLINE;
> - ret = -EINVAL;
> disable_running:
> pas->q6v5.running = false;
>
> return ret;
> }
>
> +/*
> + * The bootloader may or may not have started the subsystem. Inspect the
> + * SMP2P state, which is static until Linux interacts with the remote, to
> + * decide whether to attach or to load and start the firmware.
> + */
> +static bool qcom_pas_is_running(struct qcom_pas *pas)
> +{
> + bool ready_state;
> + bool stop_state;
> + int ret;
> +
> + /*
> + * Check ready first: if the remote never published its SMP2P
> + * entries the state read fails with -ENODEV.
> + */
> + ret = irq_get_irqchip_state(pas->q6v5.ready_irq,
> + IRQCHIP_STATE_LINE_LEVEL, &ready_state);
> + if (ret || !ready_state) {
> + dev_info(pas->dev, "Subsystem not running. Falling back to start.\n");
> + return false;
> + }
> +
> + ret = irq_get_irqchip_state(pas->q6v5.stop_irq,
> + IRQCHIP_STATE_LINE_LEVEL, &stop_state);
> + if (ret || stop_state || qcom_sysmon_shutdown_irq_state(pas->sysmon)) {
> + dev_info(pas->dev, "Subsystem found stop state set. Falling back to start.\n");
> + return false;
> + }
Nitpick: Both of these messages are a bit imprecise. desc->early_boot
does not necessarily imply desc->auto_boot, so they may just be marked
as offline and not automatically started.
But you just moved this code and I don't think it's worth resending just
to polish these messages a bit more. :-)
In any case:
Reviewed-by: Stephan Gerhold <stephan.gerhold@linaro.org>
Thanks,
Stephan
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] remoteproc: qcom: pas: Don't fail attach if the remote has crashed
2026-10-06 3:35 ` [PATCH 2/2] remoteproc: qcom: pas: Don't fail attach if the remote has crashed Shawn Guo
@ 2026-10-09 14:38 ` Stephan Gerhold
0 siblings, 0 replies; 5+ messages in thread
From: Stephan Gerhold @ 2026-10-09 14:38 UTC (permalink / raw)
To: Shawn Guo
Cc: Bjorn Andersson, Mathieu Poirier, Konrad Dybcio, Jingyi Wang,
Bartosz Golaszewski, linux-arm-msm, linux-remoteproc,
linux-kernel
On Tue, Oct 06, 2026 at 11:35:50AM +0800, Shawn Guo wrote:
> When qcom_pas_attach() finds the fatal SMP2P bit already set, it reports
> a crash and then fails the attach. The core unwinds the attach while the
> crash work is queued: rproc_boot() drops the power refcount back to 0,
> and __rproc_attach()/rproc_attach() unprepare the subdevices, clean up
> the resource table and disable the IOMMU. Once rproc_boot() releases
> rproc->lock, the crash handler finds the rproc still RPROC_DETACHED,
> marks it RPROC_CRASHED and runs rproc_boot_recovery() on top of that
> torn-down state:
>
> - the subdevices are unprepared a second time by rproc_stop(), so SSR
> and sysmon notifiers see a duplicate shutdown;
> - qcom_pas_stop() and the subsequent rproc_start() operate on resources
> that rproc_attach() already released, e.g. iommu_unmap() on a
> disabled domain for rproc->has_iommu;
> - recovery leaves the rproc RPROC_RUNNING with power == 0. A later
> "stop" via sysfs takes power to -1 and returns success without
> stopping anything, so the remote stays running. A following "start"
> then boots the firmware again on the running remote and fails to
> re-add the still registered subdevices:
>
> sysfs: cannot create duplicate filename '.../qcom_common.pd-mapper.0'
> remoteproc remoteproc0: failed to prepare subdevices for adsp: -17
> remoteproc remoteproc0: Boot failed: -17
>
> A crash found at attach time is no different from one reported by the
> fatal interrupt right after attaching. Treat it the same way as
> q6v5_fatal_interrupt() does: clear q6v5.running, report the crash and
> let the attach succeed. The core completes the attach with balanced
> bookkeeping, and the crash handler then recovers the subsystem through
> the regular RPROC_ATTACHED -> RPROC_CRASHED path. With running cleared,
> qcom_q6v5_request_stop() does not wait for a stop ack the dead remote
> cannot send, and handover_issued already prevents a spurious handover
> on stop.
>
Hmmmm okay, I have never thought of this option, but reusing the
existing crash path as-is by making the attach succeed feels actually
quite clever! I suppose starting all the subdevs is really redundant in
this case, but the crash case is also nothing worth optimizing for.
> Assisted-by: LLM
> Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
> ---
> drivers/remoteproc/qcom_q6v5_pas.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index 8f3d45c604c9..0ecd7688a54d 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -562,10 +562,14 @@ static int qcom_pas_attach(struct rproc *rproc)
> goto disable_running;
>
> if (crash_state) {
> + /*
> + * Complete the attach and let the crash handler recover the
> + * subsystem from the attached state, as for a crash reported
> + * by the fatal interrupt.
> + */
> dev_err(pas->dev, "Subsystem has crashed before driver probe\n");
> + pas->q6v5.running = false;
> rproc_report_crash(rproc, RPROC_FATAL_ERROR);
> - ret = -EINVAL;
> - goto disable_running;
> }
My only nitpick is that it would be nice to fully reuse the normal crash
handling in this case, in particular the crash_reason logging inside
q6v5_fatal_interrupt(). Can you extract that part into a common function
and call it from here?
(I guess you could also call the existing q6v5_fatal_interrupt()
function since it should work as-is, but externally calling an interrupt
handler might be a bit weird...)
Thanks,
Stephan
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-09 14:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-06 3:35 [PATCH 0/2] remoteproc: qcom: pas: Fix early_boot attach for not running and crashed remotes Shawn Guo
2026-10-06 3:35 ` [PATCH 1/2] remoteproc: qcom: pas: Decide early_boot attach at probe time Shawn Guo
2026-10-09 14:20 ` Stephan Gerhold
2026-10-06 3:35 ` [PATCH 2/2] remoteproc: qcom: pas: Don't fail attach if the remote has crashed Shawn Guo
2026-10-09 14:38 ` Stephan Gerhold
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®