in arm_scmi/notify.c [748:831]
int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
const struct scmi_protocol_handle *ph,
const struct scmi_protocol_events *ee)
{
int i;
unsigned int num_sources;
size_t payld_sz = 0;
struct scmi_registered_events_desc *pd;
struct scmi_notify_instance *ni;
const struct scmi_event *evt;
if (!ee || !ee->ops || !ee->evts || !ph ||
(!ee->num_sources && !ee->ops->get_num_sources))
return -EINVAL;
ni = scmi_notification_instance_data_get(handle);
if (!ni)
return -ENOMEM;
/* num_sources cannot be <= 0 */
if (ee->num_sources) {
num_sources = ee->num_sources;
} else {
int nsrc = ee->ops->get_num_sources(ph);
if (nsrc <= 0)
return -EINVAL;
num_sources = nsrc;
}
evt = ee->evts;
for (i = 0; i < ee->num_events; i++)
payld_sz = max_t(size_t, payld_sz, evt[i].max_payld_sz);
payld_sz += sizeof(struct scmi_event_header);
pd = scmi_allocate_registered_events_desc(ni, proto_id, ee->queue_sz,
payld_sz, ee->num_events,
ee->ops);
if (IS_ERR(pd))
return PTR_ERR(pd);
pd->ph = ph;
for (i = 0; i < ee->num_events; i++, evt++) {
struct scmi_registered_event *r_evt;
r_evt = devm_kzalloc(ni->handle->dev, sizeof(*r_evt),
GFP_KERNEL);
if (!r_evt)
return -ENOMEM;
r_evt->proto = pd;
r_evt->evt = evt;
r_evt->sources = devm_kcalloc(ni->handle->dev, num_sources,
sizeof(refcount_t), GFP_KERNEL);
if (!r_evt->sources)
return -ENOMEM;
r_evt->num_sources = num_sources;
mutex_init(&r_evt->sources_mtx);
r_evt->report = devm_kzalloc(ni->handle->dev,
evt->max_report_sz, GFP_KERNEL);
if (!r_evt->report)
return -ENOMEM;
pd->registered_events[i] = r_evt;
/* Ensure events are updated */
smp_wmb();
dev_dbg(handle->dev, "registered event - %lX\n",
MAKE_ALL_SRCS_KEY(r_evt->proto->id, r_evt->evt->id));
}
/* Register protocol and events...it will never be removed */
ni->registered_protocols[proto_id] = pd;
/* Ensure protocols are updated */
smp_wmb();
/*
* Finalize any pending events' handler which could have been waiting
* for this protocol's events registration.
*/
schedule_work(&ni->init_work);
return 0;
}