From ad28fc31dd702871764e9294d4f2314ad78d24a9 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 15 May 2025 03:17:19 +0530 Subject: [PATCH 1/8] firmware: arm_scmi: Fix up turbo frequencies selection Sustained frequency when greater than or equal to 4Ghz on 64-bit devices currently result in marking all frequencies as turbo. Address the turbo frequency selection bug by fixing the truncation. Fixes: a897575e79d7 ("firmware: arm_scmi: Add support for marking certain frequencies as turbo") Signed-off-by: Sibi Sankar Message-Id: <20250514214719.203607-1-quic_sibis@quicinc.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index c7e5a34b254b..683fd9b85c5c 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -892,7 +892,7 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph, freq = dom->opp[idx].indicative_freq * dom->mult_factor; /* All OPPs above the sustained frequency are treated as turbo */ - data.turbo = freq > dom->sustained_freq_khz * 1000; + data.turbo = freq > dom->sustained_freq_khz * 1000UL; data.level = dom->opp[idx].perf; data.freq = freq; From 555e9174ef06b7bfc54a3127a8d8fc47d55d04f4 Mon Sep 17 00:00:00 2001 From: Philip Radford Date: Mon, 30 Jun 2025 10:55:41 +0000 Subject: [PATCH 2/8] firmware: arm_scmi: Add support for debug counter decrement Introduce a new `scmi_dec_count` helper to complement the existing `scmi_inc_count`, allowing controlled decrement of SCMI debug counters. This provides symmetry in debug counter management and enables accurate tracking of counters that may both increase and decrease, such as those used for in-flight message tracking. Only active when CONFIG_ARM_SCMI_DEBUG_COUNTERS is enabled. Reviewed-by: Cristian Marussi Signed-off-by: Philip Radford Message-Id: <20250630105544.531723-2-philip.radford@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index dab758c5fdea..c6495c4a0e8a 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -314,6 +314,12 @@ static inline void scmi_inc_count(atomic_t *arr, int stat) atomic_inc(&arr[stat]); } +static inline void scmi_dec_count(atomic_t *arr, int stat) +{ + if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) + atomic_dec(&arr[stat]); +} + enum scmi_bad_msg { MSG_UNEXPECTED = -1, MSG_INVALID = -2, From a9cd861e61ae80b441af87f332bc3f44aa0b7c02 Mon Sep 17 00:00:00 2001 From: Philip Radford Date: Mon, 30 Jun 2025 10:55:42 +0000 Subject: [PATCH 3/8] firmware: arm_scmi: Track number of inflight SCMI transfers Add a new debug counter, `XFERS_INFLIGHT`, to track the number of currently active in-flight SCMI message transfers. This helps in understanding system behavior and diagnosing potential issues with pending or stuck messages. The counter is incremented when a transfer is registered as in-flight, and decremented when it completes and is released. It is automatically added to debugfs for visibility through SCMI debugfs. Reviewed-by: Cristian Marussi Signed-off-by: Philip Radford Message-Id: <20250630105544.531723-3-philip.radford@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 1 + drivers/firmware/arm_scmi/driver.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index c6495c4a0e8a..ad9232c982ce 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -305,6 +305,7 @@ enum debug_counters { ERR_MSG_INVALID, ERR_MSG_NOMEM, ERR_PROTOCOL, + XFERS_INFLIGHT, SCMI_DEBUG_COUNTERS_LAST }; diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 395fe9289035..5a4dac27afdf 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -190,6 +190,7 @@ struct scmi_info { }; #define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle) +#define tx_minfo_to_scmi_info(h) container_of(h, struct scmi_info, tx_minfo) #define bus_nb_to_scmi_info(nb) container_of(nb, struct scmi_info, bus_nb) #define req_nb_to_scmi_info(nb) container_of(nb, struct scmi_info, dev_req_nb) @@ -603,9 +604,14 @@ static inline void scmi_xfer_inflight_register_unlocked(struct scmi_xfer *xfer, struct scmi_xfers_info *minfo) { + /* In this context minfo will be tx_minfo due to the xfer pending */ + struct scmi_info *info = tx_minfo_to_scmi_info(minfo); + /* Set in-flight */ set_bit(xfer->hdr.seq, minfo->xfer_alloc_table); hash_add(minfo->pending_xfers, &xfer->node, xfer->hdr.seq); + scmi_inc_count(info->dbg->counters, XFERS_INFLIGHT); + xfer->pending = true; } @@ -807,9 +813,13 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) spin_lock_irqsave(&minfo->xfer_lock, flags); if (refcount_dec_and_test(&xfer->users)) { if (xfer->pending) { + struct scmi_info *info = tx_minfo_to_scmi_info(minfo); + scmi_xfer_token_clear(minfo, xfer); hash_del(&xfer->node); xfer->pending = false; + + scmi_dec_count(info->dbg->counters, XFERS_INFLIGHT); } hlist_add_head(&xfer->node, &minfo->free_xfers); } @@ -2912,6 +2922,7 @@ static const char * const dbg_counter_strs[] = { "err_msg_invalid", "err_msg_nomem", "err_protocol", + "xfers_inflight", }; static ssize_t reset_all_on_write(struct file *filp, const char __user *buf, From f8e656382b4aa45ae51135b72262044550224920 Mon Sep 17 00:00:00 2001 From: Philip Radford Date: Mon, 30 Jun 2025 10:55:43 +0000 Subject: [PATCH 4/8] include: trace: Add tracepoint support for inflight xfer count Enhance the existing SCMI transfer tracepoints by including the current in-flight transfer count in `scmi_xfer_begin` and `scmi_xfer_end`. Introduce a new helper `scmi_inflight_count()` to retrieve the active transfer count from the SCMI debug counters when debug is enabled. This trace data is useful for visualizing transfer activity over time and identifying congestion or unexpected behavior in SCMI messaging. Reviewed-by: Cristian Marussi Signed-off-by: Philip Radford Message-Id: <20250630105544.531723-4-philip.radford@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/common.h | 1 + drivers/firmware/arm_scmi/driver.c | 17 +++++++++++++++-- drivers/firmware/arm_scmi/raw_mode.c | 6 ++++-- include/trace/events/scmi.h | 24 ++++++++++++++---------- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index ad9232c982ce..07b9e629276d 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -505,4 +505,5 @@ static struct platform_driver __drv = { \ void scmi_notification_instance_data_set(const struct scmi_handle *handle, void *priv); void *scmi_notification_instance_data_get(const struct scmi_handle *handle); +int scmi_inflight_count(const struct scmi_handle *handle); #endif /* _SCMI_COMMON_H */ diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 5a4dac27afdf..bd56a877fdfc 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1443,7 +1443,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph, trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id, xfer->hdr.protocol_id, xfer->hdr.seq, - xfer->hdr.poll_completion); + xfer->hdr.poll_completion, + scmi_inflight_count(&info->handle)); /* Clear any stale status */ xfer->hdr.status = SCMI_SUCCESS; @@ -1479,7 +1480,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph, info->desc->ops->mark_txdone(cinfo, ret, xfer); trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, - xfer->hdr.protocol_id, xfer->hdr.seq, ret); + xfer->hdr.protocol_id, xfer->hdr.seq, ret, + scmi_inflight_count(&info->handle)); return ret; } @@ -3416,6 +3418,17 @@ static struct dentry *scmi_debugfs_init(void) return d; } +int scmi_inflight_count(const struct scmi_handle *handle) +{ + if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) { + struct scmi_info *info = handle_to_scmi_info(handle); + + return atomic_read(&info->dbg->counters[XFERS_INFLIGHT]); + } else { + return 0; + } +} + static int __init scmi_driver_init(void) { scmi_quirks_initialize(); diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c index 3d543b1d8947..73db5492ab44 100644 --- a/drivers/firmware/arm_scmi/raw_mode.c +++ b/drivers/firmware/arm_scmi/raw_mode.c @@ -475,7 +475,8 @@ static void scmi_xfer_raw_worker(struct work_struct *work) raw->desc->ops->mark_txdone(rw->cinfo, ret, xfer); trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, - xfer->hdr.protocol_id, xfer->hdr.seq, ret); + xfer->hdr.protocol_id, xfer->hdr.seq, + ret, scmi_inflight_count(raw->handle)); /* Wait also for an async delayed response if needed */ if (!ret && xfer->async_done) { @@ -642,7 +643,8 @@ static int scmi_do_xfer_raw_start(struct scmi_raw_mode_info *raw, trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id, xfer->hdr.protocol_id, xfer->hdr.seq, - xfer->hdr.poll_completion); + xfer->hdr.poll_completion, + scmi_inflight_count(raw->handle)); ret = raw->desc->ops->send_message(rw->cinfo, xfer); if (ret) { diff --git a/include/trace/events/scmi.h b/include/trace/events/scmi.h index 127300481123..703b7bb68e44 100644 --- a/include/trace/events/scmi.h +++ b/include/trace/events/scmi.h @@ -36,8 +36,8 @@ TRACE_EVENT(scmi_fc_call, TRACE_EVENT(scmi_xfer_begin, TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, - bool poll), - TP_ARGS(transfer_id, msg_id, protocol_id, seq, poll), + bool poll, int inflight), + TP_ARGS(transfer_id, msg_id, protocol_id, seq, poll, inflight), TP_STRUCT__entry( __field(int, transfer_id) @@ -45,6 +45,7 @@ TRACE_EVENT(scmi_xfer_begin, __field(u8, protocol_id) __field(u16, seq) __field(bool, poll) + __field(int, inflight) ), TP_fast_assign( @@ -53,11 +54,12 @@ TRACE_EVENT(scmi_xfer_begin, __entry->protocol_id = protocol_id; __entry->seq = seq; __entry->poll = poll; + __entry->inflight = inflight; ), - TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X poll=%u", - __entry->protocol_id, __entry->msg_id, __entry->seq, - __entry->transfer_id, __entry->poll) + TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X poll=%u inflight=%d", + __entry->protocol_id, __entry->msg_id, __entry->seq, + __entry->transfer_id, __entry->poll, __entry->inflight) ); TRACE_EVENT(scmi_xfer_response_wait, @@ -90,8 +92,8 @@ TRACE_EVENT(scmi_xfer_response_wait, TRACE_EVENT(scmi_xfer_end, TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, - int status), - TP_ARGS(transfer_id, msg_id, protocol_id, seq, status), + int status, int inflight), + TP_ARGS(transfer_id, msg_id, protocol_id, seq, status, inflight), TP_STRUCT__entry( __field(int, transfer_id) @@ -99,6 +101,7 @@ TRACE_EVENT(scmi_xfer_end, __field(u8, protocol_id) __field(u16, seq) __field(int, status) + __field(int, inflight) ), TP_fast_assign( @@ -107,11 +110,12 @@ TRACE_EVENT(scmi_xfer_end, __entry->protocol_id = protocol_id; __entry->seq = seq; __entry->status = status; + __entry->inflight = inflight; ), - TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X s=%d", - __entry->protocol_id, __entry->msg_id, __entry->seq, - __entry->transfer_id, __entry->status) + TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X s=%d inflight=%d", + __entry->protocol_id, __entry->msg_id, __entry->seq, + __entry->transfer_id, __entry->status, __entry->inflight) ); TRACE_EVENT(scmi_rx_done, From 76e65f7a0e0fb41d636c11b688db6393676f4bf4 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 4 Jul 2025 11:09:35 +0800 Subject: [PATCH 5/8] firmware: arm_scmi: Add power management operations to SCMI bus Introduce suspend and resume power management callbacks for `scmi_bus_type`, modeled after `platform_pm_ops`. This enables SCMI devices on the bus to implement their own suspend and resume behavior, allowing for more fine-grained power control at the device level. Signed-off-by: Peng Fan Message-Id: <20250704-scmi-pm-v2-1-9316cec2f9cc@nxp.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/bus.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 1adef0389475..24e59ddf85e7 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -323,6 +323,31 @@ static struct attribute *scmi_device_attributes_attrs[] = { }; ATTRIBUTE_GROUPS(scmi_device_attributes); +static int scmi_pm_suspend(struct device *dev) +{ + const struct device_driver *drv = dev->driver; + + if (drv && drv->pm && drv->pm->suspend) + return drv->pm->suspend(dev); + + return 0; +} + +static int scmi_pm_resume(struct device *dev) +{ + const struct device_driver *drv = dev->driver; + + if (drv && drv->pm && drv->pm->resume) + return drv->pm->resume(dev); + + return 0; +} + +static const struct dev_pm_ops scmi_dev_pm_ops = { + .suspend = pm_sleep_ptr(scmi_pm_suspend), + .resume = pm_sleep_ptr(scmi_pm_resume), +}; + const struct bus_type scmi_bus_type = { .name = "scmi_protocol", .match = scmi_dev_match, @@ -330,6 +355,7 @@ const struct bus_type scmi_bus_type = { .remove = scmi_dev_remove, .uevent = scmi_device_uevent, .dev_groups = scmi_device_attributes_groups, + .pm = &scmi_dev_pm_ops, }; EXPORT_SYMBOL_GPL(scmi_bus_type); From 9a0658d3991e6c82df87584b253454842f22f965 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 4 Jul 2025 11:09:36 +0800 Subject: [PATCH 6/8] firmware: arm_scmi: power_control: Ensure SCMI_SYSPOWER_IDLE is set early during resume Fix a race condition where a second suspend notification from another SCMI agent wakes the system before SCMI_SYSPOWER_IDLE is set, leading to ignored suspend requests. This is due to interrupts triggering early execution of `scmi_userspace_notifier()` before the SCMI state is updated. To resolve this, set SCMI_SYSPOWER_IDLE earlier in the device resume path, prior to `thaw_processes()`. This ensures the SCMI state is correct when the notifier runs, allowing the system to suspend again as expected. On some platforms using SCMI, SCP cannot distinguish between CPU idle and suspend since both result in cluster power-off. By explicitly setting the idle state early, the Linux SCMI agent can correctly re-suspend in response to external notifications. Signed-off-by: Peng Fan Message-Id: <20250704-scmi-pm-v2-2-9316cec2f9cc@nxp.com> Signed-off-by: Sudeep Holla --- .../firmware/arm_scmi/scmi_power_control.c | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/arm_scmi/scmi_power_control.c b/drivers/firmware/arm_scmi/scmi_power_control.c index 21f467a92942..ab0cee0d4bec 100644 --- a/drivers/firmware/arm_scmi/scmi_power_control.c +++ b/drivers/firmware/arm_scmi/scmi_power_control.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -324,12 +325,7 @@ static int scmi_userspace_notifier(struct notifier_block *nb, static void scmi_suspend_work_func(struct work_struct *work) { - struct scmi_syspower_conf *sc = - container_of(work, struct scmi_syspower_conf, suspend_work); - pm_suspend(PM_SUSPEND_MEM); - - sc->state = SCMI_SYSPOWER_IDLE; } static int scmi_syspower_probe(struct scmi_device *sdev) @@ -354,6 +350,7 @@ static int scmi_syspower_probe(struct scmi_device *sdev) sc->required_transition = SCMI_SYSTEM_MAX; sc->userspace_nb.notifier_call = &scmi_userspace_notifier; sc->dev = &sdev->dev; + dev_set_drvdata(&sdev->dev, sc); INIT_WORK(&sc->suspend_work, scmi_suspend_work_func); @@ -363,6 +360,18 @@ static int scmi_syspower_probe(struct scmi_device *sdev) NULL, &sc->userspace_nb); } +static int scmi_system_power_resume(struct device *dev) +{ + struct scmi_syspower_conf *sc = dev_get_drvdata(dev); + + sc->state = SCMI_SYSPOWER_IDLE; + return 0; +} + +static const struct dev_pm_ops scmi_system_power_pmops = { + SET_SYSTEM_SLEEP_PM_OPS(NULL, scmi_system_power_resume) +}; + static const struct scmi_device_id scmi_id_table[] = { { SCMI_PROTOCOL_SYSTEM, "syspower" }, { }, @@ -370,6 +379,9 @@ static const struct scmi_device_id scmi_id_table[] = { MODULE_DEVICE_TABLE(scmi, scmi_id_table); static struct scmi_driver scmi_system_power_driver = { + .driver = { + .pm = &scmi_system_power_pmops, + }, .name = "scmi-system-power", .probe = scmi_syspower_probe, .id_table = scmi_id_table, From b5daf93b809d13a194f8a8eeacfab1cfa241bbc3 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 7 Jul 2025 15:42:20 +0100 Subject: [PATCH 7/8] firmware: arm_scmi: Avoid notifier registration for unsupported events Some platforms may be configured to not support notification events from certain sources. This scenario is already handled gracefully by avoiding any attempt to send a notification enable request for those sources, as such requests would inevitably fail. However, in a more extreme case, a platform might not support even a single source for a given event type. In this situation, allowing notifier registration is meaningless. Attempting to register a notifier would serve no purpose and only result in unnecessary overhead. To address this, we now detect such conditions during the protocol initialization. When identified, we flag the unsupported event types and reject any subsequent notifier registration attempts for them with -ENOTSUPP. This early rejection avoids redundant processing and simplifies runtime logic. Signed-off-by: Cristian Marussi Message-Id: <20250707144220.485365-1-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/notify.c | 39 +++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index e160ecb22948..dee9f238f6fd 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -318,6 +318,9 @@ struct scmi_registered_events_desc { * customized event report * @num_sources: The number of possible sources for this event as stated at * events' registration time + * @not_supported_by_platform: A flag to indicate that not even one source was + * found to be supported by the platform for this + * event * @sources: A reference to a dynamically allocated array used to refcount the * events' enable requests for all the existing sources * @sources_mtx: A mutex to serialize the access to @sources @@ -334,6 +337,7 @@ struct scmi_registered_event { const struct scmi_event *evt; void *report; u32 num_sources; + bool not_supported_by_platform; refcount_t *sources; /* locking to serialize the access to sources */ struct mutex sources_mtx; @@ -811,10 +815,19 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id, if (!r_evt->report) return -ENOMEM; - for (id = 0; id < r_evt->num_sources; id++) - if (ee->ops->is_notify_supported && - !ee->ops->is_notify_supported(ph, r_evt->evt->id, id)) - refcount_set(&r_evt->sources[id], NOTIF_UNSUPP); + if (ee->ops->is_notify_supported) { + int supported = 0; + + for (id = 0; id < r_evt->num_sources; id++) { + if (!ee->ops->is_notify_supported(ph, r_evt->evt->id, id)) + refcount_set(&r_evt->sources[id], NOTIF_UNSUPP); + else + supported++; + } + + /* Not even one source has been found to be supported */ + r_evt->not_supported_by_platform = !supported; + } pd->registered_events[i] = r_evt; /* Ensure events are updated */ @@ -936,6 +949,11 @@ static inline int scmi_bind_event_handler(struct scmi_notify_instance *ni, * of protocol instance. */ hash_del(&hndl->hash); + + /* Bailout if event is not supported at all */ + if (r_evt->not_supported_by_platform) + return -EOPNOTSUPP; + /* * Acquire protocols only for NON pending handlers, so as NOT to trigger * protocol initialization when a notifier is registered against a still @@ -1060,6 +1078,9 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(evt_key), KEY_XTRACT_EVT_ID(evt_key)); + if (r_evt && r_evt->not_supported_by_platform) + return ERR_PTR(-EOPNOTSUPP); + mutex_lock(&ni->pending_mtx); /* Search registered events at first ... if possible at all */ if (r_evt) { @@ -1087,7 +1108,7 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, hndl->key); /* this hndl can be only a pending one */ scmi_put_handler_unlocked(ni, hndl); - hndl = NULL; + hndl = ERR_PTR(-EINVAL); } } mutex_unlock(&ni->pending_mtx); @@ -1370,8 +1391,8 @@ static int scmi_notifier_register(const struct scmi_handle *handle, evt_key = MAKE_HASH_KEY(proto_id, evt_id, src_id ? *src_id : SRC_ID_MASK); hndl = scmi_get_or_create_handler(ni, evt_key); - if (!hndl) - return -EINVAL; + if (IS_ERR(hndl)) + return PTR_ERR(hndl); blocking_notifier_chain_register(&hndl->chain, nb); @@ -1416,8 +1437,8 @@ static int scmi_notifier_unregister(const struct scmi_handle *handle, evt_key = MAKE_HASH_KEY(proto_id, evt_id, src_id ? *src_id : SRC_ID_MASK); hndl = scmi_get_handler(ni, evt_key); - if (!hndl) - return -EINVAL; + if (IS_ERR(hndl)) + return PTR_ERR(hndl); /* * Note that this chain unregistration call is safe on its own From 62d6b81e8bd207ad44eff39d1a0fe17f0df510a5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 9 Jul 2025 09:01:01 +0200 Subject: [PATCH 8/8] firmware: arm_scmi: Convert to SYSTEM_SLEEP_PM_OPS The old SET_SYSTEM_SLEEP_PM_OPS() macro leads to a warning about an unused function: | drivers/firmware/arm_scmi/scmi_power_control.c:363:12: error: | 'scmi_system_power_resume' defined but not used [-Werror=unused-function] | static int scmi_system_power_resume(struct device *dev) The proper way to do this these days is to use SYSTEM_SLEEP_PM_OPS() and pm_sleep_ptr(). Fixes: 9a0658d3991e ("firmware: arm_scmi: power_control: Ensure SCMI_SYSPOWER_IDLE is set early during resume") Signed-off-by: Arnd Bergmann Acked-by: Peng Fan Message-Id: <20250709070107.1388512-1-arnd@kernel.org> Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/scmi_power_control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/scmi_power_control.c b/drivers/firmware/arm_scmi/scmi_power_control.c index ab0cee0d4bec..955736336061 100644 --- a/drivers/firmware/arm_scmi/scmi_power_control.c +++ b/drivers/firmware/arm_scmi/scmi_power_control.c @@ -369,7 +369,7 @@ static int scmi_system_power_resume(struct device *dev) } static const struct dev_pm_ops scmi_system_power_pmops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, scmi_system_power_resume) + SYSTEM_SLEEP_PM_OPS(NULL, scmi_system_power_resume) }; static const struct scmi_device_id scmi_id_table[] = { @@ -380,7 +380,7 @@ MODULE_DEVICE_TABLE(scmi, scmi_id_table); static struct scmi_driver scmi_system_power_driver = { .driver = { - .pm = &scmi_system_power_pmops, + .pm = pm_sleep_ptr(&scmi_system_power_pmops), }, .name = "scmi-system-power", .probe = scmi_syspower_probe,