LinuxPPS (RESUBMIT 7): the PPS Linux implementation.
Subsystems (6)
This patch set adds the PPS support into Linux.
PPS means "pulse per second" and its API is specified by RFC 2783 (Pulse-Per-Second API for UNIX-like Operating Systems, Version 1.0).
The code has been tested with the NTPD program
(http://www.eecis.udel.edu/~mills/ntp/html/index.html) and several GPS antennae.
Changelog
RESUBMIT 6 -> 7:
* A new line discipline has been added in order to leave untouched the serial ports code (as suggested by Alan).
* n_tty.c exports only GPL symbols.
* ioctl numbers fixed in order to avoid any conflicts.
* Last patch (0010-PPS-low-level-IRQ-timestamps-recording.patch) implements low level IRQs timestamps recording which mproves PPS precision but can be dropped for kernel inclusion! As suggested by Alan: "After that is sorted/merged we can come back to working out the best way to improve the IRQ and HARDPPS hacks."
Rodolfo
--
b/Documentation/ABI/testing/sysfs-pps | 73 +++++++ b/Documentation/ioctl-number.txt | 2 b/Documentation/pps/Makefile | 28 ++ b/Documentation/pps/pps.txt | 172 +++++++++++++++++ b/Documentation/pps/ppsfind | 17 + b/Documentation/pps/ppsldisc.c | 46 ++++ b/Documentation/pps/ppstest.c | 151 +++++++++++++++ b/Documentation/pps/timepps.h | 195 +++++++++++++++++++ b/Documentation/tty.txt | 4 b/MAINTAINERS | 7 b/arch/x86/kernel/irq_32.c | 17 + b/arch/x86/kernel/irq_64.c | 21 +- b/drivers/Kconfig | 2 b/drivers/Makefile | 1 b/drivers/char/lp.c | 61 ++++++ b/drivers/char/n_tty.c | 54 +++-- b/drivers/pps/Kconfig | 33 +++ b/drivers/pps/Makefile | 8 b/drivers/pps/clients/Kconfig | 18 + b/drivers/pps/clients/Makefile | 9 b/drivers/pps/clients/ktimer.c | 124 ++++++++++++ b/drivers/pps/clients/pps-ldisc.c | 154 +++++++++++++++ b/drivers/pps/kapi.c | 322 ++++++++++++++++++++++++++++++++ b/drivers/pps/pps.c | 335 ++++++++++++++++++++++++++++++++++ b/drivers/pps/sysfs.c | 104 ++++++++++ b/drivers/serial/8250.c | 13 + b/include/linux/Kbuild | 1 b/include/linux/parport.h | 22 ++ b/include/linux/pps.h | 202 ++++++++++++++++++++ b/include/linux/serial_core.h | 10 - b/include/linux/tty.h | 16 + b/include/linux/tty_ldisc.h | 8 drivers/pps/Kconfig | 14 + drivers/pps/Makefile | 1 drivers/pps/clients/Kconfig | 17 + drivers/pps/clients/Makefile | 1 include/linux/pps.h | 1 include/linux/serial_core.h | 7 include/linux/tty.h | 3 39 files changed, 2247 insertions(+), 27 deletions(-)
PATCH 1/10 LinuxPPS core support.
This patch adds the kernel side of the PPS support currently named "LinuxPPS".
PPS means "pulse per second" and a PPS source is just a device which provides a high precision signal each second so that an application can use it to adjust system clock time.
Common use is the combination of the NTPD as userland program with a GPS receiver as PPS source to obtain a wallclock-time with sub-millisecond synchronisation to UTC.
To obtain this goal the userland programs shoud use the PPS API specification (RFC 2783 - Pulse-Per-Second API for UNIX-like Operating Systems, Version 1.0) which in part is implemented by this patch. It provides a set of chars devices, one per PPS source, which can be used to get the time signal. The RFC's functions can be implemented by accessing to these char devices.
--- Documentation/ABI/testing/sysfs-pps | 73 ++++++++ Documentation/ioctl-number.txt | 2 + Documentation/pps/pps.txt | 172 ++++++++++++++++++ MAINTAINERS | 7 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/pps/Kconfig | 33 ++++ drivers/pps/Makefile | 8 + drivers/pps/kapi.c | 322 +++++++++++++++++++++++++++++++++ drivers/pps/pps.c | 335 +++++++++++++++++++++++++++++++++++ drivers/pps/sysfs.c | 104 +++++++++++ include/linux/Kbuild | 1 + include/linux/pps.h | 202 +++++++++++++++++++++ 13 files changed, 1262 insertions(+), 0 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-pps create mode 100644 Documentation/pps/pps.txt create mode 100644 drivers/pps/Kconfig create mode 100644 drivers/pps/Makefile create mode 100644 drivers/pps/kapi.c create mode 100644 drivers/pps/pps.c create mode 100644 drivers/pps/sysfs.c create mode 100644 include/linux/pps.h
Documentation/ABI/testing/sysfs-pps new file +73 -0
@@ -0,0 +1,73 @@ +What: /sys/class/pps/ +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ directory will contain files and + directories that will provide a unified interface to + the PPS sources. + +What: /sys/class/pps/ppsX/ +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/ directory is related to X-th + PPS source into the system. Each directory will + contain files to manage and control its PPS source. + +What: /sys/class/pps/ppsX/assert +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/assert file reports the assert events + and the assert sequence number of the X-th source in the form: + + <secs>.<nsec>#<sequence> + + If the source has no assert events the content of this file + is void. + +What: /sys/class/pps/ppsX/clear +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/clear file reports the clear events + and the clear sequence number of the X-th source in the form: + + <secs>.<nsec>#<sequence> + + If the source has no clear events the content of this file + is void. + +What: /sys/class/pps/ppsX/mode +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/mode file reports the functioning + mode of the X-th source in hexadecimal encoding. + + Please, refer to linux/include/linux/pps.h for further + info. + +What: /sys/class/pps/ppsX/echo +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/echo file reports if the X-th source + supports or not an "echo" function. + +What: /sys/class/pps/ppsX/name +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/name file reports the name of the + X-th source. + +What: /sys/class/pps/ppsX/path +Date: February 2008 +Contact: Rodolfo Giometti <[email protected]> +Description: + The /sys/class/pps/ppsX/path file reports the path name of + the device connected with the X-th source. + + If the source is not connected with any device the content + of this file is void.
Documentation/ioctl-number.txt +2 -0
@@ -144,6 +144,8 @@ Code Seq# Include File Comments 'p' 40-7F linux/nvram.h 'p' 80-9F user-space parport <mailto:[email protected]> +'p' a0-a4 linux/pps.h LinuxPPS + <mailto:[email protected]> 'q' 00-1F linux/serio.h 'q' 80-FF Internet PhoneJACK, Internet LineJACK <http://www.quicknet.net>
Documentation/pps/pps.txt new file +172 -0
172 lines not on this page · raw message
MAINTAINERS +7 -0
@@ -3373,6 +3373,13 @@ P: James Chapman M: [email protected] S: Maintained +PPS SUPPORT +P: Rodolfo Giometti +M: [email protected] +W: http://wiki.enneenne.com/index.php/LinuxPPS_support +L: [email protected] (subscribers-only) +S: Maintained + PREEMPTIBLE KERNEL P: Robert Love M: [email protected]
drivers/Kconfig +2 -0
@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig" source "drivers/spi/Kconfig" +source "drivers/pps/Kconfig" + source "drivers/gpio/Kconfig" source "drivers/w1/Kconfig"
drivers/Makefile +1 -0
@@ -66,6 +66,7 @@ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_I2O) += message/ obj-$(CONFIG_RTC_LIB) += rtc/ obj-y += i2c/ +obj-$(CONFIG_PPS) += pps/ obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_POWER_SUPPLY) += power/ obj-$(CONFIG_HWMON) += hwmon/
drivers/pps/Kconfig new file +33 -0
@@ -0,0 +1,33 @@ +# +# PPS support configuration +# + +menu "PPS support" + +config PPS + tristate "PPS support" + depends on EXPERIMENTAL + ---help--- + PPS (Pulse Per Second) is a special pulse provided by some GPS + antennae. Userland can use it to get a high-precision time + reference. + + Some antennae's PPS signals are connected with the CD (Carrier + Detect) pin of the serial line they use to communicate with the + host. In this case use the SERIAL_LINE client support. + + Some antennae's PPS signals are connected with some special host + inputs so you have to enable the corresponding client support. + + To compile this driver as a module, choose M here: the module + will be called pps_core.ko. + +config PPS_DEBUG + bool "PPS debugging messages" + depends on PPS + help + Say Y here if you want the PPS support to produce a bunch of debug + messages to the system log. Select this if you are having a + problem with PPS support and want to see more of what is going on. + +endmenu
drivers/pps/Makefile new file +8 -0
@@ -0,0 +1,8 @@ +# +# Makefile for the PPS core. +# + +pps_core-y := pps.o kapi.o sysfs.o +obj-$(CONFIG_PPS) := pps_core.o + +ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
drivers/pps/kapi.c new file +322 -0
322 lines not on this page · raw message
drivers/pps/pps.c new file +335 -0
335 lines not on this page · raw message
drivers/pps/sysfs.c new file +104 -0
104 lines not on this page · raw message
include/linux/Kbuild +1 -0
@@ -303,6 +303,7 @@ unifdef-y += pmu.h unifdef-y += poll.h unifdef-y += ppp_defs.h unifdef-y += ppp-comp.h +unifdef-y += pps.h unifdef-y += ptrace.h unifdef-y += qnx4_fs.h unifdef-y += quota.h
include/linux/pps.h new file +202 -0
202 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 2/10 PPS: userland header file for PPS API.
This patch adds into the PPS's documentation directory a possible implementation of the PPS API (RFC 2783) by using the LinuxPPS's char devices.
This file is not just an example but it can be used into real systems. :)
--- Documentation/pps/timepps.h | 195 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 Documentation/pps/timepps.h
Documentation/pps/timepps.h new file +195 -0
@@ -0,0 +1,195 @@ +/* +* timepps.h -- PPS API main header +* +* Copyright (C) 2005-2007 Rodolfo Giometti <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SYS_TIMEPPS_H_ +#define _SYS_TIMEPPS_H_ + +#include <sys/syscall.h> +#include <unistd.h> +#include <errno.h> +#include <linux/pps.h> + +#define LINUXPPS 1/* signal we are using LinuxPPS */ + +/* +* New data structures +*/ + +struct ntp_fp { +unsigned int integral; +unsigned int fractional; +}; + +union pps_timeu { +struct timespec tspec; +struct ntp_fp ntpfp; +unsigned long longpad[3 ]; +}; + +struct pps_info { +unsigned long assert_sequence;/* seq. num. of assert event */ +unsigned long clear_sequence;/* seq. num. of clear event */ +union pps_timeu assert_tu;/* time of assert event */ +union pps_timeu clear_tu;/* time of clear event */ +int current_mode;/* current mode bits */ +}; + +struct pps_params { +int api_version;/* API version # */ +int mode;/* mode bits */ +union pps_timeu assert_off_tu;/* offset compensation for assert */ +union pps_timeu clear_off_tu;/* offset compensation for clear */ +}; + +typedef int pps_handle_t ;/* represents a PPS source */ +typedef unsigned long pps_seq_t ;/* sequence number */ +typedef struct ntp_fp ntp_fp_t ;/* NTP-compatible time stamp */ +typedef union pps_timeu pps_timeu_t ;/* generic data type for time stamps */ +typedef struct pps_info pps_info_t ; +typedef struct pps_params pps_params_t ; + +#define assert_timestamp assert_tu.tspec +#define clear_timestamp clear_tu.tspec + +#define assert_timestamp_ntpfp assert_tu.ntpfp +#define clear_timestamp_ntpfp clear_tu.ntpfp + +#define assert_offset assert_off_tu.tspec +#define clear_offset clear_off_tu.tspec + +#define assert_offset_ntpfp assert_off_tu.ntpfp +#define clear_offset_ntpfp clear_off_tu.ntpfp + +/* +* The PPS API +*/ + +static __inlineint time_pps_create (int source,pps_handle_t *handle) +{ +int ret; + +if (!handle) { + errno =EINVAL ; +return -1 ; + } + +/* First we check if current device is a PPS valid PPS one... +*/ + ret =ioctl (source,PPS_CHECK ); +if (ret) { + errno =EOPNOTSUPP ; +return -1 ; + } + +/* ... then since in LinuxPPS there are no differences between a +* "PPS source" and a "PPS handle", we simply return the same value. +*/ + *handle = source; + +return 0 ; +} + +static __inlineint time_pps_destroy (pps_handle_t handle) +{ +return close (handle); +} + +static __inlineint time_pps_getparams (pps_handle_t handle, +pps_params_t *ppsparams) +{ +int ret; +struct pps_kparams __ppsparams; + + ret =ioctl (handle,PPS_GETPARAMS , &__ppsparams); + + ppsparams->api_version = __ppsparams.api_version; + ppsparams->mode = __ppsparams.mode; + ppsparams->assert_off_tu.tspec.tv_sec = __ppsparams.assert_off_tu.sec; + ppsparams->assert_off_tu.tspec.tv_nsec = __ppsparams.assert_off_tu.nsec; + ppsparams->clear_off_tu.tspec.tv_sec = __ppsparams.clear_off_tu.sec; + ppsparams->clear_off_tu.tspec.tv_nsec = __ppsparams.clear_off_tu.nsec; + +return ret; +} + +static __inlineint time_pps_setparams (pps_handle_t handle, +const pps_params_t *ppsparams) +{ +struct pps_kparams __ppsparams; + + __ppsparams.api_version = ppsparams->api_version; + __ppsparams.mode = ppsparams->mode; + __ppsparams.assert_off_tu.sec = ppsparams->assert_off_tu.tspec.tv_sec; + __ppsparams.assert_off_tu.nsec = ppsparams->assert_off_tu.tspec.tv_nsec; + __ppsparams.clear_off_tu.sec = ppsparams->clear_off_tu.tspec.tv_sec; + __ppsparams.clear_off_tu.nsec = ppsparams->clear_off_tu.tspec.tv_nsec; + +return ioctl (handle,PPS_SETPARAMS , &__ppsparams); +} + +/* Get capabilities for handle */ +static __inlineint time_pps_getcap (pps_handle_t handle,int *mode) +{ +return ioctl (handle,PPS_GETCAP , mode); +} + +static __inlineint time_pps_fetch (pps_handle_t handle,const int tsformat, +pps_info_t *ppsinfobuf, +const struct timespec *timeout) +{ +struct pps_fdata __fdata; +int ret; + +/* Sanity checks */ +if (tsformat !=PPS_TSFMT_TSPEC ) { + errno =EINVAL ; +return -1 ; + } + +if (timeout) { + __fdata.timeout.sec = timeout->tv_sec; + __fdata.timeout.nsec = timeout->tv_nsec; + __fdata.timeout.flags = ~PPS_TIME_INVALID ; + }else + __fdata.timeout.flags =PPS_TIME_INVALID ; + + ret =ioctl (handle,PPS_FETCH , &__fdata); + + ppsinfobuf->assert_sequence = __fdata.info.assert_sequence; + ppsinfobuf->clear_sequence = __fdata.info.clear_sequence; + ppsinfobuf->assert_tu.tspec.tv_sec = __fdata.info.assert_tu.sec; + ppsinfobuf->assert_tu.tspec.tv_nsec = __fdata.info.assert_tu.nsec; + ppsinfobuf->clear_tu.tspec.tv_sec = __fdata.info.clear_tu.sec; + ppsinfobuf->clear_tu.tspec.tv_nsec = __fdata.info.clear_tu.nsec; + ppsinfobuf->current_mode = __fdata.info.current_mode; + +return ret; +} + +static __inlineint time_pps_kcbind (pps_handle_t handle, +const int kernel_consumer, +const int edge,const int tsformat) +{ +/* LinuxPPS doesn't implement kernel consumer feature */ + errno =EOPNOTSUPP ; +return -1 ; +} + +#endif /* _SYS_TIMEPPS_H_ */
Signature · 1 line
1.5.4.3
PATCH 3/10 PPS: documentation programs and examples.
Here some utilities and examples about the PPS API and the LinuxPPS support.
* ppsldisc.c shows how to manage PPS line discipline;
* ppstest.c implements an useful testing program, while
* ppsfind tries to help the user into finding a specific PPS source by using its name or path.
--- Documentation/pps/Makefile | 28 ++++++++ Documentation/pps/ppsfind | 17 +++++ Documentation/pps/ppsldisc.c | 46 +++++++++++++ Documentation/pps/ppstest.c | 151 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+), 0 deletions(-) create mode 100644 Documentation/pps/Makefile create mode 100644 Documentation/pps/ppsfind create mode 100644 Documentation/pps/ppsldisc.c create mode 100644 Documentation/pps/ppstest.c
Documentation/pps/Makefile new file +28 -0
@@ -0,0 +1,28 @@ +TARGETS = ppstest ppsldisc + +CFLAGS += -Wall -O2 -D_GNU_SOURCE +CFLAGS += -I . +CFLAGS += -ggdb +CFLAGS += -D__N_PPS=$(shell awk '/N_PPS/ {print $$3}' ../../include/linux/tty.h) + +# -- Actions section -- + +.PHONY : all depend dep + +all : .depend $(TARGETS) + +.depend depend dep : + $(CC) $(CFLAGS) -M $(TARGETS:=.c) > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + + +# -- Clean section -- + +.PHONY : clean + +clean : + rm -f *.o *~ core .depend + rm -f ${TARGETS}
Documentation/pps/ppsfind new file +17 -0
@@ -0,0 +1,17 @@ +#!/bin/sh + +SYS="/sys/class/pps/" + +if [ $# -lt 1 ] ; then + echo "usage: ppsfind <name>" >&2 + exit 1 +fi + +for d in $(ls $SYS) ; do + if grep $1 $SYS/$d/name >& /dev/null || \ + grep $1 $SYS/$d/path >& /dev/null ; then + echo "$d: name=$(cat $SYS/$d/name) path=$(cat $SYS/$d/path)" + fi +done + +exit 0
Documentation/pps/ppsldisc.c new file +46 -0
46 lines not on this page · raw message
Documentation/pps/ppstest.c new file +151 -0
151 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 4/10 PPS: LinuxPPS clients support.
Each PPS source can be registered/deregistered into the system by using special modules called "clients". They simply define the PPS sources' attributes and implement the time signal registartion mechanism.
This patch adds a special directory for such clients and adds a dummy client that can be useful to test system integrity on real systems.
--- drivers/pps/Kconfig | 2 + drivers/pps/Makefile | 1 + drivers/pps/clients/Kconfig | 18 ++++++ drivers/pps/clients/Makefile | 9 +++ drivers/pps/clients/ktimer.c | 124 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 0 deletions(-) create mode 100644 drivers/pps/clients/Kconfig create mode 100644 drivers/pps/clients/Makefile create mode 100644 drivers/pps/clients/ktimer.c
drivers/pps/Kconfig +2 -0
@@ -30,4 +30,6 @@ config PPS_DEBUG messages to the system log. Select this if you are having a problem with PPS support and want to see more of what is going on. +source drivers/pps/clients/Kconfig + endmenu
drivers/pps/Makefile +1 -0
@@ -4,5 +4,6 @@ pps_core-y := pps.o kapi.o sysfs.o obj-$(CONFIG_PPS) := pps_core.o +obj-y += clients/ ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
drivers/pps/clients/Kconfig new file +18 -0
@@ -0,0 +1,18 @@ +# +# PPS clients configuration +# + +if PPS + +comment "PPS clients support" + +config PPS_CLIENT_KTIMER + tristate "Kernel timer client (Testing client, use for debug)" + help + If you say yes here you get support for a PPS debugging client + which uses a kernel timer to generate the PPS signal. + + This driver can also be built as a module. If so, the module + will be called ktimer.ko. + +endif
drivers/pps/clients/Makefile new file +9 -0
@@ -0,0 +1,9 @@ +# +# Makefile for PPS clients. +# + +obj-$(CONFIG_PPS_CLIENT_KTIMER) += ktimer.o + +ifeq ($(CONFIG_PPS_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif
drivers/pps/clients/ktimer.c new file +124 -0
124 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 5/10 ldisc: new dcd_change() method for line disciplines.
--- Documentation/tty.txt | 4 ++++ include/linux/tty_ldisc.h | 8 ++++++++ 2 files changed, 12 insertions(+), 0 deletions(-)
Documentation/tty.txt +4 -0
@@ -100,6 +100,10 @@ write_wakeup() - May be called at any point between open and close. is permitted to call the driver write method from this function. In such a situation defer it. +dcd_change() - Report to the tty line the current DCD pin status + changes and the relative timestamp. The timestamp + can be NULL. + Driver Access
include/linux/tty_ldisc.h +8 -0
@@ -99,6 +99,12 @@* cease I/O to the tty driver. Can sleep. The driver should * seek to perform this action quickly but should wait until * any pending driver I/O is completed. +* +* void (*dcd_change)(struct tty_struct *tty, unsigned int status, +* struct timespec *ts) +* +* Tells the discipline that the DCD pin has changed its status and +* the relative timestamp. Pointer ts can be NULL. */ #include <linux/fs.h>
@@ -136,6 +142,8 @@ struct tty_ldisc_ops {void (*receive_buf)(struct tty_struct *,const unsigned char *cp,char *fp,int count);void (*write_wakeup)(struct tty_struct *); +void (*dcd_change)(struct tty_struct *,unsigned int , +struct timespec *);struct module *owner;
Signature · 1 line
1.5.4.3
PATCH 6/10 ldisc n_tty: export all N_TTY ldisc methods.
--- drivers/char/n_tty.c | 54 +++++++++++++++++++++++++++++-------------------- include/linux/tty.h | 16 ++++++++++++++ 2 files changed, 48 insertions(+), 22 deletions(-)
drivers/char/n_tty.c +32 -22
@@ -26,7 +26,7 @@* * 2002/03/18 Implemented n_tty_wakeup to send SIGIO POLL_OUTs to * waiting writing processes-Sapan Bhatia <[email protected]>. -* Also fixed a bug in BLOCKING mode where write_chan returns +* Also fixed a bug in BLOCKING mode where n_tty_write returns * EAGAIN */
@@ -43,10 +43,10 @@#include <linux/mm.h> #include <linux/string.h> #include <linux/slab.h> -#include <linux/poll.h> #include <linux/bitops.h> #include <linux/audit.h> #include <linux/file.h> +#include <linux/module.h> #include <asm/uaccess.h> #include <asm/system.h>
@@ -184,7 +184,7 @@ static void reset_buffer_flags(struct tty_struct *tty)* Locking: ctrl_lock */ -static void n_tty_flush_buffer (struct tty_struct *tty) +void n_tty_flush_buffer (struct tty_struct *tty) {unsigned long flags;/* clear everything and unthrottle the driver */
@@ -200,6 +200,7 @@ static void n_tty_flush_buffer(struct tty_struct *tty) }spin_unlock_irqrestore (&tty->ctrl_lock, flags); } +EXPORT_SYMBOL_GPL (n_tty_flush_buffer);/** * n_tty_chars_in_buffer - report available bytes
@@ -209,7 +210,7 @@ static void n_tty_flush_buffer(struct tty_struct *tty)* at this instant in time. */ -static ssize_t n_tty_chars_in_buffer (struct tty_struct *tty) +ssize_t n_tty_chars_in_buffer (struct tty_struct *tty) {unsigned long flags;ssize_t n =0 ;
@@ -225,6 +226,7 @@ static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)spin_unlock_irqrestore (&tty->read_lock, flags);return n; } +EXPORT_SYMBOL_GPL (n_tty_chars_in_buffer);/** * is_utf8_continuation - utf8 multibyte check
@@ -346,7 +348,7 @@ static int opost(unsigned char c, struct tty_struct *tty)* the simple cases normally found and helps to generate blocks of * symbols for the console driver and thus improve performance. * -* Called from write_chan under the tty layer write lock. Relies +* Called from n_tty_write under the tty layer write lock. Relies * on lock_kernel for the tty->column state. */
@@ -895,13 +897,14 @@ handle_newline:* IO must be woken up */ -static void n_tty_write_wakeup (struct tty_struct *tty) +void n_tty_write_wakeup (struct tty_struct *tty) {if (tty->fasync) {set_bit (TTY_DO_WRITE_WAKEUP , &tty->flags);kill_fasync (&tty->fasync,SIGIO ,POLL_OUT ); } } +EXPORT_SYMBOL_GPL (n_tty_write_wakeup);/** * n_tty_receive_buf - data receive
@@ -916,7 +919,7 @@ static void n_tty_write_wakeup(struct tty_struct *tty)* calls one at a time and in order (or using flush_to_ldisc) */ -static void n_tty_receive_buf (struct tty_struct *tty,const unsigned char *cp, +void n_tty_receive_buf (struct tty_struct *tty,const unsigned char *cp,char *fp,int count) {const unsigned char *p;
@@ -990,6 +993,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,if (tty->receive_room <TTY_THRESHOLD_THROTTLE )tty_throttle (tty); } +EXPORT_SYMBOL_GPL (n_tty_receive_buf);int is_ignored (int sig) {
@@ -1009,7 +1013,7 @@ int is_ignored(int sig)* when the ldisc is closed. */ -static void n_tty_set_termios (struct tty_struct *tty,struct ktermios *old) +void n_tty_set_termios (struct tty_struct *tty,struct ktermios *old) {if (!tty)return ;
@@ -1076,6 +1080,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)wake_up_interruptible (&tty->write_wait);wake_up_interruptible (&tty->read_wait); } +EXPORT_SYMBOL_GPL (n_tty_set_termios);/** * n_tty_close - close the ldisc for this tty
@@ -1087,7 +1092,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)* ldisc methods are in progress. */ -static void n_tty_close (struct tty_struct *tty) +void n_tty_close (struct tty_struct *tty) {n_tty_flush_buffer (tty);if (tty->read_buf) {
@@ -1095,6 +1100,7 @@ static void n_tty_close(struct tty_struct *tty) tty->read_buf =NULL ; } } +EXPORT_SYMBOL_GPL (n_tty_close);/** * n_tty_open - open an ldisc
@@ -1106,7 +1112,7 @@ static void n_tty_close(struct tty_struct *tty)* until a close. */ -static int n_tty_open (struct tty_struct *tty) +int n_tty_open (struct tty_struct *tty) {if (!tty)return -EINVAL ;
@@ -1125,6 +1131,7 @@ static int n_tty_open(struct tty_struct *tty) tty->closing =0 ;return 0 ; } +EXPORT_SYMBOL_GPL (n_tty_open);static inline int input_available_p (struct tty_struct *tty,int amt) {
@@ -1143,7 +1150,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)* @b: user data * @nr: size of data * -* Helper function to speed up read_chan. It is only called when +* Helper function to speed up n_tty_read. It is only called when * ICANON is off; it copies characters straight from the tty queue to * user space directly. It can be profitably called twice; once to * drain the space from the tail pointer to the (physical) end of the
@@ -1210,7 +1217,7 @@ static int job_control(struct tty_struct *tty, struct file *file)if (file->f_op->write != redirected_tty_write && current->signal->tty == tty) {if (!tty->pgrp) -printk (KERN_ERR "read_chan: no tty->pgrp!\n" ); +printk (KERN_ERR "n_tty_read: no tty->pgrp!\n" );else if (task_pgrp (current) != tty->pgrp) {if (is_ignored (SIGTTIN ) ||is_current_pgrp_orphaned ())
@@ -1225,7 +1232,7 @@ static int job_control(struct tty_struct *tty, struct file *file)/** -* read_chan - read function for tty +* n_tty_read - read function for tty * @tty: tty device * @file: file object * @buf: userspace buffer pointer
@@ -1239,7 +1246,7 @@ static int job_control(struct tty_struct *tty, struct file *file)* This code must be sure never to sleep through a hangup. */ -static ssize_t read_chan (struct tty_struct *tty,struct file *file, +ssize_t n_tty_read (struct tty_struct *tty,struct file *file,unsigned char __user *buf,size_t nr) {unsigned char __user *b = buf;
@@ -1255,7 +1262,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file, do_it_again:if (!tty->read_buf) { -printk (KERN_ERR "n_tty_read_chan: read_buf == NULL?!?\n" ); +printk (KERN_ERR "n_tty_read: read_buf == NULL?!?\n" );return -EIO ; }
@@ -1442,9 +1449,10 @@ do_it_again:n_tty_set_room (tty);return retval; } +EXPORT_SYMBOL_GPL (n_tty_read);/** -* write_chan - write function for tty +* n_tty_write - write function for tty * @tty: tty device * @file: file object * @buf: userspace buffer pointer
@@ -1458,7 +1466,7 @@ do_it_again:* This code must be sure never to sleep through a hangup. */ -static ssize_t write_chan (struct tty_struct *tty,struct file *file, +ssize_t n_tty_write (struct tty_struct *tty,struct file *file,const unsigned char *buf,size_t nr) {const unsigned char *b = buf;
@@ -1530,9 +1538,10 @@ break_out:remove_wait_queue (&tty->write_wait, &wait);return (b - buf) ? b - buf : retval; } +EXPORT_SYMBOL_GPL (n_tty_write);/** -* normal_poll - poll method for N_TTY +* n_tty_poll - poll method for N_TTY * @tty: terminal device * @file: file accessing it * @wait: poll table
@@ -1545,7 +1554,7 @@ break_out:* Called without the kernel lock held - fine */ -static unsigned int normal_poll (struct tty_struct *tty,struct file *file, +unsigned int n_tty_poll (struct tty_struct *tty,struct file *file,poll_table *wait) {unsigned int mask =0 ;
@@ -1572,6 +1581,7 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file, mask |=POLLOUT |POLLWRNORM ;return mask; } +EXPORT_SYMBOL_GPL (n_tty_poll);struct tty_ldisc_ops tty_ldisc_N_TTY = { .magic =TTY_LDISC_MAGIC ,
@@ -1580,11 +1590,11 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { .close = n_tty_close, .flush_buffer = n_tty_flush_buffer, .chars_in_buffer = n_tty_chars_in_buffer, - .read = read_chan, - .write = write_chan, + .read = n_tty_read, + .write = n_tty_write, .ioctl = n_tty_ioctl, .set_termios = n_tty_set_termios, - .poll = normal_poll, + .poll = n_tty_poll, .receive_buf = n_tty_receive_buf, .write_wakeup = n_tty_write_wakeup };
include/linux/tty.h +16 -0
@@ -13,6 +13,7 @@#include <linux/tty_driver.h> #include <linux/tty_ldisc.h> #include <linux/mutex.h> +#include <linux/poll.h> #include <asm/system.h>
@@ -393,6 +394,21 @@ extern void tty_ldisc_begin(void);/* This last one is just for the tty layer internals and shouldn't be used elsewhere */ extern void tty_ldisc_enable (struct tty_struct *tty); +extern void n_tty_flush_buffer (struct tty_struct *tty); +extern ssize_t n_tty_chars_in_buffer (struct tty_struct *tty); +extern void n_tty_write_wakeup (struct tty_struct *tty); +extern void n_tty_receive_buf (struct tty_struct *tty,const unsigned char *cp, +char *fp,int count); +extern void n_tty_set_termios (struct tty_struct *tty,struct ktermios *old); +extern void n_tty_close (struct tty_struct *tty); +extern int n_tty_open (struct tty_struct *tty); +extern ssize_t n_tty_read (struct tty_struct *tty,struct file *file, +unsigned char __user *buf,size_t nr); +extern ssize_t n_tty_write (struct tty_struct *tty,struct file *file, +const unsigned char *buf,size_t nr); +extern unsigned int n_tty_poll (struct tty_struct *tty,struct file *file, +poll_table *wait); +/* n_tty.c */ extern struct tty_ldisc_ops tty_ldisc_N_TTY;
Signature · 1 line
1.5.4.3
PATCH 7/10 tty: new PPS line discipline.
Add a new line discipline for "pulse per second" devices connected to a serial port.
--- include/linux/tty.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
include/linux/tty.h +2 -1
@@ -24,7 +24,7 @@*/ #define NR_UNIX98_PTY_DEFAULT 4096/* Default maximum for Unix98 ptys */ #define NR_UNIX98_PTY_MAX (1 << MINORBITS)/* Absolute limit */ -#define NR_LDISCS 18 +#define NR_LDISCS 19/* line disciplines */ #define N_TTY 0
@@ -46,6 +46,7 @@#define N_HCI 15/* Bluetooth HCI UART */ #define N_GIGASET_M101 16/* Siemens Gigaset M101 serial DECT adapter */ #define N_SLCAN 17/* Serial / USB serial CAN Adaptors */ +#define N_PPS 18/* Pulse per Second */ /* * This character is the same as _POSIX_VDISABLE: it cannot be used as
Signature · 1 line
1.5.4.3
PATCH 8/10 PPS: serial clients support.
Adds support, by using the PPS line discipline, for the PPS sources connected with the CD (Carrier Detect) pin of a serial port.
--- drivers/pps/clients/Kconfig | 7 ++ drivers/pps/clients/Makefile | 1 + drivers/pps/clients/pps-ldisc.c | 154 +++++++++++++++++++++++++++++++++++++++ drivers/serial/8250.c | 13 +++ include/linux/serial_core.h | 10 ++- 5 files changed, 184 insertions(+), 1 deletions(-) create mode 100644 drivers/pps/clients/pps-ldisc.c
drivers/pps/clients/Kconfig +7 -0
@@ -15,4 +15,11 @@ config PPS_CLIENT_KTIMER This driver can also be built as a module. If so, the module will be called ktimer.ko. +config PPS_CLIENT_LDISC + tristate "PPS line discipline" + depends on PPS + help + If you say yes here you get support for a PPS source connected + with the CD (Carrier Detect) pin of your serial port. + endif
drivers/pps/clients/Makefile +1 -0
@@ -3,6 +3,7 @@ # obj-$(CONFIG_PPS_CLIENT_KTIMER) += ktimer.o +obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o ifeq ($(CONFIG_PPS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG
drivers/pps/clients/pps-ldisc.c new file +154 -0
154 lines not on this page · raw message
drivers/serial/8250.c +13 -0
@@ -2247,6 +2247,18 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, }static void +serial8250_set_ldisc (struct uart_port *port) +{ +int line = port->line; + +if (line >= port->info->port.tty->driver->num) +return ; + +if (port->info->port.tty->ldisc.ops->num ==N_PPS ) +serial8250_enable_ms (port); +} + +static void serial8250_pm (struct uart_port *port,unsigned int state,unsigned int oldstate) {
@@ -2450,6 +2462,7 @@ static struct uart_ops serial8250_pops = { .startup = serial8250_startup, .shutdown = serial8250_shutdown, .set_termios = serial8250_set_termios, + .set_ldisc = serial8250_set_ldisc, .pm = serial8250_pm, .type = serial8250_type, .release_port = serial8250_release_port,
include/linux/serial_core.h +9 -1
@@ -488,9 +488,13 @@ static inline void uart_handle_dcd_change(struct uart_port *port, unsigned int status) {struct uart_info *info = port->info; +struct tty_ldisc *ld =tty_ldisc_ref (info->port.tty); +struct timespec ts; - port->icount.dcd++; +if (ld->ops->dcd_change) +getnstimeofday (&ts); + port->icount.dcd++;#ifdef CONFIG_HARD_PPS if ((port->flags &UPF_HARDPPS_CD ) && status)hardpps ();
@@ -502,6 +506,10 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status)else if (info->port.tty)tty_hangup (info->port.tty); } + +if (ld->ops->dcd_change) + ld->ops->dcd_change (port, status, &ts); +tty_ldisc_deref (ld); }/**
Signature · 1 line
1.5.4.3
PATCH 9/10 PPS: parallel port clients support.
Adds support for the PPS sources connected with the interrupt pin of a parallel port.
--- drivers/char/lp.c | 61 +++++++++++++++++++++++++++++++++++++++++++ drivers/pps/clients/Kconfig | 10 +++++++ include/linux/parport.h | 22 +++++++++++++++ 3 files changed, 93 insertions(+), 0 deletions(-)
drivers/char/lp.c +61 -0
@@ -760,6 +760,27 @@ static struct console lpcons = {#endif /* console on line printer */ +/* Support for PPS signal on the line printer */ + +#ifdef CONFIG_PPS_CLIENT_LP + +static void lp_pps_echo (int source,int event,void *data) +{ +struct parport *port = data; +unsigned char status =parport_read_status (port); + +/* echo event via SEL bit */ +parport_write_control (port, +parport_read_control (port) |PARPORT_CONTROL_SELECT ); + +/* signal no event */ +if ((status &PARPORT_STATUS_ACK ) !=0 ) +parport_write_control (port, +parport_read_control (port) & ~PARPORT_CONTROL_SELECT ); +} + +#endif +/* --- initialisation code ------------------------------------- */ static int parport_nr[LP_NO ] = { [0 ...LP_NO -1 ] =LP_PARPORT_UNSPEC };
@@ -831,6 +852,38 @@ static int lp_register(int nr, struct parport *port) }#endif +#ifdef CONFIG_PPS_CLIENT_LP + port->pps_info.owner =THIS_MODULE ; + port->pps_info.dev = port->dev; +snprintf (port->pps_info.path,PPS_MAX_NAME_LEN ,"/dev/lp%d" , nr); + +/* No PPS support if lp port has no IRQ line */ +if (port->irq !=PARPORT_IRQ_NONE ) { +strncpy (port->pps_info.name, port->name,PPS_MAX_NAME_LEN ); + + port->pps_info.mode =PPS_CAPTUREASSERT |PPS_OFFSETASSERT | \ +PPS_ECHOASSERT | \ +PPS_CANWAIT |PPS_TSFMT_TSPEC ; + + port->pps_info.echo = lp_pps_echo; + + port->pps_source =pps_register_source (&(port->pps_info), +PPS_CAPTUREASSERT |PPS_OFFSETASSERT ); +if (port->pps_source <0 ) +dev_err (port->dev, +"cannot register PPS source \"%s\"\n" , + port->pps_info.path); +else +dev_info (port->dev,"PPS source #%d \"%s\" added\n" , + port->pps_source, port->pps_info.path); + }else { + port->pps_source =-1 ; +dev_err (port->dev,"PPS support disabled because port \"%s\" " +"is in polling mode\n" , + port->pps_info.path); + } +#endif +return 0 ; }
@@ -873,6 +926,14 @@ static void lp_detach (struct parport *port) console_registered =NULL ; }#endif /* CONFIG_LP_CONSOLE */ + +#ifdef CONFIG_PPS_CLIENT_LP +if (port->pps_source >=0 ) { +pps_unregister_source (port->pps_source); +dev_dbg (port->dev,"PPS source #%d \"%s\" removed\n" , + port->pps_source, port->pps_info.path); + } +#endif } static struct parport_driver lp_driver = {
drivers/pps/clients/Kconfig +10 -0
@@ -22,4 +22,14 @@ config PPS_CLIENT_LDISC If you say yes here you get support for a PPS source connected with the CD (Carrier Detect) pin of your serial port. +comment "Parallel printer support (forced off)" + depends on !( PRINTER != n && !(PPS = m && PRINTER = y)) + +config PPS_CLIENT_LP + bool "Parallel printer support" + depends on PRINTER != n && !(PPS = m && PRINTER = y) + help + If you say yes here you get support for a PPS source connected + with the interrupt pin of your parallel port. + endif
include/linux/parport.h +22 -0
@@ -100,6 +100,7 @@ typedef enum {#include <linux/proc_fs.h> #include <linux/spinlock.h> #include <linux/wait.h> +#include <linux/pps.h> #include <linux/irqreturn.h> #include <linux/semaphore.h> #include <asm/system.h>
@@ -328,6 +329,11 @@ struct parport {struct list_head full_list;struct parport *slaves[3 ]; + +#ifdef CONFIG_PPS_CLIENT_LP +struct pps_source_info pps_info; +int pps_source;/* PPS source ID */ +#endif };#define DEFAULT_SPIN_TIME 500/* us */
@@ -516,6 +522,22 @@ extern int parport_daisy_select (struct parport *port, int daisy, int mode);/* Lowlevel drivers _can_ call this support function to handle irqs. */ static inline void parport_generic_irq (struct parport *port) { +#ifdef CONFIG_PPS_CLIENT_LP +struct timespec __ts; +struct pps_ktime ts; + +/* First of all we get the time stamp... */ +getnstimeofday (&__ts); + +/* ... and translate it to PPS time data struct */ + ts.sec = __ts.tv_sec; + ts.nsec = __ts.tv_nsec; + +pps_event (port->pps_source, &ts,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); +#endif +parport_ieee1284_interrupt (port);read_lock (&port->cad_lock);if (port->cad && port->cad->irq_func)
Signature · 1 line
1.5.4.3
PATCH 10/10 PPS: low level IRQ timestamps recording.
Add low level IRQ timestamps recording for x86 (32 and 64 bits) platforms and enable UART clients in order to use it.
This improves PPS precision. :)
--- arch/x86/kernel/irq_32.c | 17 +++++++++++++++++ arch/x86/kernel/irq_64.c | 21 +++++++++++++++++++-- drivers/pps/Kconfig | 12 ++++++++++++ include/linux/pps.h | 1 + include/linux/serial_core.h | 7 ++++++- 5 files changed, 55 insertions(+), 3 deletions(-)
arch/x86/kernel/irq_32.c +17 -0
@@ -15,6 +15,7 @@#include <linux/notifier.h> #include <linux/cpu.h> #include <linux/delay.h> +#include <linux/pps.h> #include <asm/apic.h> #include <asm/uaccess.h>
@@ -25,6 +26,11 @@ EXPORT_PER_CPU_SYMBOL(irq_stat); DEFINE_PER_CPU(struct pt_regs *, irq_regs);EXPORT_PER_CPU_SYMBOL (irq_regs); +#ifdef CONFIG_PPS_IRQ_EVENTS +struct timespec pps_irq_ts[NR_IRQS ]; +EXPORT_SYMBOL (pps_irq_ts); +#endif +/* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves.
@@ -225,6 +231,12 @@ unsigned int do_IRQ(struct pt_regs *regs)/* high bit used in ret_from_ code */ int overflow, irq = ~regs->orig_ax;struct irq_desc *desc = irq_desc + irq; +#ifdef CONFIG_PPS_IRQ_EVENTS +struct timespec ts; + +/* Get IRQ timestamps as soon as possible for the PPS layer */ +getnstimeofday (&ts); +#endif if (unlikely ((unsigned )irq >=NR_IRQS )) { printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
@@ -232,6 +244,11 @@ unsigned int do_IRQ(struct pt_regs *regs)BUG (); } +#ifdef CONFIG_PPS_IRQ_EVENTS +/* Then, after sanity check, store the IRQ timestamp */ + pps_irq_ts[irq] = ts; +#endif + old_regs =set_irq_regs (regs);irq_enter ();
arch/x86/kernel/irq_64.c +19 -2
@@ -17,9 +17,15 @@#include <asm/io_apic.h> #include <asm/idle.h> #include <asm/smp.h> +#include <linux/pps.h> atomic_t irq_err_count; +#ifdef CONFIG_PPS_IRQ_EVENTS +struct timespec pps_irq_ts[NR_IRQS ]; +EXPORT_SYMBOL (pps_irq_ts); +#endif +/* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves.
@@ -188,6 +194,12 @@ u64 arch_irq_stat(void) asmlinkage unsigned int do_IRQ(struct pt_regs *regs) {struct pt_regs *old_regs =set_irq_regs (regs); +#ifdef CONFIG_PPS_IRQ_EVENTS +struct timespec ts; + +/* Get IRQ timestamps as soon as possible for the PPS layer */ +getnstimeofday (&ts); +#endif /* high bit used in ret_from_ code */ unsigned vector = ~regs->orig_ax;
@@ -201,9 +213,14 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)stack_overflow_check (regs);#endif -if (likely (irq <NR_IRQS )) +if (likely (irq <NR_IRQS )) { +#ifdef CONFIG_PPS_IRQ_EVENTS +/* Then, after sanity check, store the IRQ timestamp */ + pps_irq_ts[irq] = ts; +#endif +generic_handle_irq (irq); -else { + }else {if (!disable_apic)ack_APIC_irq ();
drivers/pps/Kconfig +12 -0
@@ -22,6 +22,18 @@ config PPS To compile this driver as a module, choose M here: the module will be called pps_core.ko. +config PPS_IRQ_EVENTS + bool "Use low level IRQ timestamps" + depends on PPS && (X86_32 || X86_64) + default yes + help + Say Y here if you wish using low level IRQ timestamps to register + PPS events. + + This should improve PPS resolution but it delays echo functions + call. Note also that this function is not implemented on all + platforms and PPS clients! + config PPS_DEBUG bool "PPS debugging messages" depends on PPS
include/linux/pps.h +1 -0
@@ -181,6 +181,7 @@ struct pps_device {extern spinlock_t pps_idr_lock;extern struct idr pps_idr; +extern struct timespec pps_irq_ts[];extern struct device_attribute pps_attrs[];
include/linux/serial_core.h +6 -1
@@ -165,6 +165,7 @@#include <linux/tty.h> #include <linux/mutex.h> #include <linux/sysrq.h> +#include <linux/pps.h> struct uart_port ;struct uart_info ;
@@ -492,7 +493,11 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status)struct timespec ts; if (ld->ops->dcd_change) +#ifdef CONFIG_PPS_IRQ_EVENTS + ts = pps_irq_ts[port->irq]; +#else getnstimeofday (&ts); +#endif port->icount.dcd++;#ifdef CONFIG_HARD_PPS
@@ -508,7 +513,7 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status) }if (ld->ops->dcd_change) - ld->ops->dcd_change (port, status, &ts); + ld->ops->dcd_change (info->port.tty, status, &ts);tty_ldisc_deref (ld); }
Signature · 1 line
1.5.4.3
Re: [PATCH 10/10] PPS: low level IRQ timestamps recording.
Quoted 6 lines · Rodolfo Giometti
Add low level IRQ timestamps recording for x86 (32 and 64 bits) platforms and enable UART clients in order to use it.
This improves PPS precision. :)
Signed-off-by Rodolfo Giometti <[email protected]>
Hey Rodolfo,
First of all, kudos to your persistence on this patch set, it
really has been a long time that you've been pushing this. Hopefully it won't take much longer. :)
I've never had much experience with PPS devices, so other then knowing a fair number of folks who are interested in using them, most of the code is outside of my realm of knowledge, so I've not had much to comment upon.
However, Thomas asked me to check and see how this interacted with the timekeeping subsystem, so I took another look at the current code.
Quoted 1 line
From a quick review, I really don't see any interactions. The code
seems fairly well isolated.
One question I have is: Do you have any plans for integrating with the adjtimex() interface and its pps values?
My only other comment is on this last patch #10, and as you said in your original post, its deferrable. I'd agree that dropping this patch for now would be best, since adding a getnstimeofday() call, which may take a few microseconds on common hardware, to every interrupt would be a bad idea.
It seems having a special flag on the IRQ for timestamping would be better, and then we could only enable it for PPS connected interrupts. It may add a touch more jitter but I think it would allow for better performance while still reducing jitter.
So yea. Unless there are objections from the serial and parallel port maintainers, or someone who has more experience with PPS devices and might better critique the API proposed, I see no reason for holding this patch set back from my (limited) perspective.
thanks
-john
Rodolfo Giometti
maintainerRe: [PATCH 10/10] PPS: low level IRQ timestamps recording.
Quoted 4 lines · john stultz
Hey Rodolfo,
First of all, kudos to your persistence on this patch set, it
really has been a long time that you've been pushing this. Hopefully it won't take much longer. :)
I hope so. :)
Quoted 5 lines
I've never had much experience with PPS devices, so other then knowing a fair number of folks who are interested in using them, most of the code is outside of my realm of knowledge, so I've not had much to comment upon.
Quoted 7 lines
However, Thomas asked me to check and see how this interacted with the timekeeping subsystem, so I took another look at the current code.
Quoted 1 line
From a quick review, I really don't see any interactions. The code
seems fairly well isolated.
One question I have is: Do you have any plans for integrating with the
adjtimex()interface and its pps values?
Currently not.
Quoted 5 lines
My only other comment is on this last patch #10, and as you said in your original post, its deferrable. I'd agree that dropping this patch for now would be best, since adding a
getnstimeofday()call, which may take a few microseconds on common hardware, to every interrupt would be a bad idea.
I see... neither if we disable it by default in the configuration menu and we remark in the help message that it could be dangerous? :P
However if that patch is blocking for the others then I prefere dropping it.
Quoted 4 lines
It seems having a special flag on the IRQ for timestamping would be better, and then we could only enable it for PPS connected interrupts. It may add a touch more jitter but I think it would allow for better performance while still reducing jitter.
It sounds good! But do you already have any idea about how to do it? It's not an easy task since some drivers may not know at all that they are managing a PPS device! As example, think about serial PPS devices, they are managed by proper line discipline, so how can we modify the IRQ handler behaviour at PPS source registration time?
Quoted 4 lines
So yea. Unless there are objections from the serial and parallel port maintainers, or someone who has more experience with PPS devices and might better critique the API proposed, I see no reason for holding this patch set back from my (limited) perspective.
Thanks a lot for your time! I hope Linux may have this API support soon! :)
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti
H. Peter Anvin
reviewerRe: [PATCH 05/10] ldisc: new dcd_change() method for line disciplines.
In reply to Rodolfo GiomettiWhy limit this to just DCD change, and not any of the other status bits (DCD, RI, DSR, CTS)?
-hpa
Re: [PATCH 05/10] ldisc: new dcd_change() method for line disciplines.
Quoted 2 lines · On Thu, 02 Oct 2008 08:25:57 -0700 "H. Peter Anvin" <[email protected]> wrote:
Why limit this to just DCD change, and not any of the other status bits (DCD, RI, DSR, CTS)?
We can change that later if anyone wants the other bits. I'm quite happy with that side of it, the real question is the core code. The tty bits can then get a spit and polish in the ttydev tree.
Alan