summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250/8250_core.c
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2015-02-24 14:25:07 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-26 18:15:16 +0100
commita4416cd1ac7b48988f0f41a17769d65c71ffc504 (patch)
treea6bd6908872ae2f37b8334ffcc0ab4735d955555 /drivers/tty/serial/8250/8250_core.c
parent6e28157173037b779fcf90715416a21a1e5ea2f9 (diff)
downloadlwn-a4416cd1ac7b48988f0f41a17769d65c71ffc504.tar.gz
lwn-a4416cd1ac7b48988f0f41a17769d65c71ffc504.zip
serial: 8250: Separate legacy irq handling from core port operations
Prepare for 8250 split; decouple irq setup/teardown and handler from core port operations. Introduce setup_irq() and release_irq() 8250 driver methods; the 8250 core will use these methods to install and remove irq handling for the given 8250 port. Refactor irq chain linking/unlinking from 8250 core into univ8250_setup_irq()/univ8250_release_irq() for the universal 8250 driver. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/8250/8250_core.c')
-rw-r--r--drivers/tty/serial/8250/8250_core.c83
1 files changed, 53 insertions, 30 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 625f81c9b55e..06bb2ced2c94 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1890,6 +1890,48 @@ static void serial8250_backup_timeout(unsigned long data)
jiffies + uart_poll_timeout(&up->port) + HZ / 5);
}
+static int univ8250_setup_irq(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ int retval = 0;
+
+ /*
+ * The above check will only give an accurate result the first time
+ * the port is opened so this value needs to be preserved.
+ */
+ if (up->bugs & UART_BUG_THRE) {
+ pr_debug("ttyS%d - using backup timer\n", serial_index(port));
+
+ up->timer.function = serial8250_backup_timeout;
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies +
+ uart_poll_timeout(port) + HZ / 5);
+ }
+
+ /*
+ * If the "interrupt" for this port doesn't correspond with any
+ * hardware interrupt, we use a timer-based system. The original
+ * driver used to do this with IRQ0.
+ */
+ if (!port->irq) {
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
+ } else
+ retval = serial_link_irq_chain(up);
+
+ return retval;
+}
+
+static void univ8250_release_irq(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+
+ del_timer_sync(&up->timer);
+ up->timer.function = serial8250_timeout;
+ if (port->irq)
+ serial_unlink_irq_chain(up);
+}
+
static unsigned int serial8250_tx_empty(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
@@ -2194,35 +2236,12 @@ int serial8250_do_startup(struct uart_port *port)
if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
up->port.flags & UPF_BUG_THRE) {
up->bugs |= UART_BUG_THRE;
- pr_debug("ttyS%d - using backup timer\n",
- serial_index(port));
}
}
- /*
- * The above check will only give an accurate result the first time
- * the port is opened so this value needs to be preserved.
- */
- if (up->bugs & UART_BUG_THRE) {
- up->timer.function = serial8250_backup_timeout;
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies +
- uart_poll_timeout(port) + HZ / 5);
- }
-
- /*
- * If the "interrupt" for this port doesn't correspond with any
- * hardware interrupt, we use a timer-based system. The original
- * driver used to do this with IRQ0.
- */
- if (!port->irq) {
- up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
- } else {
- retval = serial_link_irq_chain(up);
- if (retval)
- goto out;
- }
+ retval = up->ops->setup_irq(up);
+ if (retval)
+ goto out;
/*
* Now, initialize the UART
@@ -2380,10 +2399,7 @@ void serial8250_do_shutdown(struct uart_port *port)
serial_port_in(port, UART_RX);
serial8250_rpm_put(up);
- del_timer_sync(&up->timer);
- up->timer.function = serial8250_timeout;
- if (port->irq)
- serial_unlink_irq_chain(up);
+ up->ops->release_irq(up);
}
EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
@@ -3083,6 +3099,11 @@ static struct uart_ops serial8250_pops = {
#endif
};
+static const struct uart_8250_ops univ8250_driver_ops = {
+ .setup_irq = univ8250_setup_irq,
+ .release_irq = univ8250_release_irq,
+};
+
static struct uart_8250_port serial8250_ports[UART_NR];
/**
@@ -3137,6 +3158,8 @@ static void __init serial8250_isa_init_ports(void)
up->timer.function = serial8250_timeout;
up->cur_iotype = 0xFF;
+ up->ops = &univ8250_driver_ops;
+
/*
* ALPHA_KLUDGE_MCR needs to be killed.
*/