diff options
52 files changed, 752 insertions, 1368 deletions
diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt index 2191dcb9f1da..9c5d19ac935c 100644 --- a/Documentation/devicetree/bindings/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt | |||
@@ -6,6 +6,9 @@ Required properties: | |||
6 | additional mode or an USART new feature. | 6 | additional mode or an USART new feature. |
7 | - reg: Should contain registers location and length | 7 | - reg: Should contain registers location and length |
8 | - interrupts: Should contain interrupt | 8 | - interrupts: Should contain interrupt |
9 | - clock-names: tuple listing input clock names. | ||
10 | Required elements: "usart" | ||
11 | - clocks: phandles to input clocks. | ||
9 | 12 | ||
10 | Optional properties: | 13 | Optional properties: |
11 | - atmel,use-dma-rx: use of PDC or DMA for receiving data | 14 | - atmel,use-dma-rx: use of PDC or DMA for receiving data |
@@ -26,6 +29,8 @@ Example: | |||
26 | compatible = "atmel,at91sam9260-usart"; | 29 | compatible = "atmel,at91sam9260-usart"; |
27 | reg = <0xfff8c000 0x4000>; | 30 | reg = <0xfff8c000 0x4000>; |
28 | interrupts = <7>; | 31 | interrupts = <7>; |
32 | clocks = <&usart0_clk>; | ||
33 | clock-names = "usart"; | ||
29 | atmel,use-dma-rx; | 34 | atmel,use-dma-rx; |
30 | atmel,use-dma-tx; | 35 | atmel,use-dma-tx; |
31 | }; | 36 | }; |
@@ -35,6 +40,8 @@ Example: | |||
35 | compatible = "atmel,at91sam9260-usart"; | 40 | compatible = "atmel,at91sam9260-usart"; |
36 | reg = <0xf001c000 0x100>; | 41 | reg = <0xf001c000 0x100>; |
37 | interrupts = <12 4 5>; | 42 | interrupts = <12 4 5>; |
43 | clocks = <&usart0_clk>; | ||
44 | clock-names = "usart"; | ||
38 | atmel,use-dma-rx; | 45 | atmel,use-dma-rx; |
39 | atmel,use-dma-tx; | 46 | atmel,use-dma-tx; |
40 | dmas = <&dma0 2 0x3>, | 47 | dmas = <&dma0 2 0x3>, |
diff --git a/Documentation/devicetree/bindings/serial/cirrus,clps711x-uart.txt b/Documentation/devicetree/bindings/serial/cirrus,clps711x-uart.txt new file mode 100644 index 000000000000..12f3cf834deb --- /dev/null +++ b/Documentation/devicetree/bindings/serial/cirrus,clps711x-uart.txt | |||
@@ -0,0 +1,28 @@ | |||
1 | * Cirrus Logic CLPS711X Universal Asynchronous Receiver/Transmitter (UART) | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "cirrus,clps711x-uart". | ||
5 | - reg: Address and length of the register set for the device. | ||
6 | - interrupts: Should contain UART TX and RX interrupt. | ||
7 | - clocks: Should contain UART core clock number. | ||
8 | - syscon: Phandle to SYSCON node, which contain UART control bits. | ||
9 | |||
10 | Optional properties: | ||
11 | - uart-use-ms: Indicate the UART has modem signal (DCD, DSR, CTS). | ||
12 | |||
13 | Note: Each UART port should have an alias correctly numbered | ||
14 | in "aliases" node. | ||
15 | |||
16 | Example: | ||
17 | aliases { | ||
18 | serial0 = &uart1; | ||
19 | }; | ||
20 | |||
21 | uart1: uart@80000480 { | ||
22 | compatible = "cirrus,clps711x-uart"; | ||
23 | reg = <0x80000480 0x80>; | ||
24 | interrupts = <12 13>; | ||
25 | clocks = <&clks 11>; | ||
26 | syscon = <&syscon1>; | ||
27 | uart-use-ms; | ||
28 | }; | ||
diff --git a/arch/arm/mach-clps711x/devices.c b/arch/arm/mach-clps711x/devices.c index fb77d1448fec..2001488a5ef2 100644 --- a/arch/arm/mach-clps711x/devices.c +++ b/arch/arm/mach-clps711x/devices.c | |||
@@ -61,8 +61,29 @@ static void __init clps711x_add_syscon(void) | |||
61 | &clps711x_syscon_res[i], 1); | 61 | &clps711x_syscon_res[i], 1); |
62 | } | 62 | } |
63 | 63 | ||
64 | static const struct resource clps711x_uart1_res[] __initconst = { | ||
65 | DEFINE_RES_MEM(CLPS711X_PHYS_BASE + UARTDR1, SZ_128), | ||
66 | DEFINE_RES_IRQ(IRQ_UTXINT1), | ||
67 | DEFINE_RES_IRQ(IRQ_URXINT1), | ||
68 | }; | ||
69 | |||
70 | static const struct resource clps711x_uart2_res[] __initconst = { | ||
71 | DEFINE_RES_MEM(CLPS711X_PHYS_BASE + UARTDR2, SZ_128), | ||
72 | DEFINE_RES_IRQ(IRQ_UTXINT2), | ||
73 | DEFINE_RES_IRQ(IRQ_URXINT2), | ||
74 | }; | ||
75 | |||
76 | static void __init clps711x_add_uart(void) | ||
77 | { | ||
78 | platform_device_register_simple("clps711x-uart", 0, clps711x_uart1_res, | ||
79 | ARRAY_SIZE(clps711x_uart1_res)); | ||
80 | platform_device_register_simple("clps711x-uart", 1, clps711x_uart2_res, | ||
81 | ARRAY_SIZE(clps711x_uart2_res)); | ||
82 | }; | ||
83 | |||
64 | void __init clps711x_devices_init(void) | 84 | void __init clps711x_devices_init(void) |
65 | { | 85 | { |
66 | clps711x_add_gpio(); | 86 | clps711x_add_gpio(); |
67 | clps711x_add_syscon(); | 87 | clps711x_add_syscon(); |
88 | clps711x_add_uart(); | ||
68 | } | 89 | } |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index d39cca659a3f..8320abd1ef14 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -2511,8 +2511,8 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
2511 | 2511 | ||
2512 | /* If port is closing, signal caller to try again */ | 2512 | /* If port is closing, signal caller to try again */ |
2513 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){ | 2513 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){ |
2514 | if (port->flags & ASYNC_CLOSING) | 2514 | wait_event_interruptible_tty(tty, port->close_wait, |
2515 | interruptible_sleep_on(&port->close_wait); | 2515 | !(port->flags & ASYNC_CLOSING)); |
2516 | retval = ((port->flags & ASYNC_HUP_NOTIFY) ? | 2516 | retval = ((port->flags & ASYNC_HUP_NOTIFY) ? |
2517 | -EAGAIN : -ERESTARTSYS); | 2517 | -EAGAIN : -ERESTARTSYS); |
2518 | goto cleanup; | 2518 | goto cleanup; |
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 8755f5f3ad37..0cb7ef59071b 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -124,7 +124,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c | |||
124 | { | 124 | { |
125 | struct serport *serport = (struct serport*) tty->disc_data; | 125 | struct serport *serport = (struct serport*) tty->disc_data; |
126 | unsigned long flags; | 126 | unsigned long flags; |
127 | unsigned int ch_flags; | 127 | unsigned int ch_flags = 0; |
128 | int i; | 128 | int i; |
129 | 129 | ||
130 | spin_lock_irqsave(&serport->lock, flags); | 130 | spin_lock_irqsave(&serport->lock, flags); |
@@ -133,18 +133,20 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c | |||
133 | goto out; | 133 | goto out; |
134 | 134 | ||
135 | for (i = 0; i < count; i++) { | 135 | for (i = 0; i < count; i++) { |
136 | switch (fp[i]) { | 136 | if (fp) { |
137 | case TTY_FRAME: | 137 | switch (fp[i]) { |
138 | ch_flags = SERIO_FRAME; | 138 | case TTY_FRAME: |
139 | break; | 139 | ch_flags = SERIO_FRAME; |
140 | 140 | break; | |
141 | case TTY_PARITY: | 141 | |
142 | ch_flags = SERIO_PARITY; | 142 | case TTY_PARITY: |
143 | break; | 143 | ch_flags = SERIO_PARITY; |
144 | 144 | break; | |
145 | default: | 145 | |
146 | ch_flags = 0; | 146 | default: |
147 | break; | 147 | ch_flags = 0; |
148 | break; | ||
149 | } | ||
148 | } | 150 | } |
149 | 151 | ||
150 | serio_interrupt(serport->serio, cp[i], ch_flags); | 152 | serio_interrupt(serport->serio, cp[i], ch_flags); |
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 1b8bdb7e9bf4..ff53314100f6 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c | |||
@@ -596,13 +596,11 @@ static int parport_serial_pci_probe(struct pci_dev *dev, | |||
596 | 596 | ||
597 | err = pci_enable_device (dev); | 597 | err = pci_enable_device (dev); |
598 | if (err) { | 598 | if (err) { |
599 | pci_set_drvdata (dev, NULL); | ||
600 | kfree (priv); | 599 | kfree (priv); |
601 | return err; | 600 | return err; |
602 | } | 601 | } |
603 | 602 | ||
604 | if (parport_register (dev, id)) { | 603 | if (parport_register (dev, id)) { |
605 | pci_set_drvdata (dev, NULL); | ||
606 | kfree (priv); | 604 | kfree (priv); |
607 | return -ENODEV; | 605 | return -ENODEV; |
608 | } | 606 | } |
@@ -611,7 +609,6 @@ static int parport_serial_pci_probe(struct pci_dev *dev, | |||
611 | int i; | 609 | int i; |
612 | for (i = 0; i < priv->num_par; i++) | 610 | for (i = 0; i < priv->num_par; i++) |
613 | parport_pc_unregister_port (priv->port[i]); | 611 | parport_pc_unregister_port (priv->port[i]); |
614 | pci_set_drvdata (dev, NULL); | ||
615 | kfree (priv); | 612 | kfree (priv); |
616 | return -ENODEV; | 613 | return -ENODEV; |
617 | } | 614 | } |
@@ -624,8 +621,6 @@ static void parport_serial_pci_remove(struct pci_dev *dev) | |||
624 | struct parport_serial_private *priv = pci_get_drvdata (dev); | 621 | struct parport_serial_private *priv = pci_get_drvdata (dev); |
625 | int i; | 622 | int i; |
626 | 623 | ||
627 | pci_set_drvdata(dev, NULL); | ||
628 | |||
629 | // Serial ports | 624 | // Serial ports |
630 | if (priv->serial) | 625 | if (priv->serial) |
631 | pciserial_remove_ports(priv->serial); | 626 | pciserial_remove_ports(priv->serial); |
diff --git a/drivers/staging/fwserial/Kconfig b/drivers/staging/fwserial/Kconfig index a0812d99136f..9c7c9267d52c 100644 --- a/drivers/staging/fwserial/Kconfig +++ b/drivers/staging/fwserial/Kconfig | |||
@@ -9,3 +9,23 @@ config FIREWIRE_SERIAL | |||
9 | 9 | ||
10 | To compile this driver as a module, say M here: the module will | 10 | To compile this driver as a module, say M here: the module will |
11 | be called firewire-serial. | 11 | be called firewire-serial. |
12 | |||
13 | if FIREWIRE_SERIAL | ||
14 | |||
15 | config FWTTY_MAX_TOTAL_PORTS | ||
16 | int "Maximum number of serial ports supported" | ||
17 | default "64" | ||
18 | help | ||
19 | Set this to the maximum number of serial ports you want the | ||
20 | firewire-serial driver to support. | ||
21 | |||
22 | config FWTTY_MAX_CARD_PORTS | ||
23 | int "Maximum number of serial ports supported per adapter" | ||
24 | range 0 FWTTY_MAX_TOTAL_PORTS | ||
25 | default "32" | ||
26 | help | ||
27 | Set this to the maximum number of serial ports each firewire | ||
28 | adapter supports. The actual number of serial ports registered | ||
29 | is set with the module parameter "ttys". | ||
30 | |||
31 | endif | ||
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 62df009e5ac7..8af136e9c9dc 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c | |||
@@ -136,14 +136,14 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card, | |||
136 | 136 | ||
137 | #ifdef FWTTY_PROFILING | 137 | #ifdef FWTTY_PROFILING |
138 | 138 | ||
139 | static void profile_fifo_avail(struct fwtty_port *port, unsigned *stat) | 139 | static void fwtty_profile_fifo(struct fwtty_port *port, unsigned *stat) |
140 | { | 140 | { |
141 | spin_lock_bh(&port->lock); | 141 | spin_lock_bh(&port->lock); |
142 | profile_size_distrib(stat, dma_fifo_avail(&port->tx_fifo)); | 142 | fwtty_profile_data(stat, dma_fifo_avail(&port->tx_fifo)); |
143 | spin_unlock_bh(&port->lock); | 143 | spin_unlock_bh(&port->lock); |
144 | } | 144 | } |
145 | 145 | ||
146 | static void dump_profile(struct seq_file *m, struct stats *stats) | 146 | static void fwtty_dump_profile(struct seq_file *m, struct stats *stats) |
147 | { | 147 | { |
148 | /* for each stat, print sum of 0 to 2^k, then individually */ | 148 | /* for each stat, print sum of 0 to 2^k, then individually */ |
149 | int k = 4; | 149 | int k = 4; |
@@ -183,8 +183,8 @@ static void dump_profile(struct seq_file *m, struct stats *stats) | |||
183 | } | 183 | } |
184 | 184 | ||
185 | #else | 185 | #else |
186 | #define profile_fifo_avail(port, stat) | 186 | #define fwtty_profile_fifo(port, stat) |
187 | #define dump_profile(m, stats) | 187 | #define fwtty_dump_profile(m, stats) |
188 | #endif | 188 | #endif |
189 | 189 | ||
190 | /* | 190 | /* |
@@ -456,16 +456,27 @@ static int fwtty_write_port_status(struct fwtty_port *port) | |||
456 | return err; | 456 | return err; |
457 | } | 457 | } |
458 | 458 | ||
459 | static void __fwtty_throttle(struct fwtty_port *port, struct tty_struct *tty) | 459 | static void fwtty_throttle_port(struct fwtty_port *port) |
460 | { | 460 | { |
461 | struct tty_struct *tty; | ||
461 | unsigned old; | 462 | unsigned old; |
462 | 463 | ||
464 | tty = tty_port_tty_get(&port->port); | ||
465 | if (!tty) | ||
466 | return; | ||
467 | |||
468 | spin_lock_bh(&port->lock); | ||
469 | |||
463 | old = port->mctrl; | 470 | old = port->mctrl; |
464 | port->mctrl |= OOB_RX_THROTTLE; | 471 | port->mctrl |= OOB_RX_THROTTLE; |
465 | if (C_CRTSCTS(tty)) | 472 | if (C_CRTSCTS(tty)) |
466 | port->mctrl &= ~TIOCM_RTS; | 473 | port->mctrl &= ~TIOCM_RTS; |
467 | if (~old & OOB_RX_THROTTLE) | 474 | if (~old & OOB_RX_THROTTLE) |
468 | __fwtty_write_port_status(port); | 475 | __fwtty_write_port_status(port); |
476 | |||
477 | spin_unlock_bh(&port->lock); | ||
478 | |||
479 | tty_kref_put(tty); | ||
469 | } | 480 | } |
470 | 481 | ||
471 | /** | 482 | /** |
@@ -532,80 +543,14 @@ static void fwtty_emit_breaks(struct work_struct *work) | |||
532 | port->icount.brk += brk; | 543 | port->icount.brk += brk; |
533 | } | 544 | } |
534 | 545 | ||
535 | static void fwtty_pushrx(struct work_struct *work) | ||
536 | { | ||
537 | struct fwtty_port *port = to_port(work, push); | ||
538 | struct tty_struct *tty; | ||
539 | struct buffered_rx *buf, *next; | ||
540 | int n, c = 0; | ||
541 | |||
542 | spin_lock_bh(&port->lock); | ||
543 | list_for_each_entry_safe(buf, next, &port->buf_list, list) { | ||
544 | n = tty_insert_flip_string_fixed_flag(&port->port, buf->data, | ||
545 | TTY_NORMAL, buf->n); | ||
546 | c += n; | ||
547 | port->buffered -= n; | ||
548 | if (n < buf->n) { | ||
549 | if (n > 0) { | ||
550 | memmove(buf->data, buf->data + n, buf->n - n); | ||
551 | buf->n -= n; | ||
552 | } | ||
553 | tty = tty_port_tty_get(&port->port); | ||
554 | if (tty) { | ||
555 | __fwtty_throttle(port, tty); | ||
556 | tty_kref_put(tty); | ||
557 | } | ||
558 | break; | ||
559 | } else { | ||
560 | list_del(&buf->list); | ||
561 | kfree(buf); | ||
562 | } | ||
563 | } | ||
564 | if (c > 0) | ||
565 | tty_flip_buffer_push(&port->port); | ||
566 | |||
567 | if (list_empty(&port->buf_list)) | ||
568 | clear_bit(BUFFERING_RX, &port->flags); | ||
569 | spin_unlock_bh(&port->lock); | ||
570 | } | ||
571 | |||
572 | static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n) | ||
573 | { | ||
574 | struct buffered_rx *buf; | ||
575 | size_t size = (n + sizeof(struct buffered_rx) + 0xFF) & ~0xFF; | ||
576 | |||
577 | if (port->buffered + n > HIGH_WATERMARK) { | ||
578 | fwtty_err_ratelimited(port, "overflowed rx buffer: buffered: %d new: %zu wtrmk: %d\n", | ||
579 | port->buffered, n, HIGH_WATERMARK); | ||
580 | return 0; | ||
581 | } | ||
582 | buf = kmalloc(size, GFP_ATOMIC); | ||
583 | if (!buf) | ||
584 | return 0; | ||
585 | INIT_LIST_HEAD(&buf->list); | ||
586 | buf->n = n; | ||
587 | memcpy(buf->data, d, n); | ||
588 | |||
589 | spin_lock_bh(&port->lock); | ||
590 | list_add_tail(&buf->list, &port->buf_list); | ||
591 | port->buffered += n; | ||
592 | if (port->buffered > port->stats.watermark) | ||
593 | port->stats.watermark = port->buffered; | ||
594 | set_bit(BUFFERING_RX, &port->flags); | ||
595 | spin_unlock_bh(&port->lock); | ||
596 | |||
597 | return n; | ||
598 | } | ||
599 | |||
600 | static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len) | 546 | static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len) |
601 | { | 547 | { |
602 | struct tty_struct *tty; | ||
603 | int c, n = len; | 548 | int c, n = len; |
604 | unsigned lsr; | 549 | unsigned lsr; |
605 | int err = 0; | 550 | int err = 0; |
606 | 551 | ||
607 | fwtty_dbg(port, "%d\n", n); | 552 | fwtty_dbg(port, "%d\n", n); |
608 | profile_size_distrib(port->stats.reads, n); | 553 | fwtty_profile_data(port->stats.reads, n); |
609 | 554 | ||
610 | if (port->write_only) { | 555 | if (port->write_only) { |
611 | n = 0; | 556 | n = 0; |
@@ -636,31 +581,24 @@ static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len) | |||
636 | goto out; | 581 | goto out; |
637 | } | 582 | } |
638 | 583 | ||
639 | if (!test_bit(BUFFERING_RX, &port->flags)) { | 584 | c = tty_insert_flip_string_fixed_flag(&port->port, data, TTY_NORMAL, n); |
640 | c = tty_insert_flip_string_fixed_flag(&port->port, data, | 585 | if (c > 0) |
641 | TTY_NORMAL, n); | 586 | tty_flip_buffer_push(&port->port); |
642 | if (c > 0) | 587 | n -= c; |
643 | tty_flip_buffer_push(&port->port); | ||
644 | n -= c; | ||
645 | |||
646 | if (n) { | ||
647 | /* start buffering and throttling */ | ||
648 | n -= fwtty_buffer_rx(port, &data[c], n); | ||
649 | |||
650 | tty = tty_port_tty_get(&port->port); | ||
651 | if (tty) { | ||
652 | spin_lock_bh(&port->lock); | ||
653 | __fwtty_throttle(port, tty); | ||
654 | spin_unlock_bh(&port->lock); | ||
655 | tty_kref_put(tty); | ||
656 | } | ||
657 | } | ||
658 | } else | ||
659 | n -= fwtty_buffer_rx(port, data, n); | ||
660 | 588 | ||
661 | if (n) { | 589 | if (n) { |
662 | port->overrun = true; | 590 | port->overrun = true; |
663 | err = -EIO; | 591 | err = -EIO; |
592 | fwtty_err_ratelimited(port, "flip buffer overrun\n"); | ||
593 | |||
594 | } else { | ||
595 | /* throttle the sender if remaining flip buffer space has | ||
596 | * reached high watermark to avoid losing data which may be | ||
597 | * in-flight. Since the AR request context is 32k, that much | ||
598 | * data may have _already_ been acked. | ||
599 | */ | ||
600 | if (tty_buffer_space_avail(&port->port) < HIGH_WATERMARK) | ||
601 | fwtty_throttle_port(port); | ||
664 | } | 602 | } |
665 | 603 | ||
666 | out: | 604 | out: |
@@ -821,7 +759,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain) | |||
821 | if (n == -EAGAIN) | 759 | if (n == -EAGAIN) |
822 | ++port->stats.tx_stall; | 760 | ++port->stats.tx_stall; |
823 | else if (n == -ENODATA) | 761 | else if (n == -ENODATA) |
824 | profile_size_distrib(port->stats.txns, 0); | 762 | fwtty_profile_data(port->stats.txns, 0); |
825 | else { | 763 | else { |
826 | ++port->stats.fifo_errs; | 764 | ++port->stats.fifo_errs; |
827 | fwtty_err_ratelimited(port, "fifo err: %d\n", | 765 | fwtty_err_ratelimited(port, "fifo err: %d\n", |
@@ -830,7 +768,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain) | |||
830 | break; | 768 | break; |
831 | } | 769 | } |
832 | 770 | ||
833 | profile_size_distrib(port->stats.txns, txn->dma_pended.len); | 771 | fwtty_profile_data(port->stats.txns, txn->dma_pended.len); |
834 | 772 | ||
835 | fwtty_send_txn_async(peer, txn, TCODE_WRITE_BLOCK_REQUEST, | 773 | fwtty_send_txn_async(peer, txn, TCODE_WRITE_BLOCK_REQUEST, |
836 | peer->fifo_addr, txn->dma_pended.data, | 774 | peer->fifo_addr, txn->dma_pended.data, |
@@ -1101,20 +1039,13 @@ static int fwtty_port_activate(struct tty_port *tty_port, | |||
1101 | static void fwtty_port_shutdown(struct tty_port *tty_port) | 1039 | static void fwtty_port_shutdown(struct tty_port *tty_port) |
1102 | { | 1040 | { |
1103 | struct fwtty_port *port = to_port(tty_port, port); | 1041 | struct fwtty_port *port = to_port(tty_port, port); |
1104 | struct buffered_rx *buf, *next; | ||
1105 | 1042 | ||
1106 | /* TODO: cancel outstanding transactions */ | 1043 | /* TODO: cancel outstanding transactions */ |
1107 | 1044 | ||
1108 | cancel_delayed_work_sync(&port->emit_breaks); | 1045 | cancel_delayed_work_sync(&port->emit_breaks); |
1109 | cancel_delayed_work_sync(&port->drain); | 1046 | cancel_delayed_work_sync(&port->drain); |
1110 | cancel_work_sync(&port->push); | ||
1111 | 1047 | ||
1112 | spin_lock_bh(&port->lock); | 1048 | spin_lock_bh(&port->lock); |
1113 | list_for_each_entry_safe(buf, next, &port->buf_list, list) { | ||
1114 | list_del(&buf->list); | ||
1115 | kfree(buf); | ||
1116 | } | ||
1117 | port->buffered = 0; | ||
1118 | port->flags = 0; | 1049 | port->flags = 0; |
1119 | port->break_ctl = 0; | 1050 | port->break_ctl = 0; |
1120 | port->overrun = 0; | 1051 | port->overrun = 0; |
@@ -1184,7 +1115,7 @@ static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c) | |||
1184 | int n, len; | 1115 | int n, len; |
1185 | 1116 | ||
1186 | fwtty_dbg(port, "%d\n", c); | 1117 | fwtty_dbg(port, "%d\n", c); |
1187 | profile_size_distrib(port->stats.writes, c); | 1118 | fwtty_profile_data(port->stats.writes, c); |
1188 | 1119 | ||
1189 | spin_lock_bh(&port->lock); | 1120 | spin_lock_bh(&port->lock); |
1190 | n = dma_fifo_in(&port->tx_fifo, buf, c); | 1121 | n = dma_fifo_in(&port->tx_fifo, buf, c); |
@@ -1262,9 +1193,7 @@ static void fwtty_unthrottle(struct tty_struct *tty) | |||
1262 | 1193 | ||
1263 | fwtty_dbg(port, "CRTSCTS: %d\n", (C_CRTSCTS(tty) != 0)); | 1194 | fwtty_dbg(port, "CRTSCTS: %d\n", (C_CRTSCTS(tty) != 0)); |
1264 | 1195 | ||
1265 | profile_fifo_avail(port, port->stats.unthrottle); | 1196 | fwtty_profile_fifo(port, port->stats.unthrottle); |
1266 | |||
1267 | schedule_work(&port->push); | ||
1268 | 1197 | ||
1269 | spin_lock_bh(&port->lock); | 1198 | spin_lock_bh(&port->lock); |
1270 | port->mctrl &= ~OOB_RX_THROTTLE; | 1199 | port->mctrl &= ~OOB_RX_THROTTLE; |
@@ -1523,15 +1452,14 @@ static void fwtty_debugfs_show_port(struct seq_file *m, struct fwtty_port *port) | |||
1523 | 1452 | ||
1524 | seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped, | 1453 | seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped, |
1525 | stats.tx_stall, stats.fifo_errs, stats.lost); | 1454 | stats.tx_stall, stats.fifo_errs, stats.lost); |
1526 | seq_printf(m, " pkts:%d thr:%d wtrmk:%d", stats.sent, stats.throttled, | 1455 | seq_printf(m, " pkts:%d thr:%d", stats.sent, stats.throttled); |
1527 | stats.watermark); | ||
1528 | 1456 | ||
1529 | if (port->port.console) { | 1457 | if (port->port.console) { |
1530 | seq_puts(m, "\n "); | 1458 | seq_puts(m, "\n "); |
1531 | (*port->fwcon_ops->proc_show)(m, port->con_data); | 1459 | (*port->fwcon_ops->proc_show)(m, port->con_data); |
1532 | } | 1460 | } |
1533 | 1461 | ||
1534 | dump_profile(m, &port->stats); | 1462 | fwtty_dump_profile(m, &port->stats); |
1535 | } | 1463 | } |
1536 | 1464 | ||
1537 | static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer) | 1465 | static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer) |
@@ -2297,13 +2225,12 @@ static int fwserial_create(struct fw_unit *unit) | |||
2297 | port->index = FWTTY_INVALID_INDEX; | 2225 | port->index = FWTTY_INVALID_INDEX; |
2298 | port->port.ops = &fwtty_port_ops; | 2226 | port->port.ops = &fwtty_port_ops; |
2299 | port->serial = serial; | 2227 | port->serial = serial; |
2228 | tty_buffer_set_limit(&port->port, 128 * 1024); | ||
2300 | 2229 | ||
2301 | spin_lock_init(&port->lock); | 2230 | spin_lock_init(&port->lock); |
2302 | INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx); | 2231 | INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx); |
2303 | INIT_DELAYED_WORK(&port->emit_breaks, fwtty_emit_breaks); | 2232 | INIT_DELAYED_WORK(&port->emit_breaks, fwtty_emit_breaks); |
2304 | INIT_WORK(&port->hangup, fwtty_do_hangup); | 2233 | INIT_WORK(&port->hangup, fwtty_do_hangup); |
2305 | INIT_WORK(&port->push, fwtty_pushrx); | ||
2306 | INIT_LIST_HEAD(&port->buf_list); | ||
2307 | init_waitqueue_head(&port->wait_tx); | 2234 | init_waitqueue_head(&port->wait_tx); |
2308 | port->max_payload = link_speed_to_max_payload(SCODE_100); | 2235 | port->max_payload = link_speed_to_max_payload(SCODE_100); |
2309 | dma_fifo_init(&port->tx_fifo); | 2236 | dma_fifo_init(&port->tx_fifo); |
diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index 24635014a2ac..54f7f9b9b212 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h | |||
@@ -22,14 +22,14 @@ | |||
22 | #ifdef FWTTY_PROFILING | 22 | #ifdef FWTTY_PROFILING |
23 | #define DISTRIBUTION_MAX_SIZE 8192 | 23 | #define DISTRIBUTION_MAX_SIZE 8192 |
24 | #define DISTRIBUTION_MAX_INDEX (ilog2(DISTRIBUTION_MAX_SIZE) + 1) | 24 | #define DISTRIBUTION_MAX_INDEX (ilog2(DISTRIBUTION_MAX_SIZE) + 1) |
25 | static inline void profile_size_distrib(unsigned stat[], unsigned val) | 25 | static inline void fwtty_profile_data(unsigned stat[], unsigned val) |
26 | { | 26 | { |
27 | int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0; | 27 | int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0; |
28 | ++stat[n]; | 28 | ++stat[n]; |
29 | } | 29 | } |
30 | #else | 30 | #else |
31 | #define DISTRIBUTION_MAX_INDEX 0 | 31 | #define DISTRIBUTION_MAX_INDEX 0 |
32 | #define profile_size_distrib(st, n) | 32 | #define fwtty_profile_data(st, n) |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | /* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */ | 35 | /* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */ |
@@ -166,7 +166,6 @@ struct stats { | |||
166 | unsigned sent; | 166 | unsigned sent; |
167 | unsigned lost; | 167 | unsigned lost; |
168 | unsigned throttled; | 168 | unsigned throttled; |
169 | unsigned watermark; | ||
170 | unsigned reads[DISTRIBUTION_MAX_INDEX + 1]; | 169 | unsigned reads[DISTRIBUTION_MAX_INDEX + 1]; |
171 | unsigned writes[DISTRIBUTION_MAX_INDEX + 1]; | 170 | unsigned writes[DISTRIBUTION_MAX_INDEX + 1]; |
172 | unsigned txns[DISTRIBUTION_MAX_INDEX + 1]; | 171 | unsigned txns[DISTRIBUTION_MAX_INDEX + 1]; |
@@ -183,12 +182,6 @@ struct fwconsole_ops { | |||
183 | #define FWCON_NOTIFY_ATTACH 1 | 182 | #define FWCON_NOTIFY_ATTACH 1 |
184 | #define FWCON_NOTIFY_DETACH 2 | 183 | #define FWCON_NOTIFY_DETACH 2 |
185 | 184 | ||
186 | struct buffered_rx { | ||
187 | struct list_head list; | ||
188 | size_t n; | ||
189 | unsigned char data[0]; | ||
190 | }; | ||
191 | |||
192 | /** | 185 | /** |
193 | * fwtty_port: structure used to track/represent underlying tty_port | 186 | * fwtty_port: structure used to track/represent underlying tty_port |
194 | * @port: underlying tty_port | 187 | * @port: underlying tty_port |
@@ -223,11 +216,6 @@ struct buffered_rx { | |||
223 | * The work can race with the writer but concurrent sending is | 216 | * The work can race with the writer but concurrent sending is |
224 | * prevented with the IN_TX flag. Scheduled under lock to | 217 | * prevented with the IN_TX flag. Scheduled under lock to |
225 | * limit scheduling when fifo has just been drained. | 218 | * limit scheduling when fifo has just been drained. |
226 | * @push: work responsible for pushing buffered rx to the ldisc. | ||
227 | * rx can become buffered if the tty buffer is filled before the | ||
228 | * ldisc throttles the sender. | ||
229 | * @buf_list: list of buffered rx yet to be sent to ldisc | ||
230 | * @buffered: byte count of buffered rx | ||
231 | * @tx_fifo: fifo used to store & block-up writes for dma to remote | 219 | * @tx_fifo: fifo used to store & block-up writes for dma to remote |
232 | * @max_payload: max bytes transmissable per dma (based on peer's max_payload) | 220 | * @max_payload: max bytes transmissable per dma (based on peer's max_payload) |
233 | * @status_mask: UART_LSR_* bitmask significant to rx (based on termios) | 221 | * @status_mask: UART_LSR_* bitmask significant to rx (based on termios) |
@@ -267,9 +255,6 @@ struct fwtty_port { | |||
267 | spinlock_t lock; | 255 | spinlock_t lock; |
268 | unsigned mctrl; | 256 | unsigned mctrl; |
269 | struct delayed_work drain; | 257 | struct delayed_work drain; |
270 | struct work_struct push; | ||
271 | struct list_head buf_list; | ||
272 | int buffered; | ||
273 | struct dma_fifo tx_fifo; | 258 | struct dma_fifo tx_fifo; |
274 | int max_payload; | 259 | int max_payload; |
275 | unsigned status_mask; | 260 | unsigned status_mask; |
@@ -291,7 +276,6 @@ struct fwtty_port { | |||
291 | /* bit #s for flags field */ | 276 | /* bit #s for flags field */ |
292 | #define IN_TX 0 | 277 | #define IN_TX 0 |
293 | #define STOP_TX 1 | 278 | #define STOP_TX 1 |
294 | #define BUFFERING_RX 2 | ||
295 | 279 | ||
296 | /* bitmasks for special mctrl/mstatus bits */ | 280 | /* bitmasks for special mctrl/mstatus bits */ |
297 | #define OOB_RX_THROTTLE 0x00010000 | 281 | #define OOB_RX_THROTTLE 0x00010000 |
@@ -307,8 +291,8 @@ struct fwtty_port { | |||
307 | #define FREQ_BREAKS (HZ / 50) | 291 | #define FREQ_BREAKS (HZ / 50) |
308 | 292 | ||
309 | /* Ports are allocated in blocks of num_ports for each fw_card */ | 293 | /* Ports are allocated in blocks of num_ports for each fw_card */ |
310 | #define MAX_CARD_PORTS 32 /* max # of ports per card */ | 294 | #define MAX_CARD_PORTS CONFIG_FWTTY_MAX_CARD_PORTS |
311 | #define MAX_TOTAL_PORTS 64 /* max # of ports total */ | 295 | #define MAX_TOTAL_PORTS CONFIG_FWTTY_MAX_TOTAL_PORTS |
312 | 296 | ||
313 | /* tuning parameters */ | 297 | /* tuning parameters */ |
314 | #define FWTTY_PORT_TXFIFO_LEN 4096 | 298 | #define FWTTY_PORT_TXFIFO_LEN 4096 |
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 71630a2af42c..979e7c3ea2cb 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c | |||
@@ -1248,6 +1248,8 @@ static int rs_ioctl(struct tty_struct *tty, | |||
1248 | struct async_icount cprev, cnow; /* kernel counter temps */ | 1248 | struct async_icount cprev, cnow; /* kernel counter temps */ |
1249 | void __user *argp = (void __user *)arg; | 1249 | void __user *argp = (void __user *)arg; |
1250 | unsigned long flags; | 1250 | unsigned long flags; |
1251 | DEFINE_WAIT(wait); | ||
1252 | int ret; | ||
1251 | 1253 | ||
1252 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) | 1254 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) |
1253 | return -ENODEV; | 1255 | return -ENODEV; |
@@ -1288,25 +1290,33 @@ static int rs_ioctl(struct tty_struct *tty, | |||
1288 | cprev = info->icount; | 1290 | cprev = info->icount; |
1289 | local_irq_restore(flags); | 1291 | local_irq_restore(flags); |
1290 | while (1) { | 1292 | while (1) { |
1291 | interruptible_sleep_on(&info->tport.delta_msr_wait); | 1293 | prepare_to_wait(&info->tport.delta_msr_wait, |
1292 | /* see if a signal did it */ | 1294 | &wait, TASK_INTERRUPTIBLE); |
1293 | if (signal_pending(current)) | ||
1294 | return -ERESTARTSYS; | ||
1295 | local_irq_save(flags); | 1295 | local_irq_save(flags); |
1296 | cnow = info->icount; /* atomic copy */ | 1296 | cnow = info->icount; /* atomic copy */ |
1297 | local_irq_restore(flags); | 1297 | local_irq_restore(flags); |
1298 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | 1298 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && |
1299 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | 1299 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { |
1300 | return -EIO; /* no change => error */ | 1300 | ret = -EIO; /* no change => error */ |
1301 | break; | ||
1302 | } | ||
1301 | if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 1303 | if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
1302 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 1304 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
1303 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | 1305 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || |
1304 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { | 1306 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { |
1305 | return 0; | 1307 | ret = 0; |
1308 | break; | ||
1309 | } | ||
1310 | schedule(); | ||
1311 | /* see if a signal did it */ | ||
1312 | if (signal_pending(current)) { | ||
1313 | ret = -ERESTARTSYS; | ||
1314 | break; | ||
1306 | } | 1315 | } |
1307 | cprev = cnow; | 1316 | cprev = cnow; |
1308 | } | 1317 | } |
1309 | /* NOTREACHED */ | 1318 | finish_wait(&info->tport.delta_msr_wait, &wait); |
1319 | return ret; | ||
1310 | 1320 | ||
1311 | case TIOCSERGWILD: | 1321 | case TIOCSERGWILD: |
1312 | case TIOCSERSWILD: | 1322 | case TIOCSERSWILD: |
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index 33f83fee9fae..a57bb5ab761c 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c | |||
@@ -2709,6 +2709,8 @@ cy_ioctl(struct tty_struct *tty, | |||
2709 | break; | 2709 | break; |
2710 | #ifndef CONFIG_CYZ_INTR | 2710 | #ifndef CONFIG_CYZ_INTR |
2711 | case CYZSETPOLLCYCLE: | 2711 | case CYZSETPOLLCYCLE: |
2712 | if (arg > LONG_MAX / HZ) | ||
2713 | return -ENODEV; | ||
2712 | cyz_polling_cycle = (arg * HZ) / 1000; | 2714 | cyz_polling_cycle = (arg * HZ) / 1000; |
2713 | break; | 2715 | break; |
2714 | case CYZGETPOLLCYCLE: | 2716 | case CYZGETPOLLCYCLE: |
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index f17d2e4ee2ca..75dc9d25f326 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/console.h> | 16 | #include <linux/console.h> |
17 | #include <linux/init.h> | ||
18 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
19 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
20 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 9eba119bcdd3..50b46881b6ca 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c | |||
@@ -788,7 +788,7 @@ static int hvc_tiocmset(struct tty_struct *tty, | |||
788 | } | 788 | } |
789 | 789 | ||
790 | #ifdef CONFIG_CONSOLE_POLL | 790 | #ifdef CONFIG_CONSOLE_POLL |
791 | int hvc_poll_init(struct tty_driver *driver, int line, char *options) | 791 | static int hvc_poll_init(struct tty_driver *driver, int line, char *options) |
792 | { | 792 | { |
793 | return 0; | 793 | return 0; |
794 | } | 794 | } |
diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c index 347050ea414a..7ae6c293e518 100644 --- a/drivers/tty/hvc/hvsi_lib.c +++ b/drivers/tty/hvc/hvsi_lib.c | |||
@@ -1,5 +1,4 @@ | |||
1 | #include <linux/types.h> | 1 | #include <linux/types.h> |
2 | #include <linux/init.h> | ||
3 | #include <linux/delay.h> | 2 | #include <linux/delay.h> |
4 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
5 | #include <linux/console.h> | 4 | #include <linux/console.h> |
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c index 8fd72ff9436e..ebd5bff0f5c1 100644 --- a/drivers/tty/ipwireless/tty.c +++ b/drivers/tty/ipwireless/tty.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * Copyright (C) 2007 David Sterba | 15 | * Copyright (C) 2007 David Sterba |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
21 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c0f76da55304..f34461c5f14e 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
@@ -194,6 +194,7 @@ struct gsm_control { | |||
194 | struct gsm_mux { | 194 | struct gsm_mux { |
195 | struct tty_struct *tty; /* The tty our ldisc is bound to */ | 195 | struct tty_struct *tty; /* The tty our ldisc is bound to */ |
196 | spinlock_t lock; | 196 | spinlock_t lock; |
197 | struct mutex mutex; | ||
197 | unsigned int num; | 198 | unsigned int num; |
198 | struct kref ref; | 199 | struct kref ref; |
199 | 200 | ||
@@ -1704,11 +1705,8 @@ static void gsm_dlci_release(struct gsm_dlci *dlci) | |||
1704 | gsm_destroy_network(dlci); | 1705 | gsm_destroy_network(dlci); |
1705 | mutex_unlock(&dlci->mutex); | 1706 | mutex_unlock(&dlci->mutex); |
1706 | 1707 | ||
1707 | /* tty_vhangup needs the tty_lock, so unlock and | ||
1708 | relock after doing the hangup. */ | ||
1709 | tty_unlock(tty); | ||
1710 | tty_vhangup(tty); | 1708 | tty_vhangup(tty); |
1711 | tty_lock(tty); | 1709 | |
1712 | tty_port_tty_set(&dlci->port, NULL); | 1710 | tty_port_tty_set(&dlci->port, NULL); |
1713 | tty_kref_put(tty); | 1711 | tty_kref_put(tty); |
1714 | } | 1712 | } |
@@ -2019,7 +2017,7 @@ static void gsm_error(struct gsm_mux *gsm, | |||
2019 | * and then shut down each device hanging up the channels as we go. | 2017 | * and then shut down each device hanging up the channels as we go. |
2020 | */ | 2018 | */ |
2021 | 2019 | ||
2022 | void gsm_cleanup_mux(struct gsm_mux *gsm) | 2020 | static void gsm_cleanup_mux(struct gsm_mux *gsm) |
2023 | { | 2021 | { |
2024 | int i; | 2022 | int i; |
2025 | struct gsm_dlci *dlci = gsm->dlci[0]; | 2023 | struct gsm_dlci *dlci = gsm->dlci[0]; |
@@ -2054,15 +2052,16 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) | |||
2054 | dlci->state == DLCI_CLOSED); | 2052 | dlci->state == DLCI_CLOSED); |
2055 | } | 2053 | } |
2056 | /* Free up any link layer users */ | 2054 | /* Free up any link layer users */ |
2055 | mutex_lock(&gsm->mutex); | ||
2057 | for (i = 0; i < NUM_DLCI; i++) | 2056 | for (i = 0; i < NUM_DLCI; i++) |
2058 | if (gsm->dlci[i]) | 2057 | if (gsm->dlci[i]) |
2059 | gsm_dlci_release(gsm->dlci[i]); | 2058 | gsm_dlci_release(gsm->dlci[i]); |
2059 | mutex_unlock(&gsm->mutex); | ||
2060 | /* Now wipe the queues */ | 2060 | /* Now wipe the queues */ |
2061 | list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) | 2061 | list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) |
2062 | kfree(txq); | 2062 | kfree(txq); |
2063 | INIT_LIST_HEAD(&gsm->tx_list); | 2063 | INIT_LIST_HEAD(&gsm->tx_list); |
2064 | } | 2064 | } |
2065 | EXPORT_SYMBOL_GPL(gsm_cleanup_mux); | ||
2066 | 2065 | ||
2067 | /** | 2066 | /** |
2068 | * gsm_activate_mux - generic GSM setup | 2067 | * gsm_activate_mux - generic GSM setup |
@@ -2073,7 +2072,7 @@ EXPORT_SYMBOL_GPL(gsm_cleanup_mux); | |||
2073 | * finally kick off connecting to DLCI 0 on the modem. | 2072 | * finally kick off connecting to DLCI 0 on the modem. |
2074 | */ | 2073 | */ |
2075 | 2074 | ||
2076 | int gsm_activate_mux(struct gsm_mux *gsm) | 2075 | static int gsm_activate_mux(struct gsm_mux *gsm) |
2077 | { | 2076 | { |
2078 | struct gsm_dlci *dlci; | 2077 | struct gsm_dlci *dlci; |
2079 | int i = 0; | 2078 | int i = 0; |
@@ -2109,7 +2108,6 @@ int gsm_activate_mux(struct gsm_mux *gsm) | |||
2109 | gsm->dead = 0; /* Tty opens are now permissible */ | 2108 | gsm->dead = 0; /* Tty opens are now permissible */ |
2110 | return 0; | 2109 | return 0; |
2111 | } | 2110 | } |
2112 | EXPORT_SYMBOL_GPL(gsm_activate_mux); | ||
2113 | 2111 | ||
2114 | /** | 2112 | /** |
2115 | * gsm_free_mux - free up a mux | 2113 | * gsm_free_mux - free up a mux |
@@ -2117,13 +2115,12 @@ EXPORT_SYMBOL_GPL(gsm_activate_mux); | |||
2117 | * | 2115 | * |
2118 | * Dispose of allocated resources for a dead mux | 2116 | * Dispose of allocated resources for a dead mux |
2119 | */ | 2117 | */ |
2120 | void gsm_free_mux(struct gsm_mux *gsm) | 2118 | static void gsm_free_mux(struct gsm_mux *gsm) |
2121 | { | 2119 | { |
2122 | kfree(gsm->txframe); | 2120 | kfree(gsm->txframe); |
2123 | kfree(gsm->buf); | 2121 | kfree(gsm->buf); |
2124 | kfree(gsm); | 2122 | kfree(gsm); |
2125 | } | 2123 | } |
2126 | EXPORT_SYMBOL_GPL(gsm_free_mux); | ||
2127 | 2124 | ||
2128 | /** | 2125 | /** |
2129 | * gsm_free_muxr - free up a mux | 2126 | * gsm_free_muxr - free up a mux |
@@ -2153,7 +2150,7 @@ static inline void mux_put(struct gsm_mux *gsm) | |||
2153 | * Creates a new mux ready for activation. | 2150 | * Creates a new mux ready for activation. |
2154 | */ | 2151 | */ |
2155 | 2152 | ||
2156 | struct gsm_mux *gsm_alloc_mux(void) | 2153 | static struct gsm_mux *gsm_alloc_mux(void) |
2157 | { | 2154 | { |
2158 | struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL); | 2155 | struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL); |
2159 | if (gsm == NULL) | 2156 | if (gsm == NULL) |
@@ -2170,6 +2167,7 @@ struct gsm_mux *gsm_alloc_mux(void) | |||
2170 | return NULL; | 2167 | return NULL; |
2171 | } | 2168 | } |
2172 | spin_lock_init(&gsm->lock); | 2169 | spin_lock_init(&gsm->lock); |
2170 | mutex_init(&gsm->mutex); | ||
2173 | kref_init(&gsm->ref); | 2171 | kref_init(&gsm->ref); |
2174 | INIT_LIST_HEAD(&gsm->tx_list); | 2172 | INIT_LIST_HEAD(&gsm->tx_list); |
2175 | 2173 | ||
@@ -2185,7 +2183,6 @@ struct gsm_mux *gsm_alloc_mux(void) | |||
2185 | 2183 | ||
2186 | return gsm; | 2184 | return gsm; |
2187 | } | 2185 | } |
2188 | EXPORT_SYMBOL_GPL(gsm_alloc_mux); | ||
2189 | 2186 | ||
2190 | /** | 2187 | /** |
2191 | * gsmld_output - write to link | 2188 | * gsmld_output - write to link |
@@ -2269,14 +2266,15 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
2269 | char *f; | 2266 | char *f; |
2270 | int i; | 2267 | int i; |
2271 | char buf[64]; | 2268 | char buf[64]; |
2272 | char flags; | 2269 | char flags = TTY_NORMAL; |
2273 | 2270 | ||
2274 | if (debug & 4) | 2271 | if (debug & 4) |
2275 | print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET, | 2272 | print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET, |
2276 | cp, count); | 2273 | cp, count); |
2277 | 2274 | ||
2278 | for (i = count, dp = cp, f = fp; i; i--, dp++) { | 2275 | for (i = count, dp = cp, f = fp; i; i--, dp++) { |
2279 | flags = *f++; | 2276 | if (f) |
2277 | flags = *f++; | ||
2280 | switch (flags) { | 2278 | switch (flags) { |
2281 | case TTY_NORMAL: | 2279 | case TTY_NORMAL: |
2282 | gsm->receive(gsm, *dp); | 2280 | gsm->receive(gsm, *dp); |
@@ -2711,7 +2709,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, | |||
2711 | return; | 2709 | return; |
2712 | } | 2710 | } |
2713 | 2711 | ||
2714 | int gsm_change_mtu(struct net_device *net, int new_mtu) | 2712 | static int gsm_change_mtu(struct net_device *net, int new_mtu) |
2715 | { | 2713 | { |
2716 | struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net); | 2714 | struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net); |
2717 | if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu)) | 2715 | if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu)) |
@@ -2909,23 +2907,33 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
2909 | This is ok from a locking | 2907 | This is ok from a locking |
2910 | perspective as we don't have to worry about this | 2908 | perspective as we don't have to worry about this |
2911 | if DLCI0 is lost */ | 2909 | if DLCI0 is lost */ |
2912 | if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) | 2910 | mutex_lock(&gsm->mutex); |
2911 | if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) { | ||
2912 | mutex_unlock(&gsm->mutex); | ||
2913 | return -EL2NSYNC; | 2913 | return -EL2NSYNC; |
2914 | } | ||
2914 | dlci = gsm->dlci[line]; | 2915 | dlci = gsm->dlci[line]; |
2915 | if (dlci == NULL) { | 2916 | if (dlci == NULL) { |
2916 | alloc = true; | 2917 | alloc = true; |
2917 | dlci = gsm_dlci_alloc(gsm, line); | 2918 | dlci = gsm_dlci_alloc(gsm, line); |
2918 | } | 2919 | } |
2919 | if (dlci == NULL) | 2920 | if (dlci == NULL) { |
2921 | mutex_unlock(&gsm->mutex); | ||
2920 | return -ENOMEM; | 2922 | return -ENOMEM; |
2923 | } | ||
2921 | ret = tty_port_install(&dlci->port, driver, tty); | 2924 | ret = tty_port_install(&dlci->port, driver, tty); |
2922 | if (ret) { | 2925 | if (ret) { |
2923 | if (alloc) | 2926 | if (alloc) |
2924 | dlci_put(dlci); | 2927 | dlci_put(dlci); |
2928 | mutex_unlock(&gsm->mutex); | ||
2925 | return ret; | 2929 | return ret; |
2926 | } | 2930 | } |
2927 | 2931 | ||
2932 | dlci_get(dlci); | ||
2933 | dlci_get(gsm->dlci[0]); | ||
2934 | mux_get(gsm); | ||
2928 | tty->driver_data = dlci; | 2935 | tty->driver_data = dlci; |
2936 | mutex_unlock(&gsm->mutex); | ||
2929 | 2937 | ||
2930 | return 0; | 2938 | return 0; |
2931 | } | 2939 | } |
@@ -2936,9 +2944,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) | |||
2936 | struct tty_port *port = &dlci->port; | 2944 | struct tty_port *port = &dlci->port; |
2937 | 2945 | ||
2938 | port->count++; | 2946 | port->count++; |
2939 | dlci_get(dlci); | ||
2940 | dlci_get(dlci->gsm->dlci[0]); | ||
2941 | mux_get(dlci->gsm); | ||
2942 | tty_port_tty_set(port, tty); | 2947 | tty_port_tty_set(port, tty); |
2943 | 2948 | ||
2944 | dlci->modem_rx = 0; | 2949 | dlci->modem_rx = 0; |
@@ -2965,7 +2970,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) | |||
2965 | mutex_unlock(&dlci->mutex); | 2970 | mutex_unlock(&dlci->mutex); |
2966 | gsm = dlci->gsm; | 2971 | gsm = dlci->gsm; |
2967 | if (tty_port_close_start(&dlci->port, tty, filp) == 0) | 2972 | if (tty_port_close_start(&dlci->port, tty, filp) == 0) |
2968 | goto out; | 2973 | return; |
2969 | gsm_dlci_begin_close(dlci); | 2974 | gsm_dlci_begin_close(dlci); |
2970 | if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) { | 2975 | if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) { |
2971 | if (C_HUPCL(tty)) | 2976 | if (C_HUPCL(tty)) |
@@ -2973,10 +2978,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) | |||
2973 | } | 2978 | } |
2974 | tty_port_close_end(&dlci->port, tty); | 2979 | tty_port_close_end(&dlci->port, tty); |
2975 | tty_port_tty_set(&dlci->port, NULL); | 2980 | tty_port_tty_set(&dlci->port, NULL); |
2976 | out: | 2981 | return; |
2977 | dlci_put(dlci); | ||
2978 | dlci_put(gsm->dlci[0]); | ||
2979 | mux_put(gsm); | ||
2980 | } | 2982 | } |
2981 | 2983 | ||
2982 | static void gsmtty_hangup(struct tty_struct *tty) | 2984 | static void gsmtty_hangup(struct tty_struct *tty) |
@@ -3153,6 +3155,16 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) | |||
3153 | return gsmtty_modem_update(dlci, encode); | 3155 | return gsmtty_modem_update(dlci, encode); |
3154 | } | 3156 | } |
3155 | 3157 | ||
3158 | static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) | ||
3159 | { | ||
3160 | struct gsm_dlci *dlci = tty->driver_data; | ||
3161 | struct gsm_mux *gsm = dlci->gsm; | ||
3162 | |||
3163 | dlci_put(dlci); | ||
3164 | dlci_put(gsm->dlci[0]); | ||
3165 | mux_put(gsm); | ||
3166 | driver->ttys[tty->index] = NULL; | ||
3167 | } | ||
3156 | 3168 | ||
3157 | /* Virtual ttys for the demux */ | 3169 | /* Virtual ttys for the demux */ |
3158 | static const struct tty_operations gsmtty_ops = { | 3170 | static const struct tty_operations gsmtty_ops = { |
@@ -3172,6 +3184,7 @@ static const struct tty_operations gsmtty_ops = { | |||
3172 | .tiocmget = gsmtty_tiocmget, | 3184 | .tiocmget = gsmtty_tiocmget, |
3173 | .tiocmset = gsmtty_tiocmset, | 3185 | .tiocmset = gsmtty_tiocmset, |
3174 | .break_ctl = gsmtty_break_ctl, | 3186 | .break_ctl = gsmtty_break_ctl, |
3187 | .remove = gsmtty_remove, | ||
3175 | }; | 3188 | }; |
3176 | 3189 | ||
3177 | 3190 | ||
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 1e6405070ce6..8b157d68a03e 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c | |||
@@ -1244,7 +1244,7 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1244 | { | 1244 | { |
1245 | struct r3964_info *pInfo = tty->disc_data; | 1245 | struct r3964_info *pInfo = tty->disc_data; |
1246 | const unsigned char *p; | 1246 | const unsigned char *p; |
1247 | char *f, flags = 0; | 1247 | char *f, flags = TTY_NORMAL; |
1248 | int i; | 1248 | int i; |
1249 | 1249 | ||
1250 | for (i = count, p = cp, f = fp; i; i--, p++) { | 1250 | for (i = count, p = cp, f = fp; i; i--, p++) { |
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 34aacaaae14a..cb8017aa4434 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -105,6 +105,7 @@ struct n_tty_data { | |||
105 | 105 | ||
106 | /* must hold exclusive termios_rwsem to reset these */ | 106 | /* must hold exclusive termios_rwsem to reset these */ |
107 | unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; | 107 | unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; |
108 | unsigned char push:1; | ||
108 | 109 | ||
109 | /* shared by producer and consumer */ | 110 | /* shared by producer and consumer */ |
110 | char read_buf[N_TTY_BUF_SIZE]; | 111 | char read_buf[N_TTY_BUF_SIZE]; |
@@ -275,7 +276,8 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) | |||
275 | return; | 276 | return; |
276 | n_tty_set_room(tty); | 277 | n_tty_set_room(tty); |
277 | n_tty_write_wakeup(tty->link); | 278 | n_tty_write_wakeup(tty->link); |
278 | wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT); | 279 | if (waitqueue_active(&tty->link->write_wait)) |
280 | wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT); | ||
279 | return; | 281 | return; |
280 | } | 282 | } |
281 | 283 | ||
@@ -342,6 +344,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) | |||
342 | 344 | ||
343 | ldata->erasing = 0; | 345 | ldata->erasing = 0; |
344 | bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); | 346 | bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); |
347 | ldata->push = 0; | ||
345 | } | 348 | } |
346 | 349 | ||
347 | static void n_tty_packet_mode_flush(struct tty_struct *tty) | 350 | static void n_tty_packet_mode_flush(struct tty_struct *tty) |
@@ -351,7 +354,8 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) | |||
351 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 354 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
352 | if (tty->link->packet) { | 355 | if (tty->link->packet) { |
353 | tty->ctrl_status |= TIOCPKT_FLUSHREAD; | 356 | tty->ctrl_status |= TIOCPKT_FLUSHREAD; |
354 | wake_up_interruptible(&tty->link->read_wait); | 357 | if (waitqueue_active(&tty->link->read_wait)) |
358 | wake_up_interruptible(&tty->link->read_wait); | ||
355 | } | 359 | } |
356 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 360 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
357 | } | 361 | } |
@@ -1162,7 +1166,8 @@ static void n_tty_receive_break(struct tty_struct *tty) | |||
1162 | put_tty_queue('\0', ldata); | 1166 | put_tty_queue('\0', ldata); |
1163 | } | 1167 | } |
1164 | put_tty_queue('\0', ldata); | 1168 | put_tty_queue('\0', ldata); |
1165 | wake_up_interruptible(&tty->read_wait); | 1169 | if (waitqueue_active(&tty->read_wait)) |
1170 | wake_up_interruptible(&tty->read_wait); | ||
1166 | } | 1171 | } |
1167 | 1172 | ||
1168 | /** | 1173 | /** |
@@ -1220,7 +1225,8 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) | |||
1220 | put_tty_queue('\0', ldata); | 1225 | put_tty_queue('\0', ldata); |
1221 | else | 1226 | else |
1222 | put_tty_queue(c, ldata); | 1227 | put_tty_queue(c, ldata); |
1223 | wake_up_interruptible(&tty->read_wait); | 1228 | if (waitqueue_active(&tty->read_wait)) |
1229 | wake_up_interruptible(&tty->read_wait); | ||
1224 | } | 1230 | } |
1225 | 1231 | ||
1226 | static void | 1232 | static void |
@@ -1264,7 +1270,6 @@ static int | |||
1264 | n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) | 1270 | n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) |
1265 | { | 1271 | { |
1266 | struct n_tty_data *ldata = tty->disc_data; | 1272 | struct n_tty_data *ldata = tty->disc_data; |
1267 | int parmrk; | ||
1268 | 1273 | ||
1269 | if (I_IXON(tty)) { | 1274 | if (I_IXON(tty)) { |
1270 | if (c == START_CHAR(tty)) { | 1275 | if (c == START_CHAR(tty)) { |
@@ -1349,8 +1354,6 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) | |||
1349 | } | 1354 | } |
1350 | if ((c == EOL_CHAR(tty)) || | 1355 | if ((c == EOL_CHAR(tty)) || |
1351 | (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { | 1356 | (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { |
1352 | parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) | ||
1353 | ? 1 : 0; | ||
1354 | /* | 1357 | /* |
1355 | * XXX are EOL_CHAR and EOL2_CHAR echoed?!? | 1358 | * XXX are EOL_CHAR and EOL2_CHAR echoed?!? |
1356 | */ | 1359 | */ |
@@ -1365,7 +1368,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) | |||
1365 | * XXX does PARMRK doubling happen for | 1368 | * XXX does PARMRK doubling happen for |
1366 | * EOL_CHAR and EOL2_CHAR? | 1369 | * EOL_CHAR and EOL2_CHAR? |
1367 | */ | 1370 | */ |
1368 | if (parmrk) | 1371 | if (c == (unsigned char) '\377' && I_PARMRK(tty)) |
1369 | put_tty_queue(c, ldata); | 1372 | put_tty_queue(c, ldata); |
1370 | 1373 | ||
1371 | handle_newline: | 1374 | handle_newline: |
@@ -1379,7 +1382,6 @@ handle_newline: | |||
1379 | } | 1382 | } |
1380 | } | 1383 | } |
1381 | 1384 | ||
1382 | parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; | ||
1383 | if (L_ECHO(tty)) { | 1385 | if (L_ECHO(tty)) { |
1384 | finish_erasing(ldata); | 1386 | finish_erasing(ldata); |
1385 | if (c == '\n') | 1387 | if (c == '\n') |
@@ -1393,7 +1395,8 @@ handle_newline: | |||
1393 | commit_echoes(tty); | 1395 | commit_echoes(tty); |
1394 | } | 1396 | } |
1395 | 1397 | ||
1396 | if (parmrk) | 1398 | /* PARMRK doubling check */ |
1399 | if (c == (unsigned char) '\377' && I_PARMRK(tty)) | ||
1397 | put_tty_queue(c, ldata); | 1400 | put_tty_queue(c, ldata); |
1398 | 1401 | ||
1399 | put_tty_queue(c, ldata); | 1402 | put_tty_queue(c, ldata); |
@@ -1404,7 +1407,6 @@ static inline void | |||
1404 | n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) | 1407 | n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) |
1405 | { | 1408 | { |
1406 | struct n_tty_data *ldata = tty->disc_data; | 1409 | struct n_tty_data *ldata = tty->disc_data; |
1407 | int parmrk; | ||
1408 | 1410 | ||
1409 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { | 1411 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { |
1410 | start_tty(tty); | 1412 | start_tty(tty); |
@@ -1418,13 +1420,13 @@ n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) | |||
1418 | echo_char(c, tty); | 1420 | echo_char(c, tty); |
1419 | commit_echoes(tty); | 1421 | commit_echoes(tty); |
1420 | } | 1422 | } |
1421 | parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; | 1423 | /* PARMRK doubling check */ |
1422 | if (parmrk) | 1424 | if (c == (unsigned char) '\377' && I_PARMRK(tty)) |
1423 | put_tty_queue(c, ldata); | 1425 | put_tty_queue(c, ldata); |
1424 | put_tty_queue(c, ldata); | 1426 | put_tty_queue(c, ldata); |
1425 | } | 1427 | } |
1426 | 1428 | ||
1427 | static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | 1429 | static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) |
1428 | { | 1430 | { |
1429 | n_tty_receive_char_inline(tty, c); | 1431 | n_tty_receive_char_inline(tty, c); |
1430 | } | 1432 | } |
@@ -1449,8 +1451,7 @@ n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) | |||
1449 | put_tty_queue(c, ldata); | 1451 | put_tty_queue(c, ldata); |
1450 | } | 1452 | } |
1451 | 1453 | ||
1452 | static inline void | 1454 | static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) |
1453 | n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) | ||
1454 | { | 1455 | { |
1455 | if (I_ISTRIP(tty)) | 1456 | if (I_ISTRIP(tty)) |
1456 | c &= 0x7f; | 1457 | c &= 0x7f; |
@@ -1681,32 +1682,9 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1681 | } | 1682 | } |
1682 | } | 1683 | } |
1683 | 1684 | ||
1684 | static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 1685 | static int |
1685 | char *fp, int count) | 1686 | n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, |
1686 | { | 1687 | char *fp, int count, int flow) |
1687 | int room, n; | ||
1688 | |||
1689 | down_read(&tty->termios_rwsem); | ||
1690 | |||
1691 | while (1) { | ||
1692 | room = receive_room(tty); | ||
1693 | n = min(count, room); | ||
1694 | if (!n) | ||
1695 | break; | ||
1696 | __receive_buf(tty, cp, fp, n); | ||
1697 | cp += n; | ||
1698 | if (fp) | ||
1699 | fp += n; | ||
1700 | count -= n; | ||
1701 | } | ||
1702 | |||
1703 | tty->receive_room = room; | ||
1704 | n_tty_check_throttle(tty); | ||
1705 | up_read(&tty->termios_rwsem); | ||
1706 | } | ||
1707 | |||
1708 | static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, | ||
1709 | char *fp, int count) | ||
1710 | { | 1688 | { |
1711 | struct n_tty_data *ldata = tty->disc_data; | 1689 | struct n_tty_data *ldata = tty->disc_data; |
1712 | int room, n, rcvd = 0; | 1690 | int room, n, rcvd = 0; |
@@ -1717,7 +1695,7 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, | |||
1717 | room = receive_room(tty); | 1695 | room = receive_room(tty); |
1718 | n = min(count, room); | 1696 | n = min(count, room); |
1719 | if (!n) { | 1697 | if (!n) { |
1720 | if (!room) | 1698 | if (flow && !room) |
1721 | ldata->no_room = 1; | 1699 | ldata->no_room = 1; |
1722 | break; | 1700 | break; |
1723 | } | 1701 | } |
@@ -1736,6 +1714,18 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, | |||
1736 | return rcvd; | 1714 | return rcvd; |
1737 | } | 1715 | } |
1738 | 1716 | ||
1717 | static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | ||
1718 | char *fp, int count) | ||
1719 | { | ||
1720 | n_tty_receive_buf_common(tty, cp, fp, count, 0); | ||
1721 | } | ||
1722 | |||
1723 | static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, | ||
1724 | char *fp, int count) | ||
1725 | { | ||
1726 | return n_tty_receive_buf_common(tty, cp, fp, count, 1); | ||
1727 | } | ||
1728 | |||
1739 | int is_ignored(int sig) | 1729 | int is_ignored(int sig) |
1740 | { | 1730 | { |
1741 | return (sigismember(¤t->blocked, sig) || | 1731 | return (sigismember(¤t->blocked, sig) || |
@@ -1762,7 +1752,16 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1762 | 1752 | ||
1763 | if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) { | 1753 | if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) { |
1764 | bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); | 1754 | bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); |
1765 | ldata->line_start = ldata->canon_head = ldata->read_tail; | 1755 | ldata->line_start = ldata->read_tail; |
1756 | if (!L_ICANON(tty) || !read_cnt(ldata)) { | ||
1757 | ldata->canon_head = ldata->read_tail; | ||
1758 | ldata->push = 0; | ||
1759 | } else { | ||
1760 | set_bit((ldata->read_head - 1) & (N_TTY_BUF_SIZE - 1), | ||
1761 | ldata->read_flags); | ||
1762 | ldata->canon_head = ldata->read_head; | ||
1763 | ldata->push = 1; | ||
1764 | } | ||
1766 | ldata->erasing = 0; | 1765 | ldata->erasing = 0; |
1767 | ldata->lnext = 0; | 1766 | ldata->lnext = 0; |
1768 | } | 1767 | } |
@@ -1825,8 +1824,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1825 | start_tty(tty); | 1824 | start_tty(tty); |
1826 | 1825 | ||
1827 | /* The termios change make the tty ready for I/O */ | 1826 | /* The termios change make the tty ready for I/O */ |
1828 | wake_up_interruptible(&tty->write_wait); | 1827 | if (waitqueue_active(&tty->write_wait)) |
1829 | wake_up_interruptible(&tty->read_wait); | 1828 | wake_up_interruptible(&tty->write_wait); |
1829 | if (waitqueue_active(&tty->read_wait)) | ||
1830 | wake_up_interruptible(&tty->read_wait); | ||
1830 | } | 1831 | } |
1831 | 1832 | ||
1832 | /** | 1833 | /** |
@@ -1892,14 +1893,15 @@ err: | |||
1892 | return -ENOMEM; | 1893 | return -ENOMEM; |
1893 | } | 1894 | } |
1894 | 1895 | ||
1895 | static inline int input_available_p(struct tty_struct *tty, int amt) | 1896 | static inline int input_available_p(struct tty_struct *tty, int poll) |
1896 | { | 1897 | { |
1897 | struct n_tty_data *ldata = tty->disc_data; | 1898 | struct n_tty_data *ldata = tty->disc_data; |
1899 | int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1; | ||
1898 | 1900 | ||
1899 | if (ldata->icanon && !L_EXTPROC(tty)) { | 1901 | if (ldata->icanon && !L_EXTPROC(tty)) { |
1900 | if (ldata->canon_head != ldata->read_tail) | 1902 | if (ldata->canon_head != ldata->read_tail) |
1901 | return 1; | 1903 | return 1; |
1902 | } else if (read_cnt(ldata) >= (amt ? amt : 1)) | 1904 | } else if (read_cnt(ldata) >= amt) |
1903 | return 1; | 1905 | return 1; |
1904 | 1906 | ||
1905 | return 0; | 1907 | return 0; |
@@ -1965,6 +1967,12 @@ static int copy_from_read_buf(struct tty_struct *tty, | |||
1965 | * it copies one line of input up to and including the line-delimiting | 1967 | * it copies one line of input up to and including the line-delimiting |
1966 | * character into the user-space buffer. | 1968 | * character into the user-space buffer. |
1967 | * | 1969 | * |
1970 | * NB: When termios is changed from non-canonical to canonical mode and | ||
1971 | * the read buffer contains data, n_tty_set_termios() simulates an EOF | ||
1972 | * push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer. | ||
1973 | * This causes data already processed as input to be immediately available | ||
1974 | * as input although a newline has not been received. | ||
1975 | * | ||
1968 | * Called under the atomic_read_lock mutex | 1976 | * Called under the atomic_read_lock mutex |
1969 | * | 1977 | * |
1970 | * n_tty_read()/consumer path: | 1978 | * n_tty_read()/consumer path: |
@@ -2011,7 +2019,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, | |||
2011 | n += found; | 2019 | n += found; |
2012 | c = n; | 2020 | c = n; |
2013 | 2021 | ||
2014 | if (found && read_buf(ldata, eol) == __DISABLED_CHAR) { | 2022 | if (found && !ldata->push && read_buf(ldata, eol) == __DISABLED_CHAR) { |
2015 | n--; | 2023 | n--; |
2016 | eof_push = !n && ldata->read_tail != ldata->line_start; | 2024 | eof_push = !n && ldata->read_tail != ldata->line_start; |
2017 | } | 2025 | } |
@@ -2038,7 +2046,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, | |||
2038 | ldata->read_tail += c; | 2046 | ldata->read_tail += c; |
2039 | 2047 | ||
2040 | if (found) { | 2048 | if (found) { |
2041 | ldata->line_start = ldata->read_tail; | 2049 | if (!ldata->push) |
2050 | ldata->line_start = ldata->read_tail; | ||
2051 | else | ||
2052 | ldata->push = 0; | ||
2042 | tty_audit_push(tty); | 2053 | tty_audit_push(tty); |
2043 | } | 2054 | } |
2044 | return eof_push ? -EAGAIN : 0; | 2055 | return eof_push ? -EAGAIN : 0; |
@@ -2398,7 +2409,7 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, | |||
2398 | 2409 | ||
2399 | poll_wait(file, &tty->read_wait, wait); | 2410 | poll_wait(file, &tty->read_wait, wait); |
2400 | poll_wait(file, &tty->write_wait, wait); | 2411 | poll_wait(file, &tty->write_wait, wait); |
2401 | if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty))) | 2412 | if (input_available_p(tty, 1)) |
2402 | mask |= POLLIN | POLLRDNORM; | 2413 | mask |= POLLIN | POLLRDNORM; |
2403 | if (tty->packet && tty->link->ctrl_status) | 2414 | if (tty->packet && tty->link->ctrl_status) |
2404 | mask |= POLLPRI | POLLIN | POLLRDNORM; | 2415 | mask |= POLLPRI | POLLIN | POLLRDNORM; |
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 354564ea47c5..383c4c796637 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c | |||
@@ -1744,7 +1744,7 @@ static void rp_flush_buffer(struct tty_struct *tty) | |||
1744 | 1744 | ||
1745 | #ifdef CONFIG_PCI | 1745 | #ifdef CONFIG_PCI |
1746 | 1746 | ||
1747 | static DEFINE_PCI_DEVICE_TABLE(rocket_pci_ids) = { | 1747 | static const struct pci_device_id rocket_pci_ids[] = { |
1748 | { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4QUAD) }, | 1748 | { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4QUAD) }, |
1749 | { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8OCTA) }, | 1749 | { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8OCTA) }, |
1750 | { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP8OCTA) }, | 1750 | { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP8OCTA) }, |
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index e33d38cb170f..61ecd709a722 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c | |||
@@ -2670,6 +2670,10 @@ static void serial8250_config_port(struct uart_port *port, int flags) | |||
2670 | if (port->type == PORT_16550A && port->iotype == UPIO_AU) | 2670 | if (port->type == PORT_16550A && port->iotype == UPIO_AU) |
2671 | up->bugs |= UART_BUG_NOMSR; | 2671 | up->bugs |= UART_BUG_NOMSR; |
2672 | 2672 | ||
2673 | /* HW bugs may trigger IRQ while IIR == NO_INT */ | ||
2674 | if (port->type == PORT_TEGRA) | ||
2675 | up->bugs |= UART_BUG_NOMSR; | ||
2676 | |||
2673 | if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) | 2677 | if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) |
2674 | autoconfig_irq(up); | 2678 | autoconfig_irq(up); |
2675 | 2679 | ||
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 06525f10e364..faa64e646100 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c | |||
@@ -14,7 +14,6 @@ | |||
14 | * raised, the LCR needs to be rewritten and the uart status register read. | 14 | * raised, the LCR needs to be rewritten and the uart status register read. |
15 | */ | 15 | */ |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/init.h> | ||
18 | #include <linux/io.h> | 17 | #include <linux/io.h> |
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/serial_8250.h> | 19 | #include <linux/serial_8250.h> |
@@ -274,7 +273,6 @@ static int dw8250_probe_of(struct uart_port *p, | |||
274 | return 0; | 273 | return 0; |
275 | } | 274 | } |
276 | 275 | ||
277 | #ifdef CONFIG_ACPI | ||
278 | static int dw8250_probe_acpi(struct uart_8250_port *up, | 276 | static int dw8250_probe_acpi(struct uart_8250_port *up, |
279 | struct dw8250_data *data) | 277 | struct dw8250_data *data) |
280 | { | 278 | { |
@@ -302,13 +300,6 @@ static int dw8250_probe_acpi(struct uart_8250_port *up, | |||
302 | 300 | ||
303 | return 0; | 301 | return 0; |
304 | } | 302 | } |
305 | #else | ||
306 | static inline int dw8250_probe_acpi(struct uart_8250_port *up, | ||
307 | struct dw8250_data *data) | ||
308 | { | ||
309 | return -ENODEV; | ||
310 | } | ||
311 | #endif /* CONFIG_ACPI */ | ||
312 | 303 | ||
313 | static int dw8250_probe(struct platform_device *pdev) | 304 | static int dw8250_probe(struct platform_device *pdev) |
314 | { | 305 | { |
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index d1a9078003bd..56c87232b6a0 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c | |||
@@ -18,7 +18,6 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/init.h> | ||
22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
24 | #include <linux/serial_8250.h> | 23 | #include <linux/serial_8250.h> |
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4697a514b80a..50228eed3b6f 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | #undef DEBUG | 12 | #undef DEBUG |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | ||
15 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
16 | #include <linux/string.h> | 15 | #include <linux/string.h> |
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
@@ -1259,10 +1258,10 @@ static int pci_quatech_init(struct pci_dev *dev) | |||
1259 | unsigned long base = pci_resource_start(dev, 0); | 1258 | unsigned long base = pci_resource_start(dev, 0); |
1260 | if (base) { | 1259 | if (base) { |
1261 | u32 tmp; | 1260 | u32 tmp; |
1262 | outl(inl(base + 0x38), base + 0x38); | 1261 | outl(inl(base + 0x38) | 0x00002000, base + 0x38); |
1263 | tmp = inl(base + 0x3c); | 1262 | tmp = inl(base + 0x3c); |
1264 | outl(tmp | 0x01000000, base + 0x3c); | 1263 | outl(tmp | 0x01000000, base + 0x3c); |
1265 | outl(tmp, base + 0x3c); | 1264 | outl(tmp &= ~0x01000000, base + 0x3c); |
1266 | } | 1265 | } |
1267 | } | 1266 | } |
1268 | return 0; | 1267 | return 0; |
@@ -1744,6 +1743,7 @@ pci_wch_ch353_setup(struct serial_private *priv, | |||
1744 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 | 1743 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 |
1745 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 | 1744 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 |
1746 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 | 1745 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 |
1746 | #define PCI_DEVICE_ID_TITAN_200V3 0xA306 | ||
1747 | #define PCI_DEVICE_ID_TITAN_400V3 0xA310 | 1747 | #define PCI_DEVICE_ID_TITAN_400V3 0xA310 |
1748 | #define PCI_DEVICE_ID_TITAN_410V3 0xA312 | 1748 | #define PCI_DEVICE_ID_TITAN_410V3 0xA312 |
1749 | #define PCI_DEVICE_ID_TITAN_800V3 0xA314 | 1749 | #define PCI_DEVICE_ID_TITAN_800V3 0xA314 |
@@ -4427,6 +4427,9 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
4427 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI, | 4427 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI, |
4428 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 4428 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
4429 | pbn_oxsemi_2_4000000 }, | 4429 | pbn_oxsemi_2_4000000 }, |
4430 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200V3, | ||
4431 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
4432 | pbn_b0_bt_2_921600 }, | ||
4430 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3, | 4433 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3, |
4431 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 4434 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
4432 | pbn_b0_4_921600 }, | 4435 | pbn_b0_4_921600 }, |
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 35d9ab95c5cb..682a2fbe5c06 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * the Free Software Foundation; either version 2 of the License. | 12 | * the Free Software Foundation; either version 2 of the License. |
13 | */ | 13 | */ |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | ||
16 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
17 | #include <linux/pnp.h> | 16 | #include <linux/pnp.h> |
18 | #include <linux/string.h> | 17 | #include <linux/string.h> |
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 1b74b88e1e1e..4d180c9423ef 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
37 | #include <linux/init.h> | ||
38 | #include <linux/ptrace.h> | 37 | #include <linux/ptrace.h> |
39 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
40 | #include <linux/string.h> | 39 | #include <linux/string.h> |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index a3817ab8602f..441ada489874 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -181,9 +181,8 @@ config SERIAL_KS8695_CONSOLE | |||
181 | 181 | ||
182 | config SERIAL_CLPS711X | 182 | config SERIAL_CLPS711X |
183 | tristate "CLPS711X serial port support" | 183 | tristate "CLPS711X serial port support" |
184 | depends on ARCH_CLPS711X | 184 | depends on ARCH_CLPS711X || COMPILE_TEST |
185 | select SERIAL_CORE | 185 | select SERIAL_CORE |
186 | default y | ||
187 | help | 186 | help |
188 | This enables the driver for the on-chip UARTs of the Cirrus | 187 | This enables the driver for the on-chip UARTs of the Cirrus |
189 | Logic EP711x/EP721x/EP731x processors. | 188 | Logic EP711x/EP721x/EP731x processors. |
@@ -1146,31 +1145,13 @@ config SERIAL_QE | |||
1146 | This driver supports the QE serial ports on Freescale embedded | 1145 | This driver supports the QE serial ports on Freescale embedded |
1147 | PowerPC that contain a QUICC Engine. | 1146 | PowerPC that contain a QUICC Engine. |
1148 | 1147 | ||
1149 | config SERIAL_SC26XX | ||
1150 | tristate "SC2681/SC2692 serial port support" | ||
1151 | depends on SNI_RM | ||
1152 | select SERIAL_CORE | ||
1153 | help | ||
1154 | This is a driver for the onboard serial ports of | ||
1155 | older RM400 machines. | ||
1156 | |||
1157 | config SERIAL_SC26XX_CONSOLE | ||
1158 | bool "Console on SC2681/SC2692 serial port" | ||
1159 | depends on SERIAL_SC26XX=y | ||
1160 | select SERIAL_CORE_CONSOLE | ||
1161 | help | ||
1162 | Support for Console on SC2681/SC2692 serial ports. | ||
1163 | |||
1164 | config SERIAL_SCCNXP | 1148 | config SERIAL_SCCNXP |
1165 | tristate "SCCNXP serial port support" | 1149 | tristate "SCCNXP serial port support" |
1166 | depends on !SERIAL_SC26XX | ||
1167 | select SERIAL_CORE | 1150 | select SERIAL_CORE |
1168 | default n | ||
1169 | help | 1151 | help |
1170 | This selects support for an advanced UART from NXP (Philips). | 1152 | This selects support for an advanced UART from NXP (Philips). |
1171 | Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92, | 1153 | Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92, |
1172 | SC28L202, SCC68681 and SCC68692. | 1154 | SC28L202, SCC68681 and SCC68692. |
1173 | Positioned as a replacement for the driver SC26XX. | ||
1174 | 1155 | ||
1175 | config SERIAL_SCCNXP_CONSOLE | 1156 | config SERIAL_SCCNXP_CONSOLE |
1176 | bool "Console on SCCNXP serial port" | 1157 | bool "Console on SCCNXP serial port" |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 3068c7722087..3680854fef41 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -47,7 +47,6 @@ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o | |||
47 | obj-$(CONFIG_SERIAL_MPSC) += mpsc.o | 47 | obj-$(CONFIG_SERIAL_MPSC) += mpsc.o |
48 | obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o | 48 | obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o |
49 | obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o | 49 | obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o |
50 | obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o | ||
51 | obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o | 50 | obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o |
52 | obj-$(CONFIG_SERIAL_JSM) += jsm/ | 51 | obj-$(CONFIG_SERIAL_JSM) += jsm/ |
53 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o | 52 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o |
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 33bd8606be62..01c9e72433e1 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c | |||
@@ -756,9 +756,10 @@ static int pl010_remove(struct amba_device *dev) | |||
756 | return 0; | 756 | return 0; |
757 | } | 757 | } |
758 | 758 | ||
759 | static int pl010_suspend(struct amba_device *dev, pm_message_t state) | 759 | #ifdef CONFIG_PM_SLEEP |
760 | static int pl010_suspend(struct device *dev) | ||
760 | { | 761 | { |
761 | struct uart_amba_port *uap = amba_get_drvdata(dev); | 762 | struct uart_amba_port *uap = dev_get_drvdata(dev); |
762 | 763 | ||
763 | if (uap) | 764 | if (uap) |
764 | uart_suspend_port(&amba_reg, &uap->port); | 765 | uart_suspend_port(&amba_reg, &uap->port); |
@@ -766,15 +767,18 @@ static int pl010_suspend(struct amba_device *dev, pm_message_t state) | |||
766 | return 0; | 767 | return 0; |
767 | } | 768 | } |
768 | 769 | ||
769 | static int pl010_resume(struct amba_device *dev) | 770 | static int pl010_resume(struct device *dev) |
770 | { | 771 | { |
771 | struct uart_amba_port *uap = amba_get_drvdata(dev); | 772 | struct uart_amba_port *uap = dev_get_drvdata(dev); |
772 | 773 | ||
773 | if (uap) | 774 | if (uap) |
774 | uart_resume_port(&amba_reg, &uap->port); | 775 | uart_resume_port(&amba_reg, &uap->port); |
775 | 776 | ||
776 | return 0; | 777 | return 0; |
777 | } | 778 | } |
779 | #endif | ||
780 | |||
781 | static SIMPLE_DEV_PM_OPS(pl010_dev_pm_ops, pl010_suspend, pl010_resume); | ||
778 | 782 | ||
779 | static struct amba_id pl010_ids[] = { | 783 | static struct amba_id pl010_ids[] = { |
780 | { | 784 | { |
@@ -789,12 +793,11 @@ MODULE_DEVICE_TABLE(amba, pl010_ids); | |||
789 | static struct amba_driver pl010_driver = { | 793 | static struct amba_driver pl010_driver = { |
790 | .drv = { | 794 | .drv = { |
791 | .name = "uart-pl010", | 795 | .name = "uart-pl010", |
796 | .pm = &pl010_dev_pm_ops, | ||
792 | }, | 797 | }, |
793 | .id_table = pl010_ids, | 798 | .id_table = pl010_ids, |
794 | .probe = pl010_probe, | 799 | .probe = pl010_probe, |
795 | .remove = pl010_remove, | 800 | .remove = pl010_remove, |
796 | .suspend = pl010_suspend, | ||
797 | .resume = pl010_resume, | ||
798 | }; | 801 | }; |
799 | 802 | ||
800 | static int __init pl010_init(void) | 803 | static int __init pl010_init(void) |
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 7203864992a5..d58783d364e3 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
@@ -112,8 +112,6 @@ static struct vendor_data vendor_st = { | |||
112 | .get_fifosize = get_fifosize_st, | 112 | .get_fifosize = get_fifosize_st, |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static struct uart_amba_port *amba_ports[UART_NR]; | ||
116 | |||
117 | /* Deals with DMA transactions */ | 115 | /* Deals with DMA transactions */ |
118 | 116 | ||
119 | struct pl011_sgbuf { | 117 | struct pl011_sgbuf { |
@@ -969,6 +967,8 @@ static void pl011_dma_rx_poll(unsigned long args) | |||
969 | 967 | ||
970 | spin_lock_irqsave(&uap->port.lock, flags); | 968 | spin_lock_irqsave(&uap->port.lock, flags); |
971 | pl011_dma_rx_stop(uap); | 969 | pl011_dma_rx_stop(uap); |
970 | uap->im |= UART011_RXIM; | ||
971 | writew(uap->im, uap->port.membase + UART011_IMSC); | ||
972 | spin_unlock_irqrestore(&uap->port.lock, flags); | 972 | spin_unlock_irqrestore(&uap->port.lock, flags); |
973 | 973 | ||
974 | uap->dmarx.running = false; | 974 | uap->dmarx.running = false; |
@@ -1216,8 +1216,8 @@ __acquires(&uap->port.lock) | |||
1216 | dev_dbg(uap->port.dev, "could not trigger RX DMA job " | 1216 | dev_dbg(uap->port.dev, "could not trigger RX DMA job " |
1217 | "fall back to interrupt mode again\n"); | 1217 | "fall back to interrupt mode again\n"); |
1218 | uap->im |= UART011_RXIM; | 1218 | uap->im |= UART011_RXIM; |
1219 | writew(uap->im, uap->port.membase + UART011_IMSC); | ||
1219 | } else { | 1220 | } else { |
1220 | uap->im &= ~UART011_RXIM; | ||
1221 | #ifdef CONFIG_DMA_ENGINE | 1221 | #ifdef CONFIG_DMA_ENGINE |
1222 | /* Start Rx DMA poll */ | 1222 | /* Start Rx DMA poll */ |
1223 | if (uap->dmarx.poll_rate) { | 1223 | if (uap->dmarx.poll_rate) { |
@@ -1229,8 +1229,6 @@ __acquires(&uap->port.lock) | |||
1229 | } | 1229 | } |
1230 | #endif | 1230 | #endif |
1231 | } | 1231 | } |
1232 | |||
1233 | writew(uap->im, uap->port.membase + UART011_IMSC); | ||
1234 | } | 1232 | } |
1235 | spin_lock(&uap->port.lock); | 1233 | spin_lock(&uap->port.lock); |
1236 | } | 1234 | } |
@@ -1513,10 +1511,25 @@ static int pl011_hwinit(struct uart_port *port) | |||
1513 | return retval; | 1511 | return retval; |
1514 | } | 1512 | } |
1515 | 1513 | ||
1514 | static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) | ||
1515 | { | ||
1516 | writew(lcr_h, uap->port.membase + uap->lcrh_rx); | ||
1517 | if (uap->lcrh_rx != uap->lcrh_tx) { | ||
1518 | int i; | ||
1519 | /* | ||
1520 | * Wait 10 PCLKs before writing LCRH_TX register, | ||
1521 | * to get this delay write read only register 10 times | ||
1522 | */ | ||
1523 | for (i = 0; i < 10; ++i) | ||
1524 | writew(0xff, uap->port.membase + UART011_MIS); | ||
1525 | writew(lcr_h, uap->port.membase + uap->lcrh_tx); | ||
1526 | } | ||
1527 | } | ||
1528 | |||
1516 | static int pl011_startup(struct uart_port *port) | 1529 | static int pl011_startup(struct uart_port *port) |
1517 | { | 1530 | { |
1518 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 1531 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
1519 | unsigned int cr; | 1532 | unsigned int cr, lcr_h, fbrd, ibrd; |
1520 | int retval; | 1533 | int retval; |
1521 | 1534 | ||
1522 | retval = pl011_hwinit(port); | 1535 | retval = pl011_hwinit(port); |
@@ -1535,32 +1548,36 @@ static int pl011_startup(struct uart_port *port) | |||
1535 | writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); | 1548 | writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); |
1536 | 1549 | ||
1537 | /* | 1550 | /* |
1538 | * Provoke TX FIFO interrupt into asserting. | 1551 | * Provoke TX FIFO interrupt into asserting. Taking care to preserve |
1552 | * baud rate and data format specified by FBRD, IBRD and LCRH as the | ||
1553 | * UART may already be in use as a console. | ||
1539 | */ | 1554 | */ |
1555 | spin_lock_irq(&uap->port.lock); | ||
1556 | |||
1557 | fbrd = readw(uap->port.membase + UART011_FBRD); | ||
1558 | ibrd = readw(uap->port.membase + UART011_IBRD); | ||
1559 | lcr_h = readw(uap->port.membase + uap->lcrh_rx); | ||
1560 | |||
1540 | cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; | 1561 | cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; |
1541 | writew(cr, uap->port.membase + UART011_CR); | 1562 | writew(cr, uap->port.membase + UART011_CR); |
1542 | writew(0, uap->port.membase + UART011_FBRD); | 1563 | writew(0, uap->port.membase + UART011_FBRD); |
1543 | writew(1, uap->port.membase + UART011_IBRD); | 1564 | writew(1, uap->port.membase + UART011_IBRD); |
1544 | writew(0, uap->port.membase + uap->lcrh_rx); | 1565 | pl011_write_lcr_h(uap, 0); |
1545 | if (uap->lcrh_tx != uap->lcrh_rx) { | ||
1546 | int i; | ||
1547 | /* | ||
1548 | * Wait 10 PCLKs before writing LCRH_TX register, | ||
1549 | * to get this delay write read only register 10 times | ||
1550 | */ | ||
1551 | for (i = 0; i < 10; ++i) | ||
1552 | writew(0xff, uap->port.membase + UART011_MIS); | ||
1553 | writew(0, uap->port.membase + uap->lcrh_tx); | ||
1554 | } | ||
1555 | writew(0, uap->port.membase + UART01x_DR); | 1566 | writew(0, uap->port.membase + UART01x_DR); |
1556 | while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) | 1567 | while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) |
1557 | barrier(); | 1568 | barrier(); |
1558 | 1569 | ||
1570 | writew(fbrd, uap->port.membase + UART011_FBRD); | ||
1571 | writew(ibrd, uap->port.membase + UART011_IBRD); | ||
1572 | pl011_write_lcr_h(uap, lcr_h); | ||
1573 | |||
1559 | /* restore RTS and DTR */ | 1574 | /* restore RTS and DTR */ |
1560 | cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); | 1575 | cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); |
1561 | cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; | 1576 | cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; |
1562 | writew(cr, uap->port.membase + UART011_CR); | 1577 | writew(cr, uap->port.membase + UART011_CR); |
1563 | 1578 | ||
1579 | spin_unlock_irq(&uap->port.lock); | ||
1580 | |||
1564 | /* | 1581 | /* |
1565 | * initialise the old status of the modem signals | 1582 | * initialise the old status of the modem signals |
1566 | */ | 1583 | */ |
@@ -1629,11 +1646,13 @@ static void pl011_shutdown(struct uart_port *port) | |||
1629 | * it during startup(). | 1646 | * it during startup(). |
1630 | */ | 1647 | */ |
1631 | uap->autorts = false; | 1648 | uap->autorts = false; |
1649 | spin_lock_irq(&uap->port.lock); | ||
1632 | cr = readw(uap->port.membase + UART011_CR); | 1650 | cr = readw(uap->port.membase + UART011_CR); |
1633 | uap->old_cr = cr; | 1651 | uap->old_cr = cr; |
1634 | cr &= UART011_CR_RTS | UART011_CR_DTR; | 1652 | cr &= UART011_CR_RTS | UART011_CR_DTR; |
1635 | cr |= UART01x_CR_UARTEN | UART011_CR_TXE; | 1653 | cr |= UART01x_CR_UARTEN | UART011_CR_TXE; |
1636 | writew(cr, uap->port.membase + UART011_CR); | 1654 | writew(cr, uap->port.membase + UART011_CR); |
1655 | spin_unlock_irq(&uap->port.lock); | ||
1637 | 1656 | ||
1638 | /* | 1657 | /* |
1639 | * disable break condition and fifos | 1658 | * disable break condition and fifos |
@@ -1797,17 +1816,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1797 | * UART011_FBRD & UART011_IBRD. | 1816 | * UART011_FBRD & UART011_IBRD. |
1798 | * ----------^----------^----------^----------^----- | 1817 | * ----------^----------^----------^----------^----- |
1799 | */ | 1818 | */ |
1800 | writew(lcr_h, port->membase + uap->lcrh_rx); | 1819 | pl011_write_lcr_h(uap, lcr_h); |
1801 | if (uap->lcrh_rx != uap->lcrh_tx) { | ||
1802 | int i; | ||
1803 | /* | ||
1804 | * Wait 10 PCLKs before writing LCRH_TX register, | ||
1805 | * to get this delay write read only register 10 times | ||
1806 | */ | ||
1807 | for (i = 0; i < 10; ++i) | ||
1808 | writew(0xff, uap->port.membase + UART011_MIS); | ||
1809 | writew(lcr_h, port->membase + uap->lcrh_tx); | ||
1810 | } | ||
1811 | writew(old_cr, port->membase + UART011_CR); | 1820 | writew(old_cr, port->membase + UART011_CR); |
1812 | 1821 | ||
1813 | spin_unlock_irqrestore(&port->lock, flags); | 1822 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -2169,10 +2178,10 @@ static int pl011_remove(struct amba_device *dev) | |||
2169 | return 0; | 2178 | return 0; |
2170 | } | 2179 | } |
2171 | 2180 | ||
2172 | #ifdef CONFIG_PM | 2181 | #ifdef CONFIG_PM_SLEEP |
2173 | static int pl011_suspend(struct amba_device *dev, pm_message_t state) | 2182 | static int pl011_suspend(struct device *dev) |
2174 | { | 2183 | { |
2175 | struct uart_amba_port *uap = amba_get_drvdata(dev); | 2184 | struct uart_amba_port *uap = dev_get_drvdata(dev); |
2176 | 2185 | ||
2177 | if (!uap) | 2186 | if (!uap) |
2178 | return -EINVAL; | 2187 | return -EINVAL; |
@@ -2180,9 +2189,9 @@ static int pl011_suspend(struct amba_device *dev, pm_message_t state) | |||
2180 | return uart_suspend_port(&amba_reg, &uap->port); | 2189 | return uart_suspend_port(&amba_reg, &uap->port); |
2181 | } | 2190 | } |
2182 | 2191 | ||
2183 | static int pl011_resume(struct amba_device *dev) | 2192 | static int pl011_resume(struct device *dev) |
2184 | { | 2193 | { |
2185 | struct uart_amba_port *uap = amba_get_drvdata(dev); | 2194 | struct uart_amba_port *uap = dev_get_drvdata(dev); |
2186 | 2195 | ||
2187 | if (!uap) | 2196 | if (!uap) |
2188 | return -EINVAL; | 2197 | return -EINVAL; |
@@ -2191,6 +2200,8 @@ static int pl011_resume(struct amba_device *dev) | |||
2191 | } | 2200 | } |
2192 | #endif | 2201 | #endif |
2193 | 2202 | ||
2203 | static SIMPLE_DEV_PM_OPS(pl011_dev_pm_ops, pl011_suspend, pl011_resume); | ||
2204 | |||
2194 | static struct amba_id pl011_ids[] = { | 2205 | static struct amba_id pl011_ids[] = { |
2195 | { | 2206 | { |
2196 | .id = 0x00041011, | 2207 | .id = 0x00041011, |
@@ -2210,14 +2221,11 @@ MODULE_DEVICE_TABLE(amba, pl011_ids); | |||
2210 | static struct amba_driver pl011_driver = { | 2221 | static struct amba_driver pl011_driver = { |
2211 | .drv = { | 2222 | .drv = { |
2212 | .name = "uart-pl011", | 2223 | .name = "uart-pl011", |
2224 | .pm = &pl011_dev_pm_ops, | ||
2213 | }, | 2225 | }, |
2214 | .id_table = pl011_ids, | 2226 | .id_table = pl011_ids, |
2215 | .probe = pl011_probe, | 2227 | .probe = pl011_probe, |
2216 | .remove = pl011_remove, | 2228 | .remove = pl011_remove, |
2217 | #ifdef CONFIG_PM | ||
2218 | .suspend = pl011_suspend, | ||
2219 | .resume = pl011_resume, | ||
2220 | #endif | ||
2221 | }; | 2229 | }; |
2222 | 2230 | ||
2223 | static int __init pl011_init(void) | 2231 | static int __init pl011_init(void) |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index c7d99af46a96..a49f10d269b2 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -825,9 +825,6 @@ static void atmel_release_rx_dma(struct uart_port *port) | |||
825 | atmel_port->desc_rx = NULL; | 825 | atmel_port->desc_rx = NULL; |
826 | atmel_port->chan_rx = NULL; | 826 | atmel_port->chan_rx = NULL; |
827 | atmel_port->cookie_rx = -EINVAL; | 827 | atmel_port->cookie_rx = -EINVAL; |
828 | |||
829 | if (!atmel_port->is_usart) | ||
830 | del_timer_sync(&atmel_port->uart_timer); | ||
831 | } | 828 | } |
832 | 829 | ||
833 | static void atmel_rx_from_dma(struct uart_port *port) | 830 | static void atmel_rx_from_dma(struct uart_port *port) |
@@ -1229,9 +1226,6 @@ static void atmel_release_rx_pdc(struct uart_port *port) | |||
1229 | DMA_FROM_DEVICE); | 1226 | DMA_FROM_DEVICE); |
1230 | kfree(pdc->buf); | 1227 | kfree(pdc->buf); |
1231 | } | 1228 | } |
1232 | |||
1233 | if (!atmel_port->is_usart) | ||
1234 | del_timer_sync(&atmel_port->uart_timer); | ||
1235 | } | 1229 | } |
1236 | 1230 | ||
1237 | static void atmel_rx_from_pdc(struct uart_port *port) | 1231 | static void atmel_rx_from_pdc(struct uart_port *port) |
@@ -1604,12 +1598,13 @@ static int atmel_startup(struct uart_port *port) | |||
1604 | /* enable xmit & rcvr */ | 1598 | /* enable xmit & rcvr */ |
1605 | UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); | 1599 | UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); |
1606 | 1600 | ||
1601 | setup_timer(&atmel_port->uart_timer, | ||
1602 | atmel_uart_timer_callback, | ||
1603 | (unsigned long)port); | ||
1604 | |||
1607 | if (atmel_use_pdc_rx(port)) { | 1605 | if (atmel_use_pdc_rx(port)) { |
1608 | /* set UART timeout */ | 1606 | /* set UART timeout */ |
1609 | if (!atmel_port->is_usart) { | 1607 | if (!atmel_port->is_usart) { |
1610 | setup_timer(&atmel_port->uart_timer, | ||
1611 | atmel_uart_timer_callback, | ||
1612 | (unsigned long)port); | ||
1613 | mod_timer(&atmel_port->uart_timer, | 1608 | mod_timer(&atmel_port->uart_timer, |
1614 | jiffies + uart_poll_timeout(port)); | 1609 | jiffies + uart_poll_timeout(port)); |
1615 | /* set USART timeout */ | 1610 | /* set USART timeout */ |
@@ -1624,9 +1619,6 @@ static int atmel_startup(struct uart_port *port) | |||
1624 | } else if (atmel_use_dma_rx(port)) { | 1619 | } else if (atmel_use_dma_rx(port)) { |
1625 | /* set UART timeout */ | 1620 | /* set UART timeout */ |
1626 | if (!atmel_port->is_usart) { | 1621 | if (!atmel_port->is_usart) { |
1627 | setup_timer(&atmel_port->uart_timer, | ||
1628 | atmel_uart_timer_callback, | ||
1629 | (unsigned long)port); | ||
1630 | mod_timer(&atmel_port->uart_timer, | 1622 | mod_timer(&atmel_port->uart_timer, |
1631 | jiffies + uart_poll_timeout(port)); | 1623 | jiffies + uart_poll_timeout(port)); |
1632 | /* set USART timeout */ | 1624 | /* set USART timeout */ |
@@ -1650,12 +1642,30 @@ static int atmel_startup(struct uart_port *port) | |||
1650 | static void atmel_shutdown(struct uart_port *port) | 1642 | static void atmel_shutdown(struct uart_port *port) |
1651 | { | 1643 | { |
1652 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 1644 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
1645 | |||
1653 | /* | 1646 | /* |
1654 | * Ensure everything is stopped. | 1647 | * Prevent any tasklets being scheduled during |
1648 | * cleanup | ||
1649 | */ | ||
1650 | del_timer_sync(&atmel_port->uart_timer); | ||
1651 | |||
1652 | /* | ||
1653 | * Clear out any scheduled tasklets before | ||
1654 | * we destroy the buffers | ||
1655 | */ | ||
1656 | tasklet_kill(&atmel_port->tasklet); | ||
1657 | |||
1658 | /* | ||
1659 | * Ensure everything is stopped and | ||
1660 | * disable all interrupts, port and break condition. | ||
1655 | */ | 1661 | */ |
1656 | atmel_stop_rx(port); | 1662 | atmel_stop_rx(port); |
1657 | atmel_stop_tx(port); | 1663 | atmel_stop_tx(port); |
1658 | 1664 | ||
1665 | UART_PUT_CR(port, ATMEL_US_RSTSTA); | ||
1666 | UART_PUT_IDR(port, -1); | ||
1667 | |||
1668 | |||
1659 | /* | 1669 | /* |
1660 | * Shut-down the DMA. | 1670 | * Shut-down the DMA. |
1661 | */ | 1671 | */ |
@@ -1665,10 +1675,10 @@ static void atmel_shutdown(struct uart_port *port) | |||
1665 | atmel_port->release_tx(port); | 1675 | atmel_port->release_tx(port); |
1666 | 1676 | ||
1667 | /* | 1677 | /* |
1668 | * Disable all interrupts, port and break condition. | 1678 | * Reset ring buffer pointers |
1669 | */ | 1679 | */ |
1670 | UART_PUT_CR(port, ATMEL_US_RSTSTA); | 1680 | atmel_port->rx_ring.head = 0; |
1671 | UART_PUT_IDR(port, -1); | 1681 | atmel_port->rx_ring.tail = 0; |
1672 | 1682 | ||
1673 | /* | 1683 | /* |
1674 | * Free the interrupt | 1684 | * Free the interrupt |
@@ -2441,11 +2451,12 @@ static int atmel_serial_remove(struct platform_device *pdev) | |||
2441 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 2451 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
2442 | int ret = 0; | 2452 | int ret = 0; |
2443 | 2453 | ||
2454 | tasklet_kill(&atmel_port->tasklet); | ||
2455 | |||
2444 | device_init_wakeup(&pdev->dev, 0); | 2456 | device_init_wakeup(&pdev->dev, 0); |
2445 | 2457 | ||
2446 | ret = uart_remove_one_port(&atmel_uart, port); | 2458 | ret = uart_remove_one_port(&atmel_uart, port); |
2447 | 2459 | ||
2448 | tasklet_kill(&atmel_port->tasklet); | ||
2449 | kfree(atmel_port->rx_ring.buf); | 2460 | kfree(atmel_port->rx_ring.buf); |
2450 | 2461 | ||
2451 | /* "port" is allocated statically, so we shouldn't free it */ | 2462 | /* "port" is allocated statically, so we shouldn't free it */ |
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 8d0b994357c8..b0eacb83f831 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c | |||
@@ -21,44 +21,66 @@ | |||
21 | #include <linux/console.h> | 21 | #include <linux/console.h> |
22 | #include <linux/serial_core.h> | 22 | #include <linux/serial_core.h> |
23 | #include <linux/serial.h> | 23 | #include <linux/serial.h> |
24 | #include <linux/io.h> | ||
25 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
25 | #include <linux/io.h> | ||
26 | #include <linux/tty.h> | 26 | #include <linux/tty.h> |
27 | #include <linux/tty_flip.h> | 27 | #include <linux/tty_flip.h> |
28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/of.h> | ||
29 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/regmap.h> | ||
30 | 32 | ||
31 | #include <mach/hardware.h> | 33 | #include <linux/mfd/syscon.h> |
34 | #include <linux/mfd/syscon/clps711x.h> | ||
32 | 35 | ||
33 | #define UART_CLPS711X_NAME "uart-clps711x" | 36 | #define UART_CLPS711X_DEVNAME "ttyCL" |
34 | #define UART_CLPS711X_NR 2 | 37 | #define UART_CLPS711X_NR 2 |
35 | #define UART_CLPS711X_MAJOR 204 | 38 | #define UART_CLPS711X_MAJOR 204 |
36 | #define UART_CLPS711X_MINOR 40 | 39 | #define UART_CLPS711X_MINOR 40 |
37 | 40 | ||
38 | #define UBRLCR(port) ((port)->line ? UBRLCR2 : UBRLCR1) | 41 | #define UARTDR_OFFSET (0x00) |
39 | #define UARTDR(port) ((port)->line ? UARTDR2 : UARTDR1) | 42 | #define UBRLCR_OFFSET (0x40) |
40 | #define SYSFLG(port) ((port)->line ? SYSFLG2 : SYSFLG1) | 43 | |
41 | #define SYSCON(port) ((port)->line ? SYSCON2 : SYSCON1) | 44 | #define UARTDR_FRMERR (1 << 8) |
42 | #define TX_IRQ(port) ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1) | 45 | #define UARTDR_PARERR (1 << 9) |
43 | #define RX_IRQ(port) ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1) | 46 | #define UARTDR_OVERR (1 << 10) |
47 | |||
48 | #define UBRLCR_BAUD_MASK ((1 << 12) - 1) | ||
49 | #define UBRLCR_BREAK (1 << 12) | ||
50 | #define UBRLCR_PRTEN (1 << 13) | ||
51 | #define UBRLCR_EVENPRT (1 << 14) | ||
52 | #define UBRLCR_XSTOP (1 << 15) | ||
53 | #define UBRLCR_FIFOEN (1 << 16) | ||
54 | #define UBRLCR_WRDLEN5 (0 << 17) | ||
55 | #define UBRLCR_WRDLEN6 (1 << 17) | ||
56 | #define UBRLCR_WRDLEN7 (2 << 17) | ||
57 | #define UBRLCR_WRDLEN8 (3 << 17) | ||
58 | #define UBRLCR_WRDLEN_MASK (3 << 17) | ||
44 | 59 | ||
45 | struct clps711x_port { | 60 | struct clps711x_port { |
46 | struct uart_driver uart; | 61 | struct uart_port port; |
47 | struct clk *uart_clk; | 62 | unsigned int tx_enabled; |
48 | struct uart_port port[UART_CLPS711X_NR]; | 63 | int rx_irq; |
49 | int tx_enabled[UART_CLPS711X_NR]; | 64 | struct regmap *syscon; |
50 | #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE | 65 | bool use_ms; |
51 | struct console console; | 66 | }; |
52 | #endif | 67 | |
68 | static struct uart_driver clps711x_uart = { | ||
69 | .owner = THIS_MODULE, | ||
70 | .driver_name = UART_CLPS711X_DEVNAME, | ||
71 | .dev_name = UART_CLPS711X_DEVNAME, | ||
72 | .major = UART_CLPS711X_MAJOR, | ||
73 | .minor = UART_CLPS711X_MINOR, | ||
74 | .nr = UART_CLPS711X_NR, | ||
53 | }; | 75 | }; |
54 | 76 | ||
55 | static void uart_clps711x_stop_tx(struct uart_port *port) | 77 | static void uart_clps711x_stop_tx(struct uart_port *port) |
56 | { | 78 | { |
57 | struct clps711x_port *s = dev_get_drvdata(port->dev); | 79 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
58 | 80 | ||
59 | if (s->tx_enabled[port->line]) { | 81 | if (s->tx_enabled) { |
60 | disable_irq(TX_IRQ(port)); | 82 | disable_irq(port->irq); |
61 | s->tx_enabled[port->line] = 0; | 83 | s->tx_enabled = 0; |
62 | } | 84 | } |
63 | } | 85 | } |
64 | 86 | ||
@@ -66,33 +88,27 @@ static void uart_clps711x_start_tx(struct uart_port *port) | |||
66 | { | 88 | { |
67 | struct clps711x_port *s = dev_get_drvdata(port->dev); | 89 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
68 | 90 | ||
69 | if (!s->tx_enabled[port->line]) { | 91 | if (!s->tx_enabled) { |
70 | enable_irq(TX_IRQ(port)); | 92 | s->tx_enabled = 1; |
71 | s->tx_enabled[port->line] = 1; | 93 | enable_irq(port->irq); |
72 | } | 94 | } |
73 | } | 95 | } |
74 | 96 | ||
75 | static void uart_clps711x_stop_rx(struct uart_port *port) | ||
76 | { | ||
77 | disable_irq(RX_IRQ(port)); | ||
78 | } | ||
79 | |||
80 | static void uart_clps711x_enable_ms(struct uart_port *port) | ||
81 | { | ||
82 | /* Do nothing */ | ||
83 | } | ||
84 | |||
85 | static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id) | 97 | static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id) |
86 | { | 98 | { |
87 | struct uart_port *port = dev_id; | 99 | struct uart_port *port = dev_id; |
88 | unsigned int status, ch, flg; | 100 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
101 | unsigned int status, flg; | ||
102 | u16 ch; | ||
89 | 103 | ||
90 | for (;;) { | 104 | for (;;) { |
91 | status = clps_readl(SYSFLG(port)); | 105 | u32 sysflg = 0; |
92 | if (status & SYSFLG_URXFE) | 106 | |
107 | regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); | ||
108 | if (sysflg & SYSFLG_URXFE) | ||
93 | break; | 109 | break; |
94 | 110 | ||
95 | ch = clps_readw(UARTDR(port)); | 111 | ch = readw(port->membase + UARTDR_OFFSET); |
96 | status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR); | 112 | status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR); |
97 | ch &= 0xff; | 113 | ch &= 0xff; |
98 | 114 | ||
@@ -138,23 +154,29 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id) | |||
138 | struct circ_buf *xmit = &port->state->xmit; | 154 | struct circ_buf *xmit = &port->state->xmit; |
139 | 155 | ||
140 | if (port->x_char) { | 156 | if (port->x_char) { |
141 | clps_writew(port->x_char, UARTDR(port)); | 157 | writew(port->x_char, port->membase + UARTDR_OFFSET); |
142 | port->icount.tx++; | 158 | port->icount.tx++; |
143 | port->x_char = 0; | 159 | port->x_char = 0; |
144 | return IRQ_HANDLED; | 160 | return IRQ_HANDLED; |
145 | } | 161 | } |
146 | 162 | ||
147 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 163 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
148 | disable_irq_nosync(TX_IRQ(port)); | 164 | if (s->tx_enabled) { |
149 | s->tx_enabled[port->line] = 0; | 165 | disable_irq_nosync(port->irq); |
166 | s->tx_enabled = 0; | ||
167 | } | ||
150 | return IRQ_HANDLED; | 168 | return IRQ_HANDLED; |
151 | } | 169 | } |
152 | 170 | ||
153 | while (!uart_circ_empty(xmit)) { | 171 | while (!uart_circ_empty(xmit)) { |
154 | clps_writew(xmit->buf[xmit->tail], UARTDR(port)); | 172 | u32 sysflg = 0; |
173 | |||
174 | writew(xmit->buf[xmit->tail], port->membase + UARTDR_OFFSET); | ||
155 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 175 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
156 | port->icount.tx++; | 176 | port->icount.tx++; |
157 | if (clps_readl(SYSFLG(port) & SYSFLG_UTXFF)) | 177 | |
178 | regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); | ||
179 | if (sysflg & SYSFLG_UTXFF) | ||
158 | break; | 180 | break; |
159 | } | 181 | } |
160 | 182 | ||
@@ -166,20 +188,28 @@ static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id) | |||
166 | 188 | ||
167 | static unsigned int uart_clps711x_tx_empty(struct uart_port *port) | 189 | static unsigned int uart_clps711x_tx_empty(struct uart_port *port) |
168 | { | 190 | { |
169 | return (clps_readl(SYSFLG(port) & SYSFLG_UBUSY)) ? 0 : TIOCSER_TEMT; | 191 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
192 | u32 sysflg = 0; | ||
193 | |||
194 | regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); | ||
195 | |||
196 | return (sysflg & SYSFLG_UBUSY) ? 0 : TIOCSER_TEMT; | ||
170 | } | 197 | } |
171 | 198 | ||
172 | static unsigned int uart_clps711x_get_mctrl(struct uart_port *port) | 199 | static unsigned int uart_clps711x_get_mctrl(struct uart_port *port) |
173 | { | 200 | { |
174 | unsigned int status, result = 0; | 201 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
202 | unsigned int result = 0; | ||
203 | |||
204 | if (s->use_ms) { | ||
205 | u32 sysflg = 0; | ||
175 | 206 | ||
176 | if (port->line == 0) { | 207 | regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); |
177 | status = clps_readl(SYSFLG1); | 208 | if (sysflg & SYSFLG1_DCD) |
178 | if (status & SYSFLG1_DCD) | ||
179 | result |= TIOCM_CAR; | 209 | result |= TIOCM_CAR; |
180 | if (status & SYSFLG1_DSR) | 210 | if (sysflg & SYSFLG1_DSR) |
181 | result |= TIOCM_DSR; | 211 | result |= TIOCM_DSR; |
182 | if (status & SYSFLG1_CTS) | 212 | if (sysflg & SYSFLG1_CTS) |
183 | result |= TIOCM_CTS; | 213 | result |= TIOCM_CTS; |
184 | } else | 214 | } else |
185 | result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; | 215 | result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; |
@@ -194,65 +224,53 @@ static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
194 | 224 | ||
195 | static void uart_clps711x_break_ctl(struct uart_port *port, int break_state) | 225 | static void uart_clps711x_break_ctl(struct uart_port *port, int break_state) |
196 | { | 226 | { |
197 | unsigned long flags; | ||
198 | unsigned int ubrlcr; | 227 | unsigned int ubrlcr; |
199 | 228 | ||
200 | spin_lock_irqsave(&port->lock, flags); | 229 | ubrlcr = readl(port->membase + UBRLCR_OFFSET); |
201 | |||
202 | ubrlcr = clps_readl(UBRLCR(port)); | ||
203 | if (break_state) | 230 | if (break_state) |
204 | ubrlcr |= UBRLCR_BREAK; | 231 | ubrlcr |= UBRLCR_BREAK; |
205 | else | 232 | else |
206 | ubrlcr &= ~UBRLCR_BREAK; | 233 | ubrlcr &= ~UBRLCR_BREAK; |
207 | clps_writel(ubrlcr, UBRLCR(port)); | 234 | writel(ubrlcr, port->membase + UBRLCR_OFFSET); |
235 | } | ||
236 | |||
237 | static void uart_clps711x_set_ldisc(struct uart_port *port, int ld) | ||
238 | { | ||
239 | if (!port->line) { | ||
240 | struct clps711x_port *s = dev_get_drvdata(port->dev); | ||
208 | 241 | ||
209 | spin_unlock_irqrestore(&port->lock, flags); | 242 | regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON1_SIREN, |
243 | (ld == N_IRDA) ? SYSCON1_SIREN : 0); | ||
244 | } | ||
210 | } | 245 | } |
211 | 246 | ||
212 | static int uart_clps711x_startup(struct uart_port *port) | 247 | static int uart_clps711x_startup(struct uart_port *port) |
213 | { | 248 | { |
214 | struct clps711x_port *s = dev_get_drvdata(port->dev); | 249 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
215 | int ret; | ||
216 | |||
217 | s->tx_enabled[port->line] = 1; | ||
218 | /* Allocate the IRQs */ | ||
219 | ret = devm_request_irq(port->dev, TX_IRQ(port), uart_clps711x_int_tx, | ||
220 | 0, UART_CLPS711X_NAME " TX", port); | ||
221 | if (ret) | ||
222 | return ret; | ||
223 | |||
224 | ret = devm_request_irq(port->dev, RX_IRQ(port), uart_clps711x_int_rx, | ||
225 | 0, UART_CLPS711X_NAME " RX", port); | ||
226 | if (ret) { | ||
227 | devm_free_irq(port->dev, TX_IRQ(port), port); | ||
228 | return ret; | ||
229 | } | ||
230 | 250 | ||
231 | /* Disable break */ | 251 | /* Disable break */ |
232 | clps_writel(clps_readl(UBRLCR(port)) & ~UBRLCR_BREAK, UBRLCR(port)); | 252 | writel(readl(port->membase + UBRLCR_OFFSET) & ~UBRLCR_BREAK, |
253 | port->membase + UBRLCR_OFFSET); | ||
233 | 254 | ||
234 | /* Enable the port */ | 255 | /* Enable the port */ |
235 | clps_writel(clps_readl(SYSCON(port)) | SYSCON_UARTEN, SYSCON(port)); | 256 | return regmap_update_bits(s->syscon, SYSCON_OFFSET, |
236 | 257 | SYSCON_UARTEN, SYSCON_UARTEN); | |
237 | return 0; | ||
238 | } | 258 | } |
239 | 259 | ||
240 | static void uart_clps711x_shutdown(struct uart_port *port) | 260 | static void uart_clps711x_shutdown(struct uart_port *port) |
241 | { | 261 | { |
242 | /* Free the interrupts */ | 262 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
243 | devm_free_irq(port->dev, TX_IRQ(port), port); | ||
244 | devm_free_irq(port->dev, RX_IRQ(port), port); | ||
245 | 263 | ||
246 | /* Disable the port */ | 264 | /* Disable the port */ |
247 | clps_writel(clps_readl(SYSCON(port)) & ~SYSCON_UARTEN, SYSCON(port)); | 265 | regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON_UARTEN, 0); |
248 | } | 266 | } |
249 | 267 | ||
250 | static void uart_clps711x_set_termios(struct uart_port *port, | 268 | static void uart_clps711x_set_termios(struct uart_port *port, |
251 | struct ktermios *termios, | 269 | struct ktermios *termios, |
252 | struct ktermios *old) | 270 | struct ktermios *old) |
253 | { | 271 | { |
254 | unsigned int ubrlcr, baud, quot; | 272 | u32 ubrlcr; |
255 | unsigned long flags; | 273 | unsigned int baud, quot; |
256 | 274 | ||
257 | /* Mask termios capabilities we don't support */ | 275 | /* Mask termios capabilities we don't support */ |
258 | termios->c_cflag &= ~CMSPAR; | 276 | termios->c_cflag &= ~CMSPAR; |
@@ -291,8 +309,6 @@ static void uart_clps711x_set_termios(struct uart_port *port, | |||
291 | /* Enable FIFO */ | 309 | /* Enable FIFO */ |
292 | ubrlcr |= UBRLCR_FIFOEN; | 310 | ubrlcr |= UBRLCR_FIFOEN; |
293 | 311 | ||
294 | spin_lock_irqsave(&port->lock, flags); | ||
295 | |||
296 | /* Set read status mask */ | 312 | /* Set read status mask */ |
297 | port->read_status_mask = UARTDR_OVERR; | 313 | port->read_status_mask = UARTDR_OVERR; |
298 | if (termios->c_iflag & INPCK) | 314 | if (termios->c_iflag & INPCK) |
@@ -306,9 +322,7 @@ static void uart_clps711x_set_termios(struct uart_port *port, | |||
306 | 322 | ||
307 | uart_update_timeout(port, termios->c_cflag, baud); | 323 | uart_update_timeout(port, termios->c_cflag, baud); |
308 | 324 | ||
309 | clps_writel(ubrlcr | (quot - 1), UBRLCR(port)); | 325 | writel(ubrlcr | (quot - 1), port->membase + UBRLCR_OFFSET); |
310 | |||
311 | spin_unlock_irqrestore(&port->lock, flags); | ||
312 | } | 326 | } |
313 | 327 | ||
314 | static const char *uart_clps711x_type(struct uart_port *port) | 328 | static const char *uart_clps711x_type(struct uart_port *port) |
@@ -322,14 +336,12 @@ static void uart_clps711x_config_port(struct uart_port *port, int flags) | |||
322 | port->type = PORT_CLPS711X; | 336 | port->type = PORT_CLPS711X; |
323 | } | 337 | } |
324 | 338 | ||
325 | static void uart_clps711x_release_port(struct uart_port *port) | 339 | static void uart_clps711x_nop_void(struct uart_port *port) |
326 | { | 340 | { |
327 | /* Do nothing */ | ||
328 | } | 341 | } |
329 | 342 | ||
330 | static int uart_clps711x_request_port(struct uart_port *port) | 343 | static int uart_clps711x_nop_int(struct uart_port *port) |
331 | { | 344 | { |
332 | /* Do nothing */ | ||
333 | return 0; | 345 | return 0; |
334 | } | 346 | } |
335 | 347 | ||
@@ -339,181 +351,237 @@ static const struct uart_ops uart_clps711x_ops = { | |||
339 | .get_mctrl = uart_clps711x_get_mctrl, | 351 | .get_mctrl = uart_clps711x_get_mctrl, |
340 | .stop_tx = uart_clps711x_stop_tx, | 352 | .stop_tx = uart_clps711x_stop_tx, |
341 | .start_tx = uart_clps711x_start_tx, | 353 | .start_tx = uart_clps711x_start_tx, |
342 | .stop_rx = uart_clps711x_stop_rx, | 354 | .stop_rx = uart_clps711x_nop_void, |
343 | .enable_ms = uart_clps711x_enable_ms, | 355 | .enable_ms = uart_clps711x_nop_void, |
344 | .break_ctl = uart_clps711x_break_ctl, | 356 | .break_ctl = uart_clps711x_break_ctl, |
357 | .set_ldisc = uart_clps711x_set_ldisc, | ||
345 | .startup = uart_clps711x_startup, | 358 | .startup = uart_clps711x_startup, |
346 | .shutdown = uart_clps711x_shutdown, | 359 | .shutdown = uart_clps711x_shutdown, |
347 | .set_termios = uart_clps711x_set_termios, | 360 | .set_termios = uart_clps711x_set_termios, |
348 | .type = uart_clps711x_type, | 361 | .type = uart_clps711x_type, |
349 | .config_port = uart_clps711x_config_port, | 362 | .config_port = uart_clps711x_config_port, |
350 | .release_port = uart_clps711x_release_port, | 363 | .release_port = uart_clps711x_nop_void, |
351 | .request_port = uart_clps711x_request_port, | 364 | .request_port = uart_clps711x_nop_int, |
352 | }; | 365 | }; |
353 | 366 | ||
354 | #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE | 367 | #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE |
355 | static void uart_clps711x_console_putchar(struct uart_port *port, int ch) | 368 | static void uart_clps711x_console_putchar(struct uart_port *port, int ch) |
356 | { | 369 | { |
357 | while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF) | 370 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
358 | barrier(); | 371 | u32 sysflg = 0; |
372 | |||
373 | do { | ||
374 | regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); | ||
375 | } while (sysflg & SYSFLG_UTXFF); | ||
359 | 376 | ||
360 | clps_writew(ch, UARTDR(port)); | 377 | writew(ch, port->membase + UARTDR_OFFSET); |
361 | } | 378 | } |
362 | 379 | ||
363 | static void uart_clps711x_console_write(struct console *co, const char *c, | 380 | static void uart_clps711x_console_write(struct console *co, const char *c, |
364 | unsigned n) | 381 | unsigned n) |
365 | { | 382 | { |
366 | struct clps711x_port *s = (struct clps711x_port *)co->data; | 383 | struct uart_port *port = clps711x_uart.state[co->index].uart_port; |
367 | struct uart_port *port = &s->port[co->index]; | 384 | struct clps711x_port *s = dev_get_drvdata(port->dev); |
368 | u32 syscon; | 385 | u32 sysflg = 0; |
369 | |||
370 | /* Ensure that the port is enabled */ | ||
371 | syscon = clps_readl(SYSCON(port)); | ||
372 | clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); | ||
373 | 386 | ||
374 | uart_console_write(port, c, n, uart_clps711x_console_putchar); | 387 | uart_console_write(port, c, n, uart_clps711x_console_putchar); |
375 | 388 | ||
376 | /* Wait for transmitter to become empty */ | 389 | /* Wait for transmitter to become empty */ |
377 | while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY) | 390 | do { |
378 | barrier(); | 391 | regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); |
379 | 392 | } while (sysflg & SYSFLG_UBUSY); | |
380 | /* Restore the uart state */ | ||
381 | clps_writel(syscon, SYSCON(port)); | ||
382 | } | 393 | } |
383 | 394 | ||
384 | static void uart_clps711x_console_get_options(struct uart_port *port, | 395 | static int uart_clps711x_console_setup(struct console *co, char *options) |
385 | int *baud, int *parity, | ||
386 | int *bits) | ||
387 | { | 396 | { |
388 | if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) { | 397 | int baud = 38400, bits = 8, parity = 'n', flow = 'n'; |
389 | unsigned int ubrlcr, quot; | 398 | int ret, index = co->index; |
399 | struct clps711x_port *s; | ||
400 | struct uart_port *port; | ||
401 | unsigned int quot; | ||
402 | u32 ubrlcr; | ||
390 | 403 | ||
391 | ubrlcr = clps_readl(UBRLCR(port)); | 404 | if (index < 0 || index >= UART_CLPS711X_NR) |
405 | return -EINVAL; | ||
392 | 406 | ||
393 | *parity = 'n'; | 407 | port = clps711x_uart.state[index].uart_port; |
394 | if (ubrlcr & UBRLCR_PRTEN) { | 408 | if (!port) |
395 | if (ubrlcr & UBRLCR_EVENPRT) | 409 | return -ENODEV; |
396 | *parity = 'e'; | ||
397 | else | ||
398 | *parity = 'o'; | ||
399 | } | ||
400 | 410 | ||
401 | if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7) | 411 | s = dev_get_drvdata(port->dev); |
402 | *bits = 7; | ||
403 | else | ||
404 | *bits = 8; | ||
405 | 412 | ||
406 | quot = ubrlcr & UBRLCR_BAUD_MASK; | 413 | if (!options) { |
407 | *baud = port->uartclk / (16 * (quot + 1)); | 414 | u32 syscon = 0; |
408 | } | ||
409 | } | ||
410 | 415 | ||
411 | static int uart_clps711x_console_setup(struct console *co, char *options) | 416 | regmap_read(s->syscon, SYSCON_OFFSET, &syscon); |
412 | { | 417 | if (syscon & SYSCON_UARTEN) { |
413 | int baud = 38400, bits = 8, parity = 'n', flow = 'n'; | 418 | ubrlcr = readl(port->membase + UBRLCR_OFFSET); |
414 | struct clps711x_port *s = (struct clps711x_port *)co->data; | 419 | |
415 | struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0]; | 420 | if (ubrlcr & UBRLCR_PRTEN) { |
421 | if (ubrlcr & UBRLCR_EVENPRT) | ||
422 | parity = 'e'; | ||
423 | else | ||
424 | parity = 'o'; | ||
425 | } | ||
426 | |||
427 | if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7) | ||
428 | bits = 7; | ||
416 | 429 | ||
417 | if (options) | 430 | quot = ubrlcr & UBRLCR_BAUD_MASK; |
431 | baud = port->uartclk / (16 * (quot + 1)); | ||
432 | } | ||
433 | } else | ||
418 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 434 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
419 | else | ||
420 | uart_clps711x_console_get_options(port, &baud, &parity, &bits); | ||
421 | 435 | ||
422 | return uart_set_options(port, co, baud, parity, bits, flow); | 436 | ret = uart_set_options(port, co, baud, parity, bits, flow); |
437 | if (ret) | ||
438 | return ret; | ||
439 | |||
440 | return regmap_update_bits(s->syscon, SYSCON_OFFSET, | ||
441 | SYSCON_UARTEN, SYSCON_UARTEN); | ||
423 | } | 442 | } |
443 | |||
444 | static struct console clps711x_console = { | ||
445 | .name = UART_CLPS711X_DEVNAME, | ||
446 | .device = uart_console_device, | ||
447 | .write = uart_clps711x_console_write, | ||
448 | .setup = uart_clps711x_console_setup, | ||
449 | .flags = CON_PRINTBUFFER, | ||
450 | .index = -1, | ||
451 | }; | ||
424 | #endif | 452 | #endif |
425 | 453 | ||
426 | static int uart_clps711x_probe(struct platform_device *pdev) | 454 | static int uart_clps711x_probe(struct platform_device *pdev) |
427 | { | 455 | { |
456 | struct device_node *np = pdev->dev.of_node; | ||
457 | int ret, index = np ? of_alias_get_id(np, "serial") : pdev->id; | ||
428 | struct clps711x_port *s; | 458 | struct clps711x_port *s; |
429 | int ret, i; | 459 | struct resource *res; |
460 | struct clk *uart_clk; | ||
430 | 461 | ||
431 | s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL); | 462 | if (index < 0 || index >= UART_CLPS711X_NR) |
432 | if (!s) { | 463 | return -EINVAL; |
433 | dev_err(&pdev->dev, "Error allocating port structure\n"); | 464 | |
465 | s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); | ||
466 | if (!s) | ||
434 | return -ENOMEM; | 467 | return -ENOMEM; |
468 | |||
469 | uart_clk = devm_clk_get(&pdev->dev, NULL); | ||
470 | if (IS_ERR(uart_clk)) | ||
471 | return PTR_ERR(uart_clk); | ||
472 | |||
473 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
474 | s->port.membase = devm_ioremap_resource(&pdev->dev, res); | ||
475 | if (IS_ERR(s->port.membase)) | ||
476 | return PTR_ERR(s->port.membase); | ||
477 | |||
478 | s->port.irq = platform_get_irq(pdev, 0); | ||
479 | if (IS_ERR_VALUE(s->port.irq)) | ||
480 | return s->port.irq; | ||
481 | |||
482 | s->rx_irq = platform_get_irq(pdev, 1); | ||
483 | if (IS_ERR_VALUE(s->rx_irq)) | ||
484 | return s->rx_irq; | ||
485 | |||
486 | if (!np) { | ||
487 | char syscon_name[9]; | ||
488 | |||
489 | sprintf(syscon_name, "syscon.%i", index + 1); | ||
490 | s->syscon = syscon_regmap_lookup_by_pdevname(syscon_name); | ||
491 | if (IS_ERR(s->syscon)) | ||
492 | return PTR_ERR(s->syscon); | ||
493 | |||
494 | s->use_ms = !index; | ||
495 | } else { | ||
496 | s->syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); | ||
497 | if (IS_ERR(s->syscon)) | ||
498 | return PTR_ERR(s->syscon); | ||
499 | |||
500 | if (!index) | ||
501 | s->use_ms = of_property_read_bool(np, "uart-use-ms"); | ||
435 | } | 502 | } |
503 | |||
504 | s->port.line = index; | ||
505 | s->port.dev = &pdev->dev; | ||
506 | s->port.iotype = UPIO_MEM32; | ||
507 | s->port.mapbase = res->start; | ||
508 | s->port.type = PORT_CLPS711X; | ||
509 | s->port.fifosize = 16; | ||
510 | s->port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; | ||
511 | s->port.uartclk = clk_get_rate(uart_clk); | ||
512 | s->port.ops = &uart_clps711x_ops; | ||
513 | |||
436 | platform_set_drvdata(pdev, s); | 514 | platform_set_drvdata(pdev, s); |
437 | 515 | ||
438 | s->uart_clk = devm_clk_get(&pdev->dev, "uart"); | 516 | ret = uart_add_one_port(&clps711x_uart, &s->port); |
439 | if (IS_ERR(s->uart_clk)) { | 517 | if (ret) |
440 | dev_err(&pdev->dev, "Can't get UART clocks\n"); | 518 | return ret; |
441 | return PTR_ERR(s->uart_clk); | ||
442 | } | ||
443 | 519 | ||
444 | s->uart.owner = THIS_MODULE; | 520 | /* Disable port */ |
445 | s->uart.dev_name = "ttyCL"; | 521 | if (!uart_console(&s->port)) |
446 | s->uart.major = UART_CLPS711X_MAJOR; | 522 | regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON_UARTEN, 0); |
447 | s->uart.minor = UART_CLPS711X_MINOR; | 523 | |
448 | s->uart.nr = UART_CLPS711X_NR; | 524 | s->tx_enabled = 1; |
449 | #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE | 525 | |
450 | s->uart.cons = &s->console; | 526 | ret = devm_request_irq(&pdev->dev, s->port.irq, uart_clps711x_int_tx, 0, |
451 | s->uart.cons->device = uart_console_device; | 527 | dev_name(&pdev->dev), &s->port); |
452 | s->uart.cons->write = uart_clps711x_console_write; | ||
453 | s->uart.cons->setup = uart_clps711x_console_setup; | ||
454 | s->uart.cons->flags = CON_PRINTBUFFER; | ||
455 | s->uart.cons->index = -1; | ||
456 | s->uart.cons->data = s; | ||
457 | strcpy(s->uart.cons->name, "ttyCL"); | ||
458 | #endif | ||
459 | ret = uart_register_driver(&s->uart); | ||
460 | if (ret) { | 528 | if (ret) { |
461 | dev_err(&pdev->dev, "Registering UART driver failed\n"); | 529 | uart_remove_one_port(&clps711x_uart, &s->port); |
462 | return ret; | 530 | return ret; |
463 | } | 531 | } |
464 | 532 | ||
465 | for (i = 0; i < UART_CLPS711X_NR; i++) { | 533 | ret = devm_request_irq(&pdev->dev, s->rx_irq, uart_clps711x_int_rx, 0, |
466 | s->port[i].line = i; | 534 | dev_name(&pdev->dev), &s->port); |
467 | s->port[i].dev = &pdev->dev; | 535 | if (ret) |
468 | s->port[i].irq = TX_IRQ(&s->port[i]); | 536 | uart_remove_one_port(&clps711x_uart, &s->port); |
469 | s->port[i].iobase = SYSCON(&s->port[i]); | ||
470 | s->port[i].type = PORT_CLPS711X; | ||
471 | s->port[i].fifosize = 16; | ||
472 | s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; | ||
473 | s->port[i].uartclk = clk_get_rate(s->uart_clk); | ||
474 | s->port[i].ops = &uart_clps711x_ops; | ||
475 | WARN_ON(uart_add_one_port(&s->uart, &s->port[i])); | ||
476 | } | ||
477 | 537 | ||
478 | return 0; | 538 | return ret; |
479 | } | 539 | } |
480 | 540 | ||
481 | static int uart_clps711x_remove(struct platform_device *pdev) | 541 | static int uart_clps711x_remove(struct platform_device *pdev) |
482 | { | 542 | { |
483 | struct clps711x_port *s = platform_get_drvdata(pdev); | 543 | struct clps711x_port *s = platform_get_drvdata(pdev); |
484 | int i; | ||
485 | 544 | ||
486 | for (i = 0; i < UART_CLPS711X_NR; i++) | 545 | return uart_remove_one_port(&clps711x_uart, &s->port); |
487 | uart_remove_one_port(&s->uart, &s->port[i]); | ||
488 | |||
489 | uart_unregister_driver(&s->uart); | ||
490 | |||
491 | return 0; | ||
492 | } | 546 | } |
493 | 547 | ||
494 | static struct platform_driver clps711x_uart_driver = { | 548 | static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = { |
549 | { .compatible = "cirrus,clps711x-uart", }, | ||
550 | { } | ||
551 | }; | ||
552 | MODULE_DEVICE_TABLE(of, clps711x_uart_dt_ids); | ||
553 | |||
554 | static struct platform_driver clps711x_uart_platform = { | ||
495 | .driver = { | 555 | .driver = { |
496 | .name = UART_CLPS711X_NAME, | 556 | .name = "clps711x-uart", |
497 | .owner = THIS_MODULE, | 557 | .owner = THIS_MODULE, |
558 | .of_match_table = of_match_ptr(clps711x_uart_dt_ids), | ||
498 | }, | 559 | }, |
499 | .probe = uart_clps711x_probe, | 560 | .probe = uart_clps711x_probe, |
500 | .remove = uart_clps711x_remove, | 561 | .remove = uart_clps711x_remove, |
501 | }; | 562 | }; |
502 | module_platform_driver(clps711x_uart_driver); | ||
503 | |||
504 | static struct platform_device clps711x_uart_device = { | ||
505 | .name = UART_CLPS711X_NAME, | ||
506 | }; | ||
507 | 563 | ||
508 | static int __init uart_clps711x_init(void) | 564 | static int __init uart_clps711x_init(void) |
509 | { | 565 | { |
510 | return platform_device_register(&clps711x_uart_device); | 566 | int ret; |
567 | |||
568 | #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE | ||
569 | clps711x_uart.cons = &clps711x_console; | ||
570 | clps711x_console.data = &clps711x_uart; | ||
571 | #endif | ||
572 | |||
573 | ret = uart_register_driver(&clps711x_uart); | ||
574 | if (ret) | ||
575 | return ret; | ||
576 | |||
577 | return platform_driver_register(&clps711x_uart_platform); | ||
511 | } | 578 | } |
512 | module_init(uart_clps711x_init); | 579 | module_init(uart_clps711x_init); |
513 | 580 | ||
514 | static void __exit uart_clps711x_exit(void) | 581 | static void __exit uart_clps711x_exit(void) |
515 | { | 582 | { |
516 | platform_device_unregister(&clps711x_uart_device); | 583 | platform_driver_unregister(&clps711x_uart_platform); |
584 | uart_unregister_driver(&clps711x_uart); | ||
517 | } | 585 | } |
518 | module_exit(uart_clps711x_exit); | 586 | module_exit(uart_clps711x_exit); |
519 | 587 | ||
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c index 527a969b0952..6d3b22e93246 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
30 | #include <linux/gfp.h> | 30 | #include <linux/gfp.h> |
31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
32 | #include <linux/init.h> | ||
33 | #include <linux/serial.h> | 32 | #include <linux/serial.h> |
34 | #include <linux/console.h> | 33 | #include <linux/console.h> |
35 | #include <linux/sysrq.h> | 34 | #include <linux/sysrq.h> |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c index a4927e66e741..f46d2ca87209 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
30 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/init.h> | ||
33 | #include <linux/serial.h> | 32 | #include <linux/serial.h> |
34 | #include <linux/console.h> | 33 | #include <linux/console.h> |
35 | #include <linux/sysrq.h> | 34 | #include <linux/sysrq.h> |
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index b2cfdb661947..d799140e53b6 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -806,6 +806,9 @@ static unsigned int imx_get_mctrl(struct uart_port *port) | |||
806 | if (readl(sport->port.membase + UCR2) & UCR2_CTS) | 806 | if (readl(sport->port.membase + UCR2) & UCR2_CTS) |
807 | tmp |= TIOCM_RTS; | 807 | tmp |= TIOCM_RTS; |
808 | 808 | ||
809 | if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP) | ||
810 | tmp |= TIOCM_LOOP; | ||
811 | |||
809 | return tmp; | 812 | return tmp; |
810 | } | 813 | } |
811 | 814 | ||
@@ -821,6 +824,11 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
821 | temp |= UCR2_CTS; | 824 | temp |= UCR2_CTS; |
822 | 825 | ||
823 | writel(temp, sport->port.membase + UCR2); | 826 | writel(temp, sport->port.membase + UCR2); |
827 | |||
828 | temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP; | ||
829 | if (mctrl & TIOCM_LOOP) | ||
830 | temp |= UTS_LOOP; | ||
831 | writel(temp, sport->port.membase + uts_reg(sport)); | ||
824 | } | 832 | } |
825 | 833 | ||
826 | /* | 834 | /* |
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c index 5dafcf1c227b..5f673b7ca50e 100644 --- a/drivers/tty/serial/kgdb_nmi.c +++ b/drivers/tty/serial/kgdb_nmi.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <linux/init.h> | ||
19 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
20 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
21 | #include <linux/atomic.h> | 20 | #include <linux/atomic.h> |
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index d8b6fee77a03..aa97fd845b4d 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c | |||
@@ -734,9 +734,12 @@ static void mxs_auart_reset(struct uart_port *u) | |||
734 | 734 | ||
735 | static int mxs_auart_startup(struct uart_port *u) | 735 | static int mxs_auart_startup(struct uart_port *u) |
736 | { | 736 | { |
737 | int ret; | ||
737 | struct mxs_auart_port *s = to_auart_port(u); | 738 | struct mxs_auart_port *s = to_auart_port(u); |
738 | 739 | ||
739 | clk_prepare_enable(s->clk); | 740 | ret = clk_prepare_enable(s->clk); |
741 | if (ret) | ||
742 | return ret; | ||
740 | 743 | ||
741 | writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); | 744 | writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); |
742 | 745 | ||
@@ -957,7 +960,9 @@ auart_console_setup(struct console *co, char *options) | |||
957 | if (!s) | 960 | if (!s) |
958 | return -ENODEV; | 961 | return -ENODEV; |
959 | 962 | ||
960 | clk_prepare_enable(s->clk); | 963 | ret = clk_prepare_enable(s->clk); |
964 | if (ret) | ||
965 | return ret; | ||
961 | 966 | ||
962 | if (options) | 967 | if (options) |
963 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 968 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 2caf9c6f6149..99246606a256 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | 12 | #include <linux/module.h> |
14 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 0aa2b528ef3d..9cbd3acaf37f 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -1853,7 +1853,6 @@ static void pch_uart_exit_port(struct eg20t_port *priv) | |||
1853 | debugfs_remove(priv->debugfs); | 1853 | debugfs_remove(priv->debugfs); |
1854 | #endif | 1854 | #endif |
1855 | uart_remove_one_port(&pch_uart_driver, &priv->port); | 1855 | uart_remove_one_port(&pch_uart_driver, &priv->port); |
1856 | pci_set_drvdata(priv->pdev, NULL); | ||
1857 | free_page((unsigned long)priv->rxbuf.buf); | 1856 | free_page((unsigned long)priv->rxbuf.buf); |
1858 | } | 1857 | } |
1859 | 1858 | ||
@@ -1907,7 +1906,7 @@ static int pch_uart_pci_resume(struct pci_dev *pdev) | |||
1907 | #define pch_uart_pci_resume NULL | 1906 | #define pch_uart_pci_resume NULL |
1908 | #endif | 1907 | #endif |
1909 | 1908 | ||
1910 | static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { | 1909 | static const struct pci_device_id pch_uart_pci_id[] = { |
1911 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), | 1910 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), |
1912 | .driver_data = pch_et20t_uart0}, | 1911 | .driver_data = pch_et20t_uart0}, |
1913 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812), | 1912 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812), |
diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c index 328d6deb6b08..056f91b3a4ca 100644 --- a/drivers/tty/serial/rp2.c +++ b/drivers/tty/serial/rp2.c | |||
@@ -810,7 +810,7 @@ static void rp2_remove(struct pci_dev *pdev) | |||
810 | rp2_remove_ports(card); | 810 | rp2_remove_ports(card); |
811 | } | 811 | } |
812 | 812 | ||
813 | static DEFINE_PCI_DEVICE_TABLE(rp2_pci_tbl) = { | 813 | static const struct pci_device_id rp2_pci_tbl[] = { |
814 | 814 | ||
815 | /* RocketPort INFINITY cards */ | 815 | /* RocketPort INFINITY cards */ |
816 | 816 | ||
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c deleted file mode 100644 index 887b4f770749..000000000000 --- a/drivers/tty/serial/sc26xx.c +++ /dev/null | |||
@@ -1,749 +0,0 @@ | |||
1 | /* | ||
2 | * SC268xx.c: Serial driver for Philiphs SC2681/SC2692 devices. | ||
3 | * | ||
4 | * Copyright (C) 2006,2007 Thomas Bogendörfer (tsbogend@alpha.franken.de) | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/tty.h> | ||
11 | #include <linux/tty_flip.h> | ||
12 | #include <linux/major.h> | ||
13 | #include <linux/circ_buf.h> | ||
14 | #include <linux/serial.h> | ||
15 | #include <linux/sysrq.h> | ||
16 | #include <linux/console.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/io.h> | ||
24 | |||
25 | #warning "Please try migrate to use new driver SCCNXP and report the status" \ | ||
26 | "in the linux-serial mailing list." | ||
27 | |||
28 | #if defined(CONFIG_MAGIC_SYSRQ) | ||
29 | #define SUPPORT_SYSRQ | ||
30 | #endif | ||
31 | |||
32 | #include <linux/serial_core.h> | ||
33 | |||
34 | #define SC26XX_MAJOR 204 | ||
35 | #define SC26XX_MINOR_START 205 | ||
36 | #define SC26XX_NR 2 | ||
37 | |||
38 | struct uart_sc26xx_port { | ||
39 | struct uart_port port[2]; | ||
40 | u8 dsr_mask[2]; | ||
41 | u8 cts_mask[2]; | ||
42 | u8 dcd_mask[2]; | ||
43 | u8 ri_mask[2]; | ||
44 | u8 dtr_mask[2]; | ||
45 | u8 rts_mask[2]; | ||
46 | u8 imr; | ||
47 | }; | ||
48 | |||
49 | /* register common to both ports */ | ||
50 | #define RD_ISR 0x14 | ||
51 | #define RD_IPR 0x34 | ||
52 | |||
53 | #define WR_ACR 0x10 | ||
54 | #define WR_IMR 0x14 | ||
55 | #define WR_OPCR 0x34 | ||
56 | #define WR_OPR_SET 0x38 | ||
57 | #define WR_OPR_CLR 0x3C | ||
58 | |||
59 | /* access common register */ | ||
60 | #define READ_SC(p, r) readb((p)->membase + RD_##r) | ||
61 | #define WRITE_SC(p, r, v) writeb((v), (p)->membase + WR_##r) | ||
62 | |||
63 | /* register per port */ | ||
64 | #define RD_PORT_MRx 0x00 | ||
65 | #define RD_PORT_SR 0x04 | ||
66 | #define RD_PORT_RHR 0x0c | ||
67 | |||
68 | #define WR_PORT_MRx 0x00 | ||
69 | #define WR_PORT_CSR 0x04 | ||
70 | #define WR_PORT_CR 0x08 | ||
71 | #define WR_PORT_THR 0x0c | ||
72 | |||
73 | /* SR bits */ | ||
74 | #define SR_BREAK (1 << 7) | ||
75 | #define SR_FRAME (1 << 6) | ||
76 | #define SR_PARITY (1 << 5) | ||
77 | #define SR_OVERRUN (1 << 4) | ||
78 | #define SR_TXRDY (1 << 2) | ||
79 | #define SR_RXRDY (1 << 0) | ||
80 | |||
81 | #define CR_RES_MR (1 << 4) | ||
82 | #define CR_RES_RX (2 << 4) | ||
83 | #define CR_RES_TX (3 << 4) | ||
84 | #define CR_STRT_BRK (6 << 4) | ||
85 | #define CR_STOP_BRK (7 << 4) | ||
86 | #define CR_DIS_TX (1 << 3) | ||
87 | #define CR_ENA_TX (1 << 2) | ||
88 | #define CR_DIS_RX (1 << 1) | ||
89 | #define CR_ENA_RX (1 << 0) | ||
90 | |||
91 | /* ISR bits */ | ||
92 | #define ISR_RXRDYB (1 << 5) | ||
93 | #define ISR_TXRDYB (1 << 4) | ||
94 | #define ISR_RXRDYA (1 << 1) | ||
95 | #define ISR_TXRDYA (1 << 0) | ||
96 | |||
97 | /* IMR bits */ | ||
98 | #define IMR_RXRDY (1 << 1) | ||
99 | #define IMR_TXRDY (1 << 0) | ||
100 | |||
101 | /* access port register */ | ||
102 | static inline u8 read_sc_port(struct uart_port *p, u8 reg) | ||
103 | { | ||
104 | return readb(p->membase + p->line * 0x20 + reg); | ||
105 | } | ||
106 | |||
107 | static inline void write_sc_port(struct uart_port *p, u8 reg, u8 val) | ||
108 | { | ||
109 | writeb(val, p->membase + p->line * 0x20 + reg); | ||
110 | } | ||
111 | |||
112 | #define READ_SC_PORT(p, r) read_sc_port(p, RD_PORT_##r) | ||
113 | #define WRITE_SC_PORT(p, r, v) write_sc_port(p, WR_PORT_##r, v) | ||
114 | |||
115 | static void sc26xx_enable_irq(struct uart_port *port, int mask) | ||
116 | { | ||
117 | struct uart_sc26xx_port *up; | ||
118 | int line = port->line; | ||
119 | |||
120 | port -= line; | ||
121 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
122 | |||
123 | up->imr |= mask << (line * 4); | ||
124 | WRITE_SC(port, IMR, up->imr); | ||
125 | } | ||
126 | |||
127 | static void sc26xx_disable_irq(struct uart_port *port, int mask) | ||
128 | { | ||
129 | struct uart_sc26xx_port *up; | ||
130 | int line = port->line; | ||
131 | |||
132 | port -= line; | ||
133 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
134 | |||
135 | up->imr &= ~(mask << (line * 4)); | ||
136 | WRITE_SC(port, IMR, up->imr); | ||
137 | } | ||
138 | |||
139 | static bool receive_chars(struct uart_port *port) | ||
140 | { | ||
141 | struct tty_port *tport = NULL; | ||
142 | int limit = 10000; | ||
143 | unsigned char ch; | ||
144 | char flag; | ||
145 | u8 status; | ||
146 | |||
147 | /* FIXME what is this trying to achieve? */ | ||
148 | if (port->state != NULL) /* Unopened serial console */ | ||
149 | tport = &port->state->port; | ||
150 | |||
151 | while (limit-- > 0) { | ||
152 | status = READ_SC_PORT(port, SR); | ||
153 | if (!(status & SR_RXRDY)) | ||
154 | break; | ||
155 | ch = READ_SC_PORT(port, RHR); | ||
156 | |||
157 | flag = TTY_NORMAL; | ||
158 | port->icount.rx++; | ||
159 | |||
160 | if (unlikely(status & (SR_BREAK | SR_FRAME | | ||
161 | SR_PARITY | SR_OVERRUN))) { | ||
162 | if (status & SR_BREAK) { | ||
163 | status &= ~(SR_PARITY | SR_FRAME); | ||
164 | port->icount.brk++; | ||
165 | if (uart_handle_break(port)) | ||
166 | continue; | ||
167 | } else if (status & SR_PARITY) | ||
168 | port->icount.parity++; | ||
169 | else if (status & SR_FRAME) | ||
170 | port->icount.frame++; | ||
171 | if (status & SR_OVERRUN) | ||
172 | port->icount.overrun++; | ||
173 | |||
174 | status &= port->read_status_mask; | ||
175 | if (status & SR_BREAK) | ||
176 | flag = TTY_BREAK; | ||
177 | else if (status & SR_PARITY) | ||
178 | flag = TTY_PARITY; | ||
179 | else if (status & SR_FRAME) | ||
180 | flag = TTY_FRAME; | ||
181 | } | ||
182 | |||
183 | if (uart_handle_sysrq_char(port, ch)) | ||
184 | continue; | ||
185 | |||
186 | if (status & port->ignore_status_mask) | ||
187 | continue; | ||
188 | |||
189 | tty_insert_flip_char(tport, ch, flag); | ||
190 | } | ||
191 | return !!tport; | ||
192 | } | ||
193 | |||
194 | static void transmit_chars(struct uart_port *port) | ||
195 | { | ||
196 | struct circ_buf *xmit; | ||
197 | |||
198 | if (!port->state) | ||
199 | return; | ||
200 | |||
201 | xmit = &port->state->xmit; | ||
202 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
203 | sc26xx_disable_irq(port, IMR_TXRDY); | ||
204 | return; | ||
205 | } | ||
206 | while (!uart_circ_empty(xmit)) { | ||
207 | if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) | ||
208 | break; | ||
209 | |||
210 | WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); | ||
211 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
212 | port->icount.tx++; | ||
213 | } | ||
214 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
215 | uart_write_wakeup(port); | ||
216 | } | ||
217 | |||
218 | static irqreturn_t sc26xx_interrupt(int irq, void *dev_id) | ||
219 | { | ||
220 | struct uart_sc26xx_port *up = dev_id; | ||
221 | unsigned long flags; | ||
222 | bool push; | ||
223 | u8 isr; | ||
224 | |||
225 | spin_lock_irqsave(&up->port[0].lock, flags); | ||
226 | |||
227 | push = false; | ||
228 | isr = READ_SC(&up->port[0], ISR); | ||
229 | if (isr & ISR_TXRDYA) | ||
230 | transmit_chars(&up->port[0]); | ||
231 | if (isr & ISR_RXRDYA) | ||
232 | push = receive_chars(&up->port[0]); | ||
233 | |||
234 | spin_unlock(&up->port[0].lock); | ||
235 | |||
236 | if (push) | ||
237 | tty_flip_buffer_push(&up->port[0].state->port); | ||
238 | |||
239 | spin_lock(&up->port[1].lock); | ||
240 | |||
241 | push = false; | ||
242 | if (isr & ISR_TXRDYB) | ||
243 | transmit_chars(&up->port[1]); | ||
244 | if (isr & ISR_RXRDYB) | ||
245 | push = receive_chars(&up->port[1]); | ||
246 | |||
247 | spin_unlock_irqrestore(&up->port[1].lock, flags); | ||
248 | |||
249 | if (push) | ||
250 | tty_flip_buffer_push(&up->port[1].state->port); | ||
251 | |||
252 | return IRQ_HANDLED; | ||
253 | } | ||
254 | |||
255 | /* port->lock is not held. */ | ||
256 | static unsigned int sc26xx_tx_empty(struct uart_port *port) | ||
257 | { | ||
258 | return (READ_SC_PORT(port, SR) & SR_TXRDY) ? TIOCSER_TEMT : 0; | ||
259 | } | ||
260 | |||
261 | /* port->lock held by caller. */ | ||
262 | static void sc26xx_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
263 | { | ||
264 | struct uart_sc26xx_port *up; | ||
265 | int line = port->line; | ||
266 | |||
267 | port -= line; | ||
268 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
269 | |||
270 | if (up->dtr_mask[line]) { | ||
271 | if (mctrl & TIOCM_DTR) | ||
272 | WRITE_SC(port, OPR_SET, up->dtr_mask[line]); | ||
273 | else | ||
274 | WRITE_SC(port, OPR_CLR, up->dtr_mask[line]); | ||
275 | } | ||
276 | if (up->rts_mask[line]) { | ||
277 | if (mctrl & TIOCM_RTS) | ||
278 | WRITE_SC(port, OPR_SET, up->rts_mask[line]); | ||
279 | else | ||
280 | WRITE_SC(port, OPR_CLR, up->rts_mask[line]); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | /* port->lock is held by caller and interrupts are disabled. */ | ||
285 | static unsigned int sc26xx_get_mctrl(struct uart_port *port) | ||
286 | { | ||
287 | struct uart_sc26xx_port *up; | ||
288 | int line = port->line; | ||
289 | unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; | ||
290 | u8 ipr; | ||
291 | |||
292 | port -= line; | ||
293 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
294 | ipr = READ_SC(port, IPR) ^ 0xff; | ||
295 | |||
296 | if (up->dsr_mask[line]) { | ||
297 | mctrl &= ~TIOCM_DSR; | ||
298 | mctrl |= ipr & up->dsr_mask[line] ? TIOCM_DSR : 0; | ||
299 | } | ||
300 | if (up->cts_mask[line]) { | ||
301 | mctrl &= ~TIOCM_CTS; | ||
302 | mctrl |= ipr & up->cts_mask[line] ? TIOCM_CTS : 0; | ||
303 | } | ||
304 | if (up->dcd_mask[line]) { | ||
305 | mctrl &= ~TIOCM_CAR; | ||
306 | mctrl |= ipr & up->dcd_mask[line] ? TIOCM_CAR : 0; | ||
307 | } | ||
308 | if (up->ri_mask[line]) { | ||
309 | mctrl &= ~TIOCM_RNG; | ||
310 | mctrl |= ipr & up->ri_mask[line] ? TIOCM_RNG : 0; | ||
311 | } | ||
312 | return mctrl; | ||
313 | } | ||
314 | |||
315 | /* port->lock held by caller. */ | ||
316 | static void sc26xx_stop_tx(struct uart_port *port) | ||
317 | { | ||
318 | return; | ||
319 | } | ||
320 | |||
321 | /* port->lock held by caller. */ | ||
322 | static void sc26xx_start_tx(struct uart_port *port) | ||
323 | { | ||
324 | struct circ_buf *xmit = &port->state->xmit; | ||
325 | |||
326 | while (!uart_circ_empty(xmit)) { | ||
327 | if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) { | ||
328 | sc26xx_enable_irq(port, IMR_TXRDY); | ||
329 | break; | ||
330 | } | ||
331 | WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); | ||
332 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
333 | port->icount.tx++; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | /* port->lock held by caller. */ | ||
338 | static void sc26xx_stop_rx(struct uart_port *port) | ||
339 | { | ||
340 | } | ||
341 | |||
342 | /* port->lock held by caller. */ | ||
343 | static void sc26xx_enable_ms(struct uart_port *port) | ||
344 | { | ||
345 | } | ||
346 | |||
347 | /* port->lock is not held. */ | ||
348 | static void sc26xx_break_ctl(struct uart_port *port, int break_state) | ||
349 | { | ||
350 | if (break_state == -1) | ||
351 | WRITE_SC_PORT(port, CR, CR_STRT_BRK); | ||
352 | else | ||
353 | WRITE_SC_PORT(port, CR, CR_STOP_BRK); | ||
354 | } | ||
355 | |||
356 | /* port->lock is not held. */ | ||
357 | static int sc26xx_startup(struct uart_port *port) | ||
358 | { | ||
359 | sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY); | ||
360 | WRITE_SC(port, OPCR, 0); | ||
361 | |||
362 | /* reset tx and rx */ | ||
363 | WRITE_SC_PORT(port, CR, CR_RES_RX); | ||
364 | WRITE_SC_PORT(port, CR, CR_RES_TX); | ||
365 | |||
366 | /* start rx/tx */ | ||
367 | WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); | ||
368 | |||
369 | /* enable irqs */ | ||
370 | sc26xx_enable_irq(port, IMR_RXRDY); | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | /* port->lock is not held. */ | ||
375 | static void sc26xx_shutdown(struct uart_port *port) | ||
376 | { | ||
377 | /* disable interrupst */ | ||
378 | sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY); | ||
379 | |||
380 | /* stop tx/rx */ | ||
381 | WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); | ||
382 | } | ||
383 | |||
384 | /* port->lock is not held. */ | ||
385 | static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios, | ||
386 | struct ktermios *old) | ||
387 | { | ||
388 | unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); | ||
389 | unsigned int quot = uart_get_divisor(port, baud); | ||
390 | unsigned int iflag, cflag; | ||
391 | unsigned long flags; | ||
392 | u8 mr1, mr2, csr; | ||
393 | |||
394 | spin_lock_irqsave(&port->lock, flags); | ||
395 | |||
396 | while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) | ||
397 | udelay(2); | ||
398 | |||
399 | WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); | ||
400 | |||
401 | iflag = termios->c_iflag; | ||
402 | cflag = termios->c_cflag; | ||
403 | |||
404 | port->read_status_mask = SR_OVERRUN; | ||
405 | if (iflag & INPCK) | ||
406 | port->read_status_mask |= SR_PARITY | SR_FRAME; | ||
407 | if (iflag & (BRKINT | PARMRK)) | ||
408 | port->read_status_mask |= SR_BREAK; | ||
409 | |||
410 | port->ignore_status_mask = 0; | ||
411 | if (iflag & IGNBRK) | ||
412 | port->ignore_status_mask |= SR_BREAK; | ||
413 | if ((cflag & CREAD) == 0) | ||
414 | port->ignore_status_mask |= SR_BREAK | SR_FRAME | | ||
415 | SR_PARITY | SR_OVERRUN; | ||
416 | |||
417 | switch (cflag & CSIZE) { | ||
418 | case CS5: | ||
419 | mr1 = 0x00; | ||
420 | break; | ||
421 | case CS6: | ||
422 | mr1 = 0x01; | ||
423 | break; | ||
424 | case CS7: | ||
425 | mr1 = 0x02; | ||
426 | break; | ||
427 | default: | ||
428 | case CS8: | ||
429 | mr1 = 0x03; | ||
430 | break; | ||
431 | } | ||
432 | mr2 = 0x07; | ||
433 | if (cflag & CSTOPB) | ||
434 | mr2 = 0x0f; | ||
435 | if (cflag & PARENB) { | ||
436 | if (cflag & PARODD) | ||
437 | mr1 |= (1 << 2); | ||
438 | } else | ||
439 | mr1 |= (2 << 3); | ||
440 | |||
441 | switch (baud) { | ||
442 | case 50: | ||
443 | csr = 0x00; | ||
444 | break; | ||
445 | case 110: | ||
446 | csr = 0x11; | ||
447 | break; | ||
448 | case 134: | ||
449 | csr = 0x22; | ||
450 | break; | ||
451 | case 200: | ||
452 | csr = 0x33; | ||
453 | break; | ||
454 | case 300: | ||
455 | csr = 0x44; | ||
456 | break; | ||
457 | case 600: | ||
458 | csr = 0x55; | ||
459 | break; | ||
460 | case 1200: | ||
461 | csr = 0x66; | ||
462 | break; | ||
463 | case 2400: | ||
464 | csr = 0x88; | ||
465 | break; | ||
466 | case 4800: | ||
467 | csr = 0x99; | ||
468 | break; | ||
469 | default: | ||
470 | case 9600: | ||
471 | csr = 0xbb; | ||
472 | break; | ||
473 | case 19200: | ||
474 | csr = 0xcc; | ||
475 | break; | ||
476 | } | ||
477 | |||
478 | WRITE_SC_PORT(port, CR, CR_RES_MR); | ||
479 | WRITE_SC_PORT(port, MRx, mr1); | ||
480 | WRITE_SC_PORT(port, MRx, mr2); | ||
481 | |||
482 | WRITE_SC(port, ACR, 0x80); | ||
483 | WRITE_SC_PORT(port, CSR, csr); | ||
484 | |||
485 | /* reset tx and rx */ | ||
486 | WRITE_SC_PORT(port, CR, CR_RES_RX); | ||
487 | WRITE_SC_PORT(port, CR, CR_RES_TX); | ||
488 | |||
489 | WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); | ||
490 | while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) | ||
491 | udelay(2); | ||
492 | |||
493 | /* XXX */ | ||
494 | uart_update_timeout(port, cflag, | ||
495 | (port->uartclk / (16 * quot))); | ||
496 | |||
497 | spin_unlock_irqrestore(&port->lock, flags); | ||
498 | } | ||
499 | |||
500 | static const char *sc26xx_type(struct uart_port *port) | ||
501 | { | ||
502 | return "SC26XX"; | ||
503 | } | ||
504 | |||
505 | static void sc26xx_release_port(struct uart_port *port) | ||
506 | { | ||
507 | } | ||
508 | |||
509 | static int sc26xx_request_port(struct uart_port *port) | ||
510 | { | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static void sc26xx_config_port(struct uart_port *port, int flags) | ||
515 | { | ||
516 | } | ||
517 | |||
518 | static int sc26xx_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
519 | { | ||
520 | return -EINVAL; | ||
521 | } | ||
522 | |||
523 | static struct uart_ops sc26xx_ops = { | ||
524 | .tx_empty = sc26xx_tx_empty, | ||
525 | .set_mctrl = sc26xx_set_mctrl, | ||
526 | .get_mctrl = sc26xx_get_mctrl, | ||
527 | .stop_tx = sc26xx_stop_tx, | ||
528 | .start_tx = sc26xx_start_tx, | ||
529 | .stop_rx = sc26xx_stop_rx, | ||
530 | .enable_ms = sc26xx_enable_ms, | ||
531 | .break_ctl = sc26xx_break_ctl, | ||
532 | .startup = sc26xx_startup, | ||
533 | .shutdown = sc26xx_shutdown, | ||
534 | .set_termios = sc26xx_set_termios, | ||
535 | .type = sc26xx_type, | ||
536 | .release_port = sc26xx_release_port, | ||
537 | .request_port = sc26xx_request_port, | ||
538 | .config_port = sc26xx_config_port, | ||
539 | .verify_port = sc26xx_verify_port, | ||
540 | }; | ||
541 | |||
542 | static struct uart_port *sc26xx_port; | ||
543 | |||
544 | #ifdef CONFIG_SERIAL_SC26XX_CONSOLE | ||
545 | static void sc26xx_console_putchar(struct uart_port *port, char c) | ||
546 | { | ||
547 | unsigned long flags; | ||
548 | int limit = 1000000; | ||
549 | |||
550 | spin_lock_irqsave(&port->lock, flags); | ||
551 | |||
552 | while (limit-- > 0) { | ||
553 | if (READ_SC_PORT(port, SR) & SR_TXRDY) { | ||
554 | WRITE_SC_PORT(port, THR, c); | ||
555 | break; | ||
556 | } | ||
557 | udelay(2); | ||
558 | } | ||
559 | |||
560 | spin_unlock_irqrestore(&port->lock, flags); | ||
561 | } | ||
562 | |||
563 | static void sc26xx_console_write(struct console *con, const char *s, unsigned n) | ||
564 | { | ||
565 | struct uart_port *port = sc26xx_port; | ||
566 | int i; | ||
567 | |||
568 | for (i = 0; i < n; i++) { | ||
569 | if (*s == '\n') | ||
570 | sc26xx_console_putchar(port, '\r'); | ||
571 | sc26xx_console_putchar(port, *s++); | ||
572 | } | ||
573 | } | ||
574 | |||
575 | static int __init sc26xx_console_setup(struct console *con, char *options) | ||
576 | { | ||
577 | struct uart_port *port = sc26xx_port; | ||
578 | int baud = 9600; | ||
579 | int bits = 8; | ||
580 | int parity = 'n'; | ||
581 | int flow = 'n'; | ||
582 | |||
583 | if (port->type != PORT_SC26XX) | ||
584 | return -1; | ||
585 | |||
586 | printk(KERN_INFO "Console: ttySC%d (SC26XX)\n", con->index); | ||
587 | if (options) | ||
588 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
589 | |||
590 | return uart_set_options(port, con, baud, parity, bits, flow); | ||
591 | } | ||
592 | |||
593 | static struct uart_driver sc26xx_reg; | ||
594 | static struct console sc26xx_console = { | ||
595 | .name = "ttySC", | ||
596 | .write = sc26xx_console_write, | ||
597 | .device = uart_console_device, | ||
598 | .setup = sc26xx_console_setup, | ||
599 | .flags = CON_PRINTBUFFER, | ||
600 | .index = -1, | ||
601 | .data = &sc26xx_reg, | ||
602 | }; | ||
603 | #define SC26XX_CONSOLE &sc26xx_console | ||
604 | #else | ||
605 | #define SC26XX_CONSOLE NULL | ||
606 | #endif | ||
607 | |||
608 | static struct uart_driver sc26xx_reg = { | ||
609 | .owner = THIS_MODULE, | ||
610 | .driver_name = "SC26xx", | ||
611 | .dev_name = "ttySC", | ||
612 | .major = SC26XX_MAJOR, | ||
613 | .minor = SC26XX_MINOR_START, | ||
614 | .nr = SC26XX_NR, | ||
615 | .cons = SC26XX_CONSOLE, | ||
616 | }; | ||
617 | |||
618 | static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos) | ||
619 | { | ||
620 | unsigned int bit = (flags >> bitpos) & 15; | ||
621 | |||
622 | return bit ? (1 << (bit - 1)) : 0; | ||
623 | } | ||
624 | |||
625 | static void sc26xx_init_masks(struct uart_sc26xx_port *up, | ||
626 | int line, unsigned int data) | ||
627 | { | ||
628 | up->dtr_mask[line] = sc26xx_flags2mask(data, 0); | ||
629 | up->rts_mask[line] = sc26xx_flags2mask(data, 4); | ||
630 | up->dsr_mask[line] = sc26xx_flags2mask(data, 8); | ||
631 | up->cts_mask[line] = sc26xx_flags2mask(data, 12); | ||
632 | up->dcd_mask[line] = sc26xx_flags2mask(data, 16); | ||
633 | up->ri_mask[line] = sc26xx_flags2mask(data, 20); | ||
634 | } | ||
635 | |||
636 | static int sc26xx_probe(struct platform_device *dev) | ||
637 | { | ||
638 | struct resource *res; | ||
639 | struct uart_sc26xx_port *up; | ||
640 | unsigned int *sc26xx_data = dev_get_platdata(&dev->dev); | ||
641 | int err; | ||
642 | |||
643 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
644 | if (!res) | ||
645 | return -ENODEV; | ||
646 | |||
647 | up = kzalloc(sizeof *up, GFP_KERNEL); | ||
648 | if (unlikely(!up)) | ||
649 | return -ENOMEM; | ||
650 | |||
651 | up->port[0].line = 0; | ||
652 | up->port[0].ops = &sc26xx_ops; | ||
653 | up->port[0].type = PORT_SC26XX; | ||
654 | up->port[0].uartclk = (29491200 / 16); /* arbitrary */ | ||
655 | |||
656 | up->port[0].mapbase = res->start; | ||
657 | up->port[0].membase = ioremap_nocache(up->port[0].mapbase, 0x40); | ||
658 | up->port[0].iotype = UPIO_MEM; | ||
659 | up->port[0].irq = platform_get_irq(dev, 0); | ||
660 | |||
661 | up->port[0].dev = &dev->dev; | ||
662 | |||
663 | sc26xx_init_masks(up, 0, sc26xx_data[0]); | ||
664 | |||
665 | sc26xx_port = &up->port[0]; | ||
666 | |||
667 | up->port[1].line = 1; | ||
668 | up->port[1].ops = &sc26xx_ops; | ||
669 | up->port[1].type = PORT_SC26XX; | ||
670 | up->port[1].uartclk = (29491200 / 16); /* arbitrary */ | ||
671 | |||
672 | up->port[1].mapbase = up->port[0].mapbase; | ||
673 | up->port[1].membase = up->port[0].membase; | ||
674 | up->port[1].iotype = UPIO_MEM; | ||
675 | up->port[1].irq = up->port[0].irq; | ||
676 | |||
677 | up->port[1].dev = &dev->dev; | ||
678 | |||
679 | sc26xx_init_masks(up, 1, sc26xx_data[1]); | ||
680 | |||
681 | err = uart_register_driver(&sc26xx_reg); | ||
682 | if (err) | ||
683 | goto out_free_port; | ||
684 | |||
685 | sc26xx_reg.tty_driver->name_base = sc26xx_reg.minor; | ||
686 | |||
687 | err = uart_add_one_port(&sc26xx_reg, &up->port[0]); | ||
688 | if (err) | ||
689 | goto out_unregister_driver; | ||
690 | |||
691 | err = uart_add_one_port(&sc26xx_reg, &up->port[1]); | ||
692 | if (err) | ||
693 | goto out_remove_port0; | ||
694 | |||
695 | err = request_irq(up->port[0].irq, sc26xx_interrupt, 0, "sc26xx", up); | ||
696 | if (err) | ||
697 | goto out_remove_ports; | ||
698 | |||
699 | platform_set_drvdata(dev, up); | ||
700 | return 0; | ||
701 | |||
702 | out_remove_ports: | ||
703 | uart_remove_one_port(&sc26xx_reg, &up->port[1]); | ||
704 | out_remove_port0: | ||
705 | uart_remove_one_port(&sc26xx_reg, &up->port[0]); | ||
706 | |||
707 | out_unregister_driver: | ||
708 | uart_unregister_driver(&sc26xx_reg); | ||
709 | |||
710 | out_free_port: | ||
711 | kfree(up); | ||
712 | sc26xx_port = NULL; | ||
713 | return err; | ||
714 | } | ||
715 | |||
716 | |||
717 | static int __exit sc26xx_driver_remove(struct platform_device *dev) | ||
718 | { | ||
719 | struct uart_sc26xx_port *up = platform_get_drvdata(dev); | ||
720 | |||
721 | free_irq(up->port[0].irq, up); | ||
722 | |||
723 | uart_remove_one_port(&sc26xx_reg, &up->port[0]); | ||
724 | uart_remove_one_port(&sc26xx_reg, &up->port[1]); | ||
725 | |||
726 | uart_unregister_driver(&sc26xx_reg); | ||
727 | |||
728 | kfree(up); | ||
729 | sc26xx_port = NULL; | ||
730 | |||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static struct platform_driver sc26xx_driver = { | ||
735 | .probe = sc26xx_probe, | ||
736 | .remove = sc26xx_driver_remove, | ||
737 | .driver = { | ||
738 | .name = "SC26xx", | ||
739 | .owner = THIS_MODULE, | ||
740 | }, | ||
741 | }; | ||
742 | |||
743 | module_platform_driver(sc26xx_driver); | ||
744 | |||
745 | MODULE_AUTHOR("Thomas Bogendörfer"); | ||
746 | MODULE_DESCRIPTION("SC681/SC2692 serial driver"); | ||
747 | MODULE_VERSION("1.0"); | ||
748 | MODULE_LICENSE("GPL"); | ||
749 | MODULE_ALIAS("platform:SC26xx"); | ||
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 0f02351c9239..ece2049bd270 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -1830,9 +1830,13 @@ uart_set_options(struct uart_port *port, struct console *co, | |||
1830 | /* | 1830 | /* |
1831 | * Ensure that the serial console lock is initialised | 1831 | * Ensure that the serial console lock is initialised |
1832 | * early. | 1832 | * early. |
1833 | * If this port is a console, then the spinlock is already | ||
1834 | * initialised. | ||
1833 | */ | 1835 | */ |
1834 | spin_lock_init(&port->lock); | 1836 | if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) { |
1835 | lockdep_set_class(&port->lock, &port_lock_key); | 1837 | spin_lock_init(&port->lock); |
1838 | lockdep_set_class(&port->lock, &port_lock_key); | ||
1839 | } | ||
1836 | 1840 | ||
1837 | memset(&termios, 0, sizeof(struct ktermios)); | 1841 | memset(&termios, 0, sizeof(struct ktermios)); |
1838 | 1842 | ||
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index f186a8fb8887..49a2ffd101a7 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c | |||
@@ -524,9 +524,11 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param) | |||
524 | struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st; | 524 | struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st; |
525 | unsigned int count; | 525 | unsigned int count; |
526 | unsigned long flags; | 526 | unsigned long flags; |
527 | struct dma_tx_state tx_state; | ||
527 | 528 | ||
528 | spin_lock_irqsave(&sirfport->rx_lock, flags); | 529 | spin_lock_irqsave(&sirfport->rx_lock, flags); |
529 | while (sirfport->rx_completed != sirfport->rx_issued) { | 530 | while (DMA_COMPLETE == dmaengine_tx_status(sirfport->rx_dma_chan, |
531 | sirfport->rx_dma_items[sirfport->rx_completed].cookie, &tx_state)) { | ||
530 | sirfsoc_uart_insert_rx_buf_to_tty(sirfport, | 532 | sirfsoc_uart_insert_rx_buf_to_tty(sirfport, |
531 | SIRFSOC_RX_DMA_BUF_SIZE); | 533 | SIRFSOC_RX_DMA_BUF_SIZE); |
532 | sirfport->rx_completed++; | 534 | sirfport->rx_completed++; |
@@ -709,8 +711,10 @@ static void sirfsoc_uart_rx_dma_complete_tl(unsigned long param) | |||
709 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | 711 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; |
710 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | 712 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; |
711 | unsigned long flags; | 713 | unsigned long flags; |
714 | struct dma_tx_state tx_state; | ||
712 | spin_lock_irqsave(&sirfport->rx_lock, flags); | 715 | spin_lock_irqsave(&sirfport->rx_lock, flags); |
713 | while (sirfport->rx_completed != sirfport->rx_issued) { | 716 | while (DMA_COMPLETE == dmaengine_tx_status(sirfport->rx_dma_chan, |
717 | sirfport->rx_dma_items[sirfport->rx_completed].cookie, &tx_state)) { | ||
714 | sirfsoc_uart_insert_rx_buf_to_tty(sirfport, | 718 | sirfsoc_uart_insert_rx_buf_to_tty(sirfport, |
715 | SIRFSOC_RX_DMA_BUF_SIZE); | 719 | SIRFSOC_RX_DMA_BUF_SIZE); |
716 | if (rd_regl(port, ureg->sirfsoc_int_en_reg) & | 720 | if (rd_regl(port, ureg->sirfsoc_int_en_reg) & |
@@ -1033,6 +1037,16 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, | |||
1033 | spin_unlock_irqrestore(&port->lock, flags); | 1037 | spin_unlock_irqrestore(&port->lock, flags); |
1034 | } | 1038 | } |
1035 | 1039 | ||
1040 | static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state, | ||
1041 | unsigned int oldstate) | ||
1042 | { | ||
1043 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
1044 | if (!state) | ||
1045 | clk_prepare_enable(sirfport->clk); | ||
1046 | else | ||
1047 | clk_disable_unprepare(sirfport->clk); | ||
1048 | } | ||
1049 | |||
1036 | static unsigned int sirfsoc_uart_init_tx_dma(struct uart_port *port) | 1050 | static unsigned int sirfsoc_uart_init_tx_dma(struct uart_port *port) |
1037 | { | 1051 | { |
1038 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | 1052 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); |
@@ -1264,6 +1278,7 @@ static struct uart_ops sirfsoc_uart_ops = { | |||
1264 | .startup = sirfsoc_uart_startup, | 1278 | .startup = sirfsoc_uart_startup, |
1265 | .shutdown = sirfsoc_uart_shutdown, | 1279 | .shutdown = sirfsoc_uart_shutdown, |
1266 | .set_termios = sirfsoc_uart_set_termios, | 1280 | .set_termios = sirfsoc_uart_set_termios, |
1281 | .pm = sirfsoc_uart_pm, | ||
1267 | .type = sirfsoc_uart_type, | 1282 | .type = sirfsoc_uart_type, |
1268 | .release_port = sirfsoc_uart_release_port, | 1283 | .release_port = sirfsoc_uart_release_port, |
1269 | .request_port = sirfsoc_uart_request_port, | 1284 | .request_port = sirfsoc_uart_request_port, |
@@ -1486,7 +1501,6 @@ usp_no_flow_control: | |||
1486 | ret = PTR_ERR(sirfport->clk); | 1501 | ret = PTR_ERR(sirfport->clk); |
1487 | goto err; | 1502 | goto err; |
1488 | } | 1503 | } |
1489 | clk_prepare_enable(sirfport->clk); | ||
1490 | port->uartclk = clk_get_rate(sirfport->clk); | 1504 | port->uartclk = clk_get_rate(sirfport->clk); |
1491 | 1505 | ||
1492 | port->ops = &sirfsoc_uart_ops; | 1506 | port->ops = &sirfsoc_uart_ops; |
@@ -1502,7 +1516,6 @@ usp_no_flow_control: | |||
1502 | return 0; | 1516 | return 0; |
1503 | 1517 | ||
1504 | port_err: | 1518 | port_err: |
1505 | clk_disable_unprepare(sirfport->clk); | ||
1506 | clk_put(sirfport->clk); | 1519 | clk_put(sirfport->clk); |
1507 | err: | 1520 | err: |
1508 | return ret; | 1521 | return ret; |
@@ -1512,38 +1525,42 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) | |||
1512 | { | 1525 | { |
1513 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); | 1526 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); |
1514 | struct uart_port *port = &sirfport->port; | 1527 | struct uart_port *port = &sirfport->port; |
1515 | clk_disable_unprepare(sirfport->clk); | ||
1516 | clk_put(sirfport->clk); | 1528 | clk_put(sirfport->clk); |
1517 | uart_remove_one_port(&sirfsoc_uart_drv, port); | 1529 | uart_remove_one_port(&sirfsoc_uart_drv, port); |
1518 | return 0; | 1530 | return 0; |
1519 | } | 1531 | } |
1520 | 1532 | ||
1533 | #ifdef CONFIG_PM_SLEEP | ||
1521 | static int | 1534 | static int |
1522 | sirfsoc_uart_suspend(struct platform_device *pdev, pm_message_t state) | 1535 | sirfsoc_uart_suspend(struct device *pdev) |
1523 | { | 1536 | { |
1524 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); | 1537 | struct sirfsoc_uart_port *sirfport = dev_get_drvdata(pdev); |
1525 | struct uart_port *port = &sirfport->port; | 1538 | struct uart_port *port = &sirfport->port; |
1526 | uart_suspend_port(&sirfsoc_uart_drv, port); | 1539 | uart_suspend_port(&sirfsoc_uart_drv, port); |
1527 | return 0; | 1540 | return 0; |
1528 | } | 1541 | } |
1529 | 1542 | ||
1530 | static int sirfsoc_uart_resume(struct platform_device *pdev) | 1543 | static int sirfsoc_uart_resume(struct device *pdev) |
1531 | { | 1544 | { |
1532 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); | 1545 | struct sirfsoc_uart_port *sirfport = dev_get_drvdata(pdev); |
1533 | struct uart_port *port = &sirfport->port; | 1546 | struct uart_port *port = &sirfport->port; |
1534 | uart_resume_port(&sirfsoc_uart_drv, port); | 1547 | uart_resume_port(&sirfsoc_uart_drv, port); |
1535 | return 0; | 1548 | return 0; |
1536 | } | 1549 | } |
1550 | #endif | ||
1551 | |||
1552 | static const struct dev_pm_ops sirfsoc_uart_pm_ops = { | ||
1553 | SET_SYSTEM_SLEEP_PM_OPS(sirfsoc_uart_suspend, sirfsoc_uart_resume) | ||
1554 | }; | ||
1537 | 1555 | ||
1538 | static struct platform_driver sirfsoc_uart_driver = { | 1556 | static struct platform_driver sirfsoc_uart_driver = { |
1539 | .probe = sirfsoc_uart_probe, | 1557 | .probe = sirfsoc_uart_probe, |
1540 | .remove = sirfsoc_uart_remove, | 1558 | .remove = sirfsoc_uart_remove, |
1541 | .suspend = sirfsoc_uart_suspend, | ||
1542 | .resume = sirfsoc_uart_resume, | ||
1543 | .driver = { | 1559 | .driver = { |
1544 | .name = SIRFUART_PORT_NAME, | 1560 | .name = SIRFUART_PORT_NAME, |
1545 | .owner = THIS_MODULE, | 1561 | .owner = THIS_MODULE, |
1546 | .of_match_table = sirfsoc_uart_ids, | 1562 | .of_match_table = sirfsoc_uart_ids, |
1563 | .pm = &sirfsoc_uart_pm_ops, | ||
1547 | }, | 1564 | }, |
1548 | }; | 1565 | }; |
1549 | 1566 | ||
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index e1ce141bad5e..5ae14b46cce0 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c | |||
@@ -3404,8 +3404,8 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) | |||
3404 | 3404 | ||
3405 | /* If port is closing, signal caller to try again */ | 3405 | /* If port is closing, signal caller to try again */ |
3406 | if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ | 3406 | if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ |
3407 | if (info->port.flags & ASYNC_CLOSING) | 3407 | wait_event_interruptible_tty(tty, info->port.close_wait, |
3408 | interruptible_sleep_on(&info->port.close_wait); | 3408 | !(info->port.flags & ASYNC_CLOSING)); |
3409 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? | 3409 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? |
3410 | -EAGAIN : -ERESTARTSYS); | 3410 | -EAGAIN : -ERESTARTSYS); |
3411 | goto cleanup; | 3411 | goto cleanup; |
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 1abf946463f6..c359a91f7346 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c | |||
@@ -674,8 +674,8 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
674 | 674 | ||
675 | /* If port is closing, signal caller to try again */ | 675 | /* If port is closing, signal caller to try again */ |
676 | if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ | 676 | if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ |
677 | if (info->port.flags & ASYNC_CLOSING) | 677 | wait_event_interruptible_tty(tty, info->port.close_wait, |
678 | interruptible_sleep_on(&info->port.close_wait); | 678 | !(info->port.flags & ASYNC_CLOSING)); |
679 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? | 679 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? |
680 | -EAGAIN : -ERESTARTSYS); | 680 | -EAGAIN : -ERESTARTSYS); |
681 | goto cleanup; | 681 | goto cleanup; |
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index dc6e96996ead..144202eef6fe 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c | |||
@@ -754,8 +754,8 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
754 | 754 | ||
755 | /* If port is closing, signal caller to try again */ | 755 | /* If port is closing, signal caller to try again */ |
756 | if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ | 756 | if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ |
757 | if (info->port.flags & ASYNC_CLOSING) | 757 | wait_event_interruptible_tty(tty, info->port.close_wait, |
758 | interruptible_sleep_on(&info->port.close_wait); | 758 | !(info->port.flags & ASYNC_CLOSING)); |
759 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? | 759 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? |
760 | -EAGAIN : -ERESTARTSYS); | 760 | -EAGAIN : -ERESTARTSYS); |
761 | goto cleanup; | 761 | goto cleanup; |
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index c043136fbe51..765125dff20e 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/init.h> | ||
15 | #include <linux/wait.h> | 14 | #include <linux/wait.h> |
16 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
17 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
@@ -26,7 +25,7 @@ | |||
26 | * Byte threshold to limit memory consumption for flip buffers. | 25 | * Byte threshold to limit memory consumption for flip buffers. |
27 | * The actual memory limit is > 2x this amount. | 26 | * The actual memory limit is > 2x this amount. |
28 | */ | 27 | */ |
29 | #define TTYB_MEM_LIMIT 65536 | 28 | #define TTYB_DEFAULT_MEM_LIMIT 65536 |
30 | 29 | ||
31 | /* | 30 | /* |
32 | * We default to dicing tty buffer allocations to this many characters | 31 | * We default to dicing tty buffer allocations to this many characters |
@@ -89,9 +88,10 @@ void tty_buffer_unlock_exclusive(struct tty_port *port) | |||
89 | 88 | ||
90 | int tty_buffer_space_avail(struct tty_port *port) | 89 | int tty_buffer_space_avail(struct tty_port *port) |
91 | { | 90 | { |
92 | int space = TTYB_MEM_LIMIT - atomic_read(&port->buf.memory_used); | 91 | int space = port->buf.mem_limit - atomic_read(&port->buf.mem_used); |
93 | return max(space, 0); | 92 | return max(space, 0); |
94 | } | 93 | } |
94 | EXPORT_SYMBOL_GPL(tty_buffer_space_avail); | ||
95 | 95 | ||
96 | static void tty_buffer_reset(struct tty_buffer *p, size_t size) | 96 | static void tty_buffer_reset(struct tty_buffer *p, size_t size) |
97 | { | 97 | { |
@@ -100,6 +100,7 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size) | |||
100 | p->next = NULL; | 100 | p->next = NULL; |
101 | p->commit = 0; | 101 | p->commit = 0; |
102 | p->read = 0; | 102 | p->read = 0; |
103 | p->flags = 0; | ||
103 | } | 104 | } |
104 | 105 | ||
105 | /** | 106 | /** |
@@ -129,7 +130,7 @@ void tty_buffer_free_all(struct tty_port *port) | |||
129 | buf->head = &buf->sentinel; | 130 | buf->head = &buf->sentinel; |
130 | buf->tail = &buf->sentinel; | 131 | buf->tail = &buf->sentinel; |
131 | 132 | ||
132 | atomic_set(&buf->memory_used, 0); | 133 | atomic_set(&buf->mem_used, 0); |
133 | } | 134 | } |
134 | 135 | ||
135 | /** | 136 | /** |
@@ -162,7 +163,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) | |||
162 | 163 | ||
163 | /* Should possibly check if this fails for the largest buffer we | 164 | /* Should possibly check if this fails for the largest buffer we |
164 | have queued and recycle that ? */ | 165 | have queued and recycle that ? */ |
165 | if (atomic_read(&port->buf.memory_used) > TTYB_MEM_LIMIT) | 166 | if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit) |
166 | return NULL; | 167 | return NULL; |
167 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); | 168 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); |
168 | if (p == NULL) | 169 | if (p == NULL) |
@@ -170,7 +171,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) | |||
170 | 171 | ||
171 | found: | 172 | found: |
172 | tty_buffer_reset(p, size); | 173 | tty_buffer_reset(p, size); |
173 | atomic_add(size, &port->buf.memory_used); | 174 | atomic_add(size, &port->buf.mem_used); |
174 | return p; | 175 | return p; |
175 | } | 176 | } |
176 | 177 | ||
@@ -188,7 +189,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) | |||
188 | struct tty_bufhead *buf = &port->buf; | 189 | struct tty_bufhead *buf = &port->buf; |
189 | 190 | ||
190 | /* Dumb strategy for now - should keep some stats */ | 191 | /* Dumb strategy for now - should keep some stats */ |
191 | WARN_ON(atomic_sub_return(b->size, &buf->memory_used) < 0); | 192 | WARN_ON(atomic_sub_return(b->size, &buf->mem_used) < 0); |
192 | 193 | ||
193 | if (b->size > MIN_TTYB_SIZE) | 194 | if (b->size > MIN_TTYB_SIZE) |
194 | kfree(b); | 195 | kfree(b); |
@@ -200,9 +201,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) | |||
200 | * tty_buffer_flush - flush full tty buffers | 201 | * tty_buffer_flush - flush full tty buffers |
201 | * @tty: tty to flush | 202 | * @tty: tty to flush |
202 | * | 203 | * |
203 | * flush all the buffers containing receive data. If the buffer is | 204 | * flush all the buffers containing receive data. |
204 | * being processed by flush_to_ldisc then we defer the processing | ||
205 | * to that function | ||
206 | * | 205 | * |
207 | * Locking: takes buffer lock to ensure single-threaded flip buffer | 206 | * Locking: takes buffer lock to ensure single-threaded flip buffer |
208 | * 'consumer' | 207 | * 'consumer' |
@@ -230,31 +229,49 @@ void tty_buffer_flush(struct tty_struct *tty) | |||
230 | * tty_buffer_request_room - grow tty buffer if needed | 229 | * tty_buffer_request_room - grow tty buffer if needed |
231 | * @tty: tty structure | 230 | * @tty: tty structure |
232 | * @size: size desired | 231 | * @size: size desired |
232 | * @flags: buffer flags if new buffer allocated (default = 0) | ||
233 | * | 233 | * |
234 | * Make at least size bytes of linear space available for the tty | 234 | * Make at least size bytes of linear space available for the tty |
235 | * buffer. If we fail return the size we managed to find. | 235 | * buffer. If we fail return the size we managed to find. |
236 | * | ||
237 | * Will change over to a new buffer if the current buffer is encoded as | ||
238 | * TTY_NORMAL (so has no flags buffer) and the new buffer requires | ||
239 | * a flags buffer. | ||
236 | */ | 240 | */ |
237 | int tty_buffer_request_room(struct tty_port *port, size_t size) | 241 | static int __tty_buffer_request_room(struct tty_port *port, size_t size, |
242 | int flags) | ||
238 | { | 243 | { |
239 | struct tty_bufhead *buf = &port->buf; | 244 | struct tty_bufhead *buf = &port->buf; |
240 | struct tty_buffer *b, *n; | 245 | struct tty_buffer *b, *n; |
241 | int left; | 246 | int left, change; |
242 | 247 | ||
243 | b = buf->tail; | 248 | b = buf->tail; |
244 | left = b->size - b->used; | 249 | if (b->flags & TTYB_NORMAL) |
250 | left = 2 * b->size - b->used; | ||
251 | else | ||
252 | left = b->size - b->used; | ||
245 | 253 | ||
246 | if (left < size) { | 254 | change = (b->flags & TTYB_NORMAL) && (~flags & TTYB_NORMAL); |
255 | if (change || left < size) { | ||
247 | /* This is the slow path - looking for new buffers to use */ | 256 | /* This is the slow path - looking for new buffers to use */ |
248 | if ((n = tty_buffer_alloc(port, size)) != NULL) { | 257 | if ((n = tty_buffer_alloc(port, size)) != NULL) { |
258 | n->flags = flags; | ||
249 | buf->tail = n; | 259 | buf->tail = n; |
250 | b->commit = b->used; | 260 | b->commit = b->used; |
251 | smp_mb(); | 261 | smp_mb(); |
252 | b->next = n; | 262 | b->next = n; |
253 | } else | 263 | } else if (change) |
264 | size = 0; | ||
265 | else | ||
254 | size = left; | 266 | size = left; |
255 | } | 267 | } |
256 | return size; | 268 | return size; |
257 | } | 269 | } |
270 | |||
271 | int tty_buffer_request_room(struct tty_port *port, size_t size) | ||
272 | { | ||
273 | return __tty_buffer_request_room(port, size, 0); | ||
274 | } | ||
258 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | 275 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); |
259 | 276 | ||
260 | /** | 277 | /** |
@@ -274,12 +291,14 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port, | |||
274 | int copied = 0; | 291 | int copied = 0; |
275 | do { | 292 | do { |
276 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); | 293 | int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); |
277 | int space = tty_buffer_request_room(port, goal); | 294 | int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0; |
295 | int space = __tty_buffer_request_room(port, goal, flags); | ||
278 | struct tty_buffer *tb = port->buf.tail; | 296 | struct tty_buffer *tb = port->buf.tail; |
279 | if (unlikely(space == 0)) | 297 | if (unlikely(space == 0)) |
280 | break; | 298 | break; |
281 | memcpy(char_buf_ptr(tb, tb->used), chars, space); | 299 | memcpy(char_buf_ptr(tb, tb->used), chars, space); |
282 | memset(flag_buf_ptr(tb, tb->used), flag, space); | 300 | if (~tb->flags & TTYB_NORMAL) |
301 | memset(flag_buf_ptr(tb, tb->used), flag, space); | ||
283 | tb->used += space; | 302 | tb->used += space; |
284 | copied += space; | 303 | copied += space; |
285 | chars += space; | 304 | chars += space; |
@@ -362,52 +381,28 @@ EXPORT_SYMBOL(tty_schedule_flip); | |||
362 | int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, | 381 | int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, |
363 | size_t size) | 382 | size_t size) |
364 | { | 383 | { |
365 | int space = tty_buffer_request_room(port, size); | 384 | int space = __tty_buffer_request_room(port, size, TTYB_NORMAL); |
366 | if (likely(space)) { | 385 | if (likely(space)) { |
367 | struct tty_buffer *tb = port->buf.tail; | 386 | struct tty_buffer *tb = port->buf.tail; |
368 | *chars = char_buf_ptr(tb, tb->used); | 387 | *chars = char_buf_ptr(tb, tb->used); |
369 | memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space); | 388 | if (~tb->flags & TTYB_NORMAL) |
389 | memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space); | ||
370 | tb->used += space; | 390 | tb->used += space; |
371 | } | 391 | } |
372 | return space; | 392 | return space; |
373 | } | 393 | } |
374 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string); | 394 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string); |
375 | 395 | ||
376 | /** | ||
377 | * tty_prepare_flip_string_flags - make room for characters | ||
378 | * @port: tty port | ||
379 | * @chars: return pointer for character write area | ||
380 | * @flags: return pointer for status flag write area | ||
381 | * @size: desired size | ||
382 | * | ||
383 | * Prepare a block of space in the buffer for data. Returns the length | ||
384 | * available and buffer pointer to the space which is now allocated and | ||
385 | * accounted for as ready for characters. This is used for drivers | ||
386 | * that need their own block copy routines into the buffer. There is no | ||
387 | * guarantee the buffer is a DMA target! | ||
388 | */ | ||
389 | |||
390 | int tty_prepare_flip_string_flags(struct tty_port *port, | ||
391 | unsigned char **chars, char **flags, size_t size) | ||
392 | { | ||
393 | int space = tty_buffer_request_room(port, size); | ||
394 | if (likely(space)) { | ||
395 | struct tty_buffer *tb = port->buf.tail; | ||
396 | *chars = char_buf_ptr(tb, tb->used); | ||
397 | *flags = flag_buf_ptr(tb, tb->used); | ||
398 | tb->used += space; | ||
399 | } | ||
400 | return space; | ||
401 | } | ||
402 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | ||
403 | |||
404 | 396 | ||
405 | static int | 397 | static int |
406 | receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) | 398 | receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) |
407 | { | 399 | { |
408 | struct tty_ldisc *disc = tty->ldisc; | 400 | struct tty_ldisc *disc = tty->ldisc; |
409 | unsigned char *p = char_buf_ptr(head, head->read); | 401 | unsigned char *p = char_buf_ptr(head, head->read); |
410 | char *f = flag_buf_ptr(head, head->read); | 402 | char *f = NULL; |
403 | |||
404 | if (~head->flags & TTYB_NORMAL) | ||
405 | f = flag_buf_ptr(head, head->read); | ||
411 | 406 | ||
412 | if (disc->ops->receive_buf2) | 407 | if (disc->ops->receive_buf2) |
413 | count = disc->ops->receive_buf2(tty, p, f, count); | 408 | count = disc->ops->receive_buf2(tty, p, f, count); |
@@ -533,7 +528,25 @@ void tty_buffer_init(struct tty_port *port) | |||
533 | buf->head = &buf->sentinel; | 528 | buf->head = &buf->sentinel; |
534 | buf->tail = &buf->sentinel; | 529 | buf->tail = &buf->sentinel; |
535 | init_llist_head(&buf->free); | 530 | init_llist_head(&buf->free); |
536 | atomic_set(&buf->memory_used, 0); | 531 | atomic_set(&buf->mem_used, 0); |
537 | atomic_set(&buf->priority, 0); | 532 | atomic_set(&buf->priority, 0); |
538 | INIT_WORK(&buf->work, flush_to_ldisc); | 533 | INIT_WORK(&buf->work, flush_to_ldisc); |
534 | buf->mem_limit = TTYB_DEFAULT_MEM_LIMIT; | ||
535 | } | ||
536 | |||
537 | /** | ||
538 | * tty_buffer_set_limit - change the tty buffer memory limit | ||
539 | * @port: tty port to change | ||
540 | * | ||
541 | * Change the tty buffer memory limit. | ||
542 | * Must be called before the other tty buffer functions are used. | ||
543 | */ | ||
544 | |||
545 | int tty_buffer_set_limit(struct tty_port *port, int limit) | ||
546 | { | ||
547 | if (limit < MIN_TTYB_SIZE) | ||
548 | return -EINVAL; | ||
549 | port->buf.mem_limit = limit; | ||
550 | return 0; | ||
539 | } | 551 | } |
552 | EXPORT_SYMBOL_GPL(tty_buffer_set_limit); | ||
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 6458e11e8e9d..2d822aa259b2 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/poll.h> | 12 | #include <linux/poll.h> |
13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
17 | #include <linux/wait.h> | 16 | #include <linux/wait.h> |
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index c94d2349dd06..3f746c8eb0dd 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/string.h> | 12 | #include <linux/string.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/init.h> | ||
16 | #include <linux/wait.h> | 15 | #include <linux/wait.h> |
17 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
diff --git a/include/linux/init.h b/include/linux/init.h index 8e68a64bfe00..e1688802964f 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -286,9 +286,11 @@ void __init parse_early_options(char *cmdline); | |||
286 | #define arch_initcall(fn) module_init(fn) | 286 | #define arch_initcall(fn) module_init(fn) |
287 | #define subsys_initcall(fn) module_init(fn) | 287 | #define subsys_initcall(fn) module_init(fn) |
288 | #define fs_initcall(fn) module_init(fn) | 288 | #define fs_initcall(fn) module_init(fn) |
289 | #define rootfs_initcall(fn) module_init(fn) | ||
289 | #define device_initcall(fn) module_init(fn) | 290 | #define device_initcall(fn) module_init(fn) |
290 | #define late_initcall(fn) module_init(fn) | 291 | #define late_initcall(fn) module_init(fn) |
291 | 292 | ||
293 | #define console_initcall(fn) module_init(fn) | ||
292 | #define security_initcall(fn) module_init(fn) | 294 | #define security_initcall(fn) module_init(fn) |
293 | 295 | ||
294 | /* Each module must use one module_init(). */ | 296 | /* Each module must use one module_init(). */ |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 97d660ed70c1..978d0f09d039 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -39,10 +39,14 @@ struct tty_buffer { | |||
39 | int size; | 39 | int size; |
40 | int commit; | 40 | int commit; |
41 | int read; | 41 | int read; |
42 | int flags; | ||
42 | /* Data points here */ | 43 | /* Data points here */ |
43 | unsigned long data[0]; | 44 | unsigned long data[0]; |
44 | }; | 45 | }; |
45 | 46 | ||
47 | /* Values for .flags field of tty_buffer */ | ||
48 | #define TTYB_NORMAL 1 /* buffer has no flags buffer */ | ||
49 | |||
46 | static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs) | 50 | static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs) |
47 | { | 51 | { |
48 | return ((unsigned char *)b->data) + ofs; | 52 | return ((unsigned char *)b->data) + ofs; |
@@ -60,7 +64,8 @@ struct tty_bufhead { | |||
60 | atomic_t priority; | 64 | atomic_t priority; |
61 | struct tty_buffer sentinel; | 65 | struct tty_buffer sentinel; |
62 | struct llist_head free; /* Free queue head */ | 66 | struct llist_head free; /* Free queue head */ |
63 | atomic_t memory_used; /* In-use buffers excluding free list */ | 67 | atomic_t mem_used; /* In-use buffers excluding free list */ |
68 | int mem_limit; | ||
64 | struct tty_buffer *tail; /* Active buffer */ | 69 | struct tty_buffer *tail; /* Active buffer */ |
65 | }; | 70 | }; |
66 | /* | 71 | /* |
@@ -422,7 +427,6 @@ extern int is_ignored(int sig); | |||
422 | extern int tty_signal(int sig, struct tty_struct *tty); | 427 | extern int tty_signal(int sig, struct tty_struct *tty); |
423 | extern void tty_hangup(struct tty_struct *tty); | 428 | extern void tty_hangup(struct tty_struct *tty); |
424 | extern void tty_vhangup(struct tty_struct *tty); | 429 | extern void tty_vhangup(struct tty_struct *tty); |
425 | extern void tty_vhangup_locked(struct tty_struct *tty); | ||
426 | extern void tty_unhangup(struct file *filp); | 430 | extern void tty_unhangup(struct file *filp); |
427 | extern int tty_hung_up_p(struct file *filp); | 431 | extern int tty_hung_up_p(struct file *filp); |
428 | extern void do_SAK(struct tty_struct *tty); | 432 | extern void do_SAK(struct tty_struct *tty); |
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 21ddd7d9ea1f..c28dd523f96e 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _LINUX_TTY_FLIP_H | 1 | #ifndef _LINUX_TTY_FLIP_H |
2 | #define _LINUX_TTY_FLIP_H | 2 | #define _LINUX_TTY_FLIP_H |
3 | 3 | ||
4 | extern int tty_buffer_set_limit(struct tty_port *port, int limit); | ||
4 | extern int tty_buffer_space_avail(struct tty_port *port); | 5 | extern int tty_buffer_space_avail(struct tty_port *port); |
5 | extern int tty_buffer_request_room(struct tty_port *port, size_t size); | 6 | extern int tty_buffer_request_room(struct tty_port *port, size_t size); |
6 | extern int tty_insert_flip_string_flags(struct tty_port *port, | 7 | extern int tty_insert_flip_string_flags(struct tty_port *port, |
@@ -9,8 +10,6 @@ extern int tty_insert_flip_string_fixed_flag(struct tty_port *port, | |||
9 | const unsigned char *chars, char flag, size_t size); | 10 | const unsigned char *chars, char flag, size_t size); |
10 | extern int tty_prepare_flip_string(struct tty_port *port, | 11 | extern int tty_prepare_flip_string(struct tty_port *port, |
11 | unsigned char **chars, size_t size); | 12 | unsigned char **chars, size_t size); |
12 | extern int tty_prepare_flip_string_flags(struct tty_port *port, | ||
13 | unsigned char **chars, char **flags, size_t size); | ||
14 | extern void tty_flip_buffer_push(struct tty_port *port); | 13 | extern void tty_flip_buffer_push(struct tty_port *port); |
15 | void tty_schedule_flip(struct tty_port *port); | 14 | void tty_schedule_flip(struct tty_port *port); |
16 | 15 | ||
@@ -18,8 +17,12 @@ static inline int tty_insert_flip_char(struct tty_port *port, | |||
18 | unsigned char ch, char flag) | 17 | unsigned char ch, char flag) |
19 | { | 18 | { |
20 | struct tty_buffer *tb = port->buf.tail; | 19 | struct tty_buffer *tb = port->buf.tail; |
21 | if (tb && tb->used < tb->size) { | 20 | int change; |
22 | *flag_buf_ptr(tb, tb->used) = flag; | 21 | |
22 | change = (tb->flags & TTYB_NORMAL) && (flag != TTY_NORMAL); | ||
23 | if (!change && tb->used < tb->size) { | ||
24 | if (~tb->flags & TTYB_NORMAL) | ||
25 | *flag_buf_ptr(tb, tb->used) = flag; | ||
23 | *char_buf_ptr(tb, tb->used++) = ch; | 26 | *char_buf_ptr(tb, tb->used++) = ch; |
24 | return 1; | 27 | return 1; |
25 | } | 28 | } |
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index f15c898ff462..b8347c207cb8 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h | |||
@@ -84,7 +84,8 @@ | |||
84 | * processing. <cp> is a pointer to the buffer of input | 84 | * processing. <cp> is a pointer to the buffer of input |
85 | * character received by the device. <fp> is a pointer to a | 85 | * character received by the device. <fp> is a pointer to a |
86 | * pointer of flag bytes which indicate whether a character was | 86 | * pointer of flag bytes which indicate whether a character was |
87 | * received with a parity error, etc. | 87 | * received with a parity error, etc. <fp> may be NULL to indicate |
88 | * all data received is TTY_NORMAL. | ||
88 | * | 89 | * |
89 | * void (*write_wakeup)(struct tty_struct *); | 90 | * void (*write_wakeup)(struct tty_struct *); |
90 | * | 91 | * |
@@ -118,7 +119,8 @@ | |||
118 | * processing. <cp> is a pointer to the buffer of input | 119 | * processing. <cp> is a pointer to the buffer of input |
119 | * character received by the device. <fp> is a pointer to a | 120 | * character received by the device. <fp> is a pointer to a |
120 | * pointer of flag bytes which indicate whether a character was | 121 | * pointer of flag bytes which indicate whether a character was |
121 | * received with a parity error, etc. | 122 | * received with a parity error, etc. <fp> may be NULL to indicate |
123 | * all data received is TTY_NORMAL. | ||
122 | * If assigned, prefer this function for automatic flow control. | 124 | * If assigned, prefer this function for automatic flow control. |
123 | */ | 125 | */ |
124 | 126 | ||