drivers/ptp/ptp_chardev.c
Source file repositories/reference/linux-study-clean/drivers/ptp/ptp_chardev.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/ptp/ptp_chardev.c- Extension
.c- Size
- 17354 bytes
- Lines
- 647
- Domain
- Driver Families
- Bucket
- drivers/ptp
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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/compat.hlinux/module.hlinux/posix-clock.hlinux/poll.hlinux/sched.hlinux/slab.hlinux/timekeeping.hlinux/debugfs.hlinux/nospec.hptp_private.h
Detected Declarations
function Copyrightfunction ptp_disable_all_eventsfunction ptp_set_pinfuncfunction ptp_openfunction ptp_releasefunction ptp_clock_getcapsfunction ptp_extts_requestfunction ptp_perout_requestfunction ptp_enable_ppsfunction ptp_sys_offset_precisefunction ptp_sys_offset_extendedfunction ptp_sys_offsetfunction ptp_pin_getfuncfunction ptp_pin_setfuncfunction ptp_mask_clear_allfunction ptp_mask_en_singlefunction ptp_ioctlfunction ptp_pollfunction ptp_readfunction scoped_guard
Annotated Snippet
if (perout->flags & PTP_PEROUT_DUTY_CYCLE) {
/* The duty cycle must be subunitary. */
if (perout->on.sec > perout->period.sec ||
(perout->on.sec == perout->period.sec &&
perout->on.nsec > perout->period.nsec))
return -ERANGE;
}
if (perout->flags & PTP_PEROUT_PHASE) {
/*
* The phase should be specified modulo the period,
* therefore anything equal or larger than 1 period
* is invalid.
*/
if (perout->phase.sec > perout->period.sec ||
(perout->phase.sec == perout->period.sec &&
perout->phase.nsec >= perout->period.nsec))
return -ERANGE;
}
} else {
perout->flags &= PTP_PEROUT_V1_VALID_FLAGS;
memset(perout->rsv, 0, sizeof(perout->rsv));
}
if (perout->index >= ops->n_per_out)
return -EINVAL;
if (perout->flags & ~ops->supported_perout_flags)
return -EOPNOTSUPP;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &ptp->pincfg_mux)
return ops->enable(ops, &req, perout->period.sec || perout->period.nsec);
}
static long ptp_enable_pps(struct ptp_clock *ptp, bool enable)
{
struct ptp_clock_request req = { .type = PTP_CLK_REQ_PPS };
struct ptp_clock_info *ops = ptp->info;
if (!capable(CAP_SYS_TIME))
return -EPERM;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &ptp->pincfg_mux)
return ops->enable(ops, &req, enable);
}
typedef int (*ptp_crosststamp_fn)(struct ptp_clock_info *,
struct system_device_crosststamp *);
static long ptp_sys_offset_precise(struct ptp_clock *ptp, void __user *arg,
ptp_crosststamp_fn crosststamp_fn)
{
struct system_device_crosststamp xtstamp = { .clock_id = CLOCK_REALTIME };
struct ptp_sys_offset_precise precise_offset;
struct timespec64 ts;
int err;
if (!crosststamp_fn)
return -EOPNOTSUPP;
err = crosststamp_fn(ptp->info, &xtstamp);
if (err)
return err;
memset(&precise_offset, 0, sizeof(precise_offset));
ts = ktime_to_timespec64(xtstamp.device);
precise_offset.device.sec = ts.tv_sec;
precise_offset.device.nsec = ts.tv_nsec;
ts = ktime_to_timespec64(xtstamp.sys_systime);
precise_offset.sys_realtime.sec = ts.tv_sec;
precise_offset.sys_realtime.nsec = ts.tv_nsec;
ts = ktime_to_timespec64(xtstamp.sys_monoraw);
precise_offset.sys_monoraw.sec = ts.tv_sec;
precise_offset.sys_monoraw.nsec = ts.tv_nsec;
return copy_to_user(arg, &precise_offset, sizeof(precise_offset)) ? -EFAULT : 0;
}
typedef int (*ptp_gettimex_fn)(struct ptp_clock_info *,
struct timespec64 *,
struct ptp_system_timestamp *);
static long ptp_sys_offset_extended(struct ptp_clock *ptp, void __user *arg,
ptp_gettimex_fn gettimex_fn)
{
struct ptp_sys_offset_extended *extoff __free(kfree) = NULL;
struct ptp_system_timestamp sts;
if (!gettimex_fn)
return -EOPNOTSUPP;
Annotation
- Immediate include surface: `linux/compat.h`, `linux/module.h`, `linux/posix-clock.h`, `linux/poll.h`, `linux/sched.h`, `linux/slab.h`, `linux/timekeeping.h`, `linux/debugfs.h`.
- Detected declarations: `function Copyright`, `function ptp_disable_all_events`, `function ptp_set_pinfunc`, `function ptp_open`, `function ptp_release`, `function ptp_clock_getcaps`, `function ptp_extts_request`, `function ptp_perout_request`, `function ptp_enable_pps`, `function ptp_sys_offset_precise`.
- Atlas domain: Driver Families / drivers/ptp.
- Implementation status: source 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.