Use flexible array members to combine allocations and remove kcalloc usage.
Add __counted_by where appropriate for extra runtime analysis. Move counting variable assignment after allocation before any potential array access. Signed-off-by: Rosen Penev <[email protected]> --- drivers/firmware/arm_scmi/notify.c | 42 ++++++++++++------------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index 40ec184eedae..45cbb3d2d684 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -209,11 +209,11 @@ struct scmi_registered_events_desc; * @init_work: A work item to perform final initializations of pending handlers * @notify_wq: A reference to the allocated Kernel cmwq * @pending_mtx: A mutex to protect @pending_events_handlers + * @pending_events_handlers: An hashtable containing all pending events' + * handlers descriptors * @registered_protocols: A statically allocated array containing pointers to * all the registered protocol-level specific information * related to events' handling - * @pending_events_handlers: An hashtable containing all pending events' - * handlers descriptors * * Each platform instance, represented by a handle, has its own instance of * the notification subsystem represented by this structure. @@ -225,8 +225,8 @@ struct scmi_notify_instance { struct workqueue_struct *notify_wq; /* lock to protect pending_events_handlers */ struct mutex pending_mtx; - struct scmi_registered_events_desc **registered_protocols; DECLARE_HASHTABLE(pending_events_handlers, SCMI_PENDING_HASH_SZ); + struct scmi_registered_events_desc *registered_protocols[]; }; /** @@ -276,13 +276,13 @@ struct scmi_registered_event; * @eh_sz: Size of the pre-allocated buffer @eh * @in_flight: A reference to an in flight &struct scmi_registered_event * @num_events: Number of events in @registered_events - * @registered_events: A dynamically allocated array holding all the registered - * events' descriptors, whose fixed-size is determined at - * compile time. * @registered_mtx: A mutex to protect @registered_events_handlers * @ph: SCMI protocol handle reference * @registered_events_handlers: An hashtable containing all events' handlers * descriptors registered for this protocol + * @registered_events: A dynamically allocated array holding all the registered + * events' descriptors, whose fixed-size is determined at + * compile time. * * All protocols that register at least one event have their protocol-specific * information stored here, together with the embedded allocated events_queue. @@ -302,11 +302,11 @@ struct scmi_registered_events_desc { size_t eh_sz; void *in_flight; int num_events; - struct scmi_registered_event **registered_events; /* mutex to protect registered_events_handlers */ struct mutex registered_mtx; const struct scmi_protocol_handle *ph; DECLARE_HASHTABLE(registered_events_handlers, SCMI_REGISTERED_HASH_SZ); + struct scmi_registered_event *registered_events[] __counted_by(num_events); }; /** @@ -338,9 +338,9 @@ struct scmi_registered_event { void *report; u32 num_sources; bool not_supported_by_platform; - refcount_t *sources; /* locking to serialize the access to sources */ struct mutex sources_mtx; + refcount_t sources[] __counted_by(num_sources); }; /** @@ -706,9 +706,12 @@ scmi_allocate_registered_events_desc(struct scmi_notify_instance *ni, if (WARN_ON(ni->registered_protocols[proto_id])) return ERR_PTR(-EINVAL); - pd = devm_kzalloc(ni->handle->dev, sizeof(*pd), GFP_KERNEL); + pd = devm_kzalloc(ni->handle->dev, struct_size(pd, registered_events, num_events), + GFP_KERNEL); if (!pd) return ERR_PTR(-ENOMEM); + + pd->num_events = num_events; pd->id = proto_id; pd->ops = ops; pd->ni = ni; @@ -722,12 +725,6 @@ scmi_allocate_registered_events_desc(struct scmi_notify_instance *ni, return ERR_PTR(-ENOMEM); pd->eh_sz = eh_sz; - pd->registered_events = devm_kcalloc(ni->handle->dev, num_events, - sizeof(char *), GFP_KERNEL); - if (!pd->registered_events) - return ERR_PTR(-ENOMEM); - pd->num_events = num_events; - /* Initialize per protocol handlers table */ mutex_init(&pd->registered_mtx); hash_init(pd->registered_events_handlers); @@ -800,14 +797,11 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id, GFP_KERNEL); if (!r_evt) return -ENOMEM; + + r_evt->num_sources = num_sources; 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, @@ -1666,18 +1660,14 @@ int scmi_notification_init(struct scmi_handle *handle) if (!gid) return -ENOMEM; - ni = devm_kzalloc(handle->dev, sizeof(*ni), GFP_KERNEL); + ni = devm_kzalloc(handle->dev, struct_size(ni, registered_protocols, SCMI_MAX_PROTO), + GFP_KERNEL); if (!ni) goto err; ni->gid = gid; ni->handle = handle; - ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTO, - sizeof(char *), GFP_KERNEL); - if (!ni->registered_protocols) - goto err; - ni->notify_wq = alloc_workqueue(dev_name(handle->dev), WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS, 0); -- 2.54.0

