drivers/pps/pps.c
Source file repositories/reference/linux-study-clean/drivers/pps/pps.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pps/pps.c- Extension
.c- Size
- 11601 bytes
- Lines
- 504
- 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.
- 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/uaccess.hlinux/idr.hlinux/mutex.hlinux/cdev.hlinux/poll.hlinux/pps_kernel.hlinux/slab.hkc.h
Detected Declarations
function pps_cdev_pollfunction pps_cdev_fasyncfunction pps_cdev_pps_fetchfunction pps_cdev_ioctlfunction pps_cdev_compat_ioctlfunction pps_cdev_openfunction pps_cdev_releasefunction pps_device_destructfunction pps_register_cdevfunction pps_unregister_cdevfunction pps_unregister_sourcefunction pps_exitfunction pps_initmodule init pps_initexport pps_lookup_dev
Annotated Snippet
static const struct file_operations pps_cdev_fops = {
.owner = THIS_MODULE,
.poll = pps_cdev_poll,
.fasync = pps_cdev_fasync,
.compat_ioctl = pps_cdev_compat_ioctl,
.unlocked_ioctl = pps_cdev_ioctl,
.open = pps_cdev_open,
.release = pps_cdev_release,
};
static void pps_device_destruct(struct device *dev)
{
struct pps_device *pps = dev_get_drvdata(dev);
pr_debug("deallocating pps%d\n", pps->id);
kfree(pps);
}
int pps_register_cdev(struct pps_device *pps)
{
int err;
mutex_lock(&pps_idr_lock);
/*
* Get new ID for the new PPS source. After idr_alloc() calling
* the new source will be freely available into the kernel.
*/
err = idr_alloc(&pps_idr, pps, 0, PPS_MAX_SOURCES, GFP_KERNEL);
if (err < 0) {
if (err == -ENOSPC) {
pr_err("%s: too many PPS sources in the system\n",
pps->info.name);
err = -EBUSY;
}
kfree(pps);
goto out_unlock;
}
pps->id = err;
pps->dev.class = &pps_class;
pps->dev.parent = pps->info.dev;
pps->dev.devt = MKDEV(pps_major, pps->id);
dev_set_drvdata(&pps->dev, pps);
dev_set_name(&pps->dev, "pps%d", pps->id);
pps->dev.release = pps_device_destruct;
err = device_register(&pps->dev);
if (err)
goto free_idr;
pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, pps_major,
pps->id);
get_device(&pps->dev);
mutex_unlock(&pps_idr_lock);
return 0;
free_idr:
idr_remove(&pps_idr, pps->id);
put_device(&pps->dev);
out_unlock:
mutex_unlock(&pps_idr_lock);
return err;
}
void pps_unregister_cdev(struct pps_device *pps)
{
pr_debug("unregistering pps%d\n", pps->id);
pps->lookup_cookie = NULL;
device_destroy(&pps_class, pps->dev.devt);
/* Now we can release the ID for re-use */
mutex_lock(&pps_idr_lock);
idr_remove(&pps_idr, pps->id);
put_device(&pps->dev);
mutex_unlock(&pps_idr_lock);
}
/*
* Look up a pps device by magic cookie.
* The cookie is usually a pointer to some enclosing device, but this
* code doesn't care; you should never be dereferencing it.
*
* This is a bit of a kludge that is currently used only by the PPS
* serial line discipline. It may need to be tweaked when a second user
* is found.
*
* There is no function interface for setting the lookup_cookie field.
* It's initialized to NULL when the pps device is created, and if a
* client wants to use it, just fill it in afterward.
*
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/module.h`, `linux/init.h`, `linux/sched.h`, `linux/uaccess.h`, `linux/idr.h`, `linux/mutex.h`, `linux/cdev.h`.
- Detected declarations: `function pps_cdev_poll`, `function pps_cdev_fasync`, `function pps_cdev_pps_fetch`, `function pps_cdev_ioctl`, `function pps_cdev_compat_ioctl`, `function pps_cdev_open`, `function pps_cdev_release`, `function pps_device_destruct`, `function pps_register_cdev`, `function pps_unregister_cdev`.
- 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.