aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ptp/ptp_chardev.c33
-rw-r--r--include/uapi/linux/ptp_clock.h17
2 files changed, 41 insertions, 9 deletions
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 375cd6e4aade..e0e6f85966e1 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -191,12 +191,33 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
err = -EFAULT;
break;
}
- if (((req.perout.flags & ~PTP_PEROUT_VALID_FLAGS) ||
- req.perout.rsv[0] || req.perout.rsv[1] ||
- req.perout.rsv[2] || req.perout.rsv[3]) &&
- cmd == PTP_PEROUT_REQUEST2) {
- err = -EINVAL;
- break;
+ if (cmd == PTP_PEROUT_REQUEST2) {
+ struct ptp_perout_request *perout = &req.perout;
+
+ if (perout->flags & ~PTP_PEROUT_VALID_FLAGS) {
+ err = -EINVAL;
+ break;
+ }
+ /*
+ * The "on" field has undefined meaning if
+ * PTP_PEROUT_DUTY_CYCLE isn't set, we must still treat
+ * it as reserved, which must be set to zero.
+ */
+ if (!(perout->flags & PTP_PEROUT_DUTY_CYCLE) &&
+ (perout->rsv[0] || perout->rsv[1] ||
+ perout->rsv[2] || perout->rsv[3])) {
+ err = -EINVAL;
+ break;
+ }
+ 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)) {
+ err = -ERANGE;
+ break;
+ }
+ }
} else if (cmd == PTP_PEROUT_REQUEST) {
req.perout.flags &= PTP_PEROUT_V1_VALID_FLAGS;
req.perout.rsv[0] = 0;
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index ff070aa64278..1d2841155f7d 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -53,12 +53,14 @@
/*
* Bits of the ptp_perout_request.flags field:
*/
-#define PTP_PEROUT_ONE_SHOT (1<<0)
+#define PTP_PEROUT_ONE_SHOT (1<<0)
+#define PTP_PEROUT_DUTY_CYCLE (1<<1)
/*
* flag fields valid for the new PTP_PEROUT_REQUEST2 ioctl.
*/
-#define PTP_PEROUT_VALID_FLAGS (PTP_PEROUT_ONE_SHOT)
+#define PTP_PEROUT_VALID_FLAGS (PTP_PEROUT_ONE_SHOT | \
+ PTP_PEROUT_DUTY_CYCLE)
/*
* No flags are valid for the original PTP_PEROUT_REQUEST ioctl
@@ -105,7 +107,16 @@ struct ptp_perout_request {
struct ptp_clock_time period; /* Desired period, zero means disable. */
unsigned int index; /* Which channel to configure. */
unsigned int flags;
- unsigned int rsv[4]; /* Reserved for future use. */
+ union {
+ /*
+ * The "on" time of the signal.
+ * Must be lower than the period.
+ * Valid only if (flags & PTP_PEROUT_DUTY_CYCLE) is set.
+ */
+ struct ptp_clock_time on;
+ /* Reserved for future use. */
+ unsigned int rsv[4];
+ };
};
#define PTP_MAX_SAMPLES 25 /* Maximum allowed offset measurement samples. */