aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-24 04:22:21 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-24 04:22:21 -0400
commit66643de455c27973ac31ad6de9f859d399916842 (patch)
tree7ebed7f051879007d4b11d6aaa9e65a1bcb0b08f /drivers/serial
parent2c23d62abb820e19c54012520f08a198c2233a85 (diff)
parent387e2b0439026aa738a9edca15a57e5c0bcb4dfc (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: include/asm-powerpc/unistd.h include/asm-sparc/unistd.h include/asm-sparc64/unistd.h Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/8250.c74
-rw-r--r--drivers/serial/8250_au1x00.c5
-rw-r--r--drivers/serial/serial_core.c123
-rw-r--r--drivers/serial/sunsu.c1
4 files changed, 128 insertions, 75 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 674b15c78f68..bbf78aaf9e01 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -362,6 +362,40 @@ serial_out(struct uart_8250_port *up, int offset, int value)
362#define serial_inp(up, offset) serial_in(up, offset) 362#define serial_inp(up, offset) serial_in(up, offset)
363#define serial_outp(up, offset, value) serial_out(up, offset, value) 363#define serial_outp(up, offset, value) serial_out(up, offset, value)
364 364
365/* Uart divisor latch read */
366static inline int _serial_dl_read(struct uart_8250_port *up)
367{
368 return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
369}
370
371/* Uart divisor latch write */
372static inline void _serial_dl_write(struct uart_8250_port *up, int value)
373{
374 serial_outp(up, UART_DLL, value & 0xff);
375 serial_outp(up, UART_DLM, value >> 8 & 0xff);
376}
377
378#ifdef CONFIG_SERIAL_8250_AU1X00
379/* Au1x00 haven't got a standard divisor latch */
380static int serial_dl_read(struct uart_8250_port *up)
381{
382 if (up->port.iotype == UPIO_AU)
383 return __raw_readl(up->port.membase + 0x28);
384 else
385 return _serial_dl_read(up);
386}
387
388static void serial_dl_write(struct uart_8250_port *up, int value)
389{
390 if (up->port.iotype == UPIO_AU)
391 __raw_writel(value, up->port.membase + 0x28);
392 else
393 _serial_dl_write(up, value);
394}
395#else
396#define serial_dl_read(up) _serial_dl_read(up)
397#define serial_dl_write(up, value) _serial_dl_write(up, value)
398#endif
365 399
366/* 400/*
367 * For the 16C950 401 * For the 16C950
@@ -494,7 +528,8 @@ static void disable_rsa(struct uart_8250_port *up)
494 */ 528 */
495static int size_fifo(struct uart_8250_port *up) 529static int size_fifo(struct uart_8250_port *up)
496{ 530{
497 unsigned char old_fcr, old_mcr, old_dll, old_dlm, old_lcr; 531 unsigned char old_fcr, old_mcr, old_lcr;
532 unsigned short old_dl;
498 int count; 533 int count;
499 534
500 old_lcr = serial_inp(up, UART_LCR); 535 old_lcr = serial_inp(up, UART_LCR);
@@ -505,10 +540,8 @@ static int size_fifo(struct uart_8250_port *up)
505 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); 540 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
506 serial_outp(up, UART_MCR, UART_MCR_LOOP); 541 serial_outp(up, UART_MCR, UART_MCR_LOOP);
507 serial_outp(up, UART_LCR, UART_LCR_DLAB); 542 serial_outp(up, UART_LCR, UART_LCR_DLAB);
508 old_dll = serial_inp(up, UART_DLL); 543 old_dl = serial_dl_read(up);
509 old_dlm = serial_inp(up, UART_DLM); 544 serial_dl_write(up, 0x0001);
510 serial_outp(up, UART_DLL, 0x01);
511 serial_outp(up, UART_DLM, 0x00);
512 serial_outp(up, UART_LCR, 0x03); 545 serial_outp(up, UART_LCR, 0x03);
513 for (count = 0; count < 256; count++) 546 for (count = 0; count < 256; count++)
514 serial_outp(up, UART_TX, count); 547 serial_outp(up, UART_TX, count);
@@ -519,8 +552,7 @@ static int size_fifo(struct uart_8250_port *up)
519 serial_outp(up, UART_FCR, old_fcr); 552 serial_outp(up, UART_FCR, old_fcr);
520 serial_outp(up, UART_MCR, old_mcr); 553 serial_outp(up, UART_MCR, old_mcr);
521 serial_outp(up, UART_LCR, UART_LCR_DLAB); 554 serial_outp(up, UART_LCR, UART_LCR_DLAB);
522 serial_outp(up, UART_DLL, old_dll); 555 serial_dl_write(up, old_dl);
523 serial_outp(up, UART_DLM, old_dlm);
524 serial_outp(up, UART_LCR, old_lcr); 556 serial_outp(up, UART_LCR, old_lcr);
525 557
526 return count; 558 return count;
@@ -750,8 +782,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
750 782
751 serial_outp(up, UART_LCR, 0xE0); 783 serial_outp(up, UART_LCR, 0xE0);
752 784
753 quot = serial_inp(up, UART_DLM) << 8; 785 quot = serial_dl_read(up);
754 quot += serial_inp(up, UART_DLL);
755 quot <<= 3; 786 quot <<= 3;
756 787
757 status1 = serial_in(up, 0x04); /* EXCR1 */ 788 status1 = serial_in(up, 0x04); /* EXCR1 */
@@ -759,8 +790,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
759 status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ 790 status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
760 serial_outp(up, 0x04, status1); 791 serial_outp(up, 0x04, status1);
761 792
762 serial_outp(up, UART_DLL, quot & 0xff); 793 serial_dl_write(up, quot);
763 serial_outp(up, UART_DLM, quot >> 8);
764 794
765 serial_outp(up, UART_LCR, 0); 795 serial_outp(up, UART_LCR, 0);
766 796
@@ -1862,8 +1892,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
1862 serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ 1892 serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
1863 } 1893 }
1864 1894
1865 serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */ 1895 serial_dl_write(up, quot);
1866 serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */
1867 1896
1868 /* 1897 /*
1869 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR 1898 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
@@ -1906,6 +1935,9 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
1906 int ret = 0; 1935 int ret = 0;
1907 1936
1908 switch (up->port.iotype) { 1937 switch (up->port.iotype) {
1938 case UPIO_AU:
1939 size = 0x100000;
1940 /* fall thru */
1909 case UPIO_MEM: 1941 case UPIO_MEM:
1910 if (!up->port.mapbase) 1942 if (!up->port.mapbase)
1911 break; 1943 break;
@@ -1938,6 +1970,9 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
1938 unsigned int size = 8 << up->port.regshift; 1970 unsigned int size = 8 << up->port.regshift;
1939 1971
1940 switch (up->port.iotype) { 1972 switch (up->port.iotype) {
1973 case UPIO_AU:
1974 size = 0x100000;
1975 /* fall thru */
1941 case UPIO_MEM: 1976 case UPIO_MEM:
1942 if (!up->port.mapbase) 1977 if (!up->port.mapbase)
1943 break; 1978 break;
@@ -2200,10 +2235,17 @@ static void
2200serial8250_console_write(struct console *co, const char *s, unsigned int count) 2235serial8250_console_write(struct console *co, const char *s, unsigned int count)
2201{ 2236{
2202 struct uart_8250_port *up = &serial8250_ports[co->index]; 2237 struct uart_8250_port *up = &serial8250_ports[co->index];
2238 unsigned long flags;
2203 unsigned int ier; 2239 unsigned int ier;
2240 int locked = 1;
2204 2241
2205 touch_nmi_watchdog(); 2242 touch_nmi_watchdog();
2206 2243
2244 if (oops_in_progress) {
2245 locked = spin_trylock_irqsave(&up->port.lock, flags);
2246 } else
2247 spin_lock_irqsave(&up->port.lock, flags);
2248
2207 /* 2249 /*
2208 * First save the IER then disable the interrupts 2250 * First save the IER then disable the interrupts
2209 */ 2251 */
@@ -2221,8 +2263,10 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
2221 * and restore the IER 2263 * and restore the IER
2222 */ 2264 */
2223 wait_for_xmitr(up, BOTH_EMPTY); 2265 wait_for_xmitr(up, BOTH_EMPTY);
2224 up->ier |= UART_IER_THRI; 2266 serial_out(up, UART_IER, ier);
2225 serial_out(up, UART_IER, ier | UART_IER_THRI); 2267
2268 if (locked)
2269 spin_unlock_irqrestore(&up->port.lock, flags);
2226} 2270}
2227 2271
2228static int serial8250_console_setup(struct console *co, char *options) 2272static int serial8250_console_setup(struct console *co, char *options)
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
index 3d1bfd07208d..58015fd14be9 100644
--- a/drivers/serial/8250_au1x00.c
+++ b/drivers/serial/8250_au1x00.c
@@ -30,13 +30,12 @@
30 { \ 30 { \
31 .iobase = _base, \ 31 .iobase = _base, \
32 .membase = (void __iomem *)_base,\ 32 .membase = (void __iomem *)_base,\
33 .mapbase = _base, \ 33 .mapbase = CPHYSADDR(_base), \
34 .irq = _irq, \ 34 .irq = _irq, \
35 .uartclk = 0, /* filled */ \ 35 .uartclk = 0, /* filled */ \
36 .regshift = 2, \ 36 .regshift = 2, \
37 .iotype = UPIO_AU, \ 37 .iotype = UPIO_AU, \
38 .flags = UPF_SKIP_TEST | \ 38 .flags = UPF_SKIP_TEST \
39 UPF_IOREMAP, \
40 } 39 }
41 40
42static struct plat_serial8250_port au1x00_data[] = { 41static struct plat_serial8250_port au1x00_data[] = {
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index fcd7744c4253..17839e753e4c 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1500,20 +1500,18 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)
1500static struct uart_state *uart_get(struct uart_driver *drv, int line) 1500static struct uart_state *uart_get(struct uart_driver *drv, int line)
1501{ 1501{
1502 struct uart_state *state; 1502 struct uart_state *state;
1503 int ret = 0;
1503 1504
1504 mutex_lock(&port_mutex);
1505 state = drv->state + line; 1505 state = drv->state + line;
1506 if (mutex_lock_interruptible(&state->mutex)) { 1506 if (mutex_lock_interruptible(&state->mutex)) {
1507 state = ERR_PTR(-ERESTARTSYS); 1507 ret = -ERESTARTSYS;
1508 goto out; 1508 goto err;
1509 } 1509 }
1510 1510
1511 state->count++; 1511 state->count++;
1512 if (!state->port) { 1512 if (!state->port || state->port->flags & UPF_DEAD) {
1513 state->count--; 1513 ret = -ENXIO;
1514 mutex_unlock(&state->mutex); 1514 goto err_unlock;
1515 state = ERR_PTR(-ENXIO);
1516 goto out;
1517 } 1515 }
1518 1516
1519 if (!state->info) { 1517 if (!state->info) {
@@ -1531,15 +1529,17 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
1531 tasklet_init(&state->info->tlet, uart_tasklet_action, 1529 tasklet_init(&state->info->tlet, uart_tasklet_action,
1532 (unsigned long)state); 1530 (unsigned long)state);
1533 } else { 1531 } else {
1534 state->count--; 1532 ret = -ENOMEM;
1535 mutex_unlock(&state->mutex); 1533 goto err_unlock;
1536 state = ERR_PTR(-ENOMEM);
1537 } 1534 }
1538 } 1535 }
1539
1540 out:
1541 mutex_unlock(&port_mutex);
1542 return state; 1536 return state;
1537
1538 err_unlock:
1539 state->count--;
1540 mutex_unlock(&state->mutex);
1541 err:
1542 return ERR_PTR(ret);
1543} 1543}
1544 1544
1545/* 1545/*
@@ -1907,9 +1907,12 @@ uart_set_options(struct uart_port *port, struct console *co,
1907static void uart_change_pm(struct uart_state *state, int pm_state) 1907static void uart_change_pm(struct uart_state *state, int pm_state)
1908{ 1908{
1909 struct uart_port *port = state->port; 1909 struct uart_port *port = state->port;
1910 if (port->ops->pm) 1910
1911 port->ops->pm(port, pm_state, state->pm_state); 1911 if (state->pm_state != pm_state) {
1912 state->pm_state = pm_state; 1912 if (port->ops->pm)
1913 port->ops->pm(port, pm_state, state->pm_state);
1914 state->pm_state = pm_state;
1915 }
1913} 1916}
1914 1917
1915int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) 1918int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
@@ -2085,45 +2088,6 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
2085 } 2088 }
2086} 2089}
2087 2090
2088/*
2089 * This reverses the effects of uart_configure_port, hanging up the
2090 * port before removal.
2091 */
2092static void
2093uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
2094{
2095 struct uart_port *port = state->port;
2096 struct uart_info *info = state->info;
2097
2098 if (info && info->tty)
2099 tty_vhangup(info->tty);
2100
2101 mutex_lock(&state->mutex);
2102
2103 state->info = NULL;
2104
2105 /*
2106 * Free the port IO and memory resources, if any.
2107 */
2108 if (port->type != PORT_UNKNOWN)
2109 port->ops->release_port(port);
2110
2111 /*
2112 * Indicate that there isn't a port here anymore.
2113 */
2114 port->type = PORT_UNKNOWN;
2115
2116 /*
2117 * Kill the tasklet, and free resources.
2118 */
2119 if (info) {
2120 tasklet_kill(&info->tlet);
2121 kfree(info);
2122 }
2123
2124 mutex_unlock(&state->mutex);
2125}
2126
2127static struct tty_operations uart_ops = { 2091static struct tty_operations uart_ops = {
2128 .open = uart_open, 2092 .open = uart_open,
2129 .close = uart_close, 2093 .close = uart_close,
@@ -2270,6 +2234,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
2270 state = drv->state + port->line; 2234 state = drv->state + port->line;
2271 2235
2272 mutex_lock(&port_mutex); 2236 mutex_lock(&port_mutex);
2237 mutex_lock(&state->mutex);
2273 if (state->port) { 2238 if (state->port) {
2274 ret = -EINVAL; 2239 ret = -EINVAL;
2275 goto out; 2240 goto out;
@@ -2304,7 +2269,13 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
2304 port->cons && !(port->cons->flags & CON_ENABLED)) 2269 port->cons && !(port->cons->flags & CON_ENABLED))
2305 register_console(port->cons); 2270 register_console(port->cons);
2306 2271
2272 /*
2273 * Ensure UPF_DEAD is not set.
2274 */
2275 port->flags &= ~UPF_DEAD;
2276
2307 out: 2277 out:
2278 mutex_unlock(&state->mutex);
2308 mutex_unlock(&port_mutex); 2279 mutex_unlock(&port_mutex);
2309 2280
2310 return ret; 2281 return ret;
@@ -2322,6 +2293,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
2322int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) 2293int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
2323{ 2294{
2324 struct uart_state *state = drv->state + port->line; 2295 struct uart_state *state = drv->state + port->line;
2296 struct uart_info *info;
2325 2297
2326 BUG_ON(in_interrupt()); 2298 BUG_ON(in_interrupt());
2327 2299
@@ -2332,11 +2304,48 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
2332 mutex_lock(&port_mutex); 2304 mutex_lock(&port_mutex);
2333 2305
2334 /* 2306 /*
2307 * Mark the port "dead" - this prevents any opens from
2308 * succeeding while we shut down the port.
2309 */
2310 mutex_lock(&state->mutex);
2311 port->flags |= UPF_DEAD;
2312 mutex_unlock(&state->mutex);
2313
2314 /*
2335 * Remove the devices from devfs 2315 * Remove the devices from devfs
2336 */ 2316 */
2337 tty_unregister_device(drv->tty_driver, port->line); 2317 tty_unregister_device(drv->tty_driver, port->line);
2338 2318
2339 uart_unconfigure_port(drv, state); 2319 info = state->info;
2320 if (info && info->tty)
2321 tty_vhangup(info->tty);
2322
2323 /*
2324 * All users of this port should now be disconnected from
2325 * this driver, and the port shut down. We should be the
2326 * only thread fiddling with this port from now on.
2327 */
2328 state->info = NULL;
2329
2330 /*
2331 * Free the port IO and memory resources, if any.
2332 */
2333 if (port->type != PORT_UNKNOWN)
2334 port->ops->release_port(port);
2335
2336 /*
2337 * Indicate that there isn't a port here anymore.
2338 */
2339 port->type = PORT_UNKNOWN;
2340
2341 /*
2342 * Kill the tasklet, and free resources.
2343 */
2344 if (info) {
2345 tasklet_kill(&info->tlet);
2346 kfree(info);
2347 }
2348
2340 state->port = NULL; 2349 state->port = NULL;
2341 mutex_unlock(&port_mutex); 2350 mutex_unlock(&port_mutex);
2342 2351
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 1c4396c2962d..2b4f96541b8e 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1730,3 +1730,4 @@ static void __exit sunsu_exit(void)
1730 1730
1731module_init(sunsu_probe); 1731module_init(sunsu_probe);
1732module_exit(sunsu_exit); 1732module_exit(sunsu_exit);
1733MODULE_LICENSE("GPL");