drivers/pps/generators/pps_gen.c
Source file repositories/reference/linux-study-clean/drivers/pps/generators/pps_gen.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pps/generators/pps_gen.c- Extension
.c- Size
- 7844 bytes
- Lines
- 347
- Domain
- Driver Families
- Bucket
- drivers/pps
- 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/kernel.hlinux/module.hlinux/init.hlinux/sched.hlinux/time.hlinux/timex.hlinux/uaccess.hlinux/idr.hlinux/cdev.hlinux/poll.hlinux/fs.hlinux/pps_gen_kernel.hlinux/slab.h
Detected Declarations
function pps_gen_cdev_pollfunction pps_gen_cdev_fasyncfunction pps_gen_cdev_ioctlfunction pps_gen_cdev_openfunction pps_gen_cdev_releasefunction pps_gen_device_destructfunction pps_gen_register_cdevfunction pps_gen_unregister_cdevfunction pps_gen_register_sourcefunction pps_gen_unregister_sourcefunction systemfunction pps_gen_exitfunction pps_gen_initmodule init pps_gen_initexport pps_gen_register_sourceexport pps_gen_unregister_sourceexport pps_gen_event
Annotated Snippet
static const struct file_operations pps_gen_cdev_fops = {
.owner = THIS_MODULE,
.poll = pps_gen_cdev_poll,
.fasync = pps_gen_cdev_fasync,
.unlocked_ioctl = pps_gen_cdev_ioctl,
.open = pps_gen_cdev_open,
.release = pps_gen_cdev_release,
};
static void pps_gen_device_destruct(struct device *dev)
{
struct pps_gen_device *pps_gen = dev_get_drvdata(dev);
cdev_del(&pps_gen->cdev);
pr_debug("deallocating pps-gen%d\n", pps_gen->id);
ida_free(&pps_gen_ida, pps_gen->id);
kfree(dev);
kfree(pps_gen);
}
static int pps_gen_register_cdev(struct pps_gen_device *pps_gen)
{
int err;
dev_t devt;
err = ida_alloc_max(&pps_gen_ida, PPS_GEN_MAX_SOURCES - 1, GFP_KERNEL);
if (err < 0) {
if (err == -ENOSPC) {
pr_err("too many PPS sources in the system\n");
err = -EBUSY;
}
return err;
}
pps_gen->id = err;
devt = MKDEV(MAJOR(pps_gen_devt), pps_gen->id);
cdev_init(&pps_gen->cdev, &pps_gen_cdev_fops);
pps_gen->cdev.owner = pps_gen->info->owner;
err = cdev_add(&pps_gen->cdev, devt, 1);
if (err) {
pr_err("failed to add char device %d:%d\n",
MAJOR(pps_gen_devt), pps_gen->id);
goto free_ida;
}
pps_gen->dev = device_create(&pps_gen_class, pps_gen->info->parent, devt,
pps_gen, "pps-gen%d", pps_gen->id);
if (IS_ERR(pps_gen->dev)) {
err = PTR_ERR(pps_gen->dev);
goto del_cdev;
}
pps_gen->dev->release = pps_gen_device_destruct;
dev_set_drvdata(pps_gen->dev, pps_gen);
pr_debug("generator got cdev (%d:%d)\n",
MAJOR(pps_gen_devt), pps_gen->id);
return 0;
del_cdev:
cdev_del(&pps_gen->cdev);
free_ida:
ida_free(&pps_gen_ida, pps_gen->id);
return err;
}
static void pps_gen_unregister_cdev(struct pps_gen_device *pps_gen)
{
pr_debug("unregistering pps-gen%d\n", pps_gen->id);
device_destroy(&pps_gen_class, pps_gen->dev->devt);
}
/*
* Exported functions
*/
/**
* pps_gen_register_source() - add a PPS generator in the system
* @info: the PPS generator info struct
*
* This function is used to register a new PPS generator in the system.
* When it returns successfully the new generator is up and running, and
* it can be managed by the userspace.
*
* Return: the PPS generator device in case of success, and ERR_PTR(errno)
* otherwise.
*/
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/module.h`, `linux/init.h`, `linux/sched.h`, `linux/time.h`, `linux/timex.h`, `linux/uaccess.h`, `linux/idr.h`.
- Detected declarations: `function pps_gen_cdev_poll`, `function pps_gen_cdev_fasync`, `function pps_gen_cdev_ioctl`, `function pps_gen_cdev_open`, `function pps_gen_cdev_release`, `function pps_gen_device_destruct`, `function pps_gen_register_cdev`, `function pps_gen_unregister_cdev`, `function pps_gen_register_source`, `function pps_gen_unregister_source`.
- Atlas domain: Driver Families / drivers/pps.
- 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.