--- v14
+++ v12
@@ -8,22 +8,22 @@
Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
- Documentation/ABI/testing/sysfs-ptp | 98 +++++++++
+ Documentation/ABI/testing/sysfs-ptp | 98 ++++++++++
Documentation/ptp/ptp.txt | 89 +++++++++
- Documentation/ptp/testptp.c | 368 +++++++++++++++++++++++++++++++++++
- Documentation/ptp/testptp.mk | 33 +++
+ Documentation/ptp/testptp.c | 352 +++++++++++++++++++++++++++++++++++
+ Documentation/ptp/testptp.mk | 33 ++++
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/ptp/Kconfig | 30 +++
drivers/ptp/Makefile | 6 +
- drivers/ptp/ptp_chardev.c | 159 +++++++++++++++
- drivers/ptp/ptp_clock.c | 343 ++++++++++++++++++++++++++++++++
- drivers/ptp/ptp_private.h | 92 +++++++++
- drivers/ptp/ptp_sysfs.c | 230 ++++++++++++++++++++++
+ drivers/ptp/ptp_chardev.c | 156 ++++++++++++++++
+ drivers/ptp/ptp_clock.c | 320 +++++++++++++++++++++++++++++++
+ drivers/ptp/ptp_private.h | 86 +++++++++
+ drivers/ptp/ptp_sysfs.c | 230 +++++++++++++++++++++++
include/linux/Kbuild | 1 +
- include/linux/ptp_clock.h | 84 ++++++++
- include/linux/ptp_clock_kernel.h | 139 +++++++++++++
- 15 files changed, 1675 insertions(+), 0 deletions(-)
+ include/linux/ptp_clock.h | 84 +++++++++
+ include/linux/ptp_clock_kernel.h | 139 ++++++++++++++
+ 15 files changed, 1627 insertions(+), 0 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-ptp
create mode 100644 Documentation/ptp/ptp.txt
create mode 100644 Documentation/ptp/testptp.c
@@ -238,10 +238,10 @@
+ - Target Time (optional interrupt)
diff --git a/Documentation/ptp/testptp.c b/Documentation/ptp/testptp.c
new file mode 100644
-index 0000000..dd53e44
+index 0000000..a1d2bf1
--- /dev/null
+++ b/Documentation/ptp/testptp.c
-@@ -0,0 +1,368 @@
+@@ -0,0 +1,352 @@
+/*
+ * PTP 1588 clock support - User space test program
+ *
@@ -326,22 +326,6 @@
+ sigaction(signum, &action, NULL);
+
+ return 0;
-+}
-+
-+static long ppb_to_scaled_ppm(int ppb)
-+{
-+ /*
-+ * The 'freq' field in the 'struct timex' is in parts per
-+ * million, but with a 16 bit binary fractional field.
-+ * Instead of calculating either one of
-+ *
-+ * scaled_ppm = (ppb / 1000) << 16 [1]
-+ * scaled_ppm = (ppb << 16) / 1000 [2]
-+ *
-+ * we simply use double precision math, in order to avoid the
-+ * truncation in [1] and the possible overflow in [2].
-+ */
-+ return (long) (ppb * 65.536);
+}
+
+static void usage(char *progname)
@@ -472,7 +456,7 @@
+ if (0x7fffffff != adjfreq) {
+ memset(&tx, 0, sizeof(tx));
+ tx.modes = ADJ_FREQUENCY;
-+ tx.freq = ppb_to_scaled_ppm(adjfreq);
++ tx.freq = (long) (adjfreq * 65.536);
+ if (clock_adjtime(clkid, &tx)) {
+ perror("clock_adjtime");
+ } else {
@@ -650,7 +634,7 @@
+distclean: clean
+ rm -f $(PROGS)
diff --git a/drivers/Kconfig b/drivers/Kconfig
-index 177c7d1..6fd7446 100644
+index 9bfb71f..82ddceb 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -54,6 +54,8 @@ source "drivers/spi/Kconfig"
@@ -663,7 +647,7 @@
source "drivers/w1/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
-index 3f135b6..71ebbf9 100644
+index b423bb1..f9b3087 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_I2O) += message/
@@ -724,10 +708,10 @@
+obj-$(CONFIG_PTP_1588_CLOCK) += ptp.o
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
new file mode 100644
-index 0000000..a8d03ae
+index 0000000..c806192
--- /dev/null
+++ b/drivers/ptp/ptp_chardev.c
-@@ -0,0 +1,159 @@
+@@ -0,0 +1,156 @@
+/*
+ * PTP 1588 clock support - character device implementation.
+ *
@@ -824,7 +808,7 @@
+ return err;
+}
+
-+unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
++uint ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
+{
+ struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+
@@ -842,9 +826,6 @@
+ unsigned long flags;
+ size_t qcnt, i;
+
-+ if (cnt % sizeof(struct ptp_extts_event) != 0)
-+ return -EINVAL;
-+
+ if (cnt > sizeof(event))
+ cnt = sizeof(event);
+
@@ -853,14 +834,10 @@
+ if (mutex_lock_interruptible(&ptp->tsevq_mux))
+ return -ERESTARTSYS;
+
-+ if (wait_event_interruptible(ptp->tsev_wq,
-+ ptp->defunct || queue_cnt(queue))) {
++ if (wait_event_interruptible(ptp->tsev_wq, queue_cnt(queue))) {
+ mutex_unlock(&ptp->tsevq_mux);
+ return -ERESTARTSYS;
+ }
-+
-+ if (ptp->defunct)
-+ return -ENODEV;
+
+ spin_lock_irqsave(&queue->lock, flags);
+
@@ -878,21 +855,25 @@
+
+ cnt = cnt * sizeof(struct ptp_extts_event);
+
-+ mutex_unlock(&ptp->tsevq_mux);
-+
+ if (copy_to_user(buf, event, cnt)) {
+ mutex_unlock(&ptp->tsevq_mux);
+ return -EFAULT;
+ }
+
++ mutex_unlock(&ptp->tsevq_mux);
+ return cnt;
++}
++
++int ptp_release(struct posix_clock *pc)
++{
++ return 0;
+}
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
new file mode 100644
-index 0000000..cf3f999
+index 0000000..1786a74
--- /dev/null
+++ b/drivers/ptp/ptp_clock.c
-@@ -0,0 +1,343 @@
+@@ -0,0 +1,320 @@
+/*
+ * PTP 1588 clock support
+ *
@@ -952,17 +933,15 @@
+{
+ struct ptp_extts_event *dst;
+ unsigned long flags;
-+ s64 seconds;
+ u32 remainder;
+
-+ seconds = div_u64_rem(src->timestamp, 1000000000, &remainder);
++ dst = &queue->buf[queue->tail];
++
++ dst->index = src->index;
++ dst->t.sec = div_u64_rem(src->timestamp, 1000000000, &remainder);
++ dst->t.nsec = remainder;
+
+ spin_lock_irqsave(&queue->lock, flags);
-+
-+ dst = &queue->buf[queue->tail];
-+ dst->index = src->index;
-+ dst->t.sec = seconds;
-+ dst->t.nsec = remainder;
+
+ if (!queue_free(queue))
+ queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
@@ -970,26 +949,6 @@
+ queue->tail = (queue->tail + 1) % PTP_MAX_TIMESTAMPS;
+
+ spin_unlock_irqrestore(&queue->lock, flags);
-+}
-+
-+static s32 scaled_ppm_to_ppb(long ppm)
-+{
-+ /*
-+ * The 'freq' field in the 'struct timex' is in parts per
-+ * million, but with a 16 bit binary fractional field.
-+ *
-+ * We want to calculate
-+ *
-+ * ppb = scaled_ppm * 1000 / 2^16
-+ *
-+ * which simplifies to
-+ *
-+ * ppb = scaled_ppm * 125 / 2^13
-+ */
-+ s64 ppb = 1 + ppm;
-+ ppb *= 125;
-+ ppb >>= 13;
-+ return (s32) ppb;
+}
+
+/* posix clock implementation */
@@ -1038,8 +997,10 @@
+ err = ops->adjtime(ops, delta);
+
+ } else if (tx->modes & ADJ_FREQUENCY) {
-+
-+ err = ops->adjfreq(ops, scaled_ppm_to_ppb(tx->freq));
++ s64 ppb = 1 + tx->freq;
++ ppb *= 125;
++ ppb >>= 13;
++ err = ops->adjfreq(ops, (s32)ppb);
+ }
+
+ return err;
@@ -1055,12 +1016,18 @@
+ .open = ptp_open,
+ .poll = ptp_poll,
+ .read = ptp_read,
++ .release = ptp_release,
+};
+
+static void delete_ptp_clock(struct posix_clock *pc)
+{
+ struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+
++ /* Release the clock's resources. */
++ if (ptp->info->pps)
++ pps_unregister_source(ptp->pps_source);
++ ptp_cleanup_sysfs(ptp);
++ device_destroy(ptp_class, ptp->devid);
+ mutex_destroy(&ptp->tsevq_mux);
+
+ /* Remove the clock from the bit map. */
@@ -1142,7 +1109,7 @@
+ return ptp;
+
+no_clock:
-+ if (ptp->pps_source)
++ if (ptp->info->pps)
+ pps_unregister_source(ptp->pps_source);
+no_pps:
+ ptp_cleanup_sysfs(ptp);
@@ -1161,15 +1128,6 @@
+
+int ptp_clock_unregister(struct ptp_clock *ptp)
+{
-+ ptp->defunct = 1;
-+ wake_up_interruptible(&ptp->tsev_wq);
-+
-+ /* Release the clock's resources. */
-+ if (ptp->pps_source)
-+ pps_unregister_source(ptp->pps_source);
-+ ptp_cleanup_sysfs(ptp);
-+ device_destroy(ptp_class, ptp->devid);
-+
+ posix_clock_unregister(&ptp->clock);
+ return 0;
+}
@@ -1238,10 +1196,10 @@
+MODULE_LICENSE("GPL");
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
new file mode 100644
-index 0000000..4d5b508
+index 0000000..2f76266
--- /dev/null
+++ b/drivers/ptp/ptp_private.h
-@@ -0,0 +1,92 @@
+@@ -0,0 +1,86 @@
+/*
+ * PTP 1588 clock support - private declarations for the core module.
+ *
@@ -1292,16 +1250,8 @@
+ struct timestamp_event_queue tsevq; /* simple fifo for time stamps */
+ struct mutex tsevq_mux; /* one process at a time reading the fifo */
+ wait_queue_head_t tsev_wq;
-+ int defunct; /* tells readers to go away when clock is being removed */
+};
+
-+/*
-+ * The function queue_cnt() is safe for readers to call without
-+ * holding q->lock. Readers use this function to verify that the queue
-+ * is nonempty before proceeding with a dequeue operation. The fact
-+ * that a writer might concurrently increment the tail does not
-+ * matter, since the queue remains nonempty nonetheless.
-+ */
+static inline int queue_cnt(struct timestamp_event_queue *q)
+{
+ int cnt = q->tail - q->head;
@@ -1319,6 +1269,8 @@
+
+ssize_t ptp_read(struct posix_clock *pc,
+ uint flags, char __user *buf, size_t cnt);
++
++int ptp_release(struct posix_clock *pc);
+
+uint ptp_poll(struct posix_clock *pc,
+ struct file *fp, poll_table *wait);
@@ -1571,10 +1523,10 @@
+ return err;
+}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
-index 75cf611..4585836 100644
+index b0ada6f..985ab2a 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
-@@ -302,6 +302,7 @@ header-y += ppp-comp.h
+@@ -300,6 +300,7 @@ header-y += ppp-comp.h
header-y += ppp_defs.h
header-y += pps.h
header-y += prctl.h