From: Mathieu Poirier <mathieu.poirier@linaro.org>
To: Yonghao Zhang <hyz3367@gmail.com>, arnaud.pouliquen@foss.st.com
Cc: andersson@kernel.org, linux-remoteproc@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 3/4] remoteproc: core: Roll a failed attach back with detach() when available
Date: Mon, 19 Oct 2026 11:14:58 -0600 [thread overview]
Message-ID: <atZQEuXMwMpvmoBz@p14s> (raw)
In-Reply-To: <20260929075453.2324597-4-hyz3367@gmail.com>
@Arnaud Pouliquen - please review this patch to make sure it doesn't break
STM32.
On Tue, Sep 29, 2026 at 03:54:52PM +0800, Yonghao Zhang wrote:
> When the subdevice registration that follows ops->attach() fails,
> __rproc_attach() rolls back with an unconditional ops->stop() call.
> That is wrong on three counts.
>
It isn't wrong, simply implemented during a time where any kind of fault in the
attach()/detach() scenario called for a stop(). I would certainly appreciate a
less reproachful tone.
> An attach-only implementation, one without stop() such as
> commit 1168af40b1ad ("remoteproc: k3-r5: Add support for IPC-only
> mode for all R5Fs"), dereferences NULL right there. A processor that
> is being attached to was started by another entity and is not ours to
> power off: detach() is the matching undo of attach(), and stop()
> should only be used as a last resort, when there is no detach() or
> it fails. This is reachable today: when the re-attach of an
> RPROC_FEAT_ATTACH_ON_RECOVERY processor fails (imx_rproc and
> xlnx_r5 use the feature), the unwind stops a processor which,
> per the feature's own contract, "does not need help from Linux to
> recover... Linux just needs to attach". And the unwind leaves
> the accounting inconsistent -- no resource table bookkeeping
> is done, unlike on the rproc_stop() and __rproc_detach() paths,
> and a processor powered off through the fallback keeps its
> RPROC_DETACHED state, so the next rproc_boot() tries to attach to a
> core that is no longer running.
>
Remove the above paragraph.
> Roll the attach back with detach() first, along with the same
> rproc_reset_rsc_table_on_detach() bookkeeping __rproc_detach() does,
> and fall back to stop() only when detach() is unavailable or failed.
> A failed resource table reset does not abort the unwind: this is an
> error path, and detaching from the remote processor, or powering it
> off as the last resort, takes precedence over the bookkeeping. A
> successful fallback moves the processor to RPROC_OFFLINE so the next
> boot reloads firmware instead of attaching to a dead core;
> implementations with neither handler keep the processor running and
> untouched, which is all an attach-only core needs. The rollback is
> factored into rproc_unwind_attach().
>
> The unwind runs the same resource table resets as the detach and
> stop paths, which free clean_table and leave a cached copy of the
> installed table in rproc->cached_table. Make rproc_attach()'s error
> cleanup, which runs right after, null clean_table after freeing it
> and release that copy along with table_ptr, or a failed attach
> double-frees clean_table and leaks the copy.
>
> Fixes: d848a4819d85 ("remoteproc: Introducing function rproc_attach()")
> Signed-off-by: Yonghao Zhang <hyz3367@gmail.com>
> ---
> drivers/remoteproc/remoteproc_core.c | 65 ++++++++++++++++++++++++++--
> 1 file changed, 62 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 19e0ea3e7240..c52212a1d180 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -1348,6 +1348,59 @@ static int rproc_start(struct rproc *rproc, const struct firmware *fw)
> return ret;
> }
>
> +static int rproc_reset_rsc_table_on_detach(struct rproc *rproc);
> +static int rproc_reset_rsc_table_on_stop(struct rproc *rproc);
> +
> +/*
> + * Undo an attach whose subdevice registration failed. The remote
> + * processor was started by another entity and is not ours to power
> + * off, so roll back with detach() when available and fall back to
> + * stop() when there is no detach() or when it failed. stop() is
> + * the only rollback that does not rely on the remote side. A
> + * processor powered off through the fallback is marked RPROC_OFFLINE,
> + * so the next boot reloads firmware instead of attaching to a dead
> + * core; with neither handler there is nothing to roll back with and
> + * the processor is left running.
> + *
> + * The resource table resets are best-effort: when one fails, the
> + * unwind carries on with detach()/stop() anyway. Unlike
> + * __rproc_detach() and rproc_stop(), which bail out before touching
> + * the processor when their reset fails, this is already an error
> + * path, and detaching the remote processor -- or, failing that,
> + * powering it off -- is the minimum it must still deliver.
> + */
> +static void rproc_unwind_attach(struct rproc *rproc)
> +{
> + struct device *dev = &rproc->dev;
> + int ret;
> +
> + if (rproc->ops->detach) {
> + ret = rproc_reset_rsc_table_on_detach(rproc);
> + if (ret)
> + dev_err(dev, "can't reset rsc table on detach: %d\n",
> + ret);
> +
> + ret = rproc->ops->detach(rproc);
> + if (!ret)
> + return;
> +
> + dev_err(dev, "can't detach from rproc %s: %d\n",
> + rproc->name, ret);
> + }
> +
> + if (rproc->ops->stop) {
> + ret = rproc_reset_rsc_table_on_stop(rproc);
> + if (ret)
> + dev_err(dev, "can't reset rsc table on stop: %d\n",
> + ret);
> +
> + if (rproc->ops->stop(rproc))
> + dev_err(dev, "can't stop rproc %s\n", rproc->name);
> + else
> + rproc->state = RPROC_OFFLINE;
> + }
> +}
Please remove all the dev_err() above. An error messages are already generate
in __rproc_attach() when something goes wrong.
> +
> static int __rproc_attach(struct rproc *rproc)
> {
> struct device *dev = &rproc->dev;
> @@ -1373,7 +1426,7 @@ static int __rproc_attach(struct rproc *rproc)
> if (ret) {
> dev_err(dev, "failed to probe subdevices for %s: %d\n",
> rproc->name, ret);
> - goto stop_rproc;
> + goto unwind_attach;
> }
>
> rproc->state = RPROC_ATTACHED;
> @@ -1382,8 +1435,8 @@ static int __rproc_attach(struct rproc *rproc)
>
> return 0;
>
> -stop_rproc:
> - rproc->ops->stop(rproc);
> +unwind_attach:
> + rproc_unwind_attach(rproc);
> unprepare_subdevices:
> rproc_unprepare_subdevices(rproc);
> out:
> @@ -1562,6 +1615,7 @@ static int rproc_reset_rsc_table_on_detach(struct rproc *rproc)
> * rproc_set_rsc_table().
> */
> kfree(rproc->clean_table);
> + rproc->clean_table = NULL;
This change is not needed.
>
> return 0;
> }
> @@ -1597,6 +1651,7 @@ static int rproc_reset_rsc_table_on_stop(struct rproc *rproc)
> * won't be needed. Allocated in rproc_set_rsc_table().
> */
> kfree(rproc->clean_table);
> + rproc->clean_table = NULL;
This change is not needed.
>
> out:
> /*
> @@ -1675,6 +1730,10 @@ static int rproc_attach(struct rproc *rproc)
> /* release HW resources if needed */
> rproc_unprepare_device(rproc);
> kfree(rproc->clean_table);
> + rproc->clean_table = NULL;
> + kfree(rproc->cached_table);
> + rproc->cached_table = NULL;
> + rproc->table_ptr = NULL;
->table_ptr doesn't need to be set to NULL.
Thanks,
Mathieu
> disable_iommu:
> rproc_disable_iommu(rproc);
> return ret;
> --
> 2.34.1
>
next prev parent reply other threads:[~2026-10-19 17:15 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 7:54 [PATCH 0/4] remoteproc: core: Fix the error unwind paths Yonghao Zhang
2026-09-29 7:54 ` [PATCH 1/4] remoteproc: core: Reset freed vring entries to FW_RSC_ADDR_ANY Yonghao Zhang
2026-10-16 15:34 ` Mathieu Poirier
2026-09-29 7:54 ` [PATCH 2/4] remoteproc: core: Guard against a missing stop() in rproc_start() Yonghao Zhang
2026-10-16 15:55 ` Mathieu Poirier
2026-09-29 7:54 ` [PATCH 3/4] remoteproc: core: Roll a failed attach back with detach() when available Yonghao Zhang
2026-10-19 17:14 ` Mathieu Poirier [this message]
2026-09-29 7:54 ` [PATCH 4/4] remoteproc: core: Clean up after a failed recovery Yonghao Zhang
2026-10-13 14:09 ` [PATCH 0/4] remoteproc: core: Fix the error unwind paths Yonghao Zhang
2026-10-13 15:18 ` Mathieu Poirier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=atZQEuXMwMpvmoBz@p14s \
--to=mathieu.poirier@linaro.org \
--cc=andersson@kernel.org \
--cc=arnaud.pouliquen@foss.st.com \
--cc=hyz3367@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-remoteproc@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.