Lines Matching +full:rx +full:- +full:eq

1 // SPDX-License-Identifier: GPL-2.0
36 * All users provided callbacks and allocated notification-chains are stored in
44 * hash-keys.
51 * Upon reception of a notification message from the platform the SCMI RX ISR
54 * pushes the event-data itself on a protocol-dedicated kfifo queue for further
59 * queued items into the proper notification-chain: notifications processing can
65 * conveyed, converted into a custom per-event report struct, as the void *data
73 #define dev_fmt(fmt) "SCMI Notifications - " fmt
74 #define pr_fmt(fmt) "SCMI Notifications - " fmt
114 * Assumes that the stored obj includes its own hash-key in a field named 'key':
130 if (obj_->key == k_) \
151 __pd = READ_ONCE(ni_->registered_protocols[(__pid)]); \
161 if (pd_ && eid_ < pd_->num_events) \
162 __revt = READ_ONCE(pd_->registered_events[eid_]); \
180 r->proto->ops->set_notify_enabled(r->proto->ni->handle, \
193 r->proto->ops->fill_custom_report(r->proto->ni->handle, \
203 * struct scmi_notify_instance - Represents an instance of the notification
211 * all the registered protocol-level specific information
231 * struct events_queue - Describes a queue and its associated worker
247 * struct scmi_event_header - A utility header
249 * to this event as soon as it entered the SCMI RX ISR
267 * struct scmi_registered_events_desc - Protocol Specific information
269 * @ops: Protocol specific and event-related operations
270 * @equeue: The embedded per-protocol events_queue
272 * @eh: A reference to pre-allocated buffer to be used as a scratch area by the
274 * @eh_sz: Size of the pre-allocated buffer @eh
278 * events' descriptors, whose fixed-size is determined at
284 * All protocols that register at least one event have their protocol-specific
291 * we safely grab a NON-NULL reference from the array we can keep it and use it.
309 * struct scmi_registered_event - Event Specific Information
313 * @report: A pre-allocated buffer used by the deferred worker to fill a
326 * safely grab a NON-NULL reference from the table we can keep it and use it.
339 * struct scmi_event_handler - Event handler information
353 * These descriptors are stored in a per-protocol @registered_events_handlers
365 #define IS_HNDL_PENDING(hndl) (!(hndl)->r_evt)
375 * scmi_lookup_and_call_event_chain() - Lookup the proper chain and call it
378 * @report: The customized event-specific report to pass down to the callbacks
398 ret = blocking_notifier_call_chain(&hndl->chain, in scmi_lookup_and_call_event_chain()
408 * scmi_process_event_header() - Dequeue and process an event header
409 * @eq: The queue to use
418 * * ERR_PTR(-EINVAL) when NO registered event could be found
422 scmi_process_event_header(struct events_queue *eq, in scmi_process_event_header() argument
428 outs = kfifo_out(&eq->kfifo, pd->eh, in scmi_process_event_header()
433 dev_err(pd->ni->handle->dev, "corrupted EVT header. Flush.\n"); in scmi_process_event_header()
434 kfifo_reset_out(&eq->kfifo); in scmi_process_event_header()
438 r_evt = SCMI_GET_REVT_FROM_PD(pd, pd->eh->evt_id); in scmi_process_event_header()
440 r_evt = ERR_PTR(-EINVAL); in scmi_process_event_header()
446 * scmi_process_event_payload() - Dequeue and process an event payload
447 * @eq: The queue to use
459 scmi_process_event_payload(struct events_queue *eq, in scmi_process_event_payload() argument
467 outs = kfifo_out(&eq->kfifo, pd->eh->payld, pd->eh->payld_sz); in scmi_process_event_payload()
471 /* Any in-flight event has now been officially processed */ in scmi_process_event_payload()
472 pd->in_flight = NULL; in scmi_process_event_payload()
474 if (outs != pd->eh->payld_sz) { in scmi_process_event_payload()
475 dev_err(pd->ni->handle->dev, "corrupted EVT Payload. Flush.\n"); in scmi_process_event_payload()
476 kfifo_reset_out(&eq->kfifo); in scmi_process_event_payload()
481 dev_warn(pd->ni->handle->dev, in scmi_process_event_payload()
482 "SKIP UNKNOWN EVT - proto:%X evt:%d\n", in scmi_process_event_payload()
483 pd->id, pd->eh->evt_id); in scmi_process_event_payload()
487 report = REVT_FILL_REPORT(r_evt, pd->eh->evt_id, pd->eh->timestamp, in scmi_process_event_payload()
488 pd->eh->payld, pd->eh->payld_sz, in scmi_process_event_payload()
489 r_evt->report, &src_id); in scmi_process_event_payload()
491 dev_err(pd->ni->handle->dev, in scmi_process_event_payload()
492 "report not available - proto:%X evt:%d\n", in scmi_process_event_payload()
493 pd->id, pd->eh->evt_id); in scmi_process_event_payload()
498 key = MAKE_ALL_SRCS_KEY(pd->id, pd->eh->evt_id); in scmi_process_event_payload()
499 scmi_lookup_and_call_event_chain(pd->ni, key, report); in scmi_process_event_payload()
502 key = MAKE_HASH_KEY(pd->id, pd->eh->evt_id, src_id); in scmi_process_event_payload()
503 scmi_lookup_and_call_event_chain(pd->ni, key, report); in scmi_process_event_payload()
509 * scmi_events_dispatcher() - Common worker logic for all work items.
513 * 1. dequeue one pending RX notification (queued in SCMI RX ISR context)
516 * - > call the related notification chain passing in the report
518 * - > call the related notification chain passing in the report
521 * * a dedicated per-protocol kfifo queue is used: in this way an anomalous
523 * * each per-protocol queue is associated to a distinct work_item, which
529 * reader/writer on the associated kfifo, so that we can use it lock-less
535 struct events_queue *eq; in scmi_events_dispatcher() local
539 eq = container_of(work, struct events_queue, notify_work); in scmi_events_dispatcher()
540 pd = container_of(eq, struct scmi_registered_events_desc, equeue); in scmi_events_dispatcher()
542 * In order to keep the queue lock-less and the number of memcopies in scmi_events_dispatcher()
544 * possibility of per-protocol in-flight events: i.e. an event whose in scmi_events_dispatcher()
549 if (!pd->in_flight) { in scmi_events_dispatcher()
550 r_evt = scmi_process_event_header(eq, pd); in scmi_events_dispatcher()
553 pd->in_flight = r_evt; in scmi_events_dispatcher()
555 r_evt = pd->in_flight; in scmi_events_dispatcher()
557 } while (scmi_process_event_payload(eq, pd, r_evt)); in scmi_events_dispatcher()
561 * scmi_notify() - Queues a notification for further deferred processing
568 * @ts: RX Timestamp in nanoseconds (boottime)
584 if (!handle->notify_priv) in scmi_notify()
586 ni = handle->notify_priv; in scmi_notify()
590 return -EINVAL; in scmi_notify()
592 if (len > r_evt->evt->max_payld_sz) { in scmi_notify()
593 dev_err(handle->dev, "discard badly sized message\n"); in scmi_notify()
594 return -EINVAL; in scmi_notify()
596 if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { in scmi_notify()
597 dev_warn(handle->dev, in scmi_notify()
600 return -ENOMEM; in scmi_notify()
609 * with in-flight events tracking. in scmi_notify()
611 kfifo_in(&r_evt->proto->equeue.kfifo, &eh, sizeof(eh)); in scmi_notify()
612 kfifo_in(&r_evt->proto->equeue.kfifo, buf, len); in scmi_notify()
617 * - if work was already queued it will simply fail to queue a new one in scmi_notify()
619 * - if work was not queued already it will be now, even in case work in scmi_notify()
625 queue_work(r_evt->proto->equeue.wq, in scmi_notify()
626 &r_evt->proto->equeue.notify_work); in scmi_notify()
632 * scmi_kfifo_free() - Devres action helper to free the kfifo
641 * scmi_initialize_events_queue() - Allocate/Initialize a kfifo buffer
655 if (kfifo_alloc(&equeue->kfifo, sz, GFP_KERNEL)) in scmi_initialize_events_queue()
656 return -ENOMEM; in scmi_initialize_events_queue()
657 /* Size could have been roundup to power-of-two */ in scmi_initialize_events_queue()
658 equeue->sz = kfifo_size(&equeue->kfifo); in scmi_initialize_events_queue()
660 ret = devm_add_action_or_reset(ni->handle->dev, scmi_kfifo_free, in scmi_initialize_events_queue()
661 &equeue->kfifo); in scmi_initialize_events_queue()
665 INIT_WORK(&equeue->notify_work, scmi_events_dispatcher); in scmi_initialize_events_queue()
666 equeue->wq = ni->notify_wq; in scmi_initialize_events_queue()
672 * scmi_allocate_registered_events_desc() - Allocate a registered events'
678 * @eh_sz: Size of the event header scratch area to pre-allocate
700 if (WARN_ON(ni->registered_protocols[proto_id])) in scmi_allocate_registered_events_desc()
701 return ERR_PTR(-EINVAL); in scmi_allocate_registered_events_desc()
703 pd = devm_kzalloc(ni->handle->dev, sizeof(*pd), GFP_KERNEL); in scmi_allocate_registered_events_desc()
705 return ERR_PTR(-ENOMEM); in scmi_allocate_registered_events_desc()
706 pd->id = proto_id; in scmi_allocate_registered_events_desc()
707 pd->ops = ops; in scmi_allocate_registered_events_desc()
708 pd->ni = ni; in scmi_allocate_registered_events_desc()
710 ret = scmi_initialize_events_queue(ni, &pd->equeue, queue_sz); in scmi_allocate_registered_events_desc()
714 pd->eh = devm_kzalloc(ni->handle->dev, eh_sz, GFP_KERNEL); in scmi_allocate_registered_events_desc()
715 if (!pd->eh) in scmi_allocate_registered_events_desc()
716 return ERR_PTR(-ENOMEM); in scmi_allocate_registered_events_desc()
717 pd->eh_sz = eh_sz; in scmi_allocate_registered_events_desc()
719 pd->registered_events = devm_kcalloc(ni->handle->dev, num_events, in scmi_allocate_registered_events_desc()
721 if (!pd->registered_events) in scmi_allocate_registered_events_desc()
722 return ERR_PTR(-ENOMEM); in scmi_allocate_registered_events_desc()
723 pd->num_events = num_events; in scmi_allocate_registered_events_desc()
726 mutex_init(&pd->registered_mtx); in scmi_allocate_registered_events_desc()
727 hash_init(pd->registered_events_handlers); in scmi_allocate_registered_events_desc()
733 * scmi_register_protocol_events() - Register Protocol Events with the core
738 * @ops: Protocol specific event-related operations
746 * pre-allocate and store all needed descriptors, scratch buffers and event
763 return -EINVAL; in scmi_register_protocol_events()
767 if (!handle->notify_priv) in scmi_register_protocol_events()
768 return -ENOMEM; in scmi_register_protocol_events()
769 ni = handle->notify_priv; in scmi_register_protocol_events()
772 if (!devres_open_group(ni->handle->dev, ni->gid, GFP_KERNEL)) in scmi_register_protocol_events()
773 return -ENOMEM; in scmi_register_protocol_events()
787 r_evt = devm_kzalloc(ni->handle->dev, sizeof(*r_evt), in scmi_register_protocol_events()
791 r_evt->proto = pd; in scmi_register_protocol_events()
792 r_evt->evt = evt; in scmi_register_protocol_events()
794 r_evt->sources = devm_kcalloc(ni->handle->dev, num_sources, in scmi_register_protocol_events()
796 if (!r_evt->sources) in scmi_register_protocol_events()
798 r_evt->num_sources = num_sources; in scmi_register_protocol_events()
799 mutex_init(&r_evt->sources_mtx); in scmi_register_protocol_events()
801 r_evt->report = devm_kzalloc(ni->handle->dev, in scmi_register_protocol_events()
802 evt->max_report_sz, GFP_KERNEL); in scmi_register_protocol_events()
803 if (!r_evt->report) in scmi_register_protocol_events()
806 pd->registered_events[i] = r_evt; in scmi_register_protocol_events()
809 dev_dbg(handle->dev, "registered event - %lX\n", in scmi_register_protocol_events()
810 MAKE_ALL_SRCS_KEY(r_evt->proto->id, r_evt->evt->id)); in scmi_register_protocol_events()
814 ni->registered_protocols[proto_id] = pd; in scmi_register_protocol_events()
818 devres_close_group(ni->handle->dev, ni->gid); in scmi_register_protocol_events()
824 schedule_work(&ni->init_work); in scmi_register_protocol_events()
829 dev_warn(handle->dev, "Proto:%X - Registration Failed !\n", proto_id); in scmi_register_protocol_events()
831 devres_close_group(ni->handle->dev, ni->gid); in scmi_register_protocol_events()
833 return -ENOMEM; in scmi_register_protocol_events()
837 * scmi_allocate_event_handler() - Allocate Event handler
845 * associated to this handler descriptor (hndl->r_evt == NULL), so the handler
859 hndl->key = evt_key; in scmi_allocate_event_handler()
860 BLOCKING_INIT_NOTIFIER_HEAD(&hndl->chain); in scmi_allocate_event_handler()
861 refcount_set(&hndl->users, 1); in scmi_allocate_event_handler()
863 hash_add(ni->pending_events_handlers, &hndl->hash, hndl->key); in scmi_allocate_event_handler()
869 * scmi_free_event_handler() - Free the provided Event handler
877 hash_del(&hndl->hash); in scmi_free_event_handler()
882 * scmi_bind_event_handler() - Helper to attempt binding an handler to an event
898 r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(hndl->key), in scmi_bind_event_handler()
899 KEY_XTRACT_EVT_ID(hndl->key)); in scmi_bind_event_handler()
901 return -EINVAL; in scmi_bind_event_handler()
904 hash_del(&hndl->hash); in scmi_bind_event_handler()
905 hndl->r_evt = r_evt; in scmi_bind_event_handler()
906 mutex_lock(&r_evt->proto->registered_mtx); in scmi_bind_event_handler()
907 hash_add(r_evt->proto->registered_events_handlers, in scmi_bind_event_handler()
908 &hndl->hash, hndl->key); in scmi_bind_event_handler()
909 mutex_unlock(&r_evt->proto->registered_mtx); in scmi_bind_event_handler()
915 * scmi_valid_pending_handler() - Helper to check pending status of handlers
934 return -EINVAL; in scmi_valid_pending_handler()
936 pd = SCMI_GET_PROTO(ni, KEY_XTRACT_PROTO_ID(hndl->key)); in scmi_valid_pending_handler()
938 return -EINVAL; in scmi_valid_pending_handler()
944 * scmi_register_event_handler() - Register whenever possible an Event handler
967 dev_dbg(ni->handle->dev, "registered NEW handler - key:%X\n", in scmi_register_event_handler()
968 hndl->key); in scmi_register_event_handler()
972 dev_dbg(ni->handle->dev, in scmi_register_event_handler()
973 "registered PENDING handler - key:%X\n", in scmi_register_event_handler()
974 hndl->key); in scmi_register_event_handler()
981 * __scmi_event_handler_get_ops() - Utility to get or create an event handler
987 * Search for the desired handler matching the key in both the per-protocol
1020 mutex_lock(&ni->pending_mtx); in __scmi_event_handler_get_ops()
1023 mutex_lock(&r_evt->proto->registered_mtx); in __scmi_event_handler_get_ops()
1024 hndl = KEY_FIND(r_evt->proto->registered_events_handlers, in __scmi_event_handler_get_ops()
1027 refcount_inc(&hndl->users); in __scmi_event_handler_get_ops()
1028 mutex_unlock(&r_evt->proto->registered_mtx); in __scmi_event_handler_get_ops()
1033 hndl = KEY_FIND(ni->pending_events_handlers, hndl, evt_key); in __scmi_event_handler_get_ops()
1035 refcount_inc(&hndl->users); in __scmi_event_handler_get_ops()
1042 dev_dbg(ni->handle->dev, in __scmi_event_handler_get_ops()
1043 "purging UNKNOWN handler - key:%X\n", in __scmi_event_handler_get_ops()
1044 hndl->key); in __scmi_event_handler_get_ops()
1050 mutex_unlock(&ni->pending_mtx); in __scmi_event_handler_get_ops()
1068 * scmi_get_active_handler() - Helper to get active handlers only
1072 * Search for the desired handler matching the key only in the per-protocol
1087 mutex_lock(&r_evt->proto->registered_mtx); in scmi_get_active_handler()
1088 hndl = KEY_FIND(r_evt->proto->registered_events_handlers, in scmi_get_active_handler()
1091 refcount_inc(&hndl->users); in scmi_get_active_handler()
1092 mutex_unlock(&r_evt->proto->registered_mtx); in scmi_get_active_handler()
1099 * __scmi_enable_evt() - Enable/disable events generation
1102 * @enable: The action to perform: true->Enable, false->Disable
1120 num_sources = r_evt->num_sources; in __scmi_enable_evt()
1121 } else if (src_id < r_evt->num_sources) { in __scmi_enable_evt()
1124 return -EINVAL; in __scmi_enable_evt()
1127 mutex_lock(&r_evt->sources_mtx); in __scmi_enable_evt()
1129 for (; num_sources; src_id++, num_sources--) { in __scmi_enable_evt()
1132 sid = &r_evt->sources[src_id]; in __scmi_enable_evt()
1134 ret = REVT_NOTIFY_ENABLE(r_evt, r_evt->evt->id, in __scmi_enable_evt()
1144 for (; num_sources; src_id++, num_sources--) { in __scmi_enable_evt()
1145 sid = &r_evt->sources[src_id]; in __scmi_enable_evt()
1148 r_evt->evt->id, src_id); in __scmi_enable_evt()
1152 mutex_unlock(&r_evt->sources_mtx); in __scmi_enable_evt()
1154 return retvals ? 0 : -EINVAL; in __scmi_enable_evt()
1161 if (!hndl->enabled) { in scmi_enable_events()
1162 ret = __scmi_enable_evt(hndl->r_evt, in scmi_enable_events()
1163 KEY_XTRACT_SRC_ID(hndl->key), true); in scmi_enable_events()
1165 hndl->enabled = true; in scmi_enable_events()
1175 if (hndl->enabled) { in scmi_disable_events()
1176 ret = __scmi_enable_evt(hndl->r_evt, in scmi_disable_events()
1177 KEY_XTRACT_SRC_ID(hndl->key), false); in scmi_disable_events()
1179 hndl->enabled = false; in scmi_disable_events()
1186 * scmi_put_handler_unlocked() - Put an event handler
1200 if (refcount_dec_and_test(&hndl->users)) { in scmi_put_handler_unlocked()
1210 struct scmi_registered_event *r_evt = hndl->r_evt; in scmi_put_handler()
1212 mutex_lock(&ni->pending_mtx); in scmi_put_handler()
1214 mutex_lock(&r_evt->proto->registered_mtx); in scmi_put_handler()
1219 mutex_unlock(&r_evt->proto->registered_mtx); in scmi_put_handler()
1220 mutex_unlock(&ni->pending_mtx); in scmi_put_handler()
1226 struct scmi_registered_event *r_evt = hndl->r_evt; in scmi_put_active_handler()
1228 mutex_lock(&r_evt->proto->registered_mtx); in scmi_put_active_handler()
1230 mutex_unlock(&r_evt->proto->registered_mtx); in scmi_put_active_handler()
1234 * scmi_event_handler_enable_events() - Enable events associated to an handler
1242 pr_err("Failed to ENABLE events for key:%X !\n", hndl->key); in scmi_event_handler_enable_events()
1243 return -EINVAL; in scmi_event_handler_enable_events()
1250 * scmi_register_notifier() - Register a notifier_block for an event
1265 * (proto_X, evt_Y, src_Z) --> chain_X_Y_Z
1293 if (!handle->notify_priv) in scmi_register_notifier()
1294 return -ENODEV; in scmi_register_notifier()
1295 ni = handle->notify_priv; in scmi_register_notifier()
1301 return -EINVAL; in scmi_register_notifier()
1303 blocking_notifier_chain_register(&hndl->chain, nb); in scmi_register_notifier()
1316 * scmi_unregister_notifier() - Unregister a notifier_block for an event
1341 if (!handle->notify_priv) in scmi_unregister_notifier()
1342 return -ENODEV; in scmi_unregister_notifier()
1343 ni = handle->notify_priv; in scmi_unregister_notifier()
1349 return -EINVAL; in scmi_unregister_notifier()
1355 blocking_notifier_chain_unregister(&hndl->chain, nb); in scmi_unregister_notifier()
1375 * scmi_protocols_late_init() - Worker for late initialization
1396 mutex_lock(&ni->pending_mtx); in scmi_protocols_late_init()
1397 hash_for_each_safe(ni->pending_events_handlers, bkt, tmp, hndl, hash) { in scmi_protocols_late_init()
1402 dev_dbg(ni->handle->dev, in scmi_protocols_late_init()
1403 "finalized PENDING handler - key:%X\n", in scmi_protocols_late_init()
1404 hndl->key); in scmi_protocols_late_init()
1407 dev_dbg(ni->handle->dev, in scmi_protocols_late_init()
1408 "purging INVALID handler - key:%X\n", in scmi_protocols_late_init()
1409 hndl->key); in scmi_protocols_late_init()
1415 dev_dbg(ni->handle->dev, in scmi_protocols_late_init()
1416 "purging PENDING handler - key:%X\n", in scmi_protocols_late_init()
1417 hndl->key); in scmi_protocols_late_init()
1423 mutex_unlock(&ni->pending_mtx); in scmi_protocols_late_init()
1436 * scmi_notification_init() - Initializes Notification Core Support
1451 * further per-protocol allocations
1466 gid = devres_open_group(handle->dev, NULL, GFP_KERNEL); in scmi_notification_init()
1468 return -ENOMEM; in scmi_notification_init()
1470 ni = devm_kzalloc(handle->dev, sizeof(*ni), GFP_KERNEL); in scmi_notification_init()
1474 ni->gid = gid; in scmi_notification_init()
1475 ni->handle = handle; in scmi_notification_init()
1477 ni->notify_wq = alloc_workqueue(dev_name(handle->dev), in scmi_notification_init()
1480 if (!ni->notify_wq) in scmi_notification_init()
1483 ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTO, in scmi_notification_init()
1485 if (!ni->registered_protocols) in scmi_notification_init()
1488 mutex_init(&ni->pending_mtx); in scmi_notification_init()
1489 hash_init(ni->pending_events_handlers); in scmi_notification_init()
1491 INIT_WORK(&ni->init_work, scmi_protocols_late_init); in scmi_notification_init()
1493 handle->notify_ops = &notify_ops; in scmi_notification_init()
1494 handle->notify_priv = ni; in scmi_notification_init()
1498 dev_info(handle->dev, "Core Enabled.\n"); in scmi_notification_init()
1500 devres_close_group(handle->dev, ni->gid); in scmi_notification_init()
1505 dev_warn(handle->dev, "Initialization Failed.\n"); in scmi_notification_init()
1506 devres_release_group(handle->dev, NULL); in scmi_notification_init()
1507 return -ENOMEM; in scmi_notification_init()
1511 * scmi_notification_exit() - Shutdown and clean Notification core
1520 if (!handle->notify_priv) in scmi_notification_exit()
1522 ni = handle->notify_priv; in scmi_notification_exit()
1524 handle->notify_priv = NULL; in scmi_notification_exit()
1529 destroy_workqueue(ni->notify_wq); in scmi_notification_exit()
1531 devres_release_group(ni->handle->dev, ni->gid); in scmi_notification_exit()