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: [email protected] Fixes: 16472c99f469 ("remoteproc: qcom: pas: Add late attach support for subsystems") Reviewed-by: Stephan Gerhold <[email protected]> Thanks for the fixes! Stephan > Signed-off-by: Shawn Guo <[email protected]> > --- > 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 >

