diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/8250.c | 24 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm.h | 8 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_driver.c | 48 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_neo.c | 8 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_tty.c | 6 | ||||
-rw-r--r-- | drivers/serial/pxa.c | 13 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 33 |
7 files changed, 89 insertions, 51 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 737b4c960971..c3e37c8e7e26 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -1339,14 +1339,12 @@ static void serial8250_start_tx(struct uart_port *port) | |||
1339 | serial_out(up, UART_IER, up->ier); | 1339 | serial_out(up, UART_IER, up->ier); |
1340 | 1340 | ||
1341 | if (up->bugs & UART_BUG_TXEN) { | 1341 | if (up->bugs & UART_BUG_TXEN) { |
1342 | unsigned char lsr, iir; | 1342 | unsigned char lsr; |
1343 | lsr = serial_in(up, UART_LSR); | 1343 | lsr = serial_in(up, UART_LSR); |
1344 | up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; | 1344 | up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; |
1345 | iir = serial_in(up, UART_IIR) & 0x0f; | ||
1346 | if ((up->port.type == PORT_RM9000) ? | 1345 | if ((up->port.type == PORT_RM9000) ? |
1347 | (lsr & UART_LSR_THRE && | 1346 | (lsr & UART_LSR_THRE) : |
1348 | (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : | 1347 | (lsr & UART_LSR_TEMT)) |
1349 | (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) | ||
1350 | transmit_chars(up); | 1348 | transmit_chars(up); |
1351 | } | 1349 | } |
1352 | } | 1350 | } |
@@ -2646,7 +2644,7 @@ static void __init serial8250_isa_init_ports(void) | |||
2646 | { | 2644 | { |
2647 | struct uart_8250_port *up; | 2645 | struct uart_8250_port *up; |
2648 | static int first = 1; | 2646 | static int first = 1; |
2649 | int i; | 2647 | int i, irqflag = 0; |
2650 | 2648 | ||
2651 | if (!first) | 2649 | if (!first) |
2652 | return; | 2650 | return; |
@@ -2670,6 +2668,9 @@ static void __init serial8250_isa_init_ports(void) | |||
2670 | up->port.ops = &serial8250_pops; | 2668 | up->port.ops = &serial8250_pops; |
2671 | } | 2669 | } |
2672 | 2670 | ||
2671 | if (share_irqs) | ||
2672 | irqflag = IRQF_SHARED; | ||
2673 | |||
2673 | for (i = 0, up = serial8250_ports; | 2674 | for (i = 0, up = serial8250_ports; |
2674 | i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; | 2675 | i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; |
2675 | i++, up++) { | 2676 | i++, up++) { |
@@ -2683,8 +2684,7 @@ static void __init serial8250_isa_init_ports(void) | |||
2683 | up->port.iotype = old_serial_port[i].io_type; | 2684 | up->port.iotype = old_serial_port[i].io_type; |
2684 | up->port.regshift = old_serial_port[i].iomem_reg_shift; | 2685 | up->port.regshift = old_serial_port[i].iomem_reg_shift; |
2685 | set_io_from_upio(&up->port); | 2686 | set_io_from_upio(&up->port); |
2686 | if (share_irqs) | 2687 | up->port.irqflags |= irqflag; |
2687 | up->port.irqflags |= IRQF_SHARED; | ||
2688 | } | 2688 | } |
2689 | } | 2689 | } |
2690 | 2690 | ||
@@ -2940,10 +2940,13 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2940 | { | 2940 | { |
2941 | struct plat_serial8250_port *p = dev->dev.platform_data; | 2941 | struct plat_serial8250_port *p = dev->dev.platform_data; |
2942 | struct uart_port port; | 2942 | struct uart_port port; |
2943 | int ret, i; | 2943 | int ret, i, irqflag = 0; |
2944 | 2944 | ||
2945 | memset(&port, 0, sizeof(struct uart_port)); | 2945 | memset(&port, 0, sizeof(struct uart_port)); |
2946 | 2946 | ||
2947 | if (share_irqs) | ||
2948 | irqflag = IRQF_SHARED; | ||
2949 | |||
2947 | for (i = 0; p && p->flags != 0; p++, i++) { | 2950 | for (i = 0; p && p->flags != 0; p++, i++) { |
2948 | port.iobase = p->iobase; | 2951 | port.iobase = p->iobase; |
2949 | port.membase = p->membase; | 2952 | port.membase = p->membase; |
@@ -2960,8 +2963,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2960 | port.serial_in = p->serial_in; | 2963 | port.serial_in = p->serial_in; |
2961 | port.serial_out = p->serial_out; | 2964 | port.serial_out = p->serial_out; |
2962 | port.dev = &dev->dev; | 2965 | port.dev = &dev->dev; |
2963 | if (share_irqs) | 2966 | port.irqflags |= irqflag; |
2964 | port.irqflags |= IRQF_SHARED; | ||
2965 | ret = serial8250_register_port(&port); | 2967 | ret = serial8250_register_port(&port); |
2966 | if (ret < 0) { | 2968 | if (ret < 0) { |
2967 | dev_err(&dev->dev, "unable to register port at index %d " | 2969 | dev_err(&dev->dev, "unable to register port at index %d " |
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 4e5f3bde0461..38a509c684cd 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h | |||
@@ -138,7 +138,6 @@ struct jsm_board | |||
138 | u32 nasync; /* Number of ports on card */ | 138 | u32 nasync; /* Number of ports on card */ |
139 | 139 | ||
140 | u32 irq; /* Interrupt request number */ | 140 | u32 irq; /* Interrupt request number */ |
141 | u64 intr_count; /* Count of interrupts */ | ||
142 | 141 | ||
143 | u64 membase; /* Start of base memory of the card */ | 142 | u64 membase; /* Start of base memory of the card */ |
144 | u64 membase_end; /* End of base memory of the card */ | 143 | u64 membase_end; /* End of base memory of the card */ |
@@ -206,8 +205,6 @@ struct jsm_channel { | |||
206 | 205 | ||
207 | u64 ch_close_delay; /* How long we should drop RTS/DTR for */ | 206 | u64 ch_close_delay; /* How long we should drop RTS/DTR for */ |
208 | 207 | ||
209 | u64 ch_cpstime; /* Time for CPS calculations */ | ||
210 | |||
211 | tcflag_t ch_c_iflag; /* channel iflags */ | 208 | tcflag_t ch_c_iflag; /* channel iflags */ |
212 | tcflag_t ch_c_cflag; /* channel cflags */ | 209 | tcflag_t ch_c_cflag; /* channel cflags */ |
213 | tcflag_t ch_c_oflag; /* channel oflags */ | 210 | tcflag_t ch_c_oflag; /* channel oflags */ |
@@ -215,11 +212,6 @@ struct jsm_channel { | |||
215 | u8 ch_stopc; /* Stop character */ | 212 | u8 ch_stopc; /* Stop character */ |
216 | u8 ch_startc; /* Start character */ | 213 | u8 ch_startc; /* Start character */ |
217 | 214 | ||
218 | u32 ch_old_baud; /* Cache of the current baud */ | ||
219 | u32 ch_custom_speed;/* Custom baud, if set */ | ||
220 | |||
221 | u32 ch_wopen; /* Waiting for open process cnt */ | ||
222 | |||
223 | u8 ch_mostat; /* FEP output modem status */ | 215 | u8 ch_mostat; /* FEP output modem status */ |
224 | u8 ch_mistat; /* FEP input modem status */ | 216 | u8 ch_mistat; /* FEP input modem status */ |
225 | 217 | ||
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index b3604aa322a4..108c3e0471fd 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
@@ -48,6 +48,17 @@ struct uart_driver jsm_uart_driver = { | |||
48 | .nr = NR_PORTS, | 48 | .nr = NR_PORTS, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, | ||
52 | pci_channel_state_t state); | ||
53 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); | ||
54 | static void jsm_io_resume(struct pci_dev *pdev); | ||
55 | |||
56 | static struct pci_error_handlers jsm_err_handler = { | ||
57 | .error_detected = jsm_io_error_detected, | ||
58 | .slot_reset = jsm_io_slot_reset, | ||
59 | .resume = jsm_io_resume, | ||
60 | }; | ||
61 | |||
51 | int jsm_debug; | 62 | int jsm_debug; |
52 | module_param(jsm_debug, int, 0); | 63 | module_param(jsm_debug, int, 0); |
53 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); | 64 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); |
@@ -123,7 +134,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
123 | } | 134 | } |
124 | 135 | ||
125 | rc = request_irq(brd->irq, brd->bd_ops->intr, | 136 | rc = request_irq(brd->irq, brd->bd_ops->intr, |
126 | IRQF_DISABLED|IRQF_SHARED, "JSM", brd); | 137 | IRQF_SHARED, "JSM", brd); |
127 | if (rc) { | 138 | if (rc) { |
128 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); | 139 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); |
129 | goto out_iounmap; | 140 | goto out_iounmap; |
@@ -164,6 +175,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
164 | } | 175 | } |
165 | 176 | ||
166 | pci_set_drvdata(pdev, brd); | 177 | pci_set_drvdata(pdev, brd); |
178 | pci_save_state(pdev); | ||
167 | 179 | ||
168 | return 0; | 180 | return 0; |
169 | out_free_irq: | 181 | out_free_irq: |
@@ -222,8 +234,42 @@ static struct pci_driver jsm_driver = { | |||
222 | .id_table = jsm_pci_tbl, | 234 | .id_table = jsm_pci_tbl, |
223 | .probe = jsm_probe_one, | 235 | .probe = jsm_probe_one, |
224 | .remove = __devexit_p(jsm_remove_one), | 236 | .remove = __devexit_p(jsm_remove_one), |
237 | .err_handler = &jsm_err_handler, | ||
225 | }; | 238 | }; |
226 | 239 | ||
240 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, | ||
241 | pci_channel_state_t state) | ||
242 | { | ||
243 | struct jsm_board *brd = pci_get_drvdata(pdev); | ||
244 | |||
245 | jsm_remove_uart_port(brd); | ||
246 | |||
247 | return PCI_ERS_RESULT_NEED_RESET; | ||
248 | } | ||
249 | |||
250 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev) | ||
251 | { | ||
252 | int rc; | ||
253 | |||
254 | rc = pci_enable_device(pdev); | ||
255 | |||
256 | if (rc) | ||
257 | return PCI_ERS_RESULT_DISCONNECT; | ||
258 | |||
259 | pci_set_master(pdev); | ||
260 | |||
261 | return PCI_ERS_RESULT_RECOVERED; | ||
262 | } | ||
263 | |||
264 | static void jsm_io_resume(struct pci_dev *pdev) | ||
265 | { | ||
266 | struct jsm_board *brd = pci_get_drvdata(pdev); | ||
267 | |||
268 | pci_restore_state(pdev); | ||
269 | |||
270 | jsm_uart_port_init(brd); | ||
271 | } | ||
272 | |||
227 | static int __init jsm_init_module(void) | 273 | static int __init jsm_init_module(void) |
228 | { | 274 | { |
229 | int rc; | 275 | int rc; |
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index b4b124e4828f..7960d9633c15 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c | |||
@@ -954,13 +954,8 @@ static void neo_param(struct jsm_channel *ch) | |||
954 | ch->ch_flags |= (CH_BAUD0); | 954 | ch->ch_flags |= (CH_BAUD0); |
955 | ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); | 955 | ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); |
956 | neo_assert_modem_signals(ch); | 956 | neo_assert_modem_signals(ch); |
957 | ch->ch_old_baud = 0; | ||
958 | return; | 957 | return; |
959 | 958 | ||
960 | } else if (ch->ch_custom_speed) { | ||
961 | baud = ch->ch_custom_speed; | ||
962 | if (ch->ch_flags & CH_BAUD0) | ||
963 | ch->ch_flags &= ~(CH_BAUD0); | ||
964 | } else { | 959 | } else { |
965 | int i; | 960 | int i; |
966 | unsigned int cflag; | 961 | unsigned int cflag; |
@@ -1045,7 +1040,6 @@ static void neo_param(struct jsm_channel *ch) | |||
1045 | quot = ch->ch_bd->bd_dividend / baud; | 1040 | quot = ch->ch_bd->bd_dividend / baud; |
1046 | 1041 | ||
1047 | if (quot != 0) { | 1042 | if (quot != 0) { |
1048 | ch->ch_old_baud = baud; | ||
1049 | writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); | 1043 | writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); |
1050 | writeb((quot & 0xff), &ch->ch_neo_uart->txrx); | 1044 | writeb((quot & 0xff), &ch->ch_neo_uart->txrx); |
1051 | writeb((quot >> 8), &ch->ch_neo_uart->ier); | 1045 | writeb((quot >> 8), &ch->ch_neo_uart->ier); |
@@ -1123,8 +1117,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) | |||
1123 | unsigned long lock_flags2; | 1117 | unsigned long lock_flags2; |
1124 | int outofloop_count = 0; | 1118 | int outofloop_count = 0; |
1125 | 1119 | ||
1126 | brd->intr_count++; | ||
1127 | |||
1128 | /* Lock out the slow poller from running on this board. */ | 1120 | /* Lock out the slow poller from running on this board. */ |
1129 | spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); | 1121 | spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); |
1130 | 1122 | ||
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 7439c0373620..cd95e215550d 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -296,8 +296,6 @@ static void jsm_tty_close(struct uart_port *port) | |||
296 | bd->bd_ops->assert_modem_signals(channel); | 296 | bd->bd_ops->assert_modem_signals(channel); |
297 | } | 297 | } |
298 | 298 | ||
299 | channel->ch_old_baud = 0; | ||
300 | |||
301 | /* Turn off UART interrupts for this port */ | 299 | /* Turn off UART interrupts for this port */ |
302 | channel->ch_bd->bd_ops->uart_off(channel); | 300 | channel->ch_bd->bd_ops->uart_off(channel); |
303 | 301 | ||
@@ -432,7 +430,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) | |||
432 | return 0; | 430 | return 0; |
433 | } | 431 | } |
434 | 432 | ||
435 | int __devinit jsm_uart_port_init(struct jsm_board *brd) | 433 | int jsm_uart_port_init(struct jsm_board *brd) |
436 | { | 434 | { |
437 | int i; | 435 | int i; |
438 | unsigned int line; | 436 | unsigned int line; |
@@ -472,7 +470,7 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd) | |||
472 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 470 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) |
473 | printk(KERN_INFO "jsm: add device failed\n"); | 471 | printk(KERN_INFO "jsm: add device failed\n"); |
474 | else | 472 | else |
475 | printk(KERN_INFO "Added device \n"); | 473 | printk(KERN_INFO "jsm: Port %d added\n", i); |
476 | } | 474 | } |
477 | 475 | ||
478 | jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); | 476 | jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); |
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index b8629d74f6a2..4a821046baae 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
@@ -438,6 +438,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, | |||
438 | unsigned char cval, fcr = 0; | 438 | unsigned char cval, fcr = 0; |
439 | unsigned long flags; | 439 | unsigned long flags; |
440 | unsigned int baud, quot; | 440 | unsigned int baud, quot; |
441 | unsigned int dll; | ||
441 | 442 | ||
442 | switch (termios->c_cflag & CSIZE) { | 443 | switch (termios->c_cflag & CSIZE) { |
443 | case CS5: | 444 | case CS5: |
@@ -534,10 +535,18 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, | |||
534 | else | 535 | else |
535 | up->mcr &= ~UART_MCR_AFE; | 536 | up->mcr &= ~UART_MCR_AFE; |
536 | 537 | ||
537 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ | 538 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ |
538 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | 539 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ |
540 | |||
541 | /* | ||
542 | * work around Errata #75 according to Intel(R) PXA27x Processor Family | ||
543 | * Specification Update (Nov 2005) | ||
544 | */ | ||
545 | dll = serial_in(up, UART_DLL); | ||
546 | WARN_ON(dll != (quot & 0xff)); | ||
547 | |||
539 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | 548 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ |
540 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | 549 | serial_out(up, UART_LCR, cval); /* reset DLAB */ |
541 | up->lcr = cval; /* Save LCR */ | 550 | up->lcr = cval; /* Save LCR */ |
542 | serial_pxa_set_mctrl(&up->port, up->port.mctrl); | 551 | serial_pxa_set_mctrl(&up->port, up->port.mctrl); |
543 | serial_out(up, UART_FCR, fcr); | 552 | serial_out(up, UART_FCR, fcr); |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index dcc72444e8e7..047530b285bb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, | |||
342 | 342 | ||
343 | if (flags == UPF_SPD_HI) | 343 | if (flags == UPF_SPD_HI) |
344 | altbaud = 57600; | 344 | altbaud = 57600; |
345 | if (flags == UPF_SPD_VHI) | 345 | else if (flags == UPF_SPD_VHI) |
346 | altbaud = 115200; | 346 | altbaud = 115200; |
347 | if (flags == UPF_SPD_SHI) | 347 | else if (flags == UPF_SPD_SHI) |
348 | altbaud = 230400; | 348 | altbaud = 230400; |
349 | if (flags == UPF_SPD_WARP) | 349 | else if (flags == UPF_SPD_WARP) |
350 | altbaud = 460800; | 350 | altbaud = 460800; |
351 | 351 | ||
352 | for (try = 0; try < 2; try++) { | 352 | for (try = 0; try < 2; try++) { |
@@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1217 | /* Handle transition to B0 status */ | 1217 | /* Handle transition to B0 status */ |
1218 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 1218 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) |
1219 | uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); | 1219 | uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); |
1220 | |||
1221 | /* Handle transition away from B0 status */ | 1220 | /* Handle transition away from B0 status */ |
1222 | if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { | 1221 | else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { |
1223 | unsigned int mask = TIOCM_DTR; | 1222 | unsigned int mask = TIOCM_DTR; |
1224 | if (!(cflag & CRTSCTS) || | 1223 | if (!(cflag & CRTSCTS) || |
1225 | !test_bit(TTY_THROTTLED, &tty->flags)) | 1224 | !test_bit(TTY_THROTTLED, &tty->flags)) |
@@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1234 | __uart_start(tty); | 1233 | __uart_start(tty); |
1235 | spin_unlock_irqrestore(&state->uart_port->lock, flags); | 1234 | spin_unlock_irqrestore(&state->uart_port->lock, flags); |
1236 | } | 1235 | } |
1237 | |||
1238 | /* Handle turning on CRTSCTS */ | 1236 | /* Handle turning on CRTSCTS */ |
1239 | if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { | 1237 | else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { |
1240 | spin_lock_irqsave(&state->uart_port->lock, flags); | 1238 | spin_lock_irqsave(&state->uart_port->lock, flags); |
1241 | if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { | 1239 | if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { |
1242 | tty->hw_stopped = 1; | 1240 | tty->hw_stopped = 1; |
@@ -2344,7 +2342,7 @@ static const struct tty_operations uart_ops = { | |||
2344 | */ | 2342 | */ |
2345 | int uart_register_driver(struct uart_driver *drv) | 2343 | int uart_register_driver(struct uart_driver *drv) |
2346 | { | 2344 | { |
2347 | struct tty_driver *normal = NULL; | 2345 | struct tty_driver *normal; |
2348 | int i, retval; | 2346 | int i, retval; |
2349 | 2347 | ||
2350 | BUG_ON(drv->state); | 2348 | BUG_ON(drv->state); |
@@ -2354,13 +2352,12 @@ int uart_register_driver(struct uart_driver *drv) | |||
2354 | * we have a large number of ports to handle. | 2352 | * we have a large number of ports to handle. |
2355 | */ | 2353 | */ |
2356 | drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); | 2354 | drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); |
2357 | retval = -ENOMEM; | ||
2358 | if (!drv->state) | 2355 | if (!drv->state) |
2359 | goto out; | 2356 | goto out; |
2360 | 2357 | ||
2361 | normal = alloc_tty_driver(drv->nr); | 2358 | normal = alloc_tty_driver(drv->nr); |
2362 | if (!normal) | 2359 | if (!normal) |
2363 | goto out; | 2360 | goto out_kfree; |
2364 | 2361 | ||
2365 | drv->tty_driver = normal; | 2362 | drv->tty_driver = normal; |
2366 | 2363 | ||
@@ -2393,12 +2390,14 @@ int uart_register_driver(struct uart_driver *drv) | |||
2393 | } | 2390 | } |
2394 | 2391 | ||
2395 | retval = tty_register_driver(normal); | 2392 | retval = tty_register_driver(normal); |
2396 | out: | 2393 | if (retval >= 0) |
2397 | if (retval < 0) { | 2394 | return retval; |
2398 | put_tty_driver(normal); | 2395 | |
2399 | kfree(drv->state); | 2396 | put_tty_driver(normal); |
2400 | } | 2397 | out_kfree: |
2401 | return retval; | 2398 | kfree(drv->state); |
2399 | out: | ||
2400 | return -ENOMEM; | ||
2402 | } | 2401 | } |
2403 | 2402 | ||
2404 | /** | 2403 | /** |