Re: [PATCH v2 2/2] remoteproc: qcom: pas: Don't fail attach if the remote has crashed
From: Stephan Gerhold
Date: Mon Oct 12 2026 - 04:51:37 EST
On Sun, Oct 11, 2026 at 10:28:02AM +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. Factor the crash handling out of
> q6v5_fatal_interrupt() into qcom_q6v5_report_fatal(), which logs the
> SMEM crash reason, clears q6v5.running and reports the crash, and call
> it from qcom_pas_attach() before letting 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
Cc: stable@xxxxxxxxxxxxxxx
Fixes: 16472c99f469 ("remoteproc: qcom: pas: Add late attach support for subsystems")
Reviewed-by: Stephan Gerhold <stephan.gerhold@xxxxxxxxxx>
Thanks for the fixes!
Stephan
> Signed-off-by: Shawn Guo <shengchao.guo@xxxxxxxxxxxxxxxx>
> ---
> drivers/remoteproc/qcom_q6v5.c | 22 +++++++++++++++++-----
> drivers/remoteproc/qcom_q6v5.h | 1 +
> drivers/remoteproc/qcom_q6v5_pas.c | 9 ++++++---
> 3 files changed, 24 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c
> index fe148b4b3775..51b24cbd4336 100644
> --- a/drivers/remoteproc/qcom_q6v5.c
> +++ b/drivers/remoteproc/qcom_q6v5.c
> @@ -147,15 +147,18 @@ static irqreturn_t q6v5_wdog_interrupt(int irq, void *data)
> return IRQ_HANDLED;
> }
>
> -static irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
> +/**
> + * qcom_q6v5_report_fatal() - report a fatal error of the remote processor
> + * @q6v5: reference to qcom_q6v5 context
> + *
> + * Log the crash reason published by the remote in SMEM, mark the remote as
> + * no longer running and report the crash to the remoteproc core.
> + */
> +void qcom_q6v5_report_fatal(struct qcom_q6v5 *q6v5)
> {
> - struct qcom_q6v5 *q6v5 = data;
> size_t len;
> char *msg;
>
> - if (!q6v5->running)
> - return IRQ_HANDLED;
> -
> msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, q6v5->crash_reason, &len);
> if (!IS_ERR(msg) && len > 0 && msg[0])
> dev_err(q6v5->dev, "fatal error received: %s\n", msg);
> @@ -164,6 +167,15 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
>
> q6v5->running = false;
> rproc_report_crash(q6v5->rproc, RPROC_FATAL_ERROR);
> +}
> +EXPORT_SYMBOL_GPL(qcom_q6v5_report_fatal);
> +
> +static irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
> +{
> + struct qcom_q6v5 *q6v5 = data;
> +
> + if (q6v5->running)
> + qcom_q6v5_report_fatal(q6v5);
>
> return IRQ_HANDLED;
> }
> diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h
> index 8991ff090579..a0507860a21c 100644
> --- a/drivers/remoteproc/qcom_q6v5.h
> +++ b/drivers/remoteproc/qcom_q6v5.h
> @@ -56,5 +56,6 @@ int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5);
> int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon);
> int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout);
> unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5);
> +void qcom_q6v5_report_fatal(struct qcom_q6v5 *q6v5);
>
> #endif
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index 56179b71fd2a..99f627db6bd3 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -562,10 +562,13 @@ 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");
> - rproc_report_crash(rproc, RPROC_FATAL_ERROR);
> - ret = -EINVAL;
> - goto disable_running;
> + qcom_q6v5_report_fatal(&pas->q6v5);
> }
>
> return 0;
> --
> 2.43.0
>