static int counter_set_event_node()

in counter-chrdev.c [130:185]


static int counter_set_event_node(struct counter_device *const counter,
				  struct counter_watch *const watch,
				  const struct counter_comp_node *const cfg)
{
	struct counter_event_node *event_node;
	int err = 0;
	struct counter_comp_node *comp_node;

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

	/* If event is not already in the list */
	if (&event_node->l == &counter->next_events_list) {
		/* Allocate new event node */
		event_node = kmalloc(sizeof(*event_node), GFP_KERNEL);
		if (!event_node)
			return -ENOMEM;

		/* Configure event node and add to the list */
		event_node->event = watch->event;
		event_node->channel = watch->channel;
		INIT_LIST_HEAD(&event_node->comp_list);
		list_add(&event_node->l, &counter->next_events_list);
	}

	/* Check if component watch has already been set before */
	list_for_each_entry(comp_node, &event_node->comp_list, l)
		if (comp_node->parent == cfg->parent &&
		    counter_comp_read_is_equal(comp_node->comp, cfg->comp)) {
			err = -EINVAL;
			goto exit_free_event_node;
		}

	/* Allocate component node */
	comp_node = kmalloc(sizeof(*comp_node), GFP_KERNEL);
	if (!comp_node) {
		err = -ENOMEM;
		goto exit_free_event_node;
	}
	*comp_node = *cfg;

	/* Add component node to event node */
	list_add_tail(&comp_node->l, &event_node->comp_list);

exit_free_event_node:
	/* Free event node if no one else is watching */
	if (list_empty(&event_node->comp_list)) {
		list_del(&event_node->l);
		kfree(event_node);
	}

	return err;
}