2008-11-25 21:12:24

by Rodolfo Giometti

[permalink] [raw]
Subject: LinuxPPS (Version 9): the PPS Linux implementation.

Note: Very few changes since last post! Please, add this patch set
into next available merge window.

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
=========

Version 8 -> 9:
---------------

* language fix up.

Version 7 -> 8:
---------------

* PPS ldisc module locking fix up.

* race during ldisc initialization fix up.

Version 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.

Note: Last patch (0009-PPS-low-level-IRQ-timestamps-recording.patch)
implements low level IRQs timestamps recording which improves
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 | 16 +
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 | 32 ++-
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 | 155 +++++++++++++++
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 | 11 +
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
38 files changed, 2235 insertions(+), 15 deletions(-)



2008-11-25 21:11:26

by Rodolfo Giometti

[permalink] [raw]
Subject: [PATCH] ldisc: new N_PPS (Pulse Per Second) line discipine.

Signed-off-by: Rodolfo Giometti <[email protected]>
---
include/linux/tty.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/include/linux/tty.h b/include/linux/tty.h
index 019c10b..50656a0 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -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 17
+#define NR_LDISCS 18

/* line disciplines */
#define N_TTY 0
@@ -45,6 +45,7 @@
#define N_SYNC_PPP 14 /* synchronous PPP */
#define N_HCI 15 /* Bluetooth HCI UART */
#define N_GIGASET_M101 16 /* Siemens Gigaset M101 serial DECT adapter */
+#define N_PPS 17 /* Pulse per Second */

