drivers/counter/counter-chrdev.c

Source file repositories/reference/linux-study-clean/drivers/counter/counter-chrdev.c

File Facts

System
Linux kernel
Corpus path
drivers/counter/counter-chrdev.c
Extension
.c
Size
17413 bytes
Lines
676
Domain
Driver Families
Bucket
drivers/counter
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations counter_fops = {
	.owner = THIS_MODULE,
	.read = counter_chrdev_read,
	.poll = counter_chrdev_poll,
	.unlocked_ioctl = counter_chrdev_ioctl,
	.open = counter_chrdev_open,
	.release = counter_chrdev_release,
};

int counter_chrdev_add(struct counter_device *const counter)
{
	/* Initialize Counter events lists */
	INIT_LIST_HEAD(&counter->events_list);
	INIT_LIST_HEAD(&counter->next_events_list);
	spin_lock_init(&counter->events_list_lock);
	mutex_init(&counter->n_events_list_lock);
	init_waitqueue_head(&counter->events_wait);
	spin_lock_init(&counter->events_in_lock);
	mutex_init(&counter->events_out_lock);

	/* Initialize character device */
	cdev_init(&counter->chrdev, &counter_fops);

	/* Allocate Counter events queue */
	return kfifo_alloc(&counter->events, 64, GFP_KERNEL);
}

void counter_chrdev_remove(struct counter_device *const counter)
{
	kfifo_free(&counter->events);
}

static int counter_get_array_data(struct counter_device *const counter,
				  const enum counter_scope scope,
				  void *const parent,
				  const struct counter_comp *const comp,
				  const size_t idx, u64 *const value)
{
	const struct counter_array *const element = comp->priv;
	u32 value_u32 = 0;
	int ret;

	switch (element->type) {
	case COUNTER_COMP_SIGNAL_POLARITY:
		if (scope != COUNTER_SCOPE_SIGNAL)
			return -EINVAL;
		ret = comp->signal_array_u32_read(counter, parent, idx,
						  &value_u32);
		*value = value_u32;
		return ret;
	case COUNTER_COMP_U64:
		switch (scope) {
		case COUNTER_SCOPE_DEVICE:
			return comp->device_array_u64_read(counter, idx, value);
		case COUNTER_SCOPE_SIGNAL:
			return comp->signal_array_u64_read(counter, parent, idx,
							   value);
		case COUNTER_SCOPE_COUNT:
			return comp->count_array_u64_read(counter, parent, idx,
							  value);
		default:
			return -EINVAL;
		}
	default:
		return -EINVAL;
	}
}

static int counter_get_data(struct counter_device *const counter,
			    const struct counter_comp_node *const comp_node,
			    u64 *const value)
{
	const struct counter_comp *const comp = &comp_node->comp;
	const enum counter_scope scope = comp_node->component.scope;
	const size_t id = comp_node->component.id;
	struct counter_signal *const signal = comp_node->parent;
	struct counter_count *const count = comp_node->parent;
	u8 value_u8 = 0;
	u32 value_u32 = 0;
	const struct counter_comp *ext;
	size_t num_ext;
	size_t ext_idx, ext_id;
	int ret;

	if (comp_node->component.type == COUNTER_COMPONENT_NONE)
		return 0;

	switch (comp->type) {
	case COUNTER_COMP_U8:
	case COUNTER_COMP_BOOL:

Annotation

Implementation Notes