diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 03:54:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:47 -0400 |
commit | f34d7a5b7010b82fe97da95496b9971435530062 (patch) | |
tree | 87e2abec1e33ed4fe5e63ee2fd000bc2ad745e57 /drivers/serial | |
parent | 251b8dd7eee30fda089a1dc088abf4fc9a0dee9c (diff) |
tty: The big operations rework
- Operations are now a shared const function block as with most other Linux
objects
- Introduce wrappers for some optional functions to get consistent behaviour
- Wrap put_char which used to be patched by the tty layer
- Document which functions are needed/optional
- Make put_char report success/fail
- Cache the driver->ops pointer in the tty as tty->ops
- Remove various surplus lock calls we no longer need
- Remove proc_write method as noted by Alexey Dobriyan
- Introduce some missing sanity checks where certain driver/ldisc
combinations would oops as they didn't check needed methods were present
[akpm@linux-foundation.org: fix fs/compat_ioctl.c build]
[akpm@linux-foundation.org: fix isicom]
[akpm@linux-foundation.org: fix arch/ia64/hp/sim/simserial.c build]
[akpm@linux-foundation.org: fix kgdb]
Signed-off-by: Alan Cox <alan@redhat.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/kgdboc.c | 6 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 38 |
2 files changed, 30 insertions, 14 deletions
diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c index 9cf03327386..eadc1ab6bbc 100644 --- a/drivers/serial/kgdboc.c +++ b/drivers/serial/kgdboc.c | |||
@@ -96,12 +96,14 @@ static void cleanup_kgdboc(void) | |||
96 | 96 | ||
97 | static int kgdboc_get_char(void) | 97 | static int kgdboc_get_char(void) |
98 | { | 98 | { |
99 | return kgdb_tty_driver->poll_get_char(kgdb_tty_driver, kgdb_tty_line); | 99 | return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver, |
100 | kgdb_tty_line); | ||
100 | } | 101 | } |
101 | 102 | ||
102 | static void kgdboc_put_char(u8 chr) | 103 | static void kgdboc_put_char(u8 chr) |
103 | { | 104 | { |
104 | kgdb_tty_driver->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr); | 105 | kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver, |
106 | kgdb_tty_line, chr); | ||
105 | } | 107 | } |
106 | 108 | ||
107 | static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) | 109 | static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 6c7a5cf7658..1e2b9d826f6 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -532,15 +532,25 @@ uart_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
532 | static int uart_write_room(struct tty_struct *tty) | 532 | static int uart_write_room(struct tty_struct *tty) |
533 | { | 533 | { |
534 | struct uart_state *state = tty->driver_data; | 534 | struct uart_state *state = tty->driver_data; |
535 | unsigned long flags; | ||
536 | int ret; | ||
535 | 537 | ||
536 | return uart_circ_chars_free(&state->info->xmit); | 538 | spin_lock_irqsave(&state->port->lock, flags); |
539 | ret = uart_circ_chars_free(&state->info->xmit); | ||
540 | spin_unlock_irqrestore(&state->port->lock, flags); | ||
541 | return ret; | ||
537 | } | 542 | } |
538 | 543 | ||
539 | static int uart_chars_in_buffer(struct tty_struct *tty) | 544 | static int uart_chars_in_buffer(struct tty_struct *tty) |
540 | { | 545 | { |
541 | struct uart_state *state = tty->driver_data; | 546 | struct uart_state *state = tty->driver_data; |
547 | unsigned long flags; | ||
548 | int ret; | ||
542 | 549 | ||
543 | return uart_circ_chars_pending(&state->info->xmit); | 550 | spin_lock_irqsave(&state->port->lock, flags); |
551 | ret = uart_circ_chars_pending(&state->info->xmit); | ||
552 | spin_unlock_irqrestore(&state->port->lock, flags); | ||
553 | return ret; | ||
544 | } | 554 | } |
545 | 555 | ||
546 | static void uart_flush_buffer(struct tty_struct *tty) | 556 | static void uart_flush_buffer(struct tty_struct *tty) |
@@ -622,6 +632,11 @@ static int uart_get_info(struct uart_state *state, | |||
622 | struct serial_struct tmp; | 632 | struct serial_struct tmp; |
623 | 633 | ||
624 | memset(&tmp, 0, sizeof(tmp)); | 634 | memset(&tmp, 0, sizeof(tmp)); |
635 | |||
636 | /* Ensure the state we copy is consistent and no hardware changes | ||
637 | occur as we go */ | ||
638 | mutex_lock(&state->mutex); | ||
639 | |||
625 | tmp.type = port->type; | 640 | tmp.type = port->type; |
626 | tmp.line = port->line; | 641 | tmp.line = port->line; |
627 | tmp.port = port->iobase; | 642 | tmp.port = port->iobase; |
@@ -641,6 +656,8 @@ static int uart_get_info(struct uart_state *state, | |||
641 | tmp.iomem_reg_shift = port->regshift; | 656 | tmp.iomem_reg_shift = port->regshift; |
642 | tmp.iomem_base = (void *)(unsigned long)port->mapbase; | 657 | tmp.iomem_base = (void *)(unsigned long)port->mapbase; |
643 | 658 | ||
659 | mutex_unlock(&state->mutex); | ||
660 | |||
644 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | 661 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) |
645 | return -EFAULT; | 662 | return -EFAULT; |
646 | return 0; | 663 | return 0; |
@@ -918,14 +935,12 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state) | |||
918 | struct uart_state *state = tty->driver_data; | 935 | struct uart_state *state = tty->driver_data; |
919 | struct uart_port *port = state->port; | 936 | struct uart_port *port = state->port; |
920 | 937 | ||
921 | lock_kernel(); | ||
922 | mutex_lock(&state->mutex); | 938 | mutex_lock(&state->mutex); |
923 | 939 | ||
924 | if (port->type != PORT_UNKNOWN) | 940 | if (port->type != PORT_UNKNOWN) |
925 | port->ops->break_ctl(port, break_state); | 941 | port->ops->break_ctl(port, break_state); |
926 | 942 | ||
927 | mutex_unlock(&state->mutex); | 943 | mutex_unlock(&state->mutex); |
928 | unlock_kernel(); | ||
929 | } | 944 | } |
930 | 945 | ||
931 | static int uart_do_autoconfig(struct uart_state *state) | 946 | static int uart_do_autoconfig(struct uart_state *state) |
@@ -1074,7 +1089,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1074 | int ret = -ENOIOCTLCMD; | 1089 | int ret = -ENOIOCTLCMD; |
1075 | 1090 | ||
1076 | 1091 | ||
1077 | lock_kernel(); | ||
1078 | /* | 1092 | /* |
1079 | * These ioctls don't rely on the hardware to be present. | 1093 | * These ioctls don't rely on the hardware to be present. |
1080 | */ | 1094 | */ |
@@ -1144,10 +1158,9 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1144 | break; | 1158 | break; |
1145 | } | 1159 | } |
1146 | } | 1160 | } |
1147 | out_up: | 1161 | out_up: |
1148 | mutex_unlock(&state->mutex); | 1162 | mutex_unlock(&state->mutex); |
1149 | out: | 1163 | out: |
1150 | unlock_kernel(); | ||
1151 | return ret; | 1164 | return ret; |
1152 | } | 1165 | } |
1153 | 1166 | ||
@@ -1173,7 +1186,6 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1173 | return; | 1186 | return; |
1174 | } | 1187 | } |
1175 | 1188 | ||
1176 | lock_kernel(); | ||
1177 | uart_change_speed(state, old_termios); | 1189 | uart_change_speed(state, old_termios); |
1178 | 1190 | ||
1179 | /* Handle transition to B0 status */ | 1191 | /* Handle transition to B0 status */ |
@@ -1206,7 +1218,6 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1206 | } | 1218 | } |
1207 | spin_unlock_irqrestore(&state->port->lock, flags); | 1219 | spin_unlock_irqrestore(&state->port->lock, flags); |
1208 | } | 1220 | } |
1209 | unlock_kernel(); | ||
1210 | #if 0 | 1221 | #if 0 |
1211 | /* | 1222 | /* |
1212 | * No need to wake up processes in open wait, since they | 1223 | * No need to wake up processes in open wait, since they |
@@ -1322,11 +1333,11 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1322 | struct uart_port *port = state->port; | 1333 | struct uart_port *port = state->port; |
1323 | unsigned long char_time, expire; | 1334 | unsigned long char_time, expire; |
1324 | 1335 | ||
1325 | BUG_ON(!kernel_locked()); | ||
1326 | |||
1327 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) | 1336 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) |
1328 | return; | 1337 | return; |
1329 | 1338 | ||
1339 | lock_kernel(); | ||
1340 | |||
1330 | /* | 1341 | /* |
1331 | * Set the check interval to be 1/5 of the estimated time to | 1342 | * Set the check interval to be 1/5 of the estimated time to |
1332 | * send a single character, and make it at least 1. The check | 1343 | * send a single character, and make it at least 1. The check |
@@ -1372,6 +1383,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1372 | break; | 1383 | break; |
1373 | } | 1384 | } |
1374 | set_current_state(TASK_RUNNING); /* might not be needed */ | 1385 | set_current_state(TASK_RUNNING); /* might not be needed */ |
1386 | unlock_kernel(); | ||
1375 | } | 1387 | } |
1376 | 1388 | ||
1377 | /* | 1389 | /* |
@@ -2085,7 +2097,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2085 | int ret; | 2097 | int ret; |
2086 | 2098 | ||
2087 | uart_change_pm(state, 0); | 2099 | uart_change_pm(state, 0); |
2100 | spin_lock_irq(&port->lock); | ||
2088 | ops->set_mctrl(port, 0); | 2101 | ops->set_mctrl(port, 0); |
2102 | spin_unlock_irq(&port->lock); | ||
2089 | ret = ops->startup(port); | 2103 | ret = ops->startup(port); |
2090 | if (ret == 0) { | 2104 | if (ret == 0) { |
2091 | uart_change_speed(state, NULL); | 2105 | uart_change_speed(state, NULL); |