mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 13:43:51 +00:00
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>
This commit is contained in:
parent
961745b2c4
commit
8733e86a80
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user