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.
- 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/cdev.hlinux/counter.hlinux/err.hlinux/errno.hlinux/export.hlinux/fs.hlinux/kfifo.hlinux/list.hlinux/mutex.hlinux/nospec.hlinux/poll.hlinux/slab.hlinux/spinlock.hlinux/timekeeping.hlinux/types.hlinux/uaccess.hlinux/wait.hcounter-chrdev.h
Detected Declarations
struct counter_comp_nodefunction counter_chrdev_readfunction counter_chrdev_pollfunction counter_events_list_freefunction list_for_each_entry_safefunction counter_set_event_nodefunction counter_enable_eventsfunction counter_disable_eventsfunction counter_get_extfunction counter_add_watchfunction counter_chrdev_ioctlfunction counter_chrdev_openfunction counter_chrdev_releasefunction counter_chrdev_addfunction counter_chrdev_removefunction counter_get_array_datafunction counter_get_datafunction counter_push_event
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
- Immediate include surface: `linux/cdev.h`, `linux/counter.h`, `linux/err.h`, `linux/errno.h`, `linux/export.h`, `linux/fs.h`, `linux/kfifo.h`, `linux/list.h`.
- Detected declarations: `struct counter_comp_node`, `function counter_chrdev_read`, `function counter_chrdev_poll`, `function counter_events_list_free`, `function list_for_each_entry_safe`, `function counter_set_event_node`, `function counter_enable_events`, `function counter_disable_events`, `function counter_get_ext`, `function counter_add_watch`.
- Atlas domain: Driver Families / drivers/counter.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.