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

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 <cristian.marussi@arm.com>
Link: https://lore.kernel.org/r/20240212123233.1230090-2-cristian.marussi@arm.com
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

authored by

Cristian Marussi and committed by
Sudeep Holla
8733e86a 961745b2

+20 -1
+16 -1
drivers/firmware/arm_scmi/notify.c
··· 99 99 #define PROTO_ID_MASK GENMASK(31, 24) 100 100 #define EVT_ID_MASK GENMASK(23, 16) 101 101 #define SRC_ID_MASK GENMASK(15, 0) 102 + #define NOTIF_UNSUPP -1 102 103 103 104 /* 104 105 * Builds an unsigned 32bit key from the given input tuple to be used ··· 789 788 790 789 pd->ph = ph; 791 790 for (i = 0; i < ee->num_events; i++, evt++) { 791 + int id; 792 792 struct scmi_registered_event *r_evt; 793 793 794 794 r_evt = devm_kzalloc(ni->handle->dev, sizeof(*r_evt), ··· 810 808 evt->max_report_sz, GFP_KERNEL); 811 809 if (!r_evt->report) 812 810 return -ENOMEM; 811 + 812 + for (id = 0; id < r_evt->num_sources; id++) 813 + if (ee->ops->is_notify_supported && 814 + !ee->ops->is_notify_supported(ph, r_evt->evt->id, id)) 815 + refcount_set(&r_evt->sources[id], NOTIF_UNSUPP); 813 816 814 817 pd->registered_events[i] = r_evt; 815 818 /* Ensure events are updated */ ··· 1173 1166 int ret = 0; 1174 1167 1175 1168 sid = &r_evt->sources[src_id]; 1176 - if (refcount_read(sid) == 0) { 1169 + if (refcount_read(sid) == NOTIF_UNSUPP) { 1170 + dev_dbg(r_evt->proto->ph->dev, 1171 + "Notification NOT supported - proto_id:%d evt_id:%d src_id:%d", 1172 + r_evt->proto->id, r_evt->evt->id, 1173 + src_id); 1174 + ret = -EOPNOTSUPP; 1175 + } else if (refcount_read(sid) == 0) { 1177 1176 ret = REVT_NOTIFY_ENABLE(r_evt, r_evt->evt->id, 1178 1177 src_id); 1179 1178 if (!ret) ··· 1192 1179 } else { 1193 1180 for (; num_sources; src_id++, num_sources--) { 1194 1181 sid = &r_evt->sources[src_id]; 1182 + if (refcount_read(sid) == NOTIF_UNSUPP) 1183 + continue; 1195 1184 if (refcount_dec_and_test(sid)) 1196 1185 REVT_NOTIFY_DISABLE(r_evt, 1197 1186 r_evt->evt->id, src_id);
+4
drivers/firmware/arm_scmi/notify.h
··· 35 35 36 36 /** 37 37 * struct scmi_event_ops - Protocol helpers called by the notification core. 38 + * @is_notify_supported: Return 0 if the specified notification for the 39 + * specified resource (src_id) is supported. 38 40 * @get_num_sources: Returns the number of possible events' sources for this 39 41 * protocol 40 42 * @set_notify_enabled: Enable/disable the required evt_id/src_id notifications ··· 52 50 * process context. 53 51 */ 54 52 struct scmi_event_ops { 53 + bool (*is_notify_supported)(const struct scmi_protocol_handle *ph, 54 + u8 evt_id, u32 src_id); 55 55 int (*get_num_sources)(const struct scmi_protocol_handle *ph); 56 56 int (*set_notify_enabled)(const struct scmi_protocol_handle *ph, 57 57 u8 evt_id, u32 src_id, bool enabled);