diff options
author | Daniel Thompson <daniel.thompson@linaro.org> | 2015-01-19 15:40:24 +0000 |
---|---|---|
committer | Daniel Thompson <daniel.thompson@linaro.org> | 2015-01-27 16:49:13 +0000 |
commit | 9230175ca2b56bc0ababd2f45efa4392c3a78f08 (patch) | |
tree | 7822a838c83812a8fdbbbf2d09863f6cf91fce1a | |
parent | 78c3d839614579aee184b2943454e49ddac8f009 (diff) |
tty: poll_nmi_wrap/unwrap
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
-rw-r--r-- | drivers/tty/serial/serial_core.c | 32 | ||||
-rw-r--r-- | include/linux/serial_core.h | 2 | ||||
-rw-r--r-- | include/linux/tty_driver.h | 12 |
3 files changed, 46 insertions, 0 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 984605bb5bf1..69df4ac7bb2f 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2305,6 +2305,36 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch) port->ops->poll_put_char(port, '\r'); port->ops->poll_put_char(port, ch); } + +static int uart_poll_request_nmi(struct tty_driver *driver, int line, + irq_handler_t handler) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + + if (!state || !state->uart_port) + return -1; + + port = state->uart_port; + if (!port->ops->poll_request_nmi || !port->ops->poll_free_nmi) + return -1; + + return port->ops->poll_request_nmi(port, handler); +} + +static void uart_poll_free_nmi(struct tty_driver *driver, int line) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + + if (!state || !state->uart_port) + return; + + port = state->uart_port; + port->ops->poll_free_nmi(port); +} #endif static const struct tty_operations uart_ops = { @@ -2337,6 +2367,8 @@ static const struct tty_operations uart_ops = { .poll_init = uart_poll_init, .poll_get_char = uart_poll_get_char, .poll_put_char = uart_poll_put_char, + .poll_request_nmi = uart_poll_request_nmi, + .poll_free_nmi = uart_poll_free_nmi, #endif }; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 3dff1a7437b8..9132048c5880 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -90,6 +90,8 @@ struct uart_ops { int (*poll_init)(struct uart_port *); void (*poll_put_char)(struct uart_port *, unsigned char); int (*poll_get_char)(struct uart_port *); + int (*poll_request_nmi)(struct uart_port *, irq_handler_t); + void (*poll_free_nmi)(struct uart_port *); #endif }; diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 92e337c18839..8eace29ecc6f 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -240,6 +240,7 @@ #include <linux/export.h> #include <linux/fs.h> +#include <linux/interrupt.h> #include <linux/list.h> #include <linux/cdev.h> #include <linux/termios.h> @@ -289,6 +290,17 @@ struct tty_operations { int (*poll_init)(struct tty_driver *driver, int line, char *options); int (*poll_get_char)(struct tty_driver *driver, int line); void (*poll_put_char)(struct tty_driver *driver, int line, char ch); + + /* + * Request that the NMI be poked when there is data available. + * This forms part of the polling API because the NMI handler will use + * the polling API to service the interrupt. If hardware cannot + * easily clearing the interrupt source using the polling API + * the pointers should be set to NULL. + */ + int (*poll_request_nmi)(struct tty_driver *driver, int line, + irq_handler_t handler); + void (*poll_free_nmi)(struct tty_driver *driver, int line); #endif const struct file_operations *proc_fops; }; |