/*
* This character is the same as _POSIX_VDISABLE: it cannot be used as
--
1.5.4.3

2008-11-25 21:11:41

by Rodolfo Giometti

[permalink] [raw]
Subject: [PATCH] PPS: UART PPS support replaced by new N_PPS line discipline.

Starting from now the PPS signal routed to the DCD pin of a serial
ports is managed by a dedicated line discipline.

Signed-off-by: Rodolfo Giometti <[email protected]>
---
drivers/pps/clients/Kconfig | 9 +--
drivers/pps/clients/Makefile | 1 +
drivers/pps/clients/pps-ldisc.c | 172 +++++++++++++++++++++++++++++++++++++++
drivers/serial/serial_core.c | 78 ------------------
include/linux/serial_core.h | 39 ++-------
5 files changed, 184 insertions(+), 115 deletions(-)
create mode 100644 drivers/pps/clients/pps-ldisc.c

diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig
index 09ba5c3..b4054cd 100644
--- a/drivers/pps/clients/Kconfig
+++ b/drivers/pps/clients/Kconfig
@@ -15,12 +15,9 @@ config PPS_CLIENT_KTIMER
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)
+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.
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
index f3c1e39..9f5b988 100644
--- a/drivers/pps/clients/Makefile
+++ b/drivers/pps/clients/Makefile
@@ -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
diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c
new file mode 100644
index 0000000..1a4c5cc
--- /dev/null
+++ b/drivers/pps/clients/pps-ldisc.c
@@ -0,0 +1,172 @@
+/*
+ * pps-ldisc.c -- PPS line discipline
+ *
+ *
+ * Copyright (C) 2008 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.
+ */
+
+#include <linux/module.h>
+#include <linux/serial_core.h>
+#include <linux/tty.h>
+#include <linux/pps.h>
+
+#define PPS_TTY_MAGIC 0x0001
+
+#ifdef CONFIG_PPS_IRQ_EVENTS
+
+static void pps_tty_dcd_change(struct uart_port *port, unsigned int status,
+ struct timespec *ts)
+{
+ int id = (int) port->info->tty->disc_data;
+
+ pps_event(id, &pps_irq_ts[port->irq],
+ status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR, port);
+
+ pr_debug("[IRQev] PPS %s at %lu on source #%d\n",
+ status ? "assert" : "clear", jiffies, id);
+}
+
+#else
+
+static void pps_tty_dcd_change(struct uart_port *port, unsigned int status,
+ struct timespec *ts)
+{
+ int id = (int) port->info->tty->disc_data;
+ struct timespec __ts;
+ struct pps_ktime pps_ts;
+
+ /* First of all we get the time stamp... */
+ getnstimeofday(&__ts);
+
+ /* Does caller give us a timestamp? */
+ if (ts) { /* Yes. Let's use it! */
+ pps_ts.sec = ts->tv_sec;
+ pps_ts.nsec = ts->tv_nsec;
+ } else { /* No. Do it ourself! */
+ pps_ts.sec = __ts.tv_sec;
+ pps_ts.nsec = __ts.tv_nsec;
+ }
+
+ /* Now do the PPS event report */
+ pps_event(id, &pps_ts, status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR,
+ port);
+
+ pr_debug("[STDev] PPS %s at %lu on source #%d\n",
+ status ? "assert" : "clear", jiffies, id);
+}
+
+#endif /* CONFIG_PPS_IRQ_EVENTS */
+
+static int pps_tty_open(struct tty_struct *tty)
+{
+ struct pps_source_info info;
+ struct tty_driver *drv = tty->driver;
+ int index = tty->index + drv->name_base;
+ int ret;
+
+ info.owner = THIS_MODULE;
+ info.dev = NULL;
+ snprintf(info.name, PPS_MAX_NAME_LEN, "%s%d", drv->driver_name, index);
+ snprintf(info.path, PPS_MAX_NAME_LEN, "/dev/%s%d", drv->name, index);
+ info.mode = PPS_CAPTUREBOTH | \
+ PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
+ PPS_CANWAIT | PPS_TSFMT_TSPEC;
+
+ ret = pps_register_source(&info, PPS_CAPTUREBOTH | \
+ PPS_OFFSETASSERT | PPS_OFFSETCLEAR);
+ if (ret < 0) {
+ pr_err("cannot register PPS source \"%s\"\n", info.path);
+ return ret;
+ }
+ tty->disc_data = (void *) ret;
+
+ /* Should open N_TTY ldisc too */
+ ret = n_tty_open(tty);
+ if (ret < 0)
+ pps_unregister_source((int) tty->disc_data);
+
+ pr_info("PPS source #%d \"%s\" added\n", ret, info.path);
+
+ return 0;
+}
+
+static void pps_tty_close(struct tty_struct *tty)
+{
+ int id = (int) tty->disc_data;
+
+ pps_unregister_source(id);
+ n_tty_close(tty);
+
+ pr_info("PPS source #%d removed\n", id);
+}
+
+struct tty_ldisc pps_ldisc = {
+ .magic = PPS_TTY_MAGIC,
+ .name = "pps_tty",
+ .dcd_change = pps_tty_dcd_change,
+ .open = pps_tty_open,
+ .close = pps_tty_close,
+
+ /* Now we should use N_TTY ldisc methods in order to have
+ * normal tty behaviour
+ */
+ .flush_buffer = n_tty_flush_buffer,
+ .chars_in_buffer = n_tty_chars_in_buffer,
+ .read = n_tty_read,
+ .write = n_tty_write,
+ .ioctl = n_tty_ioctl,
+ .set_termios = n_tty_set_termios,
+ .poll = n_tty_poll,
+ .receive_buf = n_tty_receive_buf,
+ .write_wakeup = n_tty_write_wakeup
+};
+
+/*
+ * Module stuff
+ */
+
+static int __init pps_tty_init(void)
+{
+ int err;
+
+ err = tty_register_ldisc(N_PPS, &pps_ldisc);
+ if (err)
+ pr_err("can't register PPS line discipline\n");
+ else
+ pr_info("PPS line discipline registered\n");
+
+ return err;
+}
+
+static void __exit pps_tty_cleanup(void)
+{
+ int err;
+
+ err = tty_unregister_ldisc(N_PPS);
+ if (err)
+ pr_err("can't unregister PPS line discipline\n");
+ else
+ pr_info("PPS line discipline removed\n");
+}
+
+module_init(pps_tty_init);
+module_exit(pps_tty_cleanup);
+
+MODULE_ALIAS_LDISC(N_PPS);
+MODULE_AUTHOR("Rodolfo Giometti <[email protected]>");
+MODULE_DESCRIPTION("PPS TTY device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 4368a13..7e73c45 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -33,7 +33,6 @@
#include <linux/serial.h> /* for serial_state and serial_icounter_struct */
#include <linux/delay.h>
#include <linux/mutex.h>
-#include <linux/pps.h>

#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -634,63 +633,6 @@ static int uart_get_info(struct uart_state *state,
return 0;
}

