aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Thompson <daniel.thompson@linaro.org>2015-01-19 15:40:24 +0000
committerDaniel Thompson <daniel.thompson@linaro.org>2015-01-27 16:49:13 +0000
commit9230175ca2b56bc0ababd2f45efa4392c3a78f08 (patch)
tree7822a838c83812a8fdbbbf2d09863f6cf91fce1a
parent78c3d839614579aee184b2943454e49ddac8f009 (diff)
tty: poll_nmi_wrap/unwrap
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
-rw-r--r--drivers/tty/serial/serial_core.c32
-rw-r--r--include/linux/serial_core.h2
-rw-r--r--include/linux/tty_driver.h12
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;
};