Lines Matching +full:comp +full:- +full:int
1 // SPDX-License-Identifier: GPL-2.0
24 #include "counter-chrdev.h"
29 struct counter_comp comp; member
49 #define counter_comp_read_is_set(comp) \ argument
50 (comp.action_read || \
51 comp.device_u8_read || \
52 comp.count_u8_read || \
53 comp.signal_u8_read || \
54 comp.device_u32_read || \
55 comp.count_u32_read || \
56 comp.signal_u32_read || \
57 comp.device_u64_read || \
58 comp.count_u64_read || \
59 comp.signal_u64_read || \
60 comp.signal_array_u32_read || \
61 comp.device_array_u64_read || \
62 comp.count_array_u64_read || \
63 comp.signal_array_u64_read)
68 struct counter_device *const counter = filp->private_data; in counter_chrdev_read()
69 int err; in counter_chrdev_read()
70 unsigned int copied; in counter_chrdev_read()
72 if (!counter->ops) in counter_chrdev_read()
73 return -ENODEV; in counter_chrdev_read()
76 return -EINVAL; in counter_chrdev_read()
79 if (kfifo_is_empty(&counter->events)) { in counter_chrdev_read()
80 if (filp->f_flags & O_NONBLOCK) in counter_chrdev_read()
81 return -EAGAIN; in counter_chrdev_read()
83 err = wait_event_interruptible(counter->events_wait, in counter_chrdev_read()
84 !kfifo_is_empty(&counter->events) || in counter_chrdev_read()
85 !counter->ops); in counter_chrdev_read()
88 if (!counter->ops) in counter_chrdev_read()
89 return -ENODEV; in counter_chrdev_read()
92 if (mutex_lock_interruptible(&counter->events_out_lock)) in counter_chrdev_read()
93 return -ERESTARTSYS; in counter_chrdev_read()
94 err = kfifo_to_user(&counter->events, buf, len, &copied); in counter_chrdev_read()
95 mutex_unlock(&counter->events_out_lock); in counter_chrdev_read()
106 struct counter_device *const counter = filp->private_data; in counter_chrdev_poll()
109 if (!counter->ops) in counter_chrdev_poll()
112 poll_wait(filp, &counter->events_wait, pollt); in counter_chrdev_poll()
114 if (!kfifo_is_empty(&counter->events)) in counter_chrdev_poll()
127 list_for_each_entry_safe(q, o, &p->comp_list, l) { in counter_events_list_free()
128 list_del(&q->l); in counter_events_list_free()
133 list_del(&p->l); in counter_events_list_free()
138 static int counter_set_event_node(struct counter_device *const counter, in counter_set_event_node()
143 int err = 0; in counter_set_event_node()
147 list_for_each_entry(event_node, &counter->next_events_list, l) in counter_set_event_node()
148 if (event_node->event == watch->event && in counter_set_event_node()
149 event_node->channel == watch->channel) in counter_set_event_node()
153 if (&event_node->l == &counter->next_events_list) { in counter_set_event_node()
157 return -ENOMEM; in counter_set_event_node()
160 event_node->event = watch->event; in counter_set_event_node()
161 event_node->channel = watch->channel; in counter_set_event_node()
162 INIT_LIST_HEAD(&event_node->comp_list); in counter_set_event_node()
163 list_add(&event_node->l, &counter->next_events_list); in counter_set_event_node()
167 list_for_each_entry(comp_node, &event_node->comp_list, l) in counter_set_event_node()
168 if (comp_node->parent == cfg->parent && in counter_set_event_node()
169 counter_comp_read_is_equal(comp_node->comp, cfg->comp)) { in counter_set_event_node()
170 err = -EINVAL; in counter_set_event_node()
177 err = -ENOMEM; in counter_set_event_node()
183 list_add_tail(&comp_node->l, &event_node->comp_list); in counter_set_event_node()
187 if (list_empty(&event_node->comp_list)) { in counter_set_event_node()
188 list_del(&event_node->l); in counter_set_event_node()
195 static int counter_enable_events(struct counter_device *const counter) in counter_enable_events()
198 int err = 0; in counter_enable_events()
200 mutex_lock(&counter->n_events_list_lock); in counter_enable_events()
201 spin_lock_irqsave(&counter->events_list_lock, flags); in counter_enable_events()
203 counter_events_list_free(&counter->events_list); in counter_enable_events()
204 list_replace_init(&counter->next_events_list, in counter_enable_events()
205 &counter->events_list); in counter_enable_events()
207 if (counter->ops->events_configure) in counter_enable_events()
208 err = counter->ops->events_configure(counter); in counter_enable_events()
210 spin_unlock_irqrestore(&counter->events_list_lock, flags); in counter_enable_events()
211 mutex_unlock(&counter->n_events_list_lock); in counter_enable_events()
216 static int counter_disable_events(struct counter_device *const counter) in counter_disable_events()
219 int err = 0; in counter_disable_events()
221 spin_lock_irqsave(&counter->events_list_lock, flags); in counter_disable_events()
223 counter_events_list_free(&counter->events_list); in counter_disable_events()
225 if (counter->ops->events_configure) in counter_disable_events()
226 err = counter->ops->events_configure(counter); in counter_disable_events()
228 spin_unlock_irqrestore(&counter->events_list_lock, flags); in counter_disable_events()
230 mutex_lock(&counter->n_events_list_lock); in counter_disable_events()
232 counter_events_list_free(&counter->next_events_list); in counter_disable_events()
234 mutex_unlock(&counter->n_events_list_lock); in counter_disable_events()
239 static int counter_get_ext(const struct counter_comp *const ext, in counter_get_ext()
253 if (component_id - *id < element->length) in counter_get_ext()
256 *id += element->length; in counter_get_ext()
261 return -EINVAL; in counter_get_ext()
264 static int counter_add_watch(struct counter_device *const counter, in counter_add_watch()
274 int err = 0; in counter_add_watch()
277 return -EFAULT; in counter_add_watch()
284 /* Configure parent component info for comp node */ in counter_add_watch()
287 ext = counter->ext; in counter_add_watch()
288 num_ext = counter->num_ext; in counter_add_watch()
291 if (parent >= counter->num_signals) in counter_add_watch()
292 return -EINVAL; in counter_add_watch()
293 parent = array_index_nospec(parent, counter->num_signals); in counter_add_watch()
295 comp_node.parent = counter->signals + parent; in counter_add_watch()
297 ext = counter->signals[parent].ext; in counter_add_watch()
298 num_ext = counter->signals[parent].num_ext; in counter_add_watch()
301 if (parent >= counter->num_counts) in counter_add_watch()
302 return -EINVAL; in counter_add_watch()
303 parent = array_index_nospec(parent, counter->num_counts); in counter_add_watch()
305 comp_node.parent = counter->counts + parent; in counter_add_watch()
307 ext = counter->counts[parent].ext; in counter_add_watch()
308 num_ext = counter->counts[parent].num_ext; in counter_add_watch()
311 return -EINVAL; in counter_add_watch()
316 /* Configure component info for comp node */ in counter_add_watch()
320 return -EINVAL; in counter_add_watch()
322 comp_node.comp.type = COUNTER_COMP_SIGNAL_LEVEL; in counter_add_watch()
323 comp_node.comp.signal_u32_read = counter->ops->signal_read; in counter_add_watch()
327 return -EINVAL; in counter_add_watch()
329 comp_node.comp.type = COUNTER_COMP_U64; in counter_add_watch()
330 comp_node.comp.count_u64_read = counter->ops->count_read; in counter_add_watch()
334 return -EINVAL; in counter_add_watch()
336 comp_node.comp.type = COUNTER_COMP_FUNCTION; in counter_add_watch()
337 comp_node.comp.count_u32_read = counter->ops->function_read; in counter_add_watch()
341 return -EINVAL; in counter_add_watch()
342 if (id >= counter->counts[parent].num_synapses) in counter_add_watch()
343 return -EINVAL; in counter_add_watch()
344 id = array_index_nospec(id, counter->counts[parent].num_synapses); in counter_add_watch()
346 comp_node.comp.type = COUNTER_COMP_SYNAPSE_ACTION; in counter_add_watch()
347 comp_node.comp.action_read = counter->ops->action_read; in counter_add_watch()
348 comp_node.comp.priv = counter->counts[parent].synapses + id; in counter_add_watch()
355 comp_node.comp = ext[ext_idx]; in counter_add_watch()
358 return -EINVAL; in counter_add_watch()
360 if (!counter_comp_read_is_set(comp_node.comp)) in counter_add_watch()
361 return -EOPNOTSUPP; in counter_add_watch()
364 mutex_lock(&counter->n_events_list_lock); in counter_add_watch()
366 if (counter->ops->watch_validate) { in counter_add_watch()
367 err = counter->ops->watch_validate(counter, &watch); in counter_add_watch()
377 mutex_unlock(&counter->n_events_list_lock); in counter_add_watch()
382 static long counter_chrdev_ioctl(struct file *filp, unsigned int cmd, in counter_chrdev_ioctl()
385 struct counter_device *const counter = filp->private_data; in counter_chrdev_ioctl()
386 int ret = -ENODEV; in counter_chrdev_ioctl()
388 mutex_lock(&counter->ops_exist_lock); in counter_chrdev_ioctl()
390 if (!counter->ops) in counter_chrdev_ioctl()
404 ret = -ENOIOCTLCMD; in counter_chrdev_ioctl()
409 mutex_unlock(&counter->ops_exist_lock); in counter_chrdev_ioctl()
414 static int counter_chrdev_open(struct inode *inode, struct file *filp) in counter_chrdev_open()
416 struct counter_device *const counter = container_of(inode->i_cdev, in counter_chrdev_open()
420 get_device(&counter->dev); in counter_chrdev_open()
421 filp->private_data = counter; in counter_chrdev_open()
426 static int counter_chrdev_release(struct inode *inode, struct file *filp) in counter_chrdev_release()
428 struct counter_device *const counter = filp->private_data; in counter_chrdev_release()
429 int ret = 0; in counter_chrdev_release()
431 mutex_lock(&counter->ops_exist_lock); in counter_chrdev_release()
433 if (!counter->ops) { in counter_chrdev_release()
435 counter_events_list_free(&counter->events_list); in counter_chrdev_release()
436 counter_events_list_free(&counter->next_events_list); in counter_chrdev_release()
437 ret = -ENODEV; in counter_chrdev_release()
443 mutex_unlock(&counter->ops_exist_lock); in counter_chrdev_release()
448 mutex_unlock(&counter->ops_exist_lock); in counter_chrdev_release()
450 put_device(&counter->dev); in counter_chrdev_release()
464 int counter_chrdev_add(struct counter_device *const counter) in counter_chrdev_add()
467 INIT_LIST_HEAD(&counter->events_list); in counter_chrdev_add()
468 INIT_LIST_HEAD(&counter->next_events_list); in counter_chrdev_add()
469 spin_lock_init(&counter->events_list_lock); in counter_chrdev_add()
470 mutex_init(&counter->n_events_list_lock); in counter_chrdev_add()
471 init_waitqueue_head(&counter->events_wait); in counter_chrdev_add()
472 spin_lock_init(&counter->events_in_lock); in counter_chrdev_add()
473 mutex_init(&counter->events_out_lock); in counter_chrdev_add()
476 cdev_init(&counter->chrdev, &counter_fops); in counter_chrdev_add()
479 return kfifo_alloc(&counter->events, 64, GFP_KERNEL); in counter_chrdev_add()
484 kfifo_free(&counter->events); in counter_chrdev_remove()
487 static int counter_get_array_data(struct counter_device *const counter, in counter_get_array_data()
490 const struct counter_comp *const comp, in counter_get_array_data() argument
493 const struct counter_array *const element = comp->priv; in counter_get_array_data()
495 int ret; in counter_get_array_data()
497 switch (element->type) { in counter_get_array_data()
500 return -EINVAL; in counter_get_array_data()
501 ret = comp->signal_array_u32_read(counter, parent, idx, in counter_get_array_data()
508 return comp->device_array_u64_read(counter, idx, value); in counter_get_array_data()
510 return comp->signal_array_u64_read(counter, parent, idx, in counter_get_array_data()
513 return comp->count_array_u64_read(counter, parent, idx, in counter_get_array_data()
516 return -EINVAL; in counter_get_array_data()
519 return -EINVAL; in counter_get_array_data()
523 static int counter_get_data(struct counter_device *const counter, in counter_get_data()
527 const struct counter_comp *const comp = &comp_node->comp; in counter_get_data() local
528 const enum counter_scope scope = comp_node->component.scope; in counter_get_data()
529 const size_t id = comp_node->component.id; in counter_get_data()
530 struct counter_signal *const signal = comp_node->parent; in counter_get_data()
531 struct counter_count *const count = comp_node->parent; in counter_get_data()
537 int ret; in counter_get_data()
539 if (comp_node->component.type == COUNTER_COMPONENT_NONE) in counter_get_data()
542 switch (comp->type) { in counter_get_data()
547 ret = comp->device_u8_read(counter, &value_u8); in counter_get_data()
550 ret = comp->signal_u8_read(counter, signal, &value_u8); in counter_get_data()
553 ret = comp->count_u8_read(counter, count, &value_u8); in counter_get_data()
556 return -EINVAL; in counter_get_data()
568 ret = comp->device_u32_read(counter, &value_u32); in counter_get_data()
571 ret = comp->signal_u32_read(counter, signal, in counter_get_data()
575 ret = comp->count_u32_read(counter, count, &value_u32); in counter_get_data()
578 return -EINVAL; in counter_get_data()
585 return comp->device_u64_read(counter, value); in counter_get_data()
587 return comp->signal_u64_read(counter, signal, value); in counter_get_data()
589 return comp->count_u64_read(counter, count, value); in counter_get_data()
591 return -EINVAL; in counter_get_data()
594 ret = comp->action_read(counter, count, comp->priv, &value_u32); in counter_get_data()
600 ext = counter->ext; in counter_get_data()
601 num_ext = counter->num_ext; in counter_get_data()
604 ext = signal->ext; in counter_get_data()
605 num_ext = signal->num_ext; in counter_get_data()
608 ext = count->ext; in counter_get_data()
609 num_ext = count->num_ext; in counter_get_data()
612 return -EINVAL; in counter_get_data()
618 return counter_get_array_data(counter, scope, comp_node->parent, in counter_get_data()
619 comp, id - ext_id, value); in counter_get_data()
621 return -EINVAL; in counter_get_data()
626 * counter_push_event - queue event for userspace reading
638 unsigned int copied = 0; in counter_push_event()
648 spin_lock_irqsave(&counter->events_list_lock, flags); in counter_push_event()
651 list_for_each_entry(event_node, &counter->events_list, l) in counter_push_event()
652 if (event_node->event == event && in counter_push_event()
653 event_node->channel == channel) in counter_push_event()
657 if (&event_node->l == &counter->events_list) in counter_push_event()
660 /* Read and queue relevant comp for userspace */ in counter_push_event()
661 list_for_each_entry(comp_node, &event_node->comp_list, l) { in counter_push_event()
662 ev.watch.component = comp_node->component; in counter_push_event()
663 ev.status = -counter_get_data(counter, comp_node, &ev.value); in counter_push_event()
665 copied += kfifo_in_spinlocked_noirqsave(&counter->events, &ev, in counter_push_event()
666 1, &counter->events_in_lock); in counter_push_event()
670 spin_unlock_irqrestore(&counter->events_list_lock, flags); in counter_push_event()
673 wake_up_poll(&counter->events_wait, EPOLLIN); in counter_push_event()