From: Cristian Marussi Date: Mon, 12 Feb 2024 12:32:23 +0000 (+0000) Subject: firmware: arm_scmi: Check for notification support X-Git-Tag: microblaze-v6.10~179^2~9^2~16 X-Git-Url: http://git.monstr.eu/?a=commitdiff_plain;h=8733e86a80f5a7abb7b4b6ca3f417b32c3eb68e3;p=linux-2.6-microblaze.git firmware: arm_scmi: Check for notification support When registering protocol events, use the optional .is_notify_supported callback provided by the protocol to check if that specific notification type is available for that particular resource on the running system, marking it as unsupported otherwise. Then, when a notification enable request is received, return an error if it was previously marked as unsuppported, so avoiding to send a needless notification enable command and check the returned value for failure. Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20240212123233.1230090-2-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index 0efd20cd9d69..27c52531194d 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -99,6 +99,7 @@ #define PROTO_ID_MASK GENMASK(31, 24) #define EVT_ID_MASK GENMASK(23, 16) #define SRC_ID_MASK GENMASK(15, 0) +#define NOTIF_UNSUPP -1 /* * Builds an unsigned 32bit key from the given input tuple to be used @@ -788,6 +789,7 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id, pd->ph = ph; for (i = 0; i < ee->num_events; i++, evt++) { + int id; struct scmi_registered_event *r_evt; r_evt = devm_kzalloc(ni->handle->dev, sizeof(*r_evt), @@ -809,6 +811,11 @@ 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); + pd->registered_events[i] = r_evt; /* Ensure events are updated */ smp_wmb(); @@ -1166,7 +1173,13 @@ static inline int __scmi_enable_evt(struct scmi_registered_event *r_evt, int ret = 0; sid = &r_evt->sources[src_id]; - if (refcount_read(sid) == 0) { + if (refcount_read(sid) == NOTIF_UNSUPP) { + dev_dbg(r_evt->proto->ph->dev, + "Notification NOT supported - proto_id:%d evt_id:%d src_id:%d", + r_evt->proto->id, r_evt->evt->id, + src_id); + ret = -EOPNOTSUPP; + } else if (refcount_read(sid) == 0) { ret = REVT_NOTIFY_ENABLE(r_evt, r_evt->evt->id, src_id); if (!ret) @@ -1179,6 +1192,8 @@ static inline int __scmi_enable_evt(struct scmi_registered_event *r_evt, } else { for (; num_sources; src_id++, num_sources--) { sid = &r_evt->sources[src_id]; + if (refcount_read(sid) == NOTIF_UNSUPP) + continue; if (refcount_dec_and_test(sid)) REVT_NOTIFY_DISABLE(r_evt, r_evt->evt->id, src_id); diff --git a/drivers/firmware/arm_scmi/notify.h b/drivers/firmware/arm_scmi/notify.h index 4e9b627edfef..76758a736cf4 100644 --- a/drivers/firmware/arm_scmi/notify.h +++ b/drivers/firmware/arm_scmi/notify.h @@ -35,6 +35,8 @@ struct scmi_protocol_handle; /** * struct scmi_event_ops - Protocol helpers called by the notification core. + * @is_notify_supported: Return 0 if the specified notification for the + * specified resource (src_id) is supported. * @get_num_sources: Returns the number of possible events' sources for this * protocol * @set_notify_enabled: Enable/disable the required evt_id/src_id notifications @@ -50,6 +52,8 @@ struct scmi_protocol_handle; * process context. */ struct scmi_event_ops { + bool (*is_notify_supported)(const struct scmi_protocol_handle *ph, + u8 evt_id, u32 src_id); int (*get_num_sources)(const struct scmi_protocol_handle *ph); int (*set_notify_enabled)(const struct scmi_protocol_handle *ph, u8 evt_id, u32 src_id, bool enabled);