Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <cristian.marussi@arm.com>
Message-Id: <20250707144220.485365-1-cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

authored by

Cristian Marussi and committed by
Sudeep Holla
b5daf93b 9a0658d3

+30 -9
+30 -9
drivers/firmware/arm_scmi/notify.c
··· 318 318 * customized event report 319 319 * @num_sources: The number of possible sources for this event as stated at 320 320 * events' registration time 321 + * @not_supported_by_platform: A flag to indicate that not even one source was 322 + * found to be supported by the platform for this 323 + * event 321 324 * @sources: A reference to a dynamically allocated array used to refcount the 322 325 * events' enable requests for all the existing sources 323 326 * @sources_mtx: A mutex to serialize the access to @sources ··· 337 334 const struct scmi_event *evt; 338 335 void *report; 339 336 u32 num_sources; 337 + bool not_supported_by_platform; 340 338 refcount_t *sources; 341 339 /* locking to serialize the access to sources */ 342 340 struct mutex sources_mtx; ··· 815 811 if (!r_evt->report) 816 812 return -ENOMEM; 817 813 818 - for (id = 0; id < r_evt->num_sources; id++) 819 - if (ee->ops->is_notify_supported && 820 - !ee->ops->is_notify_supported(ph, r_evt->evt->id, id)) 821 - refcount_set(&r_evt->sources[id], NOTIF_UNSUPP); 814 + if (ee->ops->is_notify_supported) { 815 + int supported = 0; 816 + 817 + for (id = 0; id < r_evt->num_sources; id++) { 818 + if (!ee->ops->is_notify_supported(ph, r_evt->evt->id, id)) 819 + refcount_set(&r_evt->sources[id], NOTIF_UNSUPP); 820 + else 821 + supported++; 822 + } 823 + 824 + /* Not even one source has been found to be supported */ 825 + r_evt->not_supported_by_platform = !supported; 826 + } 822 827 823 828 pd->registered_events[i] = r_evt; 824 829 /* Ensure events are updated */ ··· 949 936 * of protocol instance. 950 937 */ 951 938 hash_del(&hndl->hash); 939 + 940 + /* Bailout if event is not supported at all */ 941 + if (r_evt->not_supported_by_platform) 942 + return -EOPNOTSUPP; 943 + 952 944 /* 953 945 * Acquire protocols only for NON pending handlers, so as NOT to trigger 954 946 * protocol initialization when a notifier is registered against a still ··· 1078 1060 r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(evt_key), 1079 1061 KEY_XTRACT_EVT_ID(evt_key)); 1080 1062 1063 + if (r_evt && r_evt->not_supported_by_platform) 1064 + return ERR_PTR(-EOPNOTSUPP); 1065 + 1081 1066 mutex_lock(&ni->pending_mtx); 1082 1067 /* Search registered events at first ... if possible at all */ 1083 1068 if (r_evt) { ··· 1108 1087 hndl->key); 1109 1088 /* this hndl can be only a pending one */ 1110 1089 scmi_put_handler_unlocked(ni, hndl); 1111 - hndl = NULL; 1090 + hndl = ERR_PTR(-EINVAL); 1112 1091 } 1113 1092 } 1114 1093 mutex_unlock(&ni->pending_mtx); ··· 1391 1370 evt_key = MAKE_HASH_KEY(proto_id, evt_id, 1392 1371 src_id ? *src_id : SRC_ID_MASK); 1393 1372 hndl = scmi_get_or_create_handler(ni, evt_key); 1394 - if (!hndl) 1395 - return -EINVAL; 1373 + if (IS_ERR(hndl)) 1374 + return PTR_ERR(hndl); 1396 1375 1397 1376 blocking_notifier_chain_register(&hndl->chain, nb); 1398 1377 ··· 1437 1416 evt_key = MAKE_HASH_KEY(proto_id, evt_id, 1438 1417 src_id ? *src_id : SRC_ID_MASK); 1439 1418 hndl = scmi_get_handler(ni, evt_key); 1440 - if (!hndl) 1441 - return -EINVAL; 1419 + if (IS_ERR(hndl)) 1420 + return PTR_ERR(hndl); 1442 1421 1443 1422 /* 1444 1423 * Note that this chain unregistration call is safe on its own