aboutsummaryrefslogtreecommitdiffstats
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 13:15:16 -0400
commita4416cd1ac7b48988f0f41a17769d65c71ffc504 (patch)
treea6bd6908872ae2f37b8334ffcc0ab4735d955555
parent6e28157173037b779fcf90715416a21a1e5ea2f9 (diff)
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>
-rw-r--r--drivers/tty/serial/8250/8250_core.c83
-rw-r--r--include/linux/serial_8250.h15
2 files changed, 68 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)
1890 jiffies + uart_poll_timeout(&up->port) + HZ / 5); 1890 jiffies + uart_poll_timeout(&up->port) + HZ / 5);
1891} 1891}
1892 1892
1893static int univ8250_setup_irq(struct uart_8250_port *up)
1894{
1895 struct uart_port *port = &up->port;
1896 int retval = 0;
1897
1898 /*
1899 * The above check will only give an accurate result the first time
1900 * the port is opened so this value needs to be preserved.
1901 */
1902 if (up->bugs & UART_BUG_THRE) {
1903 pr_debug("ttyS%d - using backup timer\n", serial_index(port));
1904
1905 up->timer.function = serial8250_backup_timeout;
1906 up->timer.data = (unsigned long)up;
1907 mod_timer(&up->timer, jiffies +
1908 uart_poll_timeout(port) + HZ / 5);
1909 }
1910
1911 /*
1912 * If the "interrupt" for this port doesn't correspond with any
1913 * hardware interrupt, we use a timer-based system. The original
1914 * driver used to do this with IRQ0.
1915 */
1916 if (!port->irq) {
1917 up->timer.data = (unsigned long)up;
1918 mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
1919 } else
1920 retval = serial_link_irq_chain(up);
1921
1922 return retval;
1923}
1924
1925static void univ8250_release_irq(struct uart_8250_port *up)
1926{
1927 struct uart_port *port = &up->port;
1928
1929 del_timer_sync(&up->timer);
1930 up->timer.function = serial8250_timeout;
1931 if (port->irq)
1932 serial_unlink_irq_chain(up);
1933}
1934
1893static unsigned int serial8250_tx_empty(struct uart_port *port) 1935static unsigned int serial8250_tx_empty(struct uart_port *port)
1894{ 1936{
1895 struct uart_8250_port *up = up_to_u8250p(port); 1937 struct uart_8250_port *up = up_to_u8250p(port);
@@ -2194,35 +2236,12 @@ int serial8250_do_startup(struct uart_port *port)
2194 if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || 2236 if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
2195 up->port.flags & UPF_BUG_THRE) { 2237 up->port.flags & UPF_BUG_THRE) {
2196 up->bugs |= UART_BUG_THRE; 2238 up->bugs |= UART_BUG_THRE;
2197 pr_debug("ttyS%d - using backup timer\n",
2198 serial_index(port));
2199 } 2239 }
2200 } 2240 }
2201 2241
2202 /* 2242 retval = up->ops->setup_irq(up);
2203 * The above check will only give an accurate result the first time 2243 if (retval)
2204 * the port is opened so this value needs to be preserved. 2244 goto out;
2205 */
2206 if (up->bugs & UART_BUG_THRE) {
2207 up->timer.function = serial8250_backup_timeout;
2208 up->timer.data = (unsigned long)up;
2209 mod_timer(&up->timer, jiffies +
2210 uart_poll_timeout(port) + HZ / 5);
2211 }
2212
2213 /*
2214 * If the "interrupt" for this port doesn't correspond with any
2215 * hardware interrupt, we use a timer-based system. The original
2216 * driver used to do this with IRQ0.
2217 */
2218 if (!port->irq) {
2219 up->timer.data = (unsigned long)up;
2220 mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
2221 } else {
2222 retval = serial_link_irq_chain(up);
2223 if (retval)
2224 goto out;
2225 }
2226 2245
2227 /* 2246 /*
2228 * Now, initialize the UART 2247 * Now, initialize the UART
@@ -2380,10 +2399,7 @@ void serial8250_do_shutdown(struct uart_port *port)
2380 serial_port_in(port, UART_RX); 2399 serial_port_in(port, UART_RX);
2381 serial8250_rpm_put(up); 2400 serial8250_rpm_put(up);
2382 2401
2383 del_timer_sync(&up->timer); 2402 up->ops->release_irq(up);
2384 up->timer.function = serial8250_timeout;
2385 if (port->irq)
2386 serial_unlink_irq_chain(up);
2387} 2403}
2388EXPORT_SYMBOL_GPL(serial8250_do_shutdown); 2404EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
2389 2405
@@ -3083,6 +3099,11 @@ static struct uart_ops serial8250_pops = {
3083#endif 3099#endif
3084}; 3100};
3085 3101
3102static const struct uart_8250_ops univ8250_driver_ops = {
3103 .setup_irq = univ8250_setup_irq,
3104 .release_irq = univ8250_release_irq,
3105};
3106
3086static struct uart_8250_port serial8250_ports[UART_NR]; 3107static struct uart_8250_port serial8250_ports[UART_NR];
3087 3108
3088/** 3109/**
@@ -3137,6 +3158,8 @@ static void __init serial8250_isa_init_ports(void)
3137 up->timer.function = serial8250_timeout; 3158 up->timer.function = serial8250_timeout;
3138 up->cur_iotype = 0xFF; 3159 up->cur_iotype = 0xFF;
3139 3160
3161 up->ops = &univ8250_driver_ops;
3162
3140 /* 3163 /*
3141 * ALPHA_KLUDGE_MCR needs to be killed. 3164 * ALPHA_KLUDGE_MCR needs to be killed.
3142 */ 3165 */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index ca9f87beac63..50735a9ad598 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -60,6 +60,20 @@ enum {
60}; 60};
61 61
62struct uart_8250_dma; 62struct uart_8250_dma;
63struct uart_8250_port;
64
65/**
66 * 8250 core driver operations
67 *
68 * @setup_irq() Setup irq handling. The universal 8250 driver links this
69 * port to the irq chain. Other drivers may @request_irq().
70 * @release_irq() Undo irq handling. The universal 8250 driver unlinks
71 * the port from the irq chain.
72 */
73struct uart_8250_ops {
74 int (*setup_irq)(struct uart_8250_port *);
75 void (*release_irq)(struct uart_8250_port *);
76};
63 77
64/* 78/*
65 * This should be used by drivers which want to register 79 * This should be used by drivers which want to register
@@ -100,6 +114,7 @@ struct uart_8250_port {
100 unsigned char msr_saved_flags; 114 unsigned char msr_saved_flags;
101 115
102 struct uart_8250_dma *dma; 116 struct uart_8250_dma *dma;
117 const struct uart_8250_ops *ops;
103 118
104 /* 8250 specific callbacks */ 119 /* 8250 specific callbacks */
105 int (*dl_read)(struct uart_8250_port *); 120 int (*dl_read)(struct uart_8250_port *);