-#ifdef CONFIG_PPS_CLIENT_UART
-
-static int
-uart_register_pps_port(struct uart_state *state, struct uart_port *port)
-{
- struct tty_driver *drv = port->info->tty->driver;
- int ret;
-
- state->pps_info.owner = THIS_MODULE;
- state->pps_info.dev = port->dev;
- snprintf(state->pps_info.name, PPS_MAX_NAME_LEN, "%s%d",
- drv->driver_name, port->line);
- snprintf(state->pps_info.path, PPS_MAX_NAME_LEN, "/dev/%s%d",
- drv->name, port->line);
-
- state->pps_info.mode = PPS_CAPTUREBOTH | \
- PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
- PPS_CANWAIT | PPS_TSFMT_TSPEC;
-
- ret = pps_register_source(&state->pps_info, PPS_CAPTUREBOTH | \
- PPS_OFFSETASSERT | PPS_OFFSETCLEAR);
- if (ret < 0) {
- dev_err(port->dev, "cannot register PPS source \"%s\"\n",
- state->pps_info.path);
- return ret;
- }
- port->pps_source = ret;
- dev_dbg(port->dev, "PPS source #%d \"%s\" added\n",
- port->pps_source, state->pps_info.path);
-
- return 0;
-}
-
-static void
-uart_unregister_pps_port(struct uart_state *state, struct uart_port *port)
-{
- pps_unregister_source(port->pps_source);
- dev_dbg(port->dev, "PPS source #%d \"%s\" removed\n",
- port->pps_source, state->pps_info.path);
-}
-
-#else
-
-static inline int
-uart_register_pps_port(struct uart_state *state, struct uart_port *port)
-{
- return 0;
-}
-
-static inline void
-uart_unregister_pps_port(struct uart_state *state, struct uart_port *port)
-{
- /* Nop */
-}
-
-#endif /* CONFIG_PPS_CLIENT_UART */
-
static int uart_set_info(struct uart_state *state,
struct serial_struct __user *newinfo)
{
@@ -865,14 +807,6 @@ static int uart_set_info(struct uart_state *state,
(port->flags & UPF_LOW_LATENCY) ? 1 : 0;

check_and_exit:
- /* PPS support enabled/disabled? */
- if ((old_flags & UPF_HARDPPS_CD) != (new_flags & UPF_HARDPPS_CD)) {
- if (new_flags & UPF_HARDPPS_CD)
- uart_register_pps_port(state, port);
- else
- uart_unregister_pps_port(state, port);
- }
-
retval = 0;
if (port->type == PORT_UNKNOWN)
goto exit;
@@ -2206,12 +2140,6 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
port->ops->config_port(port, flags);
}

- /*
- * Add the PPS support for the current port.
- */
- if (port->flags & UPF_HARDPPS_CD)
- uart_register_pps_port(state, port);
-
if (port->type != PORT_UNKNOWN) {
unsigned long flags;

@@ -2468,12 +2396,6 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
mutex_unlock(&state->mutex);

/*
- * Remove PPS support from the current port.
- */
- if (port->flags & UPF_HARDPPS_CD)
- uart_unregister_pps_port(state, port);
-
- /*
* Remove the devices from the tty layer
*/
tty_unregister_device(drv->tty_driver, port->line);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index a80d1ea..80f85fc 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -240,9 +240,6 @@ 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)
@@ -321,10 +318,6 @@ 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;
};

@@ -488,31 +481,11 @@ 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->tty);
+ struct timespec ts;

-#ifdef CONFIG_PPS_CLIENT_UART
- 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;
-
- if (port->flags & UPF_HARDPPS_CD) {
- pps_event(port->pps_source,
-#ifdef CONFIG_PPS_IRQ_EVENTS
- &pps_irq_ts[port->irq],
-#else
- &ts,
-#endif
- status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR,
- port);
- dev_dbg(port->dev, "PPS %s at %lu on source #%d\n",
- status ? "assert" : "clear", jiffies, port->pps_source);
- }
-#endif
+ if (ld->dcd_change)
+ getnstimeofday(&ts);

port->icount.dcd++;

@@ -522,6 +495,10 @@ uart_handle_dcd_change(struct uart_port *port, unsigned int status)
else if (info->tty)
tty_hangup(info->tty);
}
+
+ if (ld->dcd_change)
+ ld->dcd_change(port, status, &ts);
+ tty_ldisc_deref(ld);
}

