Skip to content

Commit 9dc9507

Browse files
mathieupoirierandersson
authored andcommitted
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: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> Link: https://lore.kernel.org/r/20210312162453.1234145-12-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
1 parent d3962a3 commit 9dc9507

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

drivers/remoteproc/remoteproc_core.c

+81
Original file line numberDiff line numberDiff line change
@@ -1562,13 +1562,84 @@ static int rproc_set_rsc_table(struct rproc *rproc)
15621562
return ret;
15631563
}
15641564

1565+
/*
1566+
* If it is possible to detach the remote processor, keep an untouched
1567+
* copy of the resource table. That way we can start fresh again when
1568+
* the remote processor is re-attached, that is:
1569+
*
1570+
* DETACHED -> ATTACHED -> DETACHED -> ATTACHED
1571+
*
1572+
* Free'd in rproc_reset_rsc_table_on_detach() and
1573+
* rproc_reset_rsc_table_on_stop().
1574+
*/
1575+
if (rproc->ops->detach) {
1576+
rproc->clean_table = kmemdup(table_ptr, table_sz, GFP_KERNEL);
1577+
if (!rproc->clean_table)
1578+
return -ENOMEM;
1579+
} else {
1580+
rproc->clean_table = NULL;
1581+
}
1582+
15651583
rproc->cached_table = NULL;
15661584
rproc->table_ptr = table_ptr;
15671585
rproc->table_sz = table_sz;
15681586

15691587
return 0;
15701588
}
15711589

1590+
static int rproc_reset_rsc_table_on_detach(struct rproc *rproc)
1591+
{
1592+
struct resource_table *table_ptr;
1593+
1594+
/* A resource table was never retrieved, nothing to do here */
1595+
if (!rproc->table_ptr)
1596+
return 0;
1597+
1598+
/*
1599+
* If we made it to this point a clean_table _must_ have been
1600+
* allocated in rproc_set_rsc_table(). If one isn't present
1601+
* something went really wrong and we must complain.
1602+
*/
1603+
if (WARN_ON(!rproc->clean_table))
1604+
return -EINVAL;
1605+
1606+
/* Remember where the external entity installed the resource table */
1607+
table_ptr = rproc->table_ptr;
1608+
1609+
/*
1610+
* If we made it here the remote processor was started by another
1611+
* entity and a cache table doesn't exist. As such make a copy of
1612+
* the resource table currently used by the remote processor and
1613+
* use that for the rest of the shutdown process. The memory
1614+
* allocated here is free'd in rproc_detach().
1615+
*/
1616+
rproc->cached_table = kmemdup(rproc->table_ptr,
1617+
rproc->table_sz, GFP_KERNEL);
1618+
if (!rproc->cached_table)
1619+
return -ENOMEM;
1620+
1621+
/*
1622+
* Use a copy of the resource table for the remainder of the
1623+
* shutdown process.
1624+
*/
1625+
rproc->table_ptr = rproc->cached_table;
1626+
1627+
/*
1628+
* Reset the memory area where the firmware loaded the resource table
1629+
* to its original value. That way when we re-attach the remote
1630+
* processor the resource table is clean and ready to be used again.
1631+
*/
1632+
memcpy(table_ptr, rproc->clean_table, rproc->table_sz);
1633+
1634+
/*
1635+
* The clean resource table is no longer needed. Allocated in
1636+
* rproc_set_rsc_table().
1637+
*/
1638+
kfree(rproc->clean_table);
1639+
1640+
return 0;
1641+
}
1642+
15721643
/*
15731644
* Attach to remote processor - similar to rproc_fw_boot() but without
15741645
* the steps that deal with the firmware image.
@@ -1727,6 +1798,13 @@ static int __rproc_detach(struct rproc *rproc)
17271798
/* Stop any subdevices for the remote processor */
17281799
rproc_stop_subdevices(rproc, false);
17291800

1801+
/* the installed resource table is no longer accessible */
1802+
ret = rproc_reset_rsc_table_on_detach(rproc);
1803+
if (ret) {
1804+
dev_err(dev, "can't reset resource table: %d\n", ret);
1805+
return ret;
1806+
}
1807+
17301808
/* Tell the remote processor the core isn't available anymore */
17311809
ret = rproc->ops->detach(rproc);
17321810
if (ret) {
@@ -2003,6 +2081,9 @@ int rproc_detach(struct rproc *rproc)
20032081

20042082
rproc_disable_iommu(rproc);
20052083

2084+
/* Free the copy of the resource table */
2085+
kfree(rproc->cached_table);
2086+
rproc->cached_table = NULL;
20062087
rproc->table_ptr = NULL;
20072088
out:
20082089
mutex_unlock(&rproc->lock);

include/linux/remoteproc.h

+3
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,8 @@ struct rproc_dump_segment {
516516
* @recovery_disabled: flag that state if recovery was disabled
517517
* @max_notifyid: largest allocated notify id.
518518
* @table_ptr: pointer to the resource table in effect
519+
* @clean_table: copy of the resource table without modifications. Used
520+
* when a remote processor is attached or detached from the core
519521
* @cached_table: copy of the resource table
520522
* @table_sz: size of @cached_table
521523
* @has_iommu: flag to indicate if remote processor is behind an MMU
@@ -552,6 +554,7 @@ struct rproc {
552554
bool recovery_disabled;
553555
int max_notifyid;
554556
struct resource_table *table_ptr;
557+
struct resource_table *clean_table;
555558
struct resource_table *cached_table;
556559
size_t table_sz;
557560
bool has_iommu;

0 commit comments

Comments
 (0)