LinuxPPS - PPS support for Linux
Subsystems (5)
Rodolfo Giometti
maintainerPATCH 1/1 LinuxPPS - PPS support for Linux
Hello,
here my last patch for PPS support.
Please, let me know if I have something to do for kernel inclusion.
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Documentation/pps/Makefile new file +27 -0
@@ -0,0 +1,27 @@ +TARGETS = ppstest ppsctl + +CFLAGS += -Wall -O2 -D_GNU_SOURCE +CFLAGS += -I . +CFLAGS += -ggdb + +# -- 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/pps.txt new file +170 -0
170 lines not on this page · raw message
Documentation/pps/ppsctl.c new file +62 -0
62 lines not on this page · raw message
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/ppstest.c new file +151 -0
151 lines not on this page · raw message
Documentation/pps/timepps.h new file +193 -0
193 lines not on this page · raw message
MAINTAINERS +7 -0
@@ -3011,6 +3011,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] +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/w1/Kconfig" source "drivers/power/Kconfig"
drivers/Makefile +1 -0
@@ -63,6 +63,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/char/lp.c +61 -0
79 lines not on this page · raw message
drivers/pps/Kconfig new file +34 -0
@@ -0,0 +1,34 @@ +# +# 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 an high 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. + +source drivers/pps/clients/Kconfig + +endmenu
drivers/pps/Makefile new file +11 -0
@@ -0,0 +1,11 @@ +# +# Makefile for the PPS core. +# + +pps_core-objs += pps.o kapi.o sysfs.o +obj-$(CONFIG_PPS) += pps_core.o +obj-y += clients/ + +ifeq ($(CONFIG_PPS_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif
drivers/pps/clients/Kconfig new file +38 -0
@@ -0,0 +1,38 @@ +# +# 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. + +comment "UART serial support (forced off)" + depends on ! (SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y)) + +config PPS_CLIENT_UART + bool "UART serial support" + depends on SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y) + help + 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
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 +114 -0
114 lines not on this page · raw message
drivers/pps/kapi.c new file +272 -0
272 lines not on this page · raw message
drivers/pps/pps.c new file +332 -0
332 lines not on this page · raw message
drivers/pps/sysfs.c new file +142 -0
142 lines not on this page · raw message
drivers/serial/8250.c +2 -0
@@ -2118,6 +2118,8 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, up->ier |=UART_IER_MSI ;if (up->capabilities &UART_CAP_UUE ) up->ier |=UART_IER_UUE |UART_IER_RTOIE ; +if (up->port.flags &UPF_HARDPPS_CD ) + up->ier |=UART_IER_MSI ;/* enable interrupts */ serial_out (up,UART_IER , up->ier);
drivers/serial/serial_core.c +70 -1
105 lines not on this page · raw message
include/linux/Kbuild +1 -0
@@ -295,6 +295,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/parport.h +12 -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 <asm/system.h> #include <asm/ptrace.h> #include <asm/semaphore.h>
@@ -327,6 +328,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 */
@@ -517,6 +523,12 @@ 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 (int irq,struct parport *port) { +#ifdef CONFIG_PPS_CLIENT_LP +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); +#endif +parport_ieee1284_interrupt (irq, port);read_lock (&port->cad_lock);if (port->cad && port->cad->irq_func)
include/linux/pps.h new file +196 -0
196 lines not on this page · raw message
include/linux/serial_core.h +24 -6
@@ -157,6 +157,7 @@#include <linux/tty.h> #include <linux/mutex.h> #include <linux/sysrq.h> +#include <linux/pps.h> struct uart_port ;struct uart_info ;
@@ -236,6 +237,9 @@ struct uart_port {unsigned char regshift;/* reg offset shift */ unsigned char iotype;/* io access style */ unsigned char unused1; +#ifdef CONFIG_PPS_CLIENT_UART +int pps_source;/* PPS source ID */ +#endif #define UPIO_PORT (0)#define UPIO_HUB6 (1)
@@ -280,7 +284,8 @@ struct uart_port {#define UPF_IOREMAP ((__force upf_t) (1 << 31))#define UPF_CHANGE_MASK ((__force upf_t) (0x17fff)) -#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY)) +#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY\ + |UPF_HARDPPS_CD))unsigned int mctrl;/* current modem ctrl settings */ unsigned int timeout;/* character-based timeout */
@@ -312,6 +317,10 @@ struct uart_state {struct uart_info *info;struct uart_port *port; +#ifdef CONFIG_PPS_CLIENT_UART +struct pps_source_info pps_info; +#endif +struct mutex mutex; };
@@ -476,13 +485,22 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status) {struct uart_info *info = port->info; - port->icount.dcd++; - -#ifdef CONFIG_HARD_PPS -if ((port->flags &UPF_HARDPPS_CD ) && status) -hardpps (); +#ifdef CONFIG_PPS_CLIENT_UART +if (port->flags &UPF_HARDPPS_CD ) { +if (status) { +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); + }else { +pps_event (port->pps_source,PPS_CAPTURECLEAR , port); +dev_dbg (port->dev,"PPS clear at %lu on source #%d\n" , + jiffies, port->pps_source); + } + }#endif + port->icount.dcd++; +if (info->flags &UIF_CHECK_CD ) {if (status)wake_up_interruptible (&info->open_wait);
On Tue, Oct 23, 2007 at 08:04:18PM +0200, Rodolfo Giometti wrote:
Hi Rodolfo,
Quoted 3 lines
here my last patch for PPS support.
Please, let me know if I have something to do for kernel inclusion.
Thanks for trying to get this merged, we've had a few users asking us to support this in the Fedora kernel.
Quoted 1 line
From a quick look through, it doesn't look too bad.
A couple of obvious things that jumped out..
* The example program in the Documentation dir. There was some discussion recently about moving away from doing this, and instead moving code to the samples/ dir (or including it in util-linux instead if applicable).
Documentation/pps/pps.txt line 83
Quoted 9 lines
Documentation/pps/pps.txt new file +9
-0+ static struct pps_source_info_s pps_ktimer_info = { + name : "ktimer", + path : "", + mode : PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \ + PPS_ECHOASSERT | \ + PPS_CANWAIT | PPS_TSFMT_TSPEC, + echo : pps_ktimer_echo, + owner : THIS_MODULE, + };
should be
.name = "ktimer"
etc..
Quoted 1 line
+#include <
linux/version.h>
This should be getting included automatically for you.
On the whole, asides from these (very) minor nits, quite a clean submission compared to a lot of new driver submissions to lkml. Might want to run it through scripts/checkpatch.pl too to see if that picks up any more minor fluff.
Dave
Signature · 1 line
http://www.codemonkey.org.uk
Rodolfo Giometti
maintainerQuoted 3 lines · Dave Jones
On Tue, Oct 23, 2007 at 08:04:18PM +0200, Rodolfo Giometti wrote:
Hi Rodolfo,
Hi! :)
Quoted 6 lines
Quoted 3 lines
here my last patch for PPS support.
Please, let me know if I have something to do for kernel inclusion.
Thanks for trying to get this merged, we've had a few users asking us to support this in the Fedora kernel.
This sounds good! ;)
Quoted 7 lines
Quoted 1 line
From a quick look through, it doesn't look too bad.
A couple of obvious things that jumped out..
* The example program in the Documentation dir. There was some discussion recently about moving away from doing this, and instead moving code to the
samples/dir (or including it in util-linux instead if applicable).
Mmm, I just consider them as simple userland examples. They don't need to manage PPS devices.
I can remove them from Documentation/pps/, no problems, but in my modest opinion they are just documentation. :)
Quoted 5 lines
Quoted 5 lines
Documentation/pps/pps.txt new file +5
-0+ static struct pps_source_info_s pps_ktimer_info = { + name : "ktimer", + path : "", + mode : PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \ + PPS_ECHOASSERT | \
Quoted 8 lines
Documentation/pps/pps.txt line 83
Quoted 4 lines
Documentation/pps/pps.txt new file +4
-0+ PPS_CANWAIT | PPS_TSFMT_TSPEC, + echo : pps_ktimer_echo, + owner : THIS_MODULE, + };should be
.name = "ktimer"
etc..
Fixed.
Quoted 3 lines
Quoted 1 line
+#include <
linux/version.h>This should be getting included automatically for you.
Fixed.
Quoted 4 lines
On the whole, asides from these (very) minor nits, quite a clean submission compared to a lot of new driver submissions to lkml. Might want to run it through
scripts/checkpatch.pltoo to see if that picks up any more minor fluff.
Ok!
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Rodolfo Giometti
maintainerQuoted 5 lines · Dave Jones
On the whole, asides from these (very) minor nits, quite a clean submission compared to a lot of new driver submissions to lkml. Might want to run it through
scripts/checkpatch.pltoo to see if that picks up any more minor fluff.
Here the ./scripts/checkpatch.pl output:
$ ./scripts/checkpatch.pl patch WARNING: do not add new typedefs #522: FILE: Documentation/pps/timepps.h:59: +typedef int pps_handle_t; /* represents a PPS source */
WARNING: do not add new typedefs
#523: FILE: Documentation/pps/timepps.h:60:
+typedef unsigned long pps_seq_t; /* sequence number */
WARNING: do not add new typedefs
#524: FILE: Documentation/pps/timepps.h:61:
+typedef struct ntp_fp ntp_fp_t; /* NTP-compatible time stamp */
WARNING: do not add new typedefs
#525: FILE: Documentation/pps/timepps.h:62:
+typedef union pps_timeu pps_timeu_t; /* generic data type for time stamps */
WARNING: do not add new typedefs
#526: FILE: Documentation/pps/timepps.h:63:
+typedef struct pps_info pps_info_t;
WARNING: do not add new typedefs
#527: FILE: Documentation/pps/timepps.h:64:
+typedef struct pps_params pps_params_t;
These refere to an userland include file.
WARNING: line over 80 characters
#1882: FILE: drivers/serial/serial_core.c:871:
+ if (((old_flags ^ port->flags) & (UPF_SPD_MASK|UPF_HARDPPS_CD)) ||
ERROR: need consistent spacing around '|' (ctx:WxV) #2191: FILE: include/linux/serial_core.h:288:
+ |UPF_HARDPPS_CD))
^
These refere to previous code.
ERROR: Missing Signed-off-by: line(s)
Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS.
Attached the new patch.
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Documentation/pps/Makefile new file +27 -0
@@ -0,0 +1,27 @@ +TARGETS = ppstest ppsctl + +CFLAGS += -Wall -O2 -D_GNU_SOURCE +CFLAGS += -I . +CFLAGS += -ggdb + +# -- 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/pps.txt new file +170 -0
170 lines not on this page · raw message
Documentation/pps/ppsctl.c new file +62 -0
62 lines not on this page · raw message
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/ppstest.c new file +151 -0
151 lines not on this page · raw message
Documentation/pps/timepps.h new file +193 -0
193 lines not on this page · raw message
MAINTAINERS +7 -0
@@ -3011,6 +3011,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] +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/w1/Kconfig" source "drivers/power/Kconfig"
drivers/Makefile +1 -0
@@ -63,6 +63,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/char/lp.c +61 -0
79 lines not on this page · raw message
drivers/pps/Kconfig new file +34 -0
@@ -0,0 +1,34 @@ +# +# 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 an high 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. + +source drivers/pps/clients/Kconfig + +endmenu
drivers/pps/Makefile new file +11 -0
@@ -0,0 +1,11 @@ +# +# Makefile for the PPS core. +# + +pps_core-objs += pps.o kapi.o sysfs.o +obj-$(CONFIG_PPS) += pps_core.o +obj-y += clients/ + +ifeq ($(CONFIG_PPS_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif
drivers/pps/clients/Kconfig new file +38 -0
@@ -0,0 +1,38 @@ +# +# 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. + +comment "UART serial support (forced off)" + depends on ! (SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y)) + +config PPS_CLIENT_UART + bool "UART serial support" + depends on SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y) + help + 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
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 +114 -0
114 lines not on this page · raw message
drivers/pps/kapi.c new file +272 -0
272 lines not on this page · raw message
drivers/pps/pps.c new file +331 -0
331 lines not on this page · raw message
drivers/pps/sysfs.c new file +142 -0
142 lines not on this page · raw message
drivers/serial/8250.c +2 -0
@@ -2118,6 +2118,8 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, up->ier |=UART_IER_MSI ;if (up->capabilities &UART_CAP_UUE ) up->ier |=UART_IER_UUE |UART_IER_RTOIE ; +if (up->port.flags &UPF_HARDPPS_CD ) + up->ier |=UART_IER_MSI ;/* enable interrupts */ serial_out (up,UART_IER , up->ier);
drivers/serial/serial_core.c +70 -1
105 lines not on this page · raw message
include/linux/Kbuild +1 -0
@@ -295,6 +295,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/parport.h +12 -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 <asm/system.h> #include <asm/ptrace.h> #include <asm/semaphore.h>
@@ -327,6 +328,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 */
@@ -517,6 +523,12 @@ 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 (int irq,struct parport *port) { +#ifdef CONFIG_PPS_CLIENT_LP +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); +#endif +parport_ieee1284_interrupt (irq, port);read_lock (&port->cad_lock);if (port->cad && port->cad->irq_func)
include/linux/pps.h new file +196 -0
196 lines not on this page · raw message
include/linux/serial_core.h +24 -6
@@ -157,6 +157,7 @@#include <linux/tty.h> #include <linux/mutex.h> #include <linux/sysrq.h> +#include <linux/pps.h> struct uart_port ;struct uart_info ;
@@ -236,6 +237,9 @@ struct uart_port {unsigned char regshift;/* reg offset shift */ unsigned char iotype;/* io access style */ unsigned char unused1; +#ifdef CONFIG_PPS_CLIENT_UART +int pps_source;/* PPS source ID */ +#endif #define UPIO_PORT (0)#define UPIO_HUB6 (1)
@@ -280,7 +284,8 @@ struct uart_port {#define UPF_IOREMAP ((__force upf_t) (1 << 31))#define UPF_CHANGE_MASK ((__force upf_t) (0x17fff)) -#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY)) +#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY\ + |UPF_HARDPPS_CD))unsigned int mctrl;/* current modem ctrl settings */ unsigned int timeout;/* character-based timeout */
@@ -312,6 +317,10 @@ struct uart_state {struct uart_info *info;struct uart_port *port; +#ifdef CONFIG_PPS_CLIENT_UART +struct pps_source_info pps_info; +#endif +struct mutex mutex; };
@@ -476,13 +485,22 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status) {struct uart_info *info = port->info; - port->icount.dcd++; - -#ifdef CONFIG_HARD_PPS -if ((port->flags &UPF_HARDPPS_CD ) && status) -hardpps (); +#ifdef CONFIG_PPS_CLIENT_UART +if (port->flags &UPF_HARDPPS_CD ) { +if (status) { +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); + }else { +pps_event (port->pps_source,PPS_CAPTURECLEAR , port); +dev_dbg (port->dev,"PPS clear at %lu on source #%d\n" , + jiffies, port->pps_source); + } + }#endif + port->icount.dcd++; +if (info->flags &UIF_CHECK_CD ) {if (status)wake_up_interruptible (&info->open_wait);
A few comments:
drivers/char/lp.c static int lp_register(int nr, struct parport *port) · line 868
Quoted 2 lines
drivers/char/lp.c +2
-0+ dev_err(port->dev, "PPS support disabled due port \"%s\" is " + "in polling mode\n",
I think "because" instead of "due" is closer to standard English.
Review
Quoted 2 lines
(quoted diff) +2
-0+ printk(KERN_ERR "pps: %s: too much PPS sources in the system\n", + info->name);
Similarly should be "many" instead of "much".
drivers/pps/kapi.c line 107
Quoted 12 lines
drivers/pps/kapi.c new file +12
-0+/* Get new ID for the new PPS source */ +if (idr_pre_get (&pps_idr,GFP_KERNEL ) ==0 ) { + err = -ENOMEM ; + goto kfree_pps; + } + +spin_lock_irq (&idr_lock); + err =idr_get_new (&pps_idr, pps, &id); +spin_unlock_irq (&idr_lock); + +if (err <0 ) + goto kfree_pps;
You usually can handle idr_get_new() returning -EAGAIN by jumping back to the idr_pre_get(), to handle someone else coming in and stealing the memory you just preallocated. In this case it may not matter since it's pretty unlikely that a lot of contexts are using the idr at the same time. But anyway...
drivers/pps/kapi.c line 188
Quoted 7 lines
drivers/pps/kapi.c new file +6
-0+void pps_unregister_source(int source) + wait_event(pps->usage_queue, atomic_read(&pps->usage) == 0); + +pps_sysfs_remove_source_entry (pps ); +pps_unregister_cdev (pps); +kfree (pps);
This reference counting looks dubious to me... later on in the code you have:
drivers/pps/pps.c line 215
Quoted 7 lines
drivers/pps/pps.c new file +7
-0+static int pps_cdev_open (struct inode *inode,struct file *file) +{ +struct pps_device *pps =container_of (inode->i_cdev, + struct pps_device, cdev); + +/* Lock the PPS source against (possible) deregistration */ +atomic_inc (&pps->usage);
with no locking, so I see no reason why the atomic_inc() couldn't happen right after the wait_event() sees a count of 0 and lets the deregistration continue. Which would lead to use-after-free.
- R.
Rodolfo Giometti
maintainerQuoted 6 lines · Roland Dreier
A few comments:
drivers/char/lp.c static int lp_register(int nr, struct parport *port) · line 868
Quoted 2 lines
drivers/char/lp.c +2
-0+ dev_err(port->dev, "PPS support disabled due port \"%s\" is " + "in polling mode\n",I think "because" instead of "due" is closer to standard English.
Fixed.
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ printk(KERN_ERR "pps: %s: too much PPS sources in the system\n", + info->name);Similarly should be "many" instead of "much".
Fixed.
Quoted 10 lines
Quoted 10 lines
drivers/pps/kapi.c new file +10
-0+/* Get new ID for the new PPS source */ +if (idr_pre_get (&pps_idr,GFP_KERNEL ) ==0 ) { + err = -ENOMEM ; + goto kfree_pps; + } + +spin_lock_irq (&idr_lock); + err =idr_get_new (&pps_idr, pps, &id); +spin_unlock_irq (&idr_lock); +
Quoted 8 lines
drivers/pps/kapi.c line 107
Quoted 2 lines
drivers/pps/kapi.c new file +2
-0+if (err <0 ) + goto kfree_pps;You usually can handle
idr_get_new()returning-EAGAINby jumping back to theidr_pre_get(), to handle someone else coming in and stealing the memory you just preallocated. In this case it may not matter since it's pretty unlikely that a lot of contexts are using the idr at the same time. But anyway...
I don't understand what you mean. Can you please submit an example code?
Quoted 11 lines
drivers/pps/kapi.c line 188
Quoted 7 lines
drivers/pps/kapi.c new file +6
-0+void pps_unregister_source(int source) + wait_event(pps->usage_queue, atomic_read(&pps->usage) == 0); + +pps_sysfs_remove_source_entry (pps ); +pps_unregister_cdev (pps); +kfree (pps);This reference counting looks dubious to me... later on in the code you have:
Quoted 11 lines
drivers/pps/pps.c line 215
Quoted 7 lines
drivers/pps/pps.c new file +7
-0+static int pps_cdev_open (struct inode *inode,struct file *file) +{ +struct pps_device *pps =container_of (inode->i_cdev, + struct pps_device, cdev); + +/* Lock the PPS source against (possible) deregistration */ +atomic_inc (&pps->usage);with no locking, so I see no reason why the
atomic_inc()couldn't happen right after thewait_event()sees a count of 0 and lets the deregistration continue. Which would lead to use-after-free.
Mmm... you are right... can you please suggest to me how can I easily fix this problem?
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Rodolfo Giometti
maintainerQuoted 11 lines · Roland Dreier
drivers/pps/kapi.c line 188
Quoted 7 lines
drivers/pps/kapi.c new file +6
-0+void pps_unregister_source(int source) + wait_event(pps->usage_queue, atomic_read(&pps->usage) == 0); + +pps_sysfs_remove_source_entry (pps ); +pps_unregister_cdev (pps); +kfree (pps);This reference counting looks dubious to me... later on in the code you have:
Quoted 11 lines
drivers/pps/pps.c line 215
Quoted 7 lines
drivers/pps/pps.c new file +7
-0+static int pps_cdev_open (struct inode *inode,struct file *file) +{ +struct pps_device *pps =container_of (inode->i_cdev, + struct pps_device, cdev); + +/* Lock the PPS source against (possible) deregistration */ +atomic_inc (&pps->usage);with no locking, so I see no reason why the
atomic_inc()couldn't happen right after thewait_event()sees a count of 0 and lets the deregistration continue. Which would lead to use-after-free.
Since pps_unregister_source() is defined as:
void pps_unregister_source(int source)
{
struct pps_device *pps;
spin_lock_irq(&idr_lock);
pps = idr_find(&pps_idr, source);
if (!pps) {
spin_unlock_irq(&idr_lock);
return;
}
/* This should be done first in order to deny IRQ handlers
* to access PPS structs
*/
idr_remove(&pps_idr, pps->id);
spin_unlock_irq(&idr_lock);
wait_event(pps->usage_queue, atomic_read(&pps->usage) == 0);
pps_sysfs_remove_source_entry(pps);
pps_unregister_cdev(pps);
kfree(pps);
}changing pps_cdev_open() as follow should resolve this problem:
static int pps_cdev_open(struct inode *inode, struct file *file)
{
struct pps_device *pps = container_of(inode->i_cdev,
struct pps_device, cdev);
int found;
spin_lock_irq(&idr_lock);
found = idr_find(&pps_idr, pps->id) != NULL;
/* Lock the PPS source against (possible) deregistration */
if (found)
atomic_inc(&pps->usage);
spin_unlock_irq(&idr_lock);
if (!found)
return -ENODEV;
file->private_data = pps;
return 0;
}Is that right?
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Rodolfo Giometti
maintainerHello,
here my last patch for PPS support.
I merged all notes received in these days, also I added a (possible?) fix for the problem pointed out by Roland.
If you think it's ok, please let me know so I can release version 5.0.0 for inclusion.
On the userland side some NTPD's reference clock has been tested and they are working without patches (but one)! :)
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Documentation/pps/Makefile new file +27 -0
@@ -0,0 +1,27 @@ +TARGETS = ppstest ppsctl + +CFLAGS += -Wall -O2 -D_GNU_SOURCE +CFLAGS += -I . +CFLAGS += -ggdb + +# -- 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/pps.txt new file +170 -0
170 lines not on this page · raw message
Documentation/pps/ppsctl.c new file +62 -0
62 lines not on this page · raw message
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/ppstest.c new file +151 -0
151 lines not on this page · raw message
Documentation/pps/timepps.h new file +195 -0
195 lines not on this page · raw message
MAINTAINERS +7 -0
@@ -3011,6 +3011,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] +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/w1/Kconfig" source "drivers/power/Kconfig"
drivers/Makefile +1 -0
@@ -63,6 +63,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/char/lp.c +61 -0
79 lines not on this page · raw message
drivers/pps/Kconfig new file +34 -0
@@ -0,0 +1,34 @@ +# +# 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 an high 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. + +source drivers/pps/clients/Kconfig + +endmenu
drivers/pps/Makefile new file +11 -0
@@ -0,0 +1,11 @@ +# +# Makefile for the PPS core. +# + +pps_core-objs += pps.o kapi.o sysfs.o +obj-$(CONFIG_PPS) += pps_core.o +obj-y += clients/ + +ifeq ($(CONFIG_PPS_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif
drivers/pps/clients/Kconfig new file +38 -0
@@ -0,0 +1,38 @@ +# +# 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. + +comment "UART serial support (forced off)" + depends on ! (SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y)) + +config PPS_CLIENT_UART + bool "UART serial support" + depends on SERIAL_CORE != n && !(PPS = m && SERIAL_CORE = y) + help + 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
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 +114 -0
114 lines not on this page · raw message
drivers/pps/kapi.c new file +272 -0
272 lines not on this page · raw message
drivers/pps/pps.c new file +342 -0
342 lines not on this page · raw message
drivers/pps/sysfs.c new file +142 -0
142 lines not on this page · raw message
drivers/serial/8250.c +2 -0
@@ -2118,6 +2118,8 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, up->ier |=UART_IER_MSI ;if (up->capabilities &UART_CAP_UUE ) up->ier |=UART_IER_UUE |UART_IER_RTOIE ; +if (up->port.flags &UPF_HARDPPS_CD ) + up->ier |=UART_IER_MSI ;/* enable interrupts */ serial_out (up,UART_IER , up->ier);
drivers/serial/serial_core.c +70 -1
105 lines not on this page · raw message
include/linux/Kbuild +1 -0
@@ -295,6 +295,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/parport.h +12 -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 <asm/system.h> #include <asm/ptrace.h> #include <asm/semaphore.h>
@@ -327,6 +328,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 */
@@ -517,6 +523,12 @@ 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 (int irq,struct parport *port) { +#ifdef CONFIG_PPS_CLIENT_LP +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); +#endif +parport_ieee1284_interrupt (irq, port);read_lock (&port->cad_lock);if (port->cad && port->cad->irq_func)
include/linux/pps.h new file +204 -0
204 lines not on this page · raw message
include/linux/serial_core.h +24 -6
@@ -157,6 +157,7 @@#include <linux/tty.h> #include <linux/mutex.h> #include <linux/sysrq.h> +#include <linux/pps.h> struct uart_port ;struct uart_info ;
@@ -236,6 +237,9 @@ struct uart_port {unsigned char regshift;/* reg offset shift */ unsigned char iotype;/* io access style */ unsigned char unused1; +#ifdef CONFIG_PPS_CLIENT_UART +int pps_source;/* PPS source ID */ +#endif #define UPIO_PORT (0)#define UPIO_HUB6 (1)
@@ -280,7 +284,8 @@ struct uart_port {#define UPF_IOREMAP ((__force upf_t) (1 << 31))#define UPF_CHANGE_MASK ((__force upf_t) (0x17fff)) -#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY)) +#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY\ + |UPF_HARDPPS_CD))unsigned int mctrl;/* current modem ctrl settings */ unsigned int timeout;/* character-based timeout */
@@ -312,6 +317,10 @@ struct uart_state {struct uart_info *info;struct uart_port *port; +#ifdef CONFIG_PPS_CLIENT_UART +struct pps_source_info pps_info; +#endif +struct mutex mutex; };
@@ -476,13 +485,22 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status) {struct uart_info *info = port->info; - port->icount.dcd++; - -#ifdef CONFIG_HARD_PPS -if ((port->flags &UPF_HARDPPS_CD ) && status) -hardpps (); +#ifdef CONFIG_PPS_CLIENT_UART +if (port->flags &UPF_HARDPPS_CD ) { +if (status) { +pps_event (port->pps_source,PPS_CAPTUREASSERT , port); +dev_dbg (port->dev,"PPS assert at %lu on source #%d\n" , + jiffies, port->pps_source); + }else { +pps_event (port->pps_source,PPS_CAPTURECLEAR , port); +dev_dbg (port->dev,"PPS clear at %lu on source #%d\n" , + jiffies, port->pps_source); + } + }#endif + port->icount.dcd++; +if (info->flags &UIF_CHECK_CD ) {if (status)wake_up_interruptible (&info->open_wait);