/**
--
1.5.4.3

2008-11-25 21:11:55

by Rodolfo Giometti

[permalink] [raw]
Subject: [PATCH] ldisc: new dcd_change() method for line disciplines.

Signed-off-by: Rodolfo Giometti <[email protected]>
---
Documentation/tty.txt | 4 ++++
include/linux/tty_ldisc.h | 10 ++++++++++
2 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/Documentation/tty.txt b/Documentation/tty.txt
index 8e65c44..3fc812a 100644
--- a/Documentation/tty.txt
+++ b/Documentation/tty.txt
@@ -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

diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 6226504..a135d6c 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -99,11 +99,19 @@
* 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 uart_port *port, 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>
#include <linux/wait.h>

+struct uart_port;
+
struct tty_ldisc {
int magic;
char *name;
@@ -136,6 +144,8 @@ struct tty_ldisc {
void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
char *fp, int count);
void (*write_wakeup)(struct tty_struct *);
+ void (*dcd_change)(struct uart_port *, unsigned int,
+ struct timespec *);

struct module *owner;

--
1.5.4.3

2008-11-25 21:12:46

by Rodolfo Giometti

[permalink] [raw]
Subject: [PATCH] ldisc n_tty: export all N_TTY ldisc methods.

Signed-off-by: Rodolfo Giometti <[email protected]>
---
drivers/char/n_tty.c | 54 +++++++++++++++++++++++++++++--------------------
include/linux/tty.h | 17 ++++++++++++++-
2 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 596c717..ac30f1e 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -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>
@@ -187,7 +187,7 @@ static void reset_buffer_flags(struct tty_struct *tty)
* lock_kernel() still.
*/

-static void n_tty_flush_buffer(struct tty_struct * tty)
+void n_tty_flush_buffer(struct tty_struct * tty)
{
/* clear everything and unthrottle the driver */
reset_buffer_flags(tty);
@@ -200,6 +200,7 @@ static void n_tty_flush_buffer(struct tty_struct * tty)
wake_up_interruptible(&tty->link->read_wait);
}
}
+EXPORT_SYMBOL(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(n_tty_chars_in_buffer);

/**
* is_utf8_continuation - utf8 multibyte check
@@ -337,7 +339,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.
+ * Called from n_tty_write under the tty layer write lock.
*/

static ssize_t opost_block(struct tty_struct * tty,
@@ -883,7 +885,7 @@ send_signal:
* 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)
{
@@ -892,6 +894,7 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
}
return;
}
+EXPORT_SYMBOL(n_tty_write_wakeup);

/**
* n_tty_receive_buf - data receive
@@ -906,7 +909,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;
@@ -984,6 +987,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
tty->driver->throttle(tty);
}
}
+EXPORT_SYMBOL(n_tty_receive_buf);

int is_ignored(int sig)
{
@@ -1003,7 +1007,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;
@@ -1067,6 +1071,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
}
n_tty_set_room(tty);
}
+EXPORT_SYMBOL(n_tty_set_termios);

/**
* n_tty_close - close the ldisc for this tty
@@ -1078,7 +1083,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) {
@@ -1086,6 +1091,7 @@ static void n_tty_close(struct tty_struct *tty)
tty->read_buf = NULL;
}
}
+EXPORT_SYMBOL(n_tty_close);

/**
* n_tty_open - open an ldisc
@@ -1097,7 +1103,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;
@@ -1116,6 +1122,7 @@ static int n_tty_open(struct tty_struct *tty)
tty->closing = 0;
return 0;
}
+EXPORT_SYMBOL(n_tty_open);

static inline int input_available_p(struct tty_struct *tty, int amt)
{
@@ -1134,7 +1141,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
@@ -1195,7 +1202,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("read_chan: no tty->pgrp!\n");
+ printk("n_tty_read: no tty->pgrp!\n");
else if (task_pgrp(current) != tty->pgrp) {
if (is_ignored(SIGTTIN) ||
is_current_pgrp_orphaned())
@@ -1210,7 +1217,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
@@ -1224,7 +1231,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;
@@ -1239,7 +1246,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
do_it_again:

if (!tty->read_buf) {
- printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
+ printk("n_tty_read: called with read_buf == NULL?!?\n");
return -EIO;
}

@@ -1422,9 +1429,10 @@ do_it_again:

return retval;
}
+EXPORT_SYMBOL(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
@@ -1438,7 +1446,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;
@@ -1510,9 +1518,10 @@ break_out:
remove_wait_queue(&tty->write_wait, &wait);
return (b - buf) ? b - buf : retval;
}
+EXPORT_SYMBOL(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
@@ -1530,7 +1539,7 @@ break_out:
* a read wakeup to fix this bug.
*/

-static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
+unsigned int n_tty_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
{
unsigned int mask = 0;

@@ -1556,6 +1565,7 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol
mask |= POLLOUT | POLLWRNORM;
return mask;
}
+EXPORT_SYMBOL(n_tty_poll);

struct tty_ldisc tty_ldisc_N_TTY = {
.magic = TTY_LDISC_MAGIC,
@@ -1564,11 +1574,11 @@ struct tty_ldisc 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
};
diff --git a/include/linux/tty.h b/include/linux/tty.h
index defd2ab..019c10b 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -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>

@@ -383,7 +384,21 @@ static inline void tty_audit_opening(void)
#endif

/* tty_ioctl.c */
-extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
+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);
+extern int n_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);

/* serial.c */
--
1.5.4.3

2008-11-26 01:06:27

by Andrew Morton

[permalink] [raw]
Subject: Re: LinuxPPS (Version 9): the PPS Linux implementation.

On Tue, 25 Nov 2008 22:11:06 +0100
Rodolfo Giometti <[email protected]> wrote:

> This patch set adds the PPS support into Linux.

I'm having way too much trouble getting all this to apply on
2.6.28-rc6, let alone linux-next.

Please redo everything against the latest Linus tree and resend
everything with full changelogs, etc.

You could even redo the patches against linux-next, which is after all
our candidate 2.6.29 tree. But afacit there are few conflicting
changes in there at this time, apart from the fact that lots of files
have been moved into different directories, but that's a relatively
minor thing.

2008-11-28 11:42:38

by Tilman Schmidt

[permalink] [raw]
Subject: Re: [PATCH] ldisc: new dcd_change() method for line disciplines.

Rodolfo Giometti schrieb:
> --- a/include/linux/tty_ldisc.h
> +++ b/include/linux/tty_ldisc.h
> @@ -99,11 +99,19 @@
> * 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 uart_port *port, 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.
> */

I don't see an actual call to that new method getting added anywhere.
Is that planned for a later patch? Which serial drivers will support
that mechanism? Should the documentation perhaps mention that not
all drivers support this?

Thanks,
Tilman

--
Tilman Schmidt E-Mail: [email protected]
Bonn, Germany
Diese Nachricht besteht zu 100% aus wiederverwerteten Bits.
Unge?ffnet mindestens haltbar bis: (siehe R?ckseite)


Attachments:
signature.asc (250.00 B)
OpenPGP digital signature

2008-11-28 12:58:23

by Rodolfo Giometti

[permalink] [raw]
Subject: Re: [PATCH] ldisc: new dcd_change() method for line disciplines.

On Fri, Nov 28, 2008 at 12:39:16PM +0100, Tilman Schmidt wrote:
> Rodolfo Giometti schrieb:
> > --- a/include/linux/tty_ldisc.h
> > +++ b/include/linux/tty_ldisc.h
> > @@ -99,11 +99,19 @@
> > * 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 uart_port *port, 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.
> > */
>
> I don't see an actual call to that new method getting added anywhere.
> Is that planned for a later patch? Which serial drivers will support
> that mechanism? Should the documentation perhaps mention that not
> all drivers support this?

See patch pps-serial-clients-support.patch into this patchset.

Ciao,

Rodolfo

--

GNU/Linux Solutions e-mail: [email protected]
Linux Device Driver [email protected]
Embedded Systems phone: +39 349 2432127
UNIX programming skype: rodolfo.giometti

2008-11-28 14:00:07

by Alan

[permalink] [raw]
Subject: Re: [PATCH] ldisc: new dcd_change() method for line disciplines.

On Fri, 28 Nov 2008 12:39:16 +0100
Tilman Schmidt <[email protected]> wrote:

> Rodolfo Giometti schrieb:
> > --- a/include/linux/tty_ldisc.h
> > +++ b/include/linux/tty_ldisc.h
> > @@ -99,11 +99,19 @@
> > * 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 uart_port *port, 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.
> > */
>
> I don't see an actual call to that new method getting added anywhere.
> Is that planned for a later patch?

Its used in one of the later patches of the set.