Commit 9dc9507f authored by Mathieu Poirier's avatar Mathieu Poirier Committed by Bjorn Andersson

remoteproc: Properly deal with the resource table when detaching

If it is possible to detach the remote processor, keep an untouched
copy of the resource table.  That way we can start from the same
resource table without having to worry about original values or what
elements the startup code has changed when re-attaching to the remote
processor.
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: default avatarArnaud Pouliquen <arnaud.pouliquen@st.com>
Link: https://lore.kernel.org/r/20210312162453.1234145-12-mathieu.poirier@linaro.orgSigned-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent d3962a39
......@@ -1562,6 +1562,24 @@ static int rproc_set_rsc_table(struct rproc *rproc)
return ret;
}
/*
* If it is possible to detach the remote processor, keep an untouched
* copy of the resource table. That way we can start fresh again when
* the remote processor is re-attached, that is:
*
* DETACHED -> ATTACHED -> DETACHED -> ATTACHED
*
* Free'd in rproc_reset_rsc_table_on_detach() and
* rproc_reset_rsc_table_on_stop().
*/
if (rproc->ops->detach) {
rproc->clean_table = kmemdup(table_ptr, table_sz, GFP_KERNEL);
if (!rproc->clean_table)
return -ENOMEM;
} else {
rproc->clean_table = NULL;
}
rproc->cached_table = NULL;
rproc->table_ptr = table_ptr;
rproc->table_sz = table_sz;
......@@ -1569,6 +1587,59 @@ static int rproc_set_rsc_table(struct rproc *rproc)
return 0;
}
static int rproc_reset_rsc_table_on_detach(struct rproc *rproc)
{
struct resource_table *table_ptr;
/* A resource table was never retrieved, nothing to do here */
if (!rproc->table_ptr)
return 0;
/*
* If we made it to this point a clean_table _must_ have been
* allocated in rproc_set_rsc_table(). If one isn't present
* something went really wrong and we must complain.
*/
if (WARN_ON(!rproc->clean_table))
return -EINVAL;
/* Remember where the external entity installed the resource table */
table_ptr = rproc->table_ptr;
/*
* If we made it here the remote processor was started by another
* entity and a cache table doesn't exist. As such make a copy of
* the resource table currently used by the remote processor and
* use that for the rest of the shutdown process. The memory
* allocated here is free'd in rproc_detach().
*/
rproc->cached_table = kmemdup(rproc->table_ptr,
rproc->table_sz, GFP_KERNEL);
if (!rproc->cached_table)
return -ENOMEM;
/*
* Use a copy of the resource table for the remainder of the
* shutdown process.
*/
rproc->table_ptr = rproc->cached_table;
/*
* Reset the memory area where the firmware loaded the resource table
* to its original value. That way when we re-attach the remote
* processor the resource table is clean and ready to be used again.
*/
memcpy(table_ptr, rproc->clean_table, rproc->table_sz);
/*
* The clean resource table is no longer needed. Allocated in
* rproc_set_rsc_table().
*/
kfree(rproc->clean_table);
return 0;
}
/*
* Attach to remote processor - similar to rproc_fw_boot() but without
* the steps that deal with the firmware image.
......@@ -1727,6 +1798,13 @@ static int __rproc_detach(struct rproc *rproc)
/* Stop any subdevices for the remote processor */
rproc_stop_subdevices(rproc, false);
/* the installed resource table is no longer accessible */
ret = rproc_reset_rsc_table_on_detach(rproc);
if (ret) {
dev_err(dev, "can't reset resource table: %d\n", ret);
return ret;
}
/* Tell the remote processor the core isn't available anymore */
ret = rproc->ops->detach(rproc);
if (ret) {
......@@ -2003,6 +2081,9 @@ int rproc_detach(struct rproc *rproc)
rproc_disable_iommu(rproc);
/* Free the copy of the resource table */
kfree(rproc->cached_table);
rproc->cached_table = NULL;
rproc->table_ptr = NULL;
out:
mutex_unlock(&rproc->lock);
......
......@@ -516,6 +516,8 @@ struct rproc_dump_segment {
* @recovery_disabled: flag that state if recovery was disabled
* @max_notifyid: largest allocated notify id.
* @table_ptr: pointer to the resource table in effect
* @clean_table: copy of the resource table without modifications. Used
* when a remote processor is attached or detached from the core
* @cached_table: copy of the resource table
* @table_sz: size of @cached_table
* @has_iommu: flag to indicate if remote processor is behind an MMU
......@@ -552,6 +554,7 @@ struct rproc {
bool recovery_disabled;
int max_notifyid;
struct resource_table *table_ptr;
struct resource_table *clean_table;
struct resource_table *cached_table;
size_t table_sz;
bool has_iommu;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment