drivers/firmware/arm_scmi/reset.c | 59 ++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 20 deletions(-)
Improve the SCMI reset protocol implementation by centralizing domain
validation and enhancing error handling.
Add scmi_reset_domain_lookup() helper function to validate
domain ids and return appropriate error codes. Refactor all
domain-specific functions to use this helper, ensuring consistent
error handling throughout the reset protocol.
Suggested-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
---
Hi Cristian,
Thank you for suggesting! If it works for you I'll try to improve the others protocols.
It was tested on my board in QEMU and on real hardware.
The functionality didn't break, and peripherals that are reseted via SCMI work correctly.
As an example, I can provide DMA test results (as one of the processor units dependent on SCMI reset).
[ 2.559040] dw_axi_dmac_platform 1000nda0.nda_dma_0: DesignWare AXI DMA Controller, nda channels
[ 2.569265] dw_axi_dmac_platform 1000nda0.nda_dma_1: DesignWare AXI DMA Controller, nda channels
[ 2.580601] dw_axi_dmac_platform 1000nda0.nda_dma_2: DesignWare AXI DMA Controller, nda channels
# echo 2000 > /sys/module/dmatest/parameters/timeout
# echo 1000 > /sys/module/dmatest/parameters/iterations
# echo dma0chan0 > /sys/module/dmatest/parameters/channel
[ 95.917504] dmatest: Added 1 threads using dma0chan0
# echo 1 > /sys/module/dmatest/parameters/run
[ 101.931372] dmatest: Started 1 threads using dma0chan0
[ 102.731009] dmatest: dma0chan0-copy0: summary 1000 tests, 0 failures 2508.42 iops 19706 KB/s (0)
And vice versa:
1. Confirmed that the DMA module is non-functional without a proper reset via SCMI.
Disabling the reset logic causes a system crash on first access to its registers.
2. Requesting a non-existent reset domain:
[ 2.463400] dw_axi_dmac_platform 1000nda0.nda_dma_0: error -EINVAL: Failed to deassert resets
[ 2.472091] dw_axi_dmac_platform 1000nda0.nda_dma_0: probe with driver dw_axi_dmac_platform failed with error -22
[ 2.482911] dw_axi_dmac_platform 1000nda0.nda_dma_1: error -EINVAL: Failed to deassert resets
[ 2.491553] dw_axi_dmac_platform 1000nda0.nda_dma_1: probe with driver dw_axi_dmac_platform failed with error -22
[ 2.502256] dw_axi_dmac_platform 1000nda0.nda_dma_2: error -EINVAL: Failed to deassert resets
[ 2.510735] dw_axi_dmac_platform 1000nda0.nda_dma_2: probe with driver dw_axi_dmac_platform failed with error -22
--
Regards,
Artem
---
ChangeLog:
v4: Add Suggested-by tag
drivers/firmware/arm_scmi/reset.c | 59 ++++++++++++++++++++-----------
1 file changed, 39 insertions(+), 20 deletions(-)
diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
index 0aa82b96f41b..9854a3016d13 100644
--- a/drivers/firmware/arm_scmi/reset.c
+++ b/drivers/firmware/arm_scmi/reset.c
@@ -100,6 +100,7 @@ static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
static int
scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
+ struct reset_dom_info *dom_info,
struct scmi_reset_info *pinfo,
u32 domain, u32 version)
{
@@ -107,7 +108,6 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
u32 attributes;
struct scmi_xfer *t;
struct scmi_msg_resp_reset_domain_attributes *attr;
- struct reset_dom_info *dom_info = pinfo->dom_info + domain;
ret = ph->xops->xfer_get_init(ph, RESET_DOMAIN_ATTRIBUTES,
sizeof(domain), sizeof(*attr), &t);
@@ -153,23 +153,39 @@ static int scmi_reset_num_domains_get(const struct scmi_protocol_handle *ph)
return pi->num_domains;
}
+static inline struct reset_dom_info *
+scmi_reset_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain)
+{
+ struct scmi_reset_info *pi = ph->get_priv(ph);
+
+ if (domain >= pi->num_domains)
+ return ERR_PTR(-EINVAL);
+
+ return pi->dom_info + domain;
+}
+
static const char *
scmi_reset_name_get(const struct scmi_protocol_handle *ph, u32 domain)
{
- struct scmi_reset_info *pi = ph->get_priv(ph);
+ struct reset_dom_info *dom_info;
- struct reset_dom_info *dom = pi->dom_info + domain;
+ dom_info = scmi_reset_domain_lookup(ph, domain);
+ if (IS_ERR(dom_info))
+ return "unknown";
- return dom->name;
+ return dom_info->name;
}
static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph,
u32 domain)
{
- struct scmi_reset_info *pi = ph->get_priv(ph);
- struct reset_dom_info *dom = pi->dom_info + domain;
+ struct reset_dom_info *dom_info;
- return dom->latency_us;
+ dom_info = scmi_reset_domain_lookup(ph, domain);
+ if (IS_ERR(dom_info))
+ return PTR_ERR(dom_info);
+
+ return dom_info->latency_us;
}
static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
@@ -178,14 +194,13 @@ static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
int ret;
struct scmi_xfer *t;
struct scmi_msg_reset_domain_reset *dom;
- struct scmi_reset_info *pi = ph->get_priv(ph);
- struct reset_dom_info *rdom;
+ struct reset_dom_info *dom_info;
- if (domain >= pi->num_domains)
- return -EINVAL;
+ dom_info = scmi_reset_domain_lookup(ph, domain);
+ if (IS_ERR(dom_info))
+ return PTR_ERR(dom_info);
- rdom = pi->dom_info + domain;
- if (rdom->async_reset && flags & AUTONOMOUS_RESET)
+ if (dom_info->async_reset && flags & AUTONOMOUS_RESET)
flags |= ASYNCHRONOUS_RESET;
ret = ph->xops->xfer_get_init(ph, RESET, sizeof(*dom), 0, &t);
@@ -238,15 +253,16 @@ static const struct scmi_reset_proto_ops reset_proto_ops = {
static bool scmi_reset_notify_supported(const struct scmi_protocol_handle *ph,
u8 evt_id, u32 src_id)
{
- struct reset_dom_info *dom;
- struct scmi_reset_info *pi = ph->get_priv(ph);
+ struct reset_dom_info *dom_info;
- if (evt_id != SCMI_EVENT_RESET_ISSUED || src_id >= pi->num_domains)
+ if (evt_id != SCMI_EVENT_RESET_ISSUED)
return false;
- dom = pi->dom_info + src_id;
+ dom_info = scmi_reset_domain_lookup(ph, src_id);
+ if (IS_ERR(dom_info))
+ return false;
- return dom->reset_notify;
+ return dom_info->reset_notify;
}
static int scmi_reset_notify(const struct scmi_protocol_handle *ph,
@@ -363,8 +379,11 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
if (!pinfo->dom_info)
return -ENOMEM;
- for (domain = 0; domain < pinfo->num_domains; domain++)
- scmi_reset_domain_attributes_get(ph, pinfo, domain, version);
+ for (domain = 0; domain < pinfo->num_domains; domain++) {
+ struct reset_dom_info *dom_info = pinfo->dom_info + domain;
+
+ scmi_reset_domain_attributes_get(ph, dom_info, pinfo, domain, version);
+ }
pinfo->version = version;
return ph->set_priv(ph, pinfo, version);
--
2.43.0
On Sun, 23 Nov 2025 19:35:57 +0300, Artem Shimko wrote:
> Improve the SCMI reset protocol implementation by centralizing domain
> validation and enhancing error handling.
>
> Add scmi_reset_domain_lookup() helper function to validate
> domain ids and return appropriate error codes. Refactor all
> domain-specific functions to use this helper, ensuring consistent
> error handling throughout the reset protocol.
>
> [...]
Applied to sudeep.holla/linux (for-next/scmi/updates), thanks!
[1/1] firmware: arm_scmi: refactor reset domain handling
https://git.kernel.org/sudeep.holla/c/f6753869a25e
--
Regards,
Sudeep
On Sun, Nov 23, 2025 at 07:35:57PM +0300, Artem Shimko wrote:
> Improve the SCMI reset protocol implementation by centralizing domain
> validation and enhancing error handling.
>
> Add scmi_reset_domain_lookup() helper function to validate
> domain ids and return appropriate error codes. Refactor all
> domain-specific functions to use this helper, ensuring consistent
> error handling throughout the reset protocol.
>
> Suggested-by: Cristian Marussi <cristian.marussi@arm.com>
> Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
> ---
>
> Hi Cristian,
>
> Thank you for suggesting! If it works for you I'll try to improve the others protocols.
>
> It was tested on my board in QEMU and on real hardware.
> The functionality didn't break, and peripherals that are reseted via SCMI work correctly.
>
> As an example, I can provide DMA test results (as one of the processor units dependent on SCMI reset).
>
> [ 2.559040] dw_axi_dmac_platform 1000nda0.nda_dma_0: DesignWare AXI DMA Controller, nda channels
> [ 2.569265] dw_axi_dmac_platform 1000nda0.nda_dma_1: DesignWare AXI DMA Controller, nda channels
> [ 2.580601] dw_axi_dmac_platform 1000nda0.nda_dma_2: DesignWare AXI DMA Controller, nda channels
>
> # echo 2000 > /sys/module/dmatest/parameters/timeout
> # echo 1000 > /sys/module/dmatest/parameters/iterations
> # echo dma0chan0 > /sys/module/dmatest/parameters/channel
> [ 95.917504] dmatest: Added 1 threads using dma0chan0
> # echo 1 > /sys/module/dmatest/parameters/run
> [ 101.931372] dmatest: Started 1 threads using dma0chan0
> [ 102.731009] dmatest: dma0chan0-copy0: summary 1000 tests, 0 failures 2508.42 iops 19706 KB/s (0)
>
> And vice versa:
>
> 1. Confirmed that the DMA module is non-functional without a proper reset via SCMI.
> Disabling the reset logic causes a system crash on first access to its registers.
>
> 2. Requesting a non-existent reset domain:
>
> [ 2.463400] dw_axi_dmac_platform 1000nda0.nda_dma_0: error -EINVAL: Failed to deassert resets
> [ 2.472091] dw_axi_dmac_platform 1000nda0.nda_dma_0: probe with driver dw_axi_dmac_platform failed with error -22
> [ 2.482911] dw_axi_dmac_platform 1000nda0.nda_dma_1: error -EINVAL: Failed to deassert resets
> [ 2.491553] dw_axi_dmac_platform 1000nda0.nda_dma_1: probe with driver dw_axi_dmac_platform failed with error -22
> [ 2.502256] dw_axi_dmac_platform 1000nda0.nda_dma_2: error -EINVAL: Failed to deassert resets
> [ 2.510735] dw_axi_dmac_platform 1000nda0.nda_dma_2: probe with driver dw_axi_dmac_platform failed with error -22
>
> --
> Regards,
> Artem
>
> ---
> ChangeLog:
> v4: Add Suggested-by tag
>
> drivers/firmware/arm_scmi/reset.c | 59 ++++++++++++++++++++-----------
> 1 file changed, 39 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
> index 0aa82b96f41b..9854a3016d13 100644
> --- a/drivers/firmware/arm_scmi/reset.c
> +++ b/drivers/firmware/arm_scmi/reset.c
> @@ -100,6 +100,7 @@ static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
>
> static int
> scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
> + struct reset_dom_info *dom_info,
Instead of changing this, ...
> struct scmi_reset_info *pinfo,
> u32 domain, u32 version)
> {
> @@ -107,7 +108,6 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
> u32 attributes;
> struct scmi_xfer *t;
> struct scmi_msg_resp_reset_domain_attributes *attr;
> - struct reset_dom_info *dom_info = pinfo->dom_info + domain;
>
... You can just follow the pattern you have done everywhere else in this
change like:
struct reset_dom_info *dom_info;
dom_info = scmi_reset_domain_lookup(ph, domain);
if (IS_ERR(dom_info))
return PTR_ERR(dom_info);
Any particular reason for not doing that ?
--
Regards,
Sudeep
On Thu, Dec 4, 2025 at 7:26 PM Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Sun, Nov 23, 2025 at 07:35:57PM +0300, Artem Shimko wrote:
> > Improve the SCMI reset protocol implementation by centralizing domain
> > validation and enhancing error handling.
> >
> > Add scmi_reset_domain_lookup() helper function to validate
> > domain ids and return appropriate error codes. Refactor all
> > domain-specific functions to use this helper, ensuring consistent
> > error handling throughout the reset protocol.
> >
> > Suggested-by: Cristian Marussi <cristian.marussi@arm.com>
> > Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
> > ---
> >
> > Hi Cristian,
> >
> > Thank you for suggesting! If it works for you I'll try to improve the others protocols.
> >
> > It was tested on my board in QEMU and on real hardware.
> > The functionality didn't break, and peripherals that are reseted via SCMI work correctly.
> >
> > As an example, I can provide DMA test results (as one of the processor units dependent on SCMI reset).
> >
> > [ 2.559040] dw_axi_dmac_platform 1000nda0.nda_dma_0: DesignWare AXI DMA Controller, nda channels
> > [ 2.569265] dw_axi_dmac_platform 1000nda0.nda_dma_1: DesignWare AXI DMA Controller, nda channels
> > [ 2.580601] dw_axi_dmac_platform 1000nda0.nda_dma_2: DesignWare AXI DMA Controller, nda channels
> >
> > # echo 2000 > /sys/module/dmatest/parameters/timeout
> > # echo 1000 > /sys/module/dmatest/parameters/iterations
> > # echo dma0chan0 > /sys/module/dmatest/parameters/channel
> > [ 95.917504] dmatest: Added 1 threads using dma0chan0
> > # echo 1 > /sys/module/dmatest/parameters/run
> > [ 101.931372] dmatest: Started 1 threads using dma0chan0
> > [ 102.731009] dmatest: dma0chan0-copy0: summary 1000 tests, 0 failures 2508.42 iops 19706 KB/s (0)
> >
> > And vice versa:
> >
> > 1. Confirmed that the DMA module is non-functional without a proper reset via SCMI.
> > Disabling the reset logic causes a system crash on first access to its registers.
> >
> > 2. Requesting a non-existent reset domain:
> >
> > [ 2.463400] dw_axi_dmac_platform 1000nda0.nda_dma_0: error -EINVAL: Failed to deassert resets
> > [ 2.472091] dw_axi_dmac_platform 1000nda0.nda_dma_0: probe with driver dw_axi_dmac_platform failed with error -22
> > [ 2.482911] dw_axi_dmac_platform 1000nda0.nda_dma_1: error -EINVAL: Failed to deassert resets
> > [ 2.491553] dw_axi_dmac_platform 1000nda0.nda_dma_1: probe with driver dw_axi_dmac_platform failed with error -22
> > [ 2.502256] dw_axi_dmac_platform 1000nda0.nda_dma_2: error -EINVAL: Failed to deassert resets
> > [ 2.510735] dw_axi_dmac_platform 1000nda0.nda_dma_2: probe with driver dw_axi_dmac_platform failed with error -22
> >
> > --
> > Regards,
> > Artem
> >
> > ---
> > ChangeLog:
> > v4: Add Suggested-by tag
> >
> > drivers/firmware/arm_scmi/reset.c | 59 ++++++++++++++++++++-----------
> > 1 file changed, 39 insertions(+), 20 deletions(-)
> >
> > diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
> > index 0aa82b96f41b..9854a3016d13 100644
> > --- a/drivers/firmware/arm_scmi/reset.c
> > +++ b/drivers/firmware/arm_scmi/reset.c
> > @@ -100,6 +100,7 @@ static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
> >
> > static int
> > scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
> > + struct reset_dom_info *dom_info,
>
> Instead of changing this, ...
>
> > struct scmi_reset_info *pinfo,
> > u32 domain, u32 version)
> > {
> > @@ -107,7 +108,6 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
> > u32 attributes;
> > struct scmi_xfer *t;
> > struct scmi_msg_resp_reset_domain_attributes *attr;
> > - struct reset_dom_info *dom_info = pinfo->dom_info + domain;
> >
>
> ... You can just follow the pattern you have done everywhere else in this
> change like:
>
> struct reset_dom_info *dom_info;
>
> dom_info = scmi_reset_domain_lookup(ph, domain);
> if (IS_ERR(dom_info))
> return PTR_ERR(dom_info);
>
> Any particular reason for not doing that ?
Hi Sudeep,
Based on perf.c, I added this pattern only to functions that can be
called externally with an invalid domain value.
Therefore, I decided it would be better to change the signature of
scmi_reset_domain_attributes_get (similar to
scmi_perf_domain_attributes_get from pref.c)
to ensure consistency across drivers when working with domain numbers.
If you believe this pattern should be used in
scmi_reset_domain_attributes_get, I'll send you the next version of
the patch.
Thank you very much for reviewing my changes =)
Regards,
Artem
On Fri, Dec 05, 2025 at 01:36:23PM +0300, Artem Shimko wrote:
> On Thu, Dec 4, 2025 at 7:26 PM Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Sun, Nov 23, 2025 at 07:35:57PM +0300, Artem Shimko wrote:
> > > Improve the SCMI reset protocol implementation by centralizing domain
> > > validation and enhancing error handling.
> > >
> > > Add scmi_reset_domain_lookup() helper function to validate
> > > domain ids and return appropriate error codes. Refactor all
> > > domain-specific functions to use this helper, ensuring consistent
> > > error handling throughout the reset protocol.
> > >
> > > Suggested-by: Cristian Marussi <cristian.marussi@arm.com>
> > > Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
> > > ---
> > >
> > > Hi Cristian,
> > >
> > > Thank you for suggesting! If it works for you I'll try to improve the others protocols.
> > >
> > > It was tested on my board in QEMU and on real hardware.
> > > The functionality didn't break, and peripherals that are reseted via SCMI work correctly.
> > >
> > > As an example, I can provide DMA test results (as one of the processor units dependent on SCMI reset).
> > >
> > > [ 2.559040] dw_axi_dmac_platform 1000nda0.nda_dma_0: DesignWare AXI DMA Controller, nda channels
> > > [ 2.569265] dw_axi_dmac_platform 1000nda0.nda_dma_1: DesignWare AXI DMA Controller, nda channels
> > > [ 2.580601] dw_axi_dmac_platform 1000nda0.nda_dma_2: DesignWare AXI DMA Controller, nda channels
> > >
> > > # echo 2000 > /sys/module/dmatest/parameters/timeout
> > > # echo 1000 > /sys/module/dmatest/parameters/iterations
> > > # echo dma0chan0 > /sys/module/dmatest/parameters/channel
> > > [ 95.917504] dmatest: Added 1 threads using dma0chan0
> > > # echo 1 > /sys/module/dmatest/parameters/run
> > > [ 101.931372] dmatest: Started 1 threads using dma0chan0
> > > [ 102.731009] dmatest: dma0chan0-copy0: summary 1000 tests, 0 failures 2508.42 iops 19706 KB/s (0)
> > >
> > > And vice versa:
> > >
> > > 1. Confirmed that the DMA module is non-functional without a proper reset via SCMI.
> > > Disabling the reset logic causes a system crash on first access to its registers.
> > >
> > > 2. Requesting a non-existent reset domain:
> > >
> > > [ 2.463400] dw_axi_dmac_platform 1000nda0.nda_dma_0: error -EINVAL: Failed to deassert resets
> > > [ 2.472091] dw_axi_dmac_platform 1000nda0.nda_dma_0: probe with driver dw_axi_dmac_platform failed with error -22
> > > [ 2.482911] dw_axi_dmac_platform 1000nda0.nda_dma_1: error -EINVAL: Failed to deassert resets
> > > [ 2.491553] dw_axi_dmac_platform 1000nda0.nda_dma_1: probe with driver dw_axi_dmac_platform failed with error -22
> > > [ 2.502256] dw_axi_dmac_platform 1000nda0.nda_dma_2: error -EINVAL: Failed to deassert resets
> > > [ 2.510735] dw_axi_dmac_platform 1000nda0.nda_dma_2: probe with driver dw_axi_dmac_platform failed with error -22
> > >
> > > --
> > > Regards,
> > > Artem
> > >
> > > ---
> > > ChangeLog:
> > > v4: Add Suggested-by tag
> > >
> > > drivers/firmware/arm_scmi/reset.c | 59 ++++++++++++++++++++-----------
> > > 1 file changed, 39 insertions(+), 20 deletions(-)
> > >
> > > diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c
> > > index 0aa82b96f41b..9854a3016d13 100644
> > > --- a/drivers/firmware/arm_scmi/reset.c
> > > +++ b/drivers/firmware/arm_scmi/reset.c
> > > @@ -100,6 +100,7 @@ static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
> > >
> > > static int
> > > scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
> > > + struct reset_dom_info *dom_info,
> >
> > Instead of changing this, ...
> >
> > > struct scmi_reset_info *pinfo,
> > > u32 domain, u32 version)
> > > {
> > > @@ -107,7 +108,6 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
> > > u32 attributes;
> > > struct scmi_xfer *t;
> > > struct scmi_msg_resp_reset_domain_attributes *attr;
> > > - struct reset_dom_info *dom_info = pinfo->dom_info + domain;
> > >
> >
> > ... You can just follow the pattern you have done everywhere else in this
> > change like:
> >
> > struct reset_dom_info *dom_info;
> >
> > dom_info = scmi_reset_domain_lookup(ph, domain);
> > if (IS_ERR(dom_info))
> > return PTR_ERR(dom_info);
> >
> > Any particular reason for not doing that ?
>
> Hi Sudeep,
>
> Based on perf.c, I added this pattern only to functions that can be
> called externally with an invalid domain value.
> Therefore, I decided it would be better to change the signature of
> scmi_reset_domain_attributes_get (similar to
> scmi_perf_domain_attributes_get from pref.c)
> to ensure consistency across drivers when working with domain numbers.
>
> If you believe this pattern should be used in
> scmi_reset_domain_attributes_get, I'll send you the next version of
> the patch.
>
No need to post yet, I fixed it up here[1], let's see if Cristian agrees
with that. Let me know if you are happy too with that change. I will rebase
at -rc1 and apply it officially then.
--
Regards,
Sudeep
[1] https://git.kernel.org/sudeep.holla/c/8bc55f21a345
© 2016 - 2026 Red Hat, Inc.