void counter_push_event()

in counter-chrdev.c [532:572]


void counter_push_event(struct counter_device *const counter, const u8 event,
			const u8 channel)
{
	struct counter_event ev;
	unsigned int copied = 0;
	unsigned long flags;
	struct counter_event_node *event_node;
	struct counter_comp_node *comp_node;

	ev.timestamp = ktime_get_ns();
	ev.watch.event = event;
	ev.watch.channel = channel;

	/* Could be in an interrupt context, so use a spin lock */
	spin_lock_irqsave(&counter->events_list_lock, flags);

	/* Search for event in the list */
	list_for_each_entry(event_node, &counter->events_list, l)
		if (event_node->event == event &&
		    event_node->channel == channel)
			break;

	/* If event is not in the list */
	if (&event_node->l == &counter->events_list)
		goto exit_early;

	/* Read and queue relevant comp for userspace */
	list_for_each_entry(comp_node, &event_node->comp_list, l) {
		ev.watch.component = comp_node->component;
		ev.status = -counter_get_data(counter, comp_node, &ev.value);

		copied += kfifo_in_spinlocked_noirqsave(&counter->events, &ev,
							1, &counter->events_in_lock);
	}

exit_early:
	spin_unlock_irqrestore(&counter->events_list_lock, flags);

	if (copied)
		wake_up_poll(&counter->events_wait, EPOLLIN